diff --git a/haloo3d b/haloo3d index eadd683..92fd129 160000 --- a/haloo3d +++ b/haloo3d @@ -1 +1 @@ -Subproject commit eadd683885698be471fd5763b7a266786d6dec41 +Subproject commit 92fd1294cb6b910f7de2817d60b536738a2ecc7a diff --git a/maze.c b/maze.c index 7ac59ef..c4158c0 100644 --- a/maze.c +++ b/maze.c @@ -2,7 +2,7 @@ #include "haloo3d/haloo3dex_console.h" #include "haloo3d/haloo3dex_easy.h" #include "haloo3d/haloo3dex_gen.h" -// #include "haloo3d/haloo3dex_img.h" +#include "haloo3d/haloo3dex_img.h" #include "haloo3d/haloo3dex_obj.h" #include "haloo3d/haloo3dex_print.h" @@ -29,7 +29,7 @@ #define AVGWEIGHT 0.85 // Game options -#define MAZESIZE 15 +#define MAZESIZE 5 #define HSCALE 1.5 // Maze grows in the positive direction @@ -50,11 +50,14 @@ #define TURNLEFT(d) (d == 8 ? 1 : (d << 1)) #define STACKPUSH(s, t, v) s[t++] = v; +#define ENDTEXTURE "resources/mazeend.ppm" + // Store all the values users can change at the beginning float ditherstart = -1; float ditherend = 8; float fov = 90.0; float minlight = 0.25; +float speed = 1.0; int fps = 30; uint16_t sky = 0xF000; @@ -113,6 +116,11 @@ int maze_connected(uint8_t *maze, int x, int y, int size, uint8_t move) { return 0; } +void maze_to_pos(struct vec2i *maze, mfloat_t *dest, mfloat_t cellsize) { + dest[0] = cellsize * (maze->x + 0.5); + dest[2] = cellsize * (maze->y + 0.5); +} + // Calculate which direction from the given position would have you // facing down the longest hallway uint8_t maze_longesthallway(uint8_t *maze, int size, int x, int y) { @@ -168,8 +176,8 @@ void maze_generate(uint8_t *maze, int size, struct vec2i *start, // The end of the maze is the furthest into the stack we go. This should // somewhat maximize the complexity of start to finish? if (mazetop > maxmazetop) { - end->x = x; - end->y = y; + // end->x = x; + // end->y = y; maxmazetop = mazetop; } mazetop--; @@ -212,6 +220,11 @@ void maze_generate(uint8_t *maze, int size, struct vec2i *start, } } + do { + end->x = rand() % size; + end->y = rand() % size; + } while (abs(end->x - start->x) < 3 && abs(end->y - start->y) < 3); + eprintf("Maze generate: %d,%d -> %d,%d maxdepth: %d\n", start->x, start->y, end->x, end->y, maxmazetop); @@ -300,6 +313,8 @@ typedef struct { typedef struct { haloo3d_obj_instance *obj; mfloat_t *scale; + // When scales are set, they're multiplied by this + mfloat_t basescale; int *timer; } ecs_syncgrow; @@ -317,15 +332,11 @@ typedef struct { typedef struct { worldstate *state; haloo3d_obj *wallmodel; + haloo3d_obj_instance *endobj; int scaletimer; mfloat_t scaleto; } ecs_world; -// void sys_move_placement(ecs_movement *m, ecs_placement *p) { -// vec3_add(p->pos.v, p->pos.v, m->posvel.v); -// p->yaw += m->yawvel; -// } - void sys_billboard(ecs_billboard *bb) { // In our current system, the lookvec is the direction it wants to face, not a // "lookat" point. To lookat something, you simply get the vector pointing @@ -337,17 +348,22 @@ void sys_billboard(ecs_billboard *bb) { bb->obj->lookvec.x = -(bb->lookat->x - bb->obj->pos.x); bb->obj->lookvec.y = 0; bb->obj->lookvec.z = -(bb->lookat->z - bb->obj->pos.z); - // Why does inverting the lookvec do nothing?? + // if (bb->obj->pos.y != 0) { + // printf("BBY: %f LXYZ: (%f, %f, %f) S: %f,%f\n", bb->obj->pos.y, + // bb->obj->lookvec.x, bb->obj->lookvec.y, bb->obj->lookvec.z, + // bb->obj->scale.x, bb->obj->scale.y); + // } } void sys_syncgrow(ecs_syncgrow *sg) { // Only perform logic when a timer is running if (*sg->timer) { + mfloat_t scale = sg->basescale * *sg->scale; if (*sg->timer == 1) { // Just jump right to it on the last frame. We don't run on frame 0 - sg->obj->scale.y = *sg->scale; + sg->obj->scale.y = scale; } else { - mfloat_t scaleleft = *sg->scale - sg->obj->scale.y; + mfloat_t scaleleft = scale - sg->obj->scale.y; sg->obj->scale.y += scaleleft / *sg->timer; } } @@ -397,12 +413,13 @@ void sys_camera(ecs_camera *cam, ecs_placement *p) { } void sys_world(ecs_world *w) { - const int spinspeed = w->state->fps * 4 / 5; + const int spinspeed = w->state->fps * 4.0 / (5 * speed); switch (w->state->state) { case WSTATE_INIT: maze_generate(w->state->maze, MAZESIZE, &w->state->start, &w->state->end); maze_wall_generate(w->state->maze, MAZESIZE, w->wallmodel); eprintf("INIT MAZE COMPLETE, spinning up walls\n"); + maze_to_pos(&w->state->end, w->endobj->pos.v, w->state->cellsize); w->state->state = WSTATE_SPINUP; w->scaletimer = spinspeed; w->scaleto = 1; @@ -452,7 +469,7 @@ typedef struct { static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav, ecs_autorotate *arot) { - const int actiontime = smartai->ws->fps / 2; + const int actiontime = smartai->ws->fps / (2 * speed); const int rotdelaytime = 2 * actiontime / 5; switch (smartai->state) { case SAI_INIT: @@ -463,18 +480,12 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, smartai->dir = maze_longesthallway(smartai->ws->maze, MAZESIZE, smartai->ws->start.x, smartai->ws->start.y); - p->pos.x = smartai->ws->cellsize * (smartai->ws->start.x + 0.5); - p->pos.z = smartai->ws->cellsize * (smartai->ws->start.y + 0.5); + maze_to_pos(&smartai->ws->start, p->pos.v, smartai->ws->cellsize); p->rot.x = dirtoyaw(smartai->dir); // Move startmarker to in front of player. struct vec2i lookdir = dirtovec(smartai->dir); smartai->startmarker->pos.x = p->pos.x + lookdir.x; - // smartai->startmarker->pos.y = 0.0; smartai->startmarker->pos.z = p->pos.z + lookdir.y; - // vec3_subtract(smartai->startmarker->lookvec.v, p->pos.v, - // smartai->startmarker->pos.v); - // To not face up or down, always set y = 0; - // smartai->startmarker->lookvec.y = 0; // Reset autonav + autorotate anav->dest = p->pos; anav->timer = 0; @@ -542,7 +553,8 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p, smartai->rotstate = 0; } // Figure out if a rotation should be scheduled - if (smartai->timer <= 0) { + if (smartai->timer <= 0 && !(smartai->mpos.x == smartai->ws->end.x && + smartai->mpos.y == smartai->ws->end.y)) { // Ok we might be moving, we might not be. Let's go ahead and calculate // rotation based on the FUTURE direction we want to turn. uint8_t rightdir = TURNRIGHT(smartai->dir); @@ -631,24 +643,25 @@ void init_starttexture(haloo3d_fb *startt) { // make this betterin the future haloo3d_print_tracker pt; const uint16_t bgcol = 0xF888; + const uint16_t fgcol = 0xF222; char buf[64]; uint8_t dither[8]; haloo3d_print_initdefault(&pt, buf, sizeof(buf)); pt.bcolor = 0; // Full transparency pt.fb = startt; - // haloo3d_getdither4x4(0.75, dither); + // haloo3d_getdither4x4(1.0, dither); // haloo3d_apply_fillrect(startt, &rect, 0xFAAA, dither); int pbx = rect.x2 - 42; int pby = rect.y1 + 2; for (int i = 0; i < 9; i++) { int x = -1 + (i % 3); int y = -1 + (i / 3); - pt.fcolor = bgcol; + pt.fcolor = 0xFAAA; pt.x = pbx + x; pt.y = pby + y; haloo3d_print(&pt, "START"); } - pt.fcolor = 0xF222; + pt.fcolor = fgcol; pt.x = pbx; pt.y = pby; haloo3d_print(&pt, "START"); @@ -658,28 +671,46 @@ void init_starttexture(haloo3d_fb *startt) { int x = rect.x1 + 2 + 5 * (i % 2); int y = rect.y1 + 2 + 5 * (i / 2); haloo3d_recti wrect = {.x1 = x, .x2 = x + 4, .y1 = y, .y2 = y + 4}; - haloo3d_apply_fillrect(startt, &wrect, binbows[i], dither); + haloo3d_apply_fillrect(startt, wrect, binbows[i], dither); } - haloo3d_apply_rect(startt, &rect, bgcol, 1); + haloo3d_apply_rect(startt, rect, bgcol, 1); rect.x1--; rect.x2++; rect.y1--; rect.y2++; - haloo3d_apply_rect(startt, &rect, 0xF222, 1); + haloo3d_apply_rect(startt, rect, fgcol, 1); +} + +// We COULD generate the end texture maybe, but I don't want to +void init_endtexture(haloo3d_fb *endt) { + haloo3d_img_loadppmfile(endt, ENDTEXTURE); + // Assume the corner of the image is the "transparent" color + haloo3d_img_totransparent(endt, haloo3d_fb_get(endt, 0, 0)); +} + +void init_billboard(haloo3d_obj_instance *bb, mfloat_t scale) { + // Haven't actually generated the object yet, oops. We don't let billboards + // all share the same model, as they might require slightly different + // requirements. + struct vec3 center = {.x = 0, .y = 0.5, .z = 0}; + haloo3d_gen_quad(bb->model, bb->texture, center); + bb->cullbackface = 0; + // This only works if bb is not centered at 0,0. We do this so that the + // billboards "grow up" like the walls do, instead of just expanding out of + // nothingness + bb->pos.y = 0.5 * (1 - scale); + vec3(bb->scale.v, scale, 0, scale); } void init_mazeinstances(haloo3d_obj_instance *floori, haloo3d_obj_instance *ceili, - haloo3d_obj_instance *walli, - haloo3d_obj_instance *starti) { + haloo3d_obj_instance *walli) { floori->cullbackface = 0; ceili->cullbackface = 0; walli->cullbackface = 0; - starti->cullbackface = 0; vec3(floori->scale.v, HSCALE, 1, HSCALE); vec3(ceili->scale.v, HSCALE, 1, HSCALE); vec3(walli->scale.v, HSCALE, 0, HSCALE); - vec3(starti->scale.v, 1, 0, 1); floori->pos.x += MAZESIZE / 2.0 * HSCALE; floori->pos.z += MAZESIZE / 2.0 * HSCALE; ceili->pos.x += MAZESIZE / 2.0 * HSCALE; @@ -687,7 +718,6 @@ void init_mazeinstances(haloo3d_obj_instance *floori, walli->pos.x += MAZESIZE / 2.0 * HSCALE; walli->pos.z += MAZESIZE / 2.0 * HSCALE; ceili->pos.y = 1; - starti->pos.y = 0; } int main() { // int argc, char **argv) { @@ -710,25 +740,24 @@ int main() { // int argc, char **argv) { haloo3d_easytimer_init(&filltimer, AVGWEIGHT); haloo3d_easytimer_init(&logictimer, AVGWEIGHT); - // Load the junk + generate stuff - haloo3d_obj *flooro = haloo3d_easystore_addobj(&storage, "floor"); - haloo3d_obj *ceilo = haloo3d_easystore_addobj(&storage, "ceiling"); + // Load the junk + generate stuff. The floor and ceiling use the SAME model + haloo3d_obj *planeo = haloo3d_easystore_addobj(&storage, "plane"); haloo3d_obj *wallo = haloo3d_easystore_addobj(&storage, "walls"); haloo3d_obj *starto = haloo3d_easystore_addobj(&storage, "start"); + haloo3d_obj *endo = haloo3d_easystore_addobj(&storage, "end"); haloo3d_fb *floort = haloo3d_easystore_addtex(&storage, "floor"); haloo3d_fb *ceilt = haloo3d_easystore_addtex(&storage, "ceiling"); haloo3d_fb *wallt = haloo3d_easystore_addtex(&storage, "walls"); haloo3d_fb *startt = haloo3d_easystore_addtex(&storage, "start"); + haloo3d_fb *endt = haloo3d_easystore_addtex(&storage, "end"); - haloo3d_gen_plane(flooro, MAZESIZE); - haloo3d_gen_plane(ceilo, MAZESIZE); + haloo3d_gen_plane(planeo, MAZESIZE); haloo3d_gen_grid(wallo, MAZESIZE, 0); init_floortexture(floort); init_ceilingtexture(ceilt); init_walltexture(wallt); init_starttexture(startt); - struct vec3 center = {.x = 0, .y = 0.5, .z = 0}; - haloo3d_gen_quad(starto, startt, center); + init_endtexture(endt); eprintf("Initialized models and textures\n"); @@ -747,14 +776,18 @@ int main() { // int argc, char **argv) { vec3(light.v, 0, -MCOS(LIGHTANG), MSIN(LIGHTANG)); haloo3d_obj_instance *floori = - haloo3d_easyrender_addinstance(&render, flooro, floort); + haloo3d_easyrender_addinstance(&render, planeo, floort); haloo3d_obj_instance *walli = haloo3d_easyrender_addinstance(&render, wallo, wallt); haloo3d_obj_instance *ceili = - haloo3d_easyrender_addinstance(&render, ceilo, ceilt); + haloo3d_easyrender_addinstance(&render, planeo, ceilt); haloo3d_obj_instance *starti = haloo3d_easyrender_addinstance(&render, starto, startt); - init_mazeinstances(floori, ceili, walli, starti); + haloo3d_obj_instance *endi = + haloo3d_easyrender_addinstance(&render, endo, endt); + init_mazeinstances(floori, ceili, walli); + init_billboard(starti, 1.0); + init_billboard(endi, 0.25); eprintf("Setup all object instances\n"); unigi_type_event event; @@ -779,6 +812,7 @@ int main() { // int argc, char **argv) { haloo3d_debugconsole dc; haloo3d_debugconsole_init(&dc); + haloo3d_debugconsole_set(&dc, "game/speed.f", &speed); haloo3d_debugconsole_set(&dc, "render/fps.i", &wstate.fps); haloo3d_debugconsole_set(&dc, "render/fov.f", &fov); haloo3d_debugconsole_set(&dc, "render/trifunc.i", &render.trifunc); @@ -796,18 +830,32 @@ int main() { // int argc, char **argv) { ecs_eid worldid = mecs_newentity(&ecs, 0); eprintf("World eid: %d\n", worldid); ECS_SETCOMPONENT(&ecs, worldid, ecs_world){ - .state = &wstate, .wallmodel = wallo, .scaletimer = 0}; + .state = &wstate, .wallmodel = wallo, .endobj = endi, .scaletimer = 0}; ecs_world *eworld = ecs.c_ecs_world + worldid; // Setup some dynamic objects ecs_eid wallid = mecs_newentity(&ecs, 0); - ECS_SETCOMPONENT(&ecs, wallid, ecs_syncgrow){ - .obj = walli, .scale = &eworld->scaleto, .timer = &eworld->scaletimer}; + ECS_SETCOMPONENT(&ecs, wallid, ecs_syncgrow){.obj = walli, + .scale = &eworld->scaleto, + .basescale = 1, + .timer = &eworld->scaletimer}; ecs_eid startid = mecs_newentity(&ecs, 0); - ECS_SETCOMPONENT(&ecs, startid, ecs_syncgrow){ - .obj = starti, .scale = &eworld->scaleto, .timer = &eworld->scaletimer}; + ECS_SETCOMPONENT(&ecs, startid, ecs_syncgrow){.obj = starti, + .scale = &eworld->scaleto, + .basescale = starti->scale.x, + .timer = &eworld->scaletimer}; ECS_SETCOMPONENT(&ecs, startid, ecs_billboard){.obj = starti, .lookat = &render.camera.pos}; + ecs_eid endid = mecs_newentity(&ecs, 0); + // endi->scale.y = endi->scale.x; + // endi->lookvec.x = -1; + // endi->lookvec.z = 0; + ECS_SETCOMPONENT(&ecs, endid, ecs_syncgrow){.obj = endi, + .scale = &eworld->scaleto, + .basescale = endi->scale.x, + .timer = &eworld->scaletimer}; + ECS_SETCOMPONENT(&ecs, endid, ecs_billboard){.obj = endi, + .lookat = &render.camera.pos}; // Player is ofc most complicated ecs_eid playerid = mecs_newentity(&ecs, 0); @@ -922,7 +970,7 @@ int main() { // int argc, char **argv) { haloo3d_easytimer_end(&frametimer); - float waittime = (1.0 / fps) - frametimer.last; + float waittime = (1.0 / wstate.fps) - frametimer.last; if (waittime > 0) { unigi_time_sleep(waittime * unigi_time_clocks_per_s); } diff --git a/resources/mazeend.ppm b/resources/mazeend.ppm new file mode 100644 index 0000000..62e2271 Binary files /dev/null and b/resources/mazeend.ppm differ