Trying more ecs patterns (not working)

This commit is contained in:
Carlos Sanchez 2024-08-19 01:36:00 -04:00
parent 8abf116c60
commit 06385f8311

440
maze.c
View File

@ -10,7 +10,7 @@
#include "unigi/unigi.platform.sdl1/src/main.c"
#include "ecs2.h"
#include "ecs2_comps.h"
// #include "ecs2_comps.h"
#include "keys.h"
#include <stdlib.h>
@ -99,9 +99,34 @@ int maze_connected(uint8_t *maze, int x, int y, int size, uint8_t move) {
return 0;
}
// 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) {
uint8_t face = DIRNORTH;
uint8_t maxface = face;
uint16_t maxdist = 0;
while (face) {
uint16_t dist = 0;
int dx = x, dy = y;
struct vec2i move = dirtovec(face);
while (maze_connected(maze, dx, dy, size, face)) {
dx += move.x;
dy += move.y;
dist++;
}
if (dist > maxdist) {
maxface = face;
maxdist = dist;
}
face >>= 1;
}
return maxface;
}
// Generate a (square) maze. Utilize one bit of the maze (#2) to
// indicate whether it is visited
void maze_generate(uint8_t *maze, int size) {
void maze_generate(uint8_t *maze, int size, struct vec2i *start,
struct vec2i *end) {
const int mazesquare = (size) * (size);
for (int i = 0; i < mazesquare; i++) {
maze[i] = MAZENORTH | MAZEEAST;
@ -112,9 +137,12 @@ void maze_generate(uint8_t *maze, int size) {
mazestack[i] = -1;
}
// Push current cell onto stack, mark as visited
int x = size / 2;
int y = size / 2;
start->x = rand() % size;
start->y = rand() % size;
int x = start->x;
int y = start->y;
int mazetop = 0;
int maxmazetop = 0;
STACKPUSH(mazestack, mazetop, x + y * size);
maze[x + y * size] |= MAZEVISIT;
uint8_t visitable[4];
@ -122,6 +150,13 @@ void maze_generate(uint8_t *maze, int size) {
// Now let's make a maze!
while (mazetop) {
// 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;
maxmazetop = mazetop;
}
mazetop--;
visittop = 0;
x = mazestack[mazetop] % size;
@ -162,6 +197,9 @@ void maze_generate(uint8_t *maze, int size) {
}
}
eprintf("Maze generate: %d,%d -> %d,%d maxdepth: %d\n", start->x, start->y,
end->x, end->y, maxmazetop);
free(mazestack);
}
@ -184,14 +222,170 @@ void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) {
}
}
// A general position within the maze, and a pointer to the maze itself.
// Can be used to traverse the maze
// Turning into a blob? IDK. Maybe certain things should be
// global state, which is this.
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;
// float timedelta;
int fps;
uint8_t state;
uint8_t maze[MAZESIZE * MAZESIZE];
// int size;
// A suggested start and end. The end is the actual
// end, where we put the ending indicator
struct vec2i start;
struct vec2i end;
// Some simple calcs for you to use
mfloat_t cellsize;
} worldstate;
enum {
WSTATE_INIT = 0,
WSTATE_SPINUP = 1,
WSTATE_GAMEPLAY = 2,
WSTATE_GAMEOVER = 3,
WSTATE_SPINDOWN = 4
};
// A component that stores a position and a facing direction
// as an angle
typedef struct {
struct vec3 pos;
struct vec2 rot; // x is yaw, y is pitch
} ecs_placement;
// A component representing movement through the scene.
// typedef struct {
// struct vec3 posvel;
// mfloat_t yawvel;
// } ecs_movement;
// A component which links back to a camera
typedef struct {
haloo3d_camera *camera;
} ecs_camera;
// A component which allows automatic navigation
// of position through the use of timers.
typedef struct {
struct vec3 dest;
int timer;
} ecs_autonav;
// A component which allows automatic rotation
// through the use of timers.
typedef struct {
struct vec2 dest; // x is yaw, y is pitch
int timer;
} ecs_autorotate;
// A component which has pointers back to global world state.
typedef struct {
worldstate *state;
} ecs_worldstate;
// A component which holds onto data specifically for world
// entities. You can think of it as private data so people
// can't poke at the worldstate data
typedef struct {
worldstate *state;
haloo3d_obj_instance *walls;
uint16_t timer;
} 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_autonav(ecs_autonav *nav, ecs_placement *p) {
if (nav->timer <= 0) {
p->pos = nav->dest;
return;
}
mfloat_t xdiff = nav->dest.x - p->pos.x;
mfloat_t ydiff = nav->dest.y - p->pos.y;
mfloat_t zdiff = nav->dest.z - p->pos.z;
p->pos.x += xdiff / nav->timer;
p->pos.y += ydiff / nav->timer;
p->pos.z += zdiff / nav->timer;
nav->timer--;
}
void sys_autorotate(ecs_autorotate *arot, ecs_placement *p) {
if (arot->timer <= 0) {
p->rot = arot->dest;
return;
}
mfloat_t xdiff = arot->dest.x - p->rot.x;
mfloat_t ydiff = arot->dest.y - p->rot.y;
p->rot.x += xdiff / arot->timer;
p->rot.y += ydiff / arot->timer;
arot->timer--;
}
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;
}
void sys_world(ecs_world *w) {
float scaleleft;
const int spinspeed = w->state->fps * 4 / 5;
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->walls->model);
eprintf("INIT MAZE COMPLETE, spinning up walls\n");
w->state->state = WSTATE_SPINUP;
w->timer = spinspeed;
w->walls->scale.y = 0;
break;
case WSTATE_SPINUP:
// Bring walls up, timer down
scaleleft = 1 - w->walls->scale.y;
w->walls->scale.y += scaleleft / w->timer;
w->timer--;
if (w->timer == 0) {
eprintf("SPINUP COMPLETE, starting gameplay\n");
w->walls->scale.y = 1;
// Start gameplay. We won't know when it's done
w->state->state = WSTATE_GAMEPLAY;
}
break;
case WSTATE_GAMEOVER:
w->timer = spinspeed;
eprintf("GAME OVER, spinning down\n");
w->state->state = WSTATE_SPINDOWN;
break;
case WSTATE_SPINDOWN:
// Bring walls sown, timer down
scaleleft = w->walls->scale.y;
w->walls->scale.y -= scaleleft / w->timer;
w->timer--;
if (w->timer == 0) {
eprintf("SPINDOWN COMPLETE, reinitializing\n");
w->walls->scale.y = 0;
// Start gameplay. We won't know when it's done
w->state->state = WSTATE_INIT;
}
break;
}
}
// // 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;
// // Use a timer and a destination to move simply through
// typedef struct {
//
// } ecs_mazemove;
// State for tracking ai moving through the maze.
typedef struct {
@ -200,17 +394,18 @@ typedef struct {
uint32_t timer;
} ecs_smartai;
// typedef struct {
// uint8_t *maze;
// // What state the game is in, such as game initialize, animation, running,
// etc uint8_t state;
// } ecs_world;
// 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(ecs_smartai *smartai, ecs_maze *maze,
ecs_moveto *mt, ecs_rotateto *rt) {
// 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);
int actiontime = fps / 2;
// Some states are triggered based on the timer
if (smartai->timer > 0) {
@ -273,60 +468,91 @@ static void sys_ecs_smartai(ecs_smartai *smartai, ecs_maze *maze,
}
}
}
*/
// static void sys_ecs_world(ecs_world *world, ecs_maze *maze, ecs_moveto *mt,
// ecs_rotateto *rt) {}
// Setup ECS system for our game
ECS_START(mecs)
ECS_COMPONENT(ecs_moveto);
ECS_COMPONENT(ecs_rotateto);
ECS_COMPONENT(ecs_smartai);
ECS_COMPONENT(ecs_worldstate);
ECS_COMPONENT(ecs_world);
ECS_COMPONENT(ecs_autonav);
ECS_COMPONENT(ecs_autorotate);
ECS_COMPONENT(ecs_placement);
ECS_COMPONENT(ecs_camera);
ECS_COMPONENT(ecs_maze);
// ECS_COMPONENT(ecs_moveto);
// ECS_COMPONENT(ecs_rotateto);
// ECS_COMPONENT(ecs_smartai);
// ECS_COMPONENT(ecs_camera);
// ECS_COMPONENT(ecs_maze);
ECS_END(mecs)
// And then a copy of the components here... that sucksssss
ECS_CID(ecs_moveto, 0);
ECS_CID(ecs_rotateto, 1);
ECS_CID(ecs_smartai, 2);
ECS_CID(ecs_camera, 3);
ECS_CID(ecs_maze, 4);
ECS_CID(ecs_worldstate, 0);
ECS_CID(ecs_world, 1);
ECS_CID(ecs_autonav, 2);
ECS_CID(ecs_autorotate, 3);
ECS_CID(ecs_placement, 4);
ECS_CID(ecs_camera, 5);
ECS_SYSTEM1(mecs, sys_ecs_moveto, ecs_moveto);
ECS_SYSTEM1(mecs, sys_ecs_rotateto, ecs_rotateto);
ECS_SYSTEM2(mecs, sys_ecs_moveto_camera, ecs_moveto, ecs_camera);
ECS_SYSTEM2(mecs, sys_ecs_rotateto_camera, ecs_rotateto, ecs_camera);
ECS_SYSTEM4(mecs, sys_ecs_smartai, ecs_smartai, ecs_maze, ecs_moveto,
ecs_rotateto);
// ECS_CID(ecs_moveto, 0);
// ECS_CID(ecs_rotateto, 1);
// ECS_CID(ecs_smartai, 2);
// ECS_CID(ecs_camera, 3);
// ECS_CID(ecs_maze, 4);
// ECS_SYSTEM1(mecs, sys2_moveto, ecs_moveto, mt) {
// mt->pos.x = 1;
// }
ECS_SYSTEM1(mecs, sys_world, ecs_world);
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_SYSTEM1(mecs, sys_ecs_moveto, ecs_moveto);
// ECS_SYSTEM1(mecs, sys_ecs_rotateto, ecs_rotateto);
// ECS_SYSTEM2(mecs, sys_ecs_moveto_camera, ecs_moveto, ecs_camera);
// ECS_SYSTEM2(mecs, sys_ecs_rotateto_camera, ecs_rotateto, ecs_camera);
// ECS_SYSTEM4(mecs, sys_ecs_smartai, ecs_smartai, ecs_maze, ecs_moveto,
// ecs_rotateto);
void init_floortexture(haloo3d_fb *floort) {
// uint16_t cols[4] = {0xFD93, 0xFB83, 0xFFFF}; //, 0xFDDD};
uint16_t cols[1] = {0xFD93};
haloo3d_fb_init_tex(floort, 64, 64);
haloo3d_apply_alternating(floort, cols, 1);
haloo3d_apply_noise(floort, NULL, 1.0 / 6);
}
void init_ceilingtexture(haloo3d_fb *ceilt) {
uint16_t cols[1] = {0xFFFF}; //, 0xFDDD};
// haloo3d_apply_alternating(floort, cols, 2);
haloo3d_fb_init_tex(ceilt, 64, 64);
haloo3d_apply_alternating(ceilt, cols, 1);
haloo3d_apply_noise(ceilt, NULL, 1.0 / 4);
haloo3d_apply_brick(ceilt, 16, 8, 0xFAAA);
}
void init_walltexture(haloo3d_fb *wallt) {
haloo3d_fb_init_tex(wallt, 64, 64);
uint16_t wallcols[] = {0xFA22};
haloo3d_apply_alternating(wallt, wallcols, 1);
haloo3d_apply_noise(wallt, NULL, 1.0 / 8);
haloo3d_apply_brick(wallt, 18, 13, 0xFEEE);
// haloo3d_apply_brick(wallt, 14, 8, 0xFD94);
haloo3d_apply_noise(wallt, NULL, 1.0 / 8);
}
int main() { // int argc, char **argv) {
haloo3d_easystore storage;
haloo3d_easystore_init(&storage);
haloo3d_debugconsole dc;
haloo3d_debugconsole_init(&dc);
haloo3d_fb screen;
haloo3d_fb_init(&screen, SWIDTH, SHEIGHT);
haloo3d_easyrender render;
haloo3d_easyrender_init(&render, WIDTH, HEIGHT);
render.camera.pos.y = 0.5;
eprintf("Initialized renderer\n");
haloo3d_debugconsole_set(&dc, "render/fps.i", &fps);
haloo3d_debugconsole_set(&dc, "render/fov.f", &fov);
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, "camera/pos_y.f", &render.camera.pos.y);
haloo3d_debugconsole_set(&dc, "camera/pitch.f", &render.camera.pitch);
render.tprint.fb = &screen;
eprintf("Initialized renderer\n");
haloo3d_easytimer frametimer, sdltimer, filltimer;
haloo3d_easytimer_init(&frametimer, AVGWEIGHT);
@ -340,36 +566,22 @@ int main() { // int argc, char **argv) {
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_gen_plane(flooro, MAZESIZE);
haloo3d_gen_plane(ceilo, MAZESIZE);
haloo3d_gen_grid(wallo, MAZESIZE, 0);
init_floortexture(floort);
init_ceilingtexture(ceilt);
init_walltexture(wallt);
// no generic maze generator, we just do it raw. Each cell has a byte which
// indicates if the wall to the NORTH (#0 bit) and the wall to the WEST (#1
// bit) are solid. Because of this, we need one additional row and column
uint8_t maze[MAZESIZE * MAZESIZE];
maze_generate(maze, MAZESIZE);
maze_wall_generate(maze, MAZESIZE, wallo);
uint16_t cols[4] = {0xFD93, 0xFB83, 0xFFFF}; //, 0xFDDD};
haloo3d_fb_init_tex(floort, 64, 64);
haloo3d_apply_alternating(floort, cols, 1);
haloo3d_apply_noise(floort, NULL, 1.0 / 6);
// haloo3d_apply_alternating(floort, cols, 2);
haloo3d_fb_init_tex(ceilt, 64, 64);
haloo3d_apply_alternating(ceilt, cols + 2, 1);
haloo3d_apply_noise(ceilt, NULL, 1.0 / 4);
haloo3d_apply_brick(ceilt, 16, 8, 0xFAAA);
haloo3d_fb_init_tex(wallt, 64, 64);
uint16_t wallcols[] = {0xFA22};
haloo3d_apply_alternating(wallt, wallcols, 1);
haloo3d_apply_noise(wallt, NULL, 1.0 / 8);
haloo3d_apply_brick(wallt, 18, 13, 0xFEEE);
// haloo3d_apply_brick(wallt, 14, 8, 0xFD94);
haloo3d_apply_noise(wallt, NULL, 1.0 / 8);
eprintf("Initialized models and textures\n");
worldstate wstate;
memset(&wstate, 0, sizeof(worldstate));
wstate.fps = fps;
wstate.state = WSTATE_INIT;
wstate.cellsize = HSCALE;
// Lighting. Note that for performance, the lighting is always calculated
// against the base model, and is thus not realistic if the object rotates in
// the world. This can be fixed easily, since each object gets its own
@ -412,7 +624,6 @@ int main() { // int argc, char **argv) {
render.totalverts);
// Init unigi system
// sprintf(render.printbuf, "maze.exe - %s %s %s", argv[1], argv[2], argv[3]);
unigi_graphics_init();
unigi_window_create(res, "maze.exe"); // render.printbuf);
@ -420,34 +631,53 @@ int main() { // int argc, char **argv) {
// render.camera.pitch = MPI - 0.1; // 2.2;
// ceili->pos.y = -10;
haloo3d_debugconsole dc;
haloo3d_debugconsole_init(&dc);
haloo3d_debugconsole_set(&dc, "render/fps.i", &fps);
haloo3d_debugconsole_set(&dc, "render/fov.f", &fov);
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, "camera/pos_y.f", &render.camera.pos.y);
haloo3d_debugconsole_set(&dc, "camera/pitch.f", &render.camera.pitch);
haloo3d_debugconsole_set(&dc, "obj/ceil/pos_y.f", &ceili->pos.y);
// Set up the various systems
// Set up ECS entities. For this game, we mostly have global entities.
mecs ecs;
mecs_init(&ecs);
ecs_eid worldid = mecs_newentity(&ecs, 0);
eprintf("World eid: %d\n", worldid);
ECS_SETCOMPONENT(&ecs, worldid,
ecs_world){.state = &wstate, .walls = walli, .timer = 0};
ecs_eid playerid = mecs_newentity(&ecs, 0);
if (playerid == -1) {
dieerr("WHY IS PLAYERID -1???\n");
}
eprintf("Player eid: %d\n", playerid);
ECS_SETCOMPONENT(&ecs, playerid, ecs_worldstate){.state = &wstate};
ECS_SETCOMPONENT(&ecs, playerid, ecs_camera){.camera = &render.camera};
ECS_SETCOMPONENT(&ecs, playerid, ecs_autonav){.timer = 0};
ECS_SETCOMPONENT(&ecs, playerid, ecs_autorotate){.timer = 0};
// System is setup such that camera position matches maze index
render.camera.pos.x = 0.5 * HSCALE;
render.camera.pos.z = 0.5 * HSCALE;
struct vec2i playerstart = {.x = 0, .y = 0};
struct vec2 playerrotation = {.x = render.camera.yaw,
.y = render.camera.pitch};
ECS_SETCOMPONENT(&ecs, playerid, ecs_moveto){
.pos = render.camera.pos, .dst = render.camera.pos, .timer = 0};
ECS_SETCOMPONENT(&ecs, playerid, ecs_rotateto){
.rot = playerrotation, .dstrot = playerrotation, .timer = 0};
ECS_SETCOMPONENT(&ecs, playerid, ecs_maze){
.maze = maze, .pos = playerstart, .size = MAZESIZE, .dir = DIRSOUTH};
ECS_SETCOMPONENT(&ecs, playerid, ecs_camera) & render.camera;
ECS_SETCOMPONENT(&ecs, playerid, ecs_smartai){.state = 0, .timer = 0};
// if (playerid == -1) {
// dieerr("WHY IS PLAYERID -1???\n");
// }
eprintf("Player component mask: %lx\n", ecs.entities[playerid]);
// // System is setup such that camera position matches maze index
// render.camera.pos.x = 0.5 * HSCALE;
// render.camera.pos.z = 0.5 * HSCALE;
// struct vec2i playerstart = {.x = 0, .y = 0};
// struct vec2 playerrotation = {.x = render.camera.yaw,
// .y = render.camera.pitch};
// ECS_SETCOMPONENT(&ecs, playerid, ecs_rotateto){
// .rot = playerrotation, .dstrot = playerrotation, .timer = 0};
// ECS_SETCOMPONENT(&ecs, playerid, ecs_maze){
// .maze = maze, .pos = playerstart, .size = MAZESIZE, .dir = DIRSOUTH};
// ECS_SETCOMPONENT(&ecs, playerid, ecs_camera) & render.camera;
// ECS_SETCOMPONENT(&ecs, playerid, ecs_smartai){.state = 0, .timer = 0};
// eprintf("Player component mask: %lx\n", ecs.entities[playerid]);
// -----------------------------------
// Actual rendering
@ -468,8 +698,10 @@ int main() { // int argc, char **argv) {
// walli->up.x = sin(3 * render.camera.yaw);
// walli->up.y = cos(4 * render.camera.yaw);
do {
unigi_event_get(&event);
if (event.type == unigi_enum_event_input_keyboard) {
switch (event.type) {
case unigi_enum_event_input_keyboard:
if (event.data.input_keyboard.down) {
switch (event.data.input_keyboard.button) {
case KEY_SPACE:
@ -479,18 +711,26 @@ int main() { // int argc, char **argv) {
exit(0);
}
}
break;
}
} while (event.type != unigi_enum_event_none);
// ---------------------------
// Game logic?
// ---------------------------
for (int i = 0; i < ECS_MAXENTITIES; i++) {
sys_ecs_smartai_run(&ecs, i);
sys_ecs_moveto_run(&ecs, i);
sys_ecs_rotateto_run(&ecs, i);
sys_ecs_moveto_camera_run(&ecs, i);
sys_ecs_rotateto_camera_run(&ecs, i);
sys_world_run(&ecs, i);
sys_autonav_run(&ecs, i);
sys_autorotate_run(&ecs, i);
sys_camera_run(&ecs, i);
// sys_ecs_world_run(&ecs, i);
// sys_ecs_smartai_run(&ecs, i);
// sys_ecs_moveto_run(&ecs, i);
// sys_ecs_rotateto_run(&ecs, i);
// sys_ecs_moveto_camera_run(&ecs, i);
// sys_ecs_rotateto_camera_run(&ecs, i);
}
totaldrawn = 0;
@ -543,7 +783,7 @@ int main() { // int argc, char **argv) {
}
// Just to get the compiler to STOP COMPLAINING about unused
mecs_deleteentity(&ecs, playerid);
mecs_deleteentity(&ecs, worldid);
haloo3d_easystore_deleteallobj(&storage, haloo3d_obj_free);
haloo3d_easystore_deletealltex(&storage, haloo3d_fb_free);