Maze complete v1
This commit is contained in:
parent
52daa83f2f
commit
0fdfc7e4c2
12
ecs2.h
12
ecs2.h
@ -59,6 +59,16 @@ typedef int ecs_eid;
|
||||
ecs_cid _realcomps = ECS_SELFFLAG | _comps; \
|
||||
return (_ecs->entities[_eid] & _realcomps) == _realcomps; \
|
||||
} \
|
||||
/* fill given list with eids of entities that match. careful with size */ \
|
||||
static int name##_query(name *_ecs, ecs_cid _comps, ecs_eid *out) { \
|
||||
int count = 0; \
|
||||
for (int i = 0; i < ECS_MAXENTITIES; i++) { \
|
||||
if (name##_match(_ecs, i, _comps)) { \
|
||||
out[count++] = i; \
|
||||
} \
|
||||
} \
|
||||
return count; \
|
||||
} \
|
||||
/* Calculate the eid from a double ecs pointer. Useful to get eid in sys */ \
|
||||
static ecs_eid name##_eid(name **_ecs) { \
|
||||
return (ecs_eid)(_ecs - (*_ecs)->c_##name); \
|
||||
@ -68,6 +78,8 @@ typedef int ecs_eid;
|
||||
// Create an ECS component within an ECS struct
|
||||
#define ECS_COMPONENT(type) type c_##type[ECS_MAXENTITIES];
|
||||
|
||||
#define ECS_GETCOMPONENT(_ecs, eid, type) (_ecs)->c_##type[eid]
|
||||
|
||||
// Define the CIDs necessary to access a component (each component MUST
|
||||
// have a unique id and I can't do that inside a macro without requiring
|
||||
// extensions)
|
||||
|
2
haloo3d
2
haloo3d
@ -1 +1 @@
|
||||
Subproject commit 917dfe41aa118cefe36779c9bba7957160cc52e4
|
||||
Subproject commit b6347c5360b84079a50d943d4b1fe8e0edd946b8
|
112
maze.c
112
maze.c
@ -48,7 +48,7 @@
|
||||
#define PRINTMAZE
|
||||
// Max amount of flip polys to generate in maze. actual amount can be lower,
|
||||
// but there will always at least be 1
|
||||
#define MAXFLIPPOLYS 17
|
||||
#define MAXFLIPPOLYS 6
|
||||
// Min space between flip polys
|
||||
#define FLIPPOLYBUFFER 3
|
||||
|
||||
@ -58,6 +58,8 @@
|
||||
#define MAZEVISIT 4
|
||||
#define MAZEFLIP 8
|
||||
|
||||
#define MAZETYPEFLIP 1
|
||||
|
||||
// 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
|
||||
@ -84,7 +86,7 @@ const char POLYNAMES[NUMPOLYS][20] = {"tetrahedron"};
|
||||
float ditherstart = -1;
|
||||
float ditherend = 8;
|
||||
float fov = 90.0;
|
||||
float minlight = 0.25;
|
||||
float minlight = 0.15;
|
||||
float speed = 1.0;
|
||||
int fps = 45;
|
||||
uint16_t sky = 0xF000;
|
||||
@ -276,7 +278,13 @@ void create_flippoly(struct vec2i mazepos, haloo3d_easyinstancer *ins,
|
||||
(mazepos.y + 0.5) * world->state->cellsize);
|
||||
ecs_eid id = mecs_newentity(ecs, 0);
|
||||
mallocordie(poly->lighting, sizeof(struct vec3));
|
||||
// vec3(poly->lighting->v, 0, 0, -1); //-MPI / 4, -1);
|
||||
vec3(poly->lighting->v, 0, -MPI / 4, -1);
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_placement){
|
||||
.pos = {.x = (mazepos.x + 0.5) * world->state->cellsize,
|
||||
.y = 0.35,
|
||||
.z = (mazepos.y + 0.5) * world->state->cellsize},
|
||||
.rot = {.x = 0, .y = MPI * 0.3}};
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_syncgrow){.obj = poly,
|
||||
.scale = &world->scaleto,
|
||||
.basescale = poly->scale.x,
|
||||
@ -285,6 +293,11 @@ void create_flippoly(struct vec2i mazepos, haloo3d_easyinstancer *ins,
|
||||
.render = ins->render,
|
||||
.ws = world->state,
|
||||
.diefunc = kill_flippoly};
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_autorotate){
|
||||
.dest = {.x = MPI * 60 * 60 * 24, .y = 0}, .timer = fps * 60 * 60 * 24};
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_object) poly;
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_mazeentity){.type = MAZETYPEFLIP,
|
||||
.mpos = mazepos};
|
||||
}
|
||||
|
||||
// Generate walls AND create paintings. Kind of doing too much
|
||||
@ -394,8 +407,13 @@ void sys_camera(ecs_camera *cam, ecs_placement *p) {
|
||||
(*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_object(ecs_object *obj, ecs_placement *p) {
|
||||
(*obj)->pos = p->pos;
|
||||
YAWP2VEC(p->rot.x, p->rot.y, (*obj)->lookvec.v);
|
||||
// eprintf("OBJ: %f %f %f (%f %f %f)\n", (*obj)->pos.x, (*obj)->pos.y,
|
||||
// (*obj)->pos.z, (*obj)->lookvec.x, (*obj)->lookvec.y,
|
||||
// (*obj)->lookvec.z);
|
||||
}
|
||||
|
||||
void sys_dieoninit(ecs_dieoninit *die, mecs **ecs) {
|
||||
if (die->ws->state == WSTATE_INIT) {
|
||||
@ -425,6 +443,9 @@ void sys_world(ecs_world *w, mecs **ecs) {
|
||||
for (int i = 0; i < MAXFLIPPOLYS; i++) {
|
||||
struct vec2i m = {.x = rand() % w->state->size,
|
||||
.y = rand() % w->state->size};
|
||||
if (m.x == w->state->start.x && m.y == w->state->start.y) {
|
||||
continue;
|
||||
}
|
||||
for (int yc = m.y - FLIPPOLYBUFFER; yc < m.y + FLIPPOLYBUFFER; yc++) {
|
||||
if (yc < 0 || yc >= w->state->size)
|
||||
continue;
|
||||
@ -473,11 +494,7 @@ void sys_world(ecs_world *w, mecs **ecs) {
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
SAI_INIT,
|
||||
SAI_READY,
|
||||
SAI_GAMEPLAY,
|
||||
};
|
||||
enum { SAI_INIT, SAI_READY, SAI_GAMEPLAY, SAI_FLIP, SAI_HOLD };
|
||||
|
||||
int smartai_mazeend(ecs_smartai *smartai) {
|
||||
if (smartai->mpos.x == smartai->ws->end.x &&
|
||||
@ -491,7 +508,7 @@ int smartai_mazeend(ecs_smartai *smartai) {
|
||||
}
|
||||
|
||||
void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav,
|
||||
ecs_autorotate *arot) {
|
||||
ecs_autorotate *arot, mecs **ecs, ecs_camera *cam) {
|
||||
const int actiontime = fps / (2 * speed);
|
||||
const int rotdelaytime = actiontime / 2; // 2 * actiontime / 5;
|
||||
switch (smartai->state) {
|
||||
@ -499,6 +516,9 @@ void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav,
|
||||
// Here, we wait until the world state is spinup, in which
|
||||
// case we can spawn and face
|
||||
if (smartai->ws->state == WSTATE_SPINUP) {
|
||||
// Reset up vector (even though I like starting upside down, it's a
|
||||
// bit jarring)
|
||||
vec3((*cam)->up.v, 0, 1, 0);
|
||||
smartai->mpos = smartai->ws->start;
|
||||
smartai->dir =
|
||||
maze_longesthallway(smartai->ws->maze, smartai->ws->size,
|
||||
@ -551,6 +571,31 @@ void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav,
|
||||
if (smartai_mazeend(smartai)) {
|
||||
return;
|
||||
}
|
||||
int mazeind = smartai->mpos.x + smartai->mpos.y * smartai->ws->size;
|
||||
// I'm being SUPER lazy and we don't do proper collision detection with
|
||||
// ecs, we just detect the tile and assign objects to tiles
|
||||
// clang-format off
|
||||
if (smartai->ws->maze[mazeind] & MAZEFLIP) {
|
||||
ecs_eid eids[ECS_MAXENTITIES];
|
||||
int count = mecs_query(*ecs, ecs_mazeentity_fl | ecs_placement_fl, eids);
|
||||
eprintf("CHECKING MAZEFLIP (%d entities)\n", count);
|
||||
for(int i = 0; i < count; i++) {
|
||||
ecs_mazeentity * mze = &ECS_GETCOMPONENT(*ecs, eids[i], ecs_mazeentity);
|
||||
if(mze->mpos.x == smartai->mpos.x && mze->mpos.y == smartai->mpos.y) {
|
||||
eprintf("FLIPPING WORLD\n");
|
||||
smartai->state = SAI_FLIP;
|
||||
smartai->timer = 0;
|
||||
// To be SUPER lazy, we just remove the flag and move the object
|
||||
// somewhere else
|
||||
ecs_placement * pl = &ECS_GETCOMPONENT(*ecs, eids[i], ecs_placement);
|
||||
pl->pos.y = -10000;
|
||||
smartai->ws->maze[mazeind] &= ~MAZEFLIP;
|
||||
smartai->upsidedown = !smartai->upsidedown;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
// Player can only move forward if there's nothing in front of them
|
||||
if (maze_connected(smartai->ws->maze, smartai->mpos.x, smartai->mpos.y,
|
||||
smartai->ws->size, smartai->dir)) {
|
||||
@ -592,7 +637,41 @@ void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SAI_FLIP:
|
||||
smartai->timer++;
|
||||
mfloat_t towards = smartai->upsidedown ? -1 : 1;
|
||||
if (smartai->timer >= actiontime) {
|
||||
eprintf("FLIP COMPLETE\n");
|
||||
smartai->timer = actiontime / 8;
|
||||
smartai->state = SAI_HOLD;
|
||||
vec3((*cam)->up.v, 0, towards, 0);
|
||||
} else {
|
||||
mfloat_t angle = MPI * smartai->timer / actiontime;
|
||||
mfloat_t y = towards * -cos(angle);
|
||||
mfloat_t x = towards * -sin(angle);
|
||||
switch (smartai->dir) {
|
||||
case DIRNORTH:
|
||||
vec3((*cam)->up.v, -x, y, 0);
|
||||
break;
|
||||
case DIRSOUTH:
|
||||
vec3((*cam)->up.v, x, y, 0);
|
||||
break;
|
||||
case DIREAST:
|
||||
vec3((*cam)->up.v, 0, y, x);
|
||||
break;
|
||||
case DIRWEST:
|
||||
vec3((*cam)->up.v, 0, y, -x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SAI_HOLD:
|
||||
smartai->timer--;
|
||||
if (smartai->timer <= 0) {
|
||||
eprintf("HOLD COMPLETE\n");
|
||||
smartai->state = SAI_GAMEPLAY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -684,8 +763,8 @@ 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_SYSTEM6(mecs, sys_smartai, ecs_smartai, ecs_placement, ecs_autonav,
|
||||
ecs_autorotate, mecs, ecs_camera);
|
||||
ECS_SYSTEM3(mecs, sys_mouseai, ecs_mouseai, ecs_placement, ecs_autonav);
|
||||
|
||||
void init_floortexture(haloo3d_fb *floort) {
|
||||
@ -1045,12 +1124,13 @@ int main() { // int argc, char **argv) {
|
||||
.ws = &wstate,
|
||||
.rotchange = 0,
|
||||
.timer = 0,
|
||||
.upsidedown = 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_placement){.pos = mousei->pos,
|
||||
.rot = {.x = 0, .y = 0}};
|
||||
ECS_SETCOMPONENT(&ecs, mouseid, ecs_autonav){.timer = 0};
|
||||
ECS_SETCOMPONENT(&ecs, mouseid, ecs_object) mousei;
|
||||
ECS_SETCOMPONENT(&ecs, mouseid, ecs_mouseai){.state = SAI_INIT,
|
||||
@ -1111,6 +1191,8 @@ int main() { // int argc, char **argv) {
|
||||
sys_autonav_run(&ecs, i);
|
||||
sys_autorotate_run(&ecs, i);
|
||||
sys_camera_run(&ecs, i);
|
||||
// NOTE: must run object BEFORE billboard so that billboard
|
||||
// overrides the rotation from object (we want this)
|
||||
sys_object_run(&ecs, i);
|
||||
sys_billboard_run(&ecs, i);
|
||||
sys_dieoninit_run(&ecs, i);
|
||||
|
@ -76,13 +76,14 @@ typedef struct {
|
||||
|
||||
// State for tracking a smart ai moving through the maze.
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t dir;
|
||||
uint32_t timer;
|
||||
int32_t timer;
|
||||
mfloat_t rotchange;
|
||||
struct vec2i mpos;
|
||||
worldstate *ws;
|
||||
haloo3d_obj_instance *startmarker;
|
||||
uint8_t state;
|
||||
uint8_t dir;
|
||||
uint8_t upsidedown;
|
||||
} ecs_smartai;
|
||||
|
||||
typedef struct {
|
||||
@ -101,6 +102,14 @@ typedef struct {
|
||||
void (*diefunc)(haloo3d_obj_instance *);
|
||||
} ecs_dieoninit;
|
||||
|
||||
// A component which indicates where in a maze an entity is.
|
||||
// This is tile-based and so entities can't overlap (here at least),
|
||||
// but just in case, there's an entity type too
|
||||
typedef struct {
|
||||
struct vec2i mpos;
|
||||
uint8_t type;
|
||||
} ecs_mazeentity;
|
||||
|
||||
// Setup ECS system for our game
|
||||
ECS_START(mecs)
|
||||
ECS_COMPONENT(ecs_world);
|
||||
@ -114,6 +123,7 @@ ECS_COMPONENT(ecs_billboard);
|
||||
ECS_COMPONENT(ecs_dieoninit);
|
||||
ECS_COMPONENT(ecs_mouseai);
|
||||
ECS_COMPONENT(ecs_object);
|
||||
ECS_COMPONENT(ecs_mazeentity);
|
||||
ECS_END(mecs)
|
||||
|
||||
// And then a copy of the components here... that sucksssss
|
||||
@ -129,5 +139,6 @@ ECS_CID(ecs_billboard, 8);
|
||||
ECS_CID(ecs_dieoninit, 9);
|
||||
ECS_CID(ecs_mouseai, 10);
|
||||
ECS_CID(ecs_object, 11);
|
||||
ECS_CID(ecs_mazeentity, 12);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user