diff --git a/maze.c b/maze.c index 644147a..fa9a528 100644 --- a/maze.c +++ b/maze.c @@ -18,10 +18,10 @@ // INteresting flags for performance comparisons #define FASTFILL -#define WIDTH 320 -#define HEIGHT 200 +#define WIDTH 640 +#define HEIGHT 400 #define ASPECT ((float)WIDTH / HEIGHT) -#define SCREENSCALE 3 +#define SCREENSCALE 2 #define SWIDTH (WIDTH * SCREENSCALE) #define SHEIGHT (HEIGHT * SCREENSCALE) #define NEARCLIP 0.01 @@ -33,6 +33,8 @@ #define MAZESIZE 15 #define MAZEENDGAP (MAZESIZE / 5) #define HSCALE 1.5 +#define MOUSESCALE 0.25 +#define MOUSESPEED 0.45 // Player speed is 0.5. Lower is faster #define PAINTINGODDS 20 // Some arbitrarily large number, up to you #define MAZEHRAND 100 @@ -62,6 +64,7 @@ #define ENDTEXTURE "resources/mazeend.ppm" #define PAINTINGTEXTURE "resources/specwall.ppm" +#define MOUSETEXTURE "resources/mouse.ppm" #define PAINTINGNAME "painting" // Store all the values users can change at the beginning @@ -379,11 +382,14 @@ void sys_autorotate(ecs_autorotate *arot, ecs_placement *p) { // update camera with placement value on entity void sys_camera(ecs_camera *cam, ecs_placement *p) { - cam->camera->pos = p->pos; - cam->camera->yaw = p->rot.x; - cam->camera->pitch = p->rot.y; + (*cam)->pos = p->pos; + (*cam)->yaw = p->rot.x; + (*cam)->pitch = p->rot.y; } +// do we do anything with the lookvec? idk... +void sys_object(ecs_object *obj, ecs_placement *p) { (*obj)->pos = p->pos; } + void sys_dieoninit(ecs_dieoninit *die, mecs **ecs) { if (die->ws->state == WSTATE_INIT) { ecs_eid id = mecs_eid(ecs); @@ -467,7 +473,7 @@ void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav, smartai->dir = maze_longesthallway(smartai->ws->maze, smartai->ws->size, smartai->ws->start.x, smartai->ws->start.y); - maze_to_pos(&smartai->ws->start, p->pos.v, smartai->ws->cellsize); + maze_to_pos(&smartai->mpos, 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); @@ -561,6 +567,62 @@ void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav, } } +void sys_mouseai(ecs_mouseai *mouseai, ecs_placement *p, ecs_autonav *anav) { + const int actiontime = fps * MOUSESPEED / speed; + switch (mouseai->state) { + case SAI_INIT: // Just reuse smartai state + // Here, we wait until the world state is spinup, in which + // case we can spawn and face + if (mouseai->ws->state == WSTATE_SPINUP) { + mouseai->mpos = (struct vec2i){.x = rand() % mouseai->ws->size, + .y = rand() % mouseai->ws->size}; + mouseai->dir = 1; + maze_to_pos(&mouseai->mpos, p->pos.v, mouseai->ws->cellsize); + // Reset autonav + autorotate + anav->dest = p->pos; + anav->timer = 0; + mouseai->state = SAI_READY; + eprintf("MOUSE READY: %f %f, waiting for spinup\n", anav->dest.x, + anav->dest.z); + } + break; + case SAI_READY: + if (mouseai->ws->state == WSTATE_GAMEPLAY) { + mouseai->state = SAI_GAMEPLAY; + eprintf("MOUSE STARTING GAMEPLAY\n"); + } + break; + case SAI_GAMEPLAY: + // Normal gameplay: move through the maze, etc. + if (mouseai->ws->state != WSTATE_GAMEPLAY) { + eprintf("GAMEPLAY OVER, MOUSE RESETTING\n"); + mouseai->state = SAI_INIT; + anav->timer = 0; // Stop moving + return; + } + // Only decide to do things if you're not moving anymore. Movement is the + // most important thing + if (anav->timer == 0) { + eprintf("MOUSEAI DIR: %d POS: (%f, %f)\n", mouseai->dir, p->pos.x, + p->pos.z); + // Player can only move forward if there's nothing in front of them + if (maze_connected(mouseai->ws->maze, mouseai->mpos.x, mouseai->mpos.y, + mouseai->ws->size, mouseai->dir)) { + struct vec2i movement = dirtovec(mouseai->dir); + mouseai->mpos.x += movement.x; + mouseai->mpos.y += movement.y; + anav->timer = actiontime; + anav->dest.x = p->pos.x + mouseai->ws->cellsize * movement.x; + anav->dest.z = p->pos.z + mouseai->ws->cellsize * movement.y; + } else { + // Mouse only picks new direction if it can't move forward anymore + mouseai->dir = (1 << (rand() % 4)); + } + } + break; + } +} + ECS_SYSTEM2(mecs, sys_world, ecs_world, mecs); ECS_SYSTEM2(mecs, sys_dieoninit, ecs_dieoninit, mecs); ECS_SYSTEM1(mecs, sys_syncgrow, ecs_syncgrow); @@ -568,8 +630,10 @@ ECS_SYSTEM1(mecs, sys_billboard, ecs_billboard); ECS_SYSTEM2(mecs, sys_autonav, ecs_autonav, ecs_placement); ECS_SYSTEM2(mecs, sys_autorotate, ecs_autorotate, ecs_placement); ECS_SYSTEM2(mecs, sys_camera, ecs_camera, ecs_placement); +ECS_SYSTEM2(mecs, sys_object, ecs_object, ecs_placement); ECS_SYSTEM4(mecs, sys_smartai, ecs_smartai, ecs_placement, ecs_autonav, ecs_autorotate); +ECS_SYSTEM3(mecs, sys_mouseai, ecs_mouseai, ecs_placement, ecs_autonav); void init_floortexture(haloo3d_fb *floort) { uint16_t cols[1] = {0xFD93}; @@ -652,6 +716,12 @@ void init_paintingtexture(haloo3d_fb *endt) { haloo3d_img_loadppmfile(endt, PAINTINGTEXTURE); } +void init_mousetexture(haloo3d_fb *mouset) { + haloo3d_img_loadppmfile(mouset, MOUSETEXTURE); + // Assume the corner of the image is the "transparent" color + haloo3d_img_totransparent(mouset, haloo3d_fb_get(mouset, 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 @@ -761,12 +831,14 @@ int main() { // int argc, char **argv) { 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_obj *mouseo = haloo3d_easystore_addobj(&storage, "mouse"); haloo3d_obj *paintingo = haloo3d_easystore_addobj(&storage, PAINTINGNAME); 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_fb *mouset = haloo3d_easystore_addtex(&storage, "mouse"); haloo3d_fb *paintingt = haloo3d_easystore_addtex(&storage, PAINTINGNAME); haloo3d_gen_plane(planeo, MAZESIZE); @@ -777,6 +849,7 @@ int main() { // int argc, char **argv) { init_walltexture(wallt); init_starttexture(startt); init_endtexture(endt); + init_mousetexture(mouset); init_paintingtexture(paintingt); eprintf("Initialized models and textures\n"); @@ -809,9 +882,14 @@ int main() { // int argc, char **argv) { haloo3d_easyrender_addinstance(&render, starto, startt); haloo3d_obj_instance *endi = haloo3d_easyrender_addinstance(&render, endo, endt); + haloo3d_obj_instance *mousei = + haloo3d_easyrender_addinstance(&render, mouseo, mouset); init_mazeinstances(floori, ceili, walli); init_billboard(starti, 1.0); init_billboard(endi, 0.25); + init_billboard(mousei, MOUSESCALE); + // Mouse should be near the floor + mousei->pos.y = MOUSESCALE; eprintf("Setup all static object instances\n"); unigi_type_event event; @@ -863,10 +941,11 @@ int main() { // int argc, char **argv) { // Setup some dynamic objects ecs_eid wallid = mecs_newentity(&ecs, 0); - ECS_SETCOMPONENT(&ecs, wallid, ecs_syncgrow){.obj = walli, - .scale = &eworld->scaleto, - .basescale = 1, - .timer = &eworld->scaletimer}; + ECS_SETCOMPONENT(&ecs, wallid, ecs_syncgrow){ + .obj = walli, + .scale = &eworld->scaleto, + .basescale = 1, // can't set to scale because hscale + .timer = &eworld->scaletimer}; ecs_eid startid = mecs_newentity(&ecs, 0); ECS_SETCOMPONENT(&ecs, startid, ecs_syncgrow){.obj = starti, .scale = &eworld->scaleto, @@ -888,7 +967,7 @@ int main() { // int argc, char **argv) { ECS_SETCOMPONENT(&ecs, playerid, ecs_placement){ .pos = render.camera.pos, .rot = {.x = render.camera.yaw, .y = render.camera.pitch}}; - ECS_SETCOMPONENT(&ecs, playerid, ecs_camera){.camera = &render.camera}; + ECS_SETCOMPONENT(&ecs, playerid, ecs_camera) & render.camera; ECS_SETCOMPONENT(&ecs, playerid, ecs_autonav){.timer = 0}; ECS_SETCOMPONENT(&ecs, playerid, ecs_autorotate){.timer = 0}; ECS_SETCOMPONENT(&ecs, playerid, ecs_smartai){.state = SAI_INIT, @@ -897,6 +976,21 @@ int main() { // int argc, char **argv) { .timer = 0, .startmarker = starti}; + ecs_eid mouseid = mecs_newentity(&ecs, 0); + eprintf("Mouse eid: %d\n", mouseid); + ECS_SETCOMPONENT(&ecs, mouseid, + ecs_placement){.pos = mousei->pos}; // we don't use rot + ECS_SETCOMPONENT(&ecs, mouseid, ecs_autonav){.timer = 0}; + ECS_SETCOMPONENT(&ecs, mouseid, ecs_object) mousei; + ECS_SETCOMPONENT(&ecs, mouseid, ecs_mouseai){.state = SAI_INIT, + .ws = &wstate}; + ECS_SETCOMPONENT(&ecs, mouseid, ecs_billboard){.obj = mousei, + .lookat = &render.camera.pos}; + ECS_SETCOMPONENT(&ecs, mouseid, ecs_syncgrow){.obj = mousei, + .scale = &eworld->scaleto, + .basescale = mousei->scale.x, + .timer = &eworld->scaletimer}; + // ----------------------------------- // Actual rendering // ----------------------------------- @@ -941,10 +1035,12 @@ int main() { // int argc, char **argv) { for (int i = 0; i < ECS_MAXENTITIES; i++) { sys_world_run(&ecs, i); sys_smartai_run(&ecs, i); + sys_mouseai_run(&ecs, i); sys_syncgrow_run(&ecs, i); sys_autonav_run(&ecs, i); sys_autorotate_run(&ecs, i); sys_camera_run(&ecs, i); + sys_object_run(&ecs, i); sys_billboard_run(&ecs, i); sys_dieoninit_run(&ecs, i); } diff --git a/maze_ecstypes.h b/maze_ecstypes.h index 13356a8..17d6e24 100644 --- a/maze_ecstypes.h +++ b/maze_ecstypes.h @@ -26,10 +26,8 @@ typedef struct { struct vec2 rot; // x is yaw, y is pitch } ecs_placement; -// A component which links back to a camera -typedef struct { - haloo3d_camera *camera; -} ecs_camera; +typedef haloo3d_camera *ecs_camera; +typedef haloo3d_obj_instance *ecs_object; // A component which allows automatic navigation // of position through the use of timers. @@ -87,6 +85,13 @@ typedef struct { haloo3d_obj_instance *startmarker; } ecs_smartai; +typedef struct { + uint8_t state; + uint8_t dir; + struct vec2i mpos; + worldstate *ws; +} ecs_mouseai; + // A component which allows an object instance to die // when the maze is initiailized. typedef struct { @@ -106,6 +111,8 @@ ECS_COMPONENT(ecs_smartai); ECS_COMPONENT(ecs_syncgrow); ECS_COMPONENT(ecs_billboard); ECS_COMPONENT(ecs_dieoninit); +ECS_COMPONENT(ecs_mouseai); +ECS_COMPONENT(ecs_object); ECS_END(mecs) // And then a copy of the components here... that sucksssss @@ -119,5 +126,7 @@ ECS_CID(ecs_smartai, 6); ECS_CID(ecs_syncgrow, 7); ECS_CID(ecs_billboard, 8); ECS_CID(ecs_dieoninit, 9); +ECS_CID(ecs_mouseai, 10); +ECS_CID(ecs_object, 11); #endif diff --git a/resources/mouse.ppm b/resources/mouse.ppm new file mode 100644 index 0000000..c3a7fa1 Binary files /dev/null and b/resources/mouse.ppm differ