From 67cbfb03294c8f9b4544407f2cb732f965c4c035 Mon Sep 17 00:00:00 2001 From: Carlos Sanchez Date: Sun, 18 Aug 2024 04:33:01 -0400 Subject: [PATCH] Somewhat working maze thing --- Makefile | 8 ++- ecs.h | 27 +++----- ecs_comps.h | 76 +++++++++++++++++++---- haloo3d | 2 +- maze.c | 175 ++++++++++++++++++++++++++++++++++++++-------------- 5 files changed, 209 insertions(+), 79 deletions(-) diff --git a/Makefile b/Makefile index 42d4ffe..819ca86 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,13 @@ -# Compiler and other things +# Compiler and other things. CC = gcc CFLAGS = -std=c99 -Wall -Wextra BUILDD = build + +# NOTE: there is a gcc bug (?) which is making some of the code produce spurrious warnings +# for "stringop-overflow" even though no string operations are taking place +# ifeq ($(CC),gcc) +# CFLAGS += -Wno-error=stringop-overflow +# endif ifdef MARCH # Allows you to define the architecture (usually not required) CFLAGS += -march=$(MARCH) endif diff --git a/ecs.h b/ecs.h index 889fd81..03ea9f9 100644 --- a/ecs.h +++ b/ecs.h @@ -32,7 +32,7 @@ static void haloo_ecs_init(haloo_ecs *ecs) { static hecs_eidt haloo_ecs_newentity(haloo_ecs *ecs, hecs_cidt basecomponents) { for (int i = 0; i < HECS_MAXENTITIES; i++) { hecs_eidt id = ecs->entitytop++; - if (ecs->e_components[id]) { + if (ecs->e_components[id] == 0) { // Utilize the very last bit to indicate that the entity is active ecs->e_components[id] = (1ULL << HECS_MAXCTYPES) | basecomponents; return id; @@ -59,31 +59,18 @@ static int haloo_ecs_newcomponent(haloo_ecs *ecs, void *component) { return id; } -// Retrieve the component list for the given component id -// static void *haloo_ecs_getcomponents(haloo_ecs *ecs, int cid) { -// // Let the user fail in spectacular ways if cid is bad -// return ecs->components[cid]; -// } - -// static void * haloo_ecs_entitycomponent(haloo_ecs *ecs, int eid, int cid) { -// // Let the user fail in spectacular ways if cid is bad -// return haloo_ecs_getcomponents(ecs, cid) -// } - // Convert component id into flag for use with system identification #define HECS_CIDF(id) (1ULL << id) -// Create the storage for a new component within the entity system. Will -// create a variable within the given scope with the given name. DOES -// NOT MALLOC -#define HECS_NEWCOMPONENT(type, name) type name[HECS_MAXENTITIES]; + // Shortcut to both create the storage and add it to the given ecs. // Automatically stores the name as __type. Stores the id for the component in // type_id. For convenience, another variable of type_f is created for the flag // version of the component id #define HECS_ADDNEWCOMPONENT(type, ecs) \ - HECS_NEWCOMPONENT(type, __##type); \ + type __##type[HECS_MAXENTITIES]; \ hecs_cidt type##_id = haloo_ecs_newcomponent(ecs, __##type); \ hecs_cidt type##_f = HECS_CIDF(type##_id); + // Set component values on a given entity, also sets the flag indicating this // component is now registered with the given entity. You should follow this // statement immediately with the values for your component. @@ -91,12 +78,11 @@ static int haloo_ecs_newcomponent(haloo_ecs *ecs, void *component) { #define HECS_SETCOMPONENT(type, ecs, eid) \ (ecs)->e_components[eid] |= type##_f; \ __##type[eid] = (type) -//__ecs_cpos[playerid] = (ecs_cpos){.x = 1, .y = 1}; + // Retrieve a component for a single entity from the entity system, // casting it to the given type #define HECS_ENTITYCOMPONENT(type, eid, cid, ecs) \ (((type)ecs->components[cid]) + eid) -// ecs.compenents[ecs.numcomponents++] = __ecs__type; // Run a function against ecs using the given limiting components. Note that // components MUST be passed in the EXACT order the function expects them! @@ -105,8 +91,9 @@ static int haloo_ecs_newcomponent(haloo_ecs *ecs, void *component) { const hecs_cidt _hecstemp[] = {__VA_ARGS__}; \ const int _hecsnumargs = sizeof(_hecstemp) / sizeof(hecs_cidt); \ hecs_cidt _hecsflags = 0; \ + /*eprintf("MADE ARGS: %d\n", _hecsnumargs);*/ \ for (int _hecsi = 0; _hecsi < _hecsnumargs; _hecsi++) { \ - _hecsflags |= _hecstemp[_hecsi]; \ + _hecsflags |= HECS_CIDF(_hecstemp[_hecsi]); \ } \ if (haloo_ecs_match(ecs, eid, _hecsflags)) { \ func(ecs, eid, __VA_ARGS__); \ diff --git a/ecs_comps.h b/ecs_comps.h index 442ed2f..52c3e63 100644 --- a/ecs_comps.h +++ b/ecs_comps.h @@ -30,11 +30,32 @@ typedef struct { } ecs_rotateto; // Move object position into moveto -static void sys_ecs_objin_moveto(haloo_ecs *ecs, hecs_eidt id, hecs_cidt oiid, - hecs_cidt mtid) { +// static void sys_ecs_objin_moveto(haloo_ecs *ecs, hecs_eidt id, hecs_cidt +// oiid, +// hecs_cidt mtid) { +// eprintf("Objin moveto %ld, %ld\n", oiid, mtid); +// ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs); +// ecs_objin *oi = HECS_ENTITYCOMPONENT(ecs_objin *, id, oiid, ecs); +// eprintf("Objin moveto END\n"); +// mt->pos = (*oi)->pos; +// } + +// Move camera position into moveto +static void sys_ecs_camera_moveto(haloo_ecs *ecs, hecs_eidt id, hecs_cidt camid, + hecs_cidt mtid) { + // eprintf("Camera moveto %ld, %ld\n", camid, mtid); ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs); - ecs_objin *oi = HECS_ENTITYCOMPONENT(ecs_objin *, id, oiid, ecs); - mt->pos = (*oi)->pos; + ecs_camera *cam = HECS_ENTITYCOMPONENT(ecs_camera *, id, camid, ecs); + // eprintf("Camera moveto END\n"); + mt->pos = (*cam)->pos; +} + +static void sys_ecs_camera_rotateto(haloo_ecs *ecs, hecs_eidt id, + hecs_cidt camid, hecs_cidt rtid) { + ecs_rotateto *rt = HECS_ENTITYCOMPONENT(ecs_rotateto *, id, rtid, ecs); + ecs_camera *cam = HECS_ENTITYCOMPONENT(ecs_camera *, id, camid, ecs); + rt->rot.x = (*cam)->yaw; + rt->rot.y = (*cam)->pitch; } static void sys_ecs_moveto(haloo_ecs *ecs, hecs_eidt id, hecs_cidt mtid) { @@ -45,17 +66,50 @@ static void sys_ecs_moveto(haloo_ecs *ecs, hecs_eidt id, hecs_cidt mtid) { } mfloat_t xdiff = mt->dst.x - mt->pos.x; mfloat_t ydiff = mt->dst.y - mt->pos.y; - mt->pos.x = xdiff / mt->timer; - mt->pos.y = ydiff / mt->timer; + mfloat_t zdiff = mt->dst.z - mt->pos.z; + mt->pos.x += xdiff / mt->timer; + mt->pos.y += ydiff / mt->timer; + mt->pos.z += zdiff / mt->timer; mt->timer--; } -// Move movement pos back into object -static void sys_ecs_moveto_objin(haloo_ecs *ecs, hecs_eidt id, hecs_cidt mtid, - hecs_cidt oiid) { +static void sys_ecs_rotateto(haloo_ecs *ecs, hecs_eidt id, hecs_cidt rtid) { + ecs_rotateto *rt = HECS_ENTITYCOMPONENT(ecs_rotateto *, id, rtid, ecs); + if (rt->timer <= 0) { + rt->rot = rt->dstrot; + return; + } + mfloat_t xdiff = rt->dstrot.x - rt->rot.x; + mfloat_t ydiff = rt->dstrot.y - rt->rot.y; + rt->rot.x += xdiff / rt->timer; + rt->rot.y += ydiff / rt->timer; + rt->timer--; +} + +// // Move movement pos back into object +// static void sys_ecs_moveto_objin(haloo_ecs *ecs, hecs_eidt id, hecs_cidt +// mtid, +// hecs_cidt oiid) { +// ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs); +// ecs_objin *oi = HECS_ENTITYCOMPONENT(ecs_objin *, id, oiid, ecs); +// (*oi)->pos = mt->pos; +// } + +// Move movement pos back into camera +static void sys_ecs_moveto_camera(haloo_ecs *ecs, hecs_eidt id, hecs_cidt mtid, + hecs_cidt camid) { ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs); - ecs_objin *oi = HECS_ENTITYCOMPONENT(ecs_objin *, id, oiid, ecs); - (*oi)->pos = mt->pos; + ecs_camera *cam = HECS_ENTITYCOMPONENT(ecs_camera *, id, camid, ecs); + (*cam)->pos = mt->pos; +} + +// Move rotation back into camera +static void sys_ecs_rotateto_camera(haloo_ecs *ecs, hecs_eidt id, + hecs_cidt rtid, hecs_cidt camid) { + ecs_rotateto *rt = HECS_ENTITYCOMPONENT(ecs_rotateto *, id, rtid, ecs); + ecs_camera *cam = HECS_ENTITYCOMPONENT(ecs_camera *, id, camid, ecs); + (*cam)->yaw = rt->rot.x; + (*cam)->pitch = rt->rot.y; } #endif diff --git a/haloo3d b/haloo3d index e56cb41..75417f6 160000 --- a/haloo3d +++ b/haloo3d @@ -1 +1 @@ -Subproject commit e56cb417a66afffd2cdd5b9d14d2af2acdf9f718 +Subproject commit 75417f662edaf756c1c286f533007df6fcfd5aaa diff --git a/maze.c b/maze.c index b812315..c6ec9e3 100644 --- a/maze.c +++ b/maze.c @@ -31,24 +31,47 @@ // Game options #define MAZESIZE 15 -#define HSCALE 2.0 +#define HSCALE 1.0 // Maze grows in the positive direction #define MAZENORTH 1 #define MAZEEAST 2 #define MAZEVISIT 4 -// When you rightshift these values, you "turn right" +// When you rightshift these values, you "turn right". +// NOTE: north in this case is "towards the screen" because it moves in the +// positive direction. In this case, it's actually wound in the opposite +// direction of what you'd expect #define DIRNORTH 8 -#define DIREAST 4 +#define DIRWEST 4 #define DIRSOUTH 2 -#define DIRWEST 1 +#define DIREAST 1 +#define TURNRIGHT(d) (d == 1 ? 8 : (d >> 1)) +#define TURNLEFT(d) (d == 8 ? 1 : (d << 1)) #define STACKPUSH(s, t, v) s[t++] = v; -// everything in the maze is controlled by the CPU. As such, movement -// is as simple as "go here by this time". No need to complicate the -// components? +// Store all the values users can change at the beginning +float ditherstart = -1; +float ditherend = 8; +float fov = 90.0; +float minlight = 0.25; +int fps = 30; +uint16_t sky = 0xF000; + +// A general position within the maze, and a pointer to the maze itself. +// Can be used to traverse the maze +typedef struct { + uint8_t *maze; + struct vec2i pos; // tile position within maze + int size; + uint8_t dir; // facing dir (see DIREAST/DIRSOUTH/etc); +} ecs_maze; + +// State for tracking ai moving through the maze. +typedef struct { + uint8_t state; +} ecs_smartai; struct vec2i dirtovec(uint8_t dir) { struct vec2i result; @@ -71,20 +94,13 @@ struct vec2i dirtovec(uint8_t dir) { return result; } -// A general position within the maze, and a pointer to the maze itself. -// Can be used to traverse the maze -typedef struct { - uint8_t *maze; - struct vec2i pos; // tile position within maze - int size; - uint8_t dir; // facing dir (see DIREAST/DIRSOUTH/etc); -} ecs_maze; - int maze_visited(uint8_t *maze, int x, int y, int size) { return (maze[x + y * size] & MAZEVISIT) > 0; } int maze_connected(uint8_t *maze, int x, int y, int size, uint8_t move) { + eprintf("CHECKING DIR %d at (%d,%d), it is %d\n", move, x, y, + maze[x + y * size]); if (move == DIREAST) { return (maze[x + y * size] & MAZEEAST) == 0; } else if (move == DIRWEST) { @@ -166,7 +182,7 @@ void maze_generate(uint8_t *maze, int size) { void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) { // Simple: for each cell, we check if north or east is a wall. If so, - // generate it. Also, generate walls for the north and west global wall + // generate it. Also, generate walls for the south and west global wall for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { if (!maze_connected(maze, x, y, size, DIREAST)) { @@ -183,15 +199,58 @@ void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) { } } -int main() { // int argc, char **argv) { +// everything in the maze is controlled by the CPU. As such, movement +// is as simple as "go here by this time". No need to complicate the +// components? +static void sys_ecs_smartai(haloo_ecs *ecs, hecs_eidt id, hecs_cidt said, + hecs_cidt mzid, hecs_cidt mtid, hecs_cidt rtid) { + ecs_smartai *smartai = HECS_ENTITYCOMPONENT(ecs_smartai *, id, said, ecs); + ecs_maze *maze = HECS_ENTITYCOMPONENT(ecs_maze *, id, mzid, ecs); + ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs); + ecs_rotateto *rt = HECS_ENTITYCOMPONENT(ecs_rotateto *, id, rtid, ecs); + if (mt->timer == 0) { // && rt->timer == 0) { + eprintf("SMARTAI: %d DIR: %d POS: (%f, %f)\n", smartai->state, maze->dir, + mt->pos.x, mt->pos.z); + // We can only do things if we're not moving and not rotating + // First, we see if we can turn right. If so, go for it. + uint8_t newdir = TURNRIGHT(maze->dir); + if (smartai->state == 0 && rt->timer == 0 && + maze_connected(maze->maze, maze->pos.x, maze->pos.y, maze->size, + newdir)) { + rt->dstrot.x = rt->rot.x + MPI_2; + rt->timer = fps / 2; + maze->dir = newdir; + smartai->state = 2; + // We are turning and want to move forward, do not turn right again + eprintf("TURN RIGHT TO: %d\n", maze->dir); + return; + } + // -=------------ SEPARATE + // Now, we see if we can move in the direction we're now facing. If so, + // begin an animation to move there. Otherwise, turn left + if (!maze_connected(maze->maze, maze->pos.x, maze->pos.y, maze->size, + maze->dir)) { + if (rt->timer == 0) { + rt->dstrot.x = rt->rot.x - MPI_2; + rt->timer = fps / 2; + maze->dir = TURNLEFT(maze->dir); + eprintf("TURN LEFT (stuck): %d\n", maze->dir); + smartai->state = 1; // We are stuck, do not turn right + } + } else { + // Move in the direction + struct vec2i movement = dirtovec(maze->dir); + maze->pos.x += movement.x; + maze->pos.y += movement.y; + mt->timer = fps / 2; + mt->dst.x += movement.x; + mt->dst.z += movement.y; + smartai->state = 0; // We are no longer stuck, you can turn right + } + } +} - // Store all the values users can change at the beginning - float ditherstart = -1; - float ditherend = 8; - float fov = 90.0; - float minlight = 0.25; - int fps = 30; - uint16_t sky = 0xF000; +int main() { // int argc, char **argv) { haloo3d_easystore storage; haloo3d_easystore_init(&storage); @@ -209,11 +268,10 @@ int main() { // int argc, char **argv) { haloo3d_debugconsole_set(&dc, "render/fps.i", &fps); haloo3d_debugconsole_set(&dc, "render/fov.f", &fov); - haloo3d_debugconsole_set(&dc, "render/trifunc.f", &render.trifunc); + haloo3d_debugconsole_set(&dc, "render/trifunc.i", &render.trifunc); haloo3d_debugconsole_set(&dc, "render/ditherstart.f", &ditherstart); haloo3d_debugconsole_set(&dc, "render/ditherend.f", &ditherend); haloo3d_debugconsole_set(&dc, "render/sky.u16x", &sky); - haloo3d_debugconsole_set(&dc, "render/fasttris.i", &sky); haloo3d_debugconsole_set(&dc, "camera/pos_y.f", &render.camera.pos.y); haloo3d_debugconsole_set(&dc, "camera/pitch.f", &render.camera.pitch); @@ -278,7 +336,8 @@ int main() { // int argc, char **argv) { walli->cullbackface = 0; vec3(floori->scale.v, HSCALE, 1, HSCALE); vec3(ceili->scale.v, HSCALE, 1, HSCALE); - vec3(walli->scale.v, HSCALE, 0, HSCALE); + vec3(walli->scale.v, HSCALE, 1, HSCALE); + // vec3(walli->scale.v, HSCALE, 0, HSCALE); ceili->pos.y = 1; //-1; eprintf("Setup all object instances\n"); @@ -298,9 +357,9 @@ int main() { // int argc, char **argv) { unigi_graphics_init(); unigi_window_create(res, "maze.exe"); // render.printbuf); - render.camera.pos.y = 5; - render.camera.pitch = 2.2; - ceili->pos.y = -10; + // render.camera.pos.y = 4; // 5; + // render.camera.pitch = MPI - 0.1; // 2.2; + // ceili->pos.y = -10; haloo3d_debugconsole_set(&dc, "obj/ceil/pos_y.f", &ceili->pos.y); @@ -309,20 +368,32 @@ int main() { // int argc, char **argv) { haloo_ecs_init(&ecs); HECS_ADDNEWCOMPONENT(ecs_moveto, &ecs); - // HECS_ADDNEWCOMPONENT(ecs_rotateto, &ecs); + HECS_ADDNEWCOMPONENT(ecs_rotateto, &ecs); HECS_ADDNEWCOMPONENT(ecs_maze, &ecs); - HECS_ADDNEWCOMPONENT(ecs_objin, &ecs); + // HECS_ADDNEWCOMPONENT(ecs_objin, &ecs); HECS_ADDNEWCOMPONENT(ecs_camera, &ecs); + HECS_ADDNEWCOMPONENT(ecs_smartai, &ecs); hecs_eidt playerid = haloo_ecs_newentity(&ecs, 0); + if (playerid == -1) { + dieerr("WHY IS PLAYERID -1???\n"); + } + eprintf("Player eid: %d\n", playerid); - // struct vec2i playerstart = {.x = 0, .y = 0}; - // struct vec2i playerface = {.x = 0, .y = -1}; + // This is VERY critical: the player start is at 0 0 but in the maze that's + // the center of the maze! This should probably be fixed or something! + struct vec2i playerstart = {.x = MAZESIZE / 2, .y = MAZESIZE / 2}; + struct vec2 playerrotation = {.x = render.camera.yaw, + .y = render.camera.pitch}; HECS_SETCOMPONENT(ecs_moveto, &ecs, playerid){ .pos = render.camera.pos, .dst = render.camera.pos, .timer = 0}; - HECS_SETCOMPONENT(ecs_maze, &ecs, playerid){}; - //.maze = maze, .pos = playerstart, .size = MAZESIZE, .dir = DIRSOUTH}; + HECS_SETCOMPONENT(ecs_rotateto, &ecs, playerid){ + .rot = playerrotation, .dstrot = playerrotation, .timer = 0}; + HECS_SETCOMPONENT(ecs_maze, &ecs, playerid){ + .maze = maze, .pos = playerstart, .size = MAZESIZE, .dir = DIRSOUTH}; HECS_SETCOMPONENT(ecs_camera, &ecs, playerid) & render.camera; + HECS_SETCOMPONENT(ecs_smartai, &ecs, playerid){.state = 0}; + eprintf("Player component mask: %lx\n", ecs.e_components[playerid]); // ----------------------------------- // Actual rendering @@ -332,16 +403,16 @@ int main() { // int argc, char **argv) { while (1) { haloo3d_easytimer_start(&frametimer); - render.camera.yaw += 0.008; + // render.camera.yaw += 0.008; haloo3d_perspective(render.perspective, fov, ASPECT, NEARCLIP, FARCLIP); haloo3d_easyrender_beginframe(&render); haloo3d_fb_clear(&render.window, sky); - walli->scale.y = fabs(sin(3 * render.camera.yaw)); - // render.camera.up.x = sin(render.camera.yaw); - // render.camera.up.y = cos(render.camera.yaw); - // walli->up.x = sin(3 * render.camera.yaw); - // walli->up.y = cos(4 * render.camera.yaw); + // walli->scale.y = fabs(sin(3 * render.camera.yaw)); + // render.camera.up.x = sin(render.camera.yaw); + // render.camera.up.y = cos(render.camera.yaw); + // walli->up.x = sin(3 * render.camera.yaw); + // walli->up.y = cos(4 * render.camera.yaw); unigi_event_get(&event); if (event.type == unigi_enum_event_input_keyboard) { @@ -361,9 +432,21 @@ int main() { // int argc, char **argv) { // --------------------------- for (int i = 0; i < HECS_MAXENTITIES; i++) { - HECS_RUNSYS(&ecs, i, sys_ecs_objin_moveto, ecs_objin_f, ecs_moveto_f); - HECS_RUNSYS(&ecs, i, sys_ecs_moveto, ecs_moveto_f); - HECS_RUNSYS(&ecs, i, sys_ecs_moveto_objin, ecs_moveto_f, ecs_objin_f); + // eprintf("CHECKING EID %d\n", i); + // HECS_RUNSYS(&ecs, i, sys_ecs_objin_moveto, ecs_objin_id, + // ecs_moveto_id); + HECS_RUNSYS(&ecs, i, sys_ecs_camera_rotateto, ecs_camera_id, + ecs_rotateto_id); + HECS_RUNSYS(&ecs, i, sys_ecs_camera_moveto, ecs_camera_id, ecs_moveto_id); + HECS_RUNSYS(&ecs, i, sys_ecs_smartai, ecs_smartai_id, ecs_maze_id, + ecs_moveto_id, ecs_rotateto_id); + HECS_RUNSYS(&ecs, i, sys_ecs_moveto, ecs_moveto_id); + HECS_RUNSYS(&ecs, i, sys_ecs_rotateto, ecs_rotateto_id); + HECS_RUNSYS(&ecs, i, sys_ecs_moveto_camera, ecs_moveto_id, ecs_camera_id); + HECS_RUNSYS(&ecs, i, sys_ecs_rotateto_camera, ecs_rotateto_id, + ecs_camera_id); + // HECS_RUNSYS(&ecs, i, sys_ecs_moveto_objin, ecs_moveto_id, + // ecs_objin_id); } totaldrawn = 0;