Paintings ALMOST worked
This commit is contained in:
parent
29c5ece6da
commit
aa0c785a49
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ ignore/
|
||||
*.obj
|
||||
*.cam
|
||||
*.tar.gz
|
||||
*.Identifier
|
||||
callgrind.*
|
||||
|
||||
# Images
|
||||
|
53
ecs2.h
53
ecs2.h
@ -11,41 +11,64 @@
|
||||
#define ECS_MAXENTITIES 1024
|
||||
#endif
|
||||
|
||||
#define ECS_MAXCTYPES 63 // uint64 bits minus one
|
||||
// We reserve one slot to automatically point back to the ecs system.
|
||||
// This is the unusable 64th ID = 63 (your ids should start from 0)
|
||||
#define ECS_MAXCTYPES 63
|
||||
// The self flag is an ID that will get you back a component that is
|
||||
// the ecs system itself. It is ALSO used to identify is an entity is
|
||||
// valid, as ALL entities will implicitly have the ECS component
|
||||
#define ECS_SELFFLAG (1ULL << ECS_MAXCTYPES)
|
||||
|
||||
typedef unsigned long long ecs_cid;
|
||||
typedef int ecs_eid;
|
||||
|
||||
#define ECS_START(name) \
|
||||
typedef struct { \
|
||||
typedef struct name name; \
|
||||
struct name { \
|
||||
ecs_cid entities[ECS_MAXENTITIES]; \
|
||||
ecs_eid entitytop;
|
||||
ecs_eid entitytop; \
|
||||
name *c_##name[ECS_MAXENTITIES];
|
||||
|
||||
#define ECS_END(name) \
|
||||
} \
|
||||
name; \
|
||||
; \
|
||||
/* Always initialize the ecs system when you create a new one! */ \
|
||||
static void name##_init(name *_ecs) { memset(_ecs, 0, sizeof(name)); } \
|
||||
/* Create an entity with the given base components (usually 0) */ \
|
||||
static ecs_eid name##_newentity(name *_ecs, ecs_cid basecomponents) { \
|
||||
for (int i = 0; i < ECS_MAXENTITIES; i++) { \
|
||||
ecs_eid id = _ecs->entitytop++; \
|
||||
ecs_eid id = _ecs->entitytop; \
|
||||
_ecs->entitytop = (_ecs->entitytop + 1) % ECS_MAXENTITIES; \
|
||||
if (_ecs->entities[id] == 0) { \
|
||||
_ecs->entities[id] = (1ULL << ECS_MAXCTYPES) | basecomponents; \
|
||||
_ecs->entities[id] = ECS_SELFFLAG | basecomponents; \
|
||||
_ecs->c_##name[id] = _ecs; \
|
||||
return id; \
|
||||
} \
|
||||
} \
|
||||
return -1; \
|
||||
} \
|
||||
/* Delete an entity by eid from the given ecs sys */ \
|
||||
static void name##_deleteentity(name *_ecs, ecs_eid eid) { \
|
||||
if (eid >= 0 && eid < ECS_MAXENTITIES) \
|
||||
_ecs->entities[eid] = 0; \
|
||||
} \
|
||||
/* Whether an entity matches a given list of components by flag */ \
|
||||
static int name##_match(name *_ecs, ecs_eid _eid, ecs_cid _comps) { \
|
||||
ecs_cid _realcomps = (1ULL << ECS_MAXCTYPES) | _comps; \
|
||||
ecs_cid _realcomps = ECS_SELFFLAG | _comps; \
|
||||
return (_ecs->entities[_eid] & _realcomps) == _realcomps; \
|
||||
}
|
||||
} \
|
||||
/* 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); \
|
||||
} \
|
||||
const ecs_cid name##_fl = ECS_SELFFLAG;
|
||||
|
||||
// Create an ECS component within an ECS struct
|
||||
#define ECS_COMPONENT(type) type c_##type[ECS_MAXENTITIES];
|
||||
|
||||
// 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)
|
||||
#define ECS_CID(type, id) \
|
||||
const int type##_id = id; \
|
||||
const ecs_cid type##_fl = (1ULL << id);
|
||||
@ -116,4 +139,18 @@ typedef int ecs_eid;
|
||||
} \
|
||||
}
|
||||
|
||||
// Add a system function which automatically calls your given function with
|
||||
// pre-pulled items from the entity component arrays. The new function is
|
||||
// named the same as the old one, just with _run appeneded
|
||||
#define ECS_SYSTEM6(ecsname, fname, type1, type2, type3, type4, type5, type6) \
|
||||
void fname##_run(ecsname *_ecs, ecs_eid eid) { \
|
||||
ecs_cid _ecsflags = type1##_fl | type2##_fl | type3##_fl | type4##_fl | \
|
||||
type5##_fl | type6##_fl; \
|
||||
if (ecsname##_match(_ecs, eid, _ecsflags)) { \
|
||||
fname(_ecs->c_##type1 + eid, _ecs->c_##type2 + eid, \
|
||||
_ecs->c_##type3 + eid, _ecs->c_##type4 + eid, \
|
||||
_ecs->c_##type5 + eid, _ecs->c_##type6 + eid); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
2
haloo3d
2
haloo3d
@ -1 +1 @@
|
||||
Subproject commit 8d814bd4abae2fb0113e5675f838ed2caa4e938f
|
||||
Subproject commit 96dbee2942ae8b3d09302a24b075024c8134bb55
|
347
maze.c
347
maze.c
@ -9,8 +9,11 @@
|
||||
#include "unigi/unigi.headers/src/main.h"
|
||||
#include "unigi/unigi.platform.sdl1/src/main.c"
|
||||
|
||||
#define ECS_MAXENTITIES 100
|
||||
|
||||
#include "ecs2.h"
|
||||
#include "keys.h"
|
||||
#include "maze_ecstypes.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -20,7 +23,7 @@
|
||||
#define WIDTH 320
|
||||
#define HEIGHT 200
|
||||
#define ASPECT ((float)WIDTH / HEIGHT)
|
||||
#define SCREENSCALE 2
|
||||
#define SCREENSCALE 1
|
||||
#define SWIDTH (WIDTH * SCREENSCALE)
|
||||
#define SHEIGHT (HEIGHT * SCREENSCALE)
|
||||
#define NEARCLIP 0.01
|
||||
@ -29,8 +32,9 @@
|
||||
#define AVGWEIGHT 0.85
|
||||
|
||||
// Game options
|
||||
#define MAZESIZE 15
|
||||
#define MAZESIZE 5
|
||||
#define HSCALE 1.5
|
||||
#define PAINTINGODDS 2
|
||||
|
||||
// Maze grows in the positive direction
|
||||
#define MAZENORTH 1
|
||||
@ -51,6 +55,8 @@
|
||||
#define STACKPUSH(s, t, v) s[t++] = v;
|
||||
|
||||
#define ENDTEXTURE "resources/mazeend.ppm"
|
||||
#define PAINTINGTEXTURE "resources/specwall.ppm"
|
||||
#define PAINTINGNAME "painting"
|
||||
|
||||
// Store all the values users can change at the beginning
|
||||
float ditherstart = -1;
|
||||
@ -229,18 +235,63 @@ void maze_generate(uint8_t *maze, int size, struct vec2i *start,
|
||||
free(mazestack);
|
||||
}
|
||||
|
||||
void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) {
|
||||
// int rand_painting(int size) {
|
||||
// return (rand() % ()) == 0;
|
||||
// }
|
||||
|
||||
void create_painting(struct vec2i mazepos, uint8_t dir,
|
||||
haloo3d_easyinstancer *ins, mecs *ecs, ecs_world *world) {
|
||||
// Create the painting render instance, set up the ecs instance, etc.
|
||||
haloo3d_obj_instance *painting = haloo3d_easyinstantiate(ins, PAINTINGNAME);
|
||||
ecs_eid id = mecs_newentity(ecs, 0);
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_syncgrow){.obj = painting,
|
||||
.scale = &world->scaleto,
|
||||
.basescale = 1,
|
||||
.timer = &world->scaletimer};
|
||||
ECS_SETCOMPONENT(ecs, id, ecs_dieoninit){
|
||||
.obj = painting, .render = ins->render, .ws = world->state};
|
||||
// Fix up some things based on dir.
|
||||
switch (dir) {
|
||||
case DIRNORTH:
|
||||
mazepos.y++;
|
||||
break;
|
||||
case DIREAST: // East also needs the rotation from west
|
||||
mazepos.x++;
|
||||
// fall through
|
||||
case DIRWEST:
|
||||
vec3(painting->lookvec.v, 1, 0, 0);
|
||||
break;
|
||||
}
|
||||
// OK now that it's setup, we need to put it in the right spot and scale it
|
||||
vec3(painting->pos.v, mazepos.x * world->state->cellsize, 0,
|
||||
mazepos.y * world->state->cellsize);
|
||||
vec3(painting->scale.v, HSCALE, world->scaleto, HSCALE);
|
||||
// rotation is around the left edge. That's both where we put it AND
|
||||
// where the painting rotates around.
|
||||
}
|
||||
|
||||
// Generate walls AND create paintings. Kind of doing too much
|
||||
void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj,
|
||||
haloo3d_easyinstancer *ins, mecs *ecs,
|
||||
ecs_world *world) {
|
||||
// Reset ALL walls
|
||||
obj->numfaces = 0;
|
||||
// Simple: for each cell, we check if north or east is a wall. If so,
|
||||
// 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++) {
|
||||
struct vec2i mazepos = {.x = x, .y = y};
|
||||
if (!maze_connected(maze, x, y, size, DIREAST)) {
|
||||
haloo3d_gen_grid_quad(obj, x, y, dirtovec(DIREAST));
|
||||
if ((rand() % PAINTINGODDS) == 0) {
|
||||
create_painting(mazepos, DIREAST, ins, ecs, world);
|
||||
}
|
||||
}
|
||||
if (!maze_connected(maze, x, y, size, DIRNORTH)) {
|
||||
haloo3d_gen_grid_quad(obj, x, y, dirtovec(DIRNORTH));
|
||||
if ((rand() % PAINTINGODDS) == 0) {
|
||||
create_painting(mazepos, DIRNORTH, ins, ecs, world);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -250,21 +301,33 @@ void maze_wall_generate(uint8_t *maze, int size, haloo3d_obj *obj) {
|
||||
}
|
||||
}
|
||||
|
||||
// Turning into a blob? IDK. Maybe certain things should be
|
||||
// global state, which is this.
|
||||
typedef struct {
|
||||
// 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;
|
||||
// // A simple linked list of objects
|
||||
// struct objlist {
|
||||
// haloo3d_obj_instance *obj;
|
||||
// struct objlist *next;
|
||||
// };
|
||||
//
|
||||
// // Add a new link at the given elem
|
||||
// struct objlist *objlist_add(struct objlist *elem, haloo3d_obj_instance *obj)
|
||||
// {
|
||||
// mallocordie(elem->next, sizeof(struct objlist *));
|
||||
// elem->next->obj = obj;
|
||||
// elem->next->next = NULL;
|
||||
// return elem->next;
|
||||
// }
|
||||
//
|
||||
// // Free every single element starting at head
|
||||
// void objlist_free(struct objlist *head, haloo3d_easyrender *r) {
|
||||
// // void (*freefunc)(haloo3d_obj_instance *obj)) {
|
||||
// if (head) {
|
||||
// objlist_free(head->next, r);
|
||||
// haloo3d_easyrender_deleteinstance(r, head->obj);
|
||||
// // if (freefunc) {
|
||||
// // freefunc(head->obj);
|
||||
// //}
|
||||
// free(head);
|
||||
// }
|
||||
// }
|
||||
|
||||
enum {
|
||||
WSTATE_INIT = 0,
|
||||
@ -274,61 +337,6 @@ enum {
|
||||
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 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;
|
||||
|
||||
// Component which enables synchronized scale y from 0 to 1 or 1 to 0. It is
|
||||
// expected that an external source is modifying the value
|
||||
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;
|
||||
|
||||
// A billboard for OUR system, which does not look up or down at the target. As
|
||||
// such, no matter what the lookat is set to, y is always going to be equal to
|
||||
// the y of the instance, so it appears to be looking "straight"
|
||||
typedef struct {
|
||||
haloo3d_obj_instance *obj;
|
||||
struct vec3 *lookat;
|
||||
} ecs_billboard;
|
||||
|
||||
// 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 *wallmodel;
|
||||
haloo3d_obj_instance *endobj;
|
||||
int scaletimer;
|
||||
mfloat_t scaleto;
|
||||
} ecs_world;
|
||||
|
||||
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
|
||||
@ -397,12 +405,27 @@ void sys_camera(ecs_camera *cam, ecs_placement *p) {
|
||||
cam->camera->pitch = p->rot.y;
|
||||
}
|
||||
|
||||
void sys_world(ecs_world *w) {
|
||||
void sys_dieoninit(ecs_dieoninit *die, mecs **ecs) {
|
||||
if (die->ws->state == WSTATE_INIT) {
|
||||
ecs_eid id = mecs_eid(ecs);
|
||||
eprintf("DELETING SELF: %d\n", id);
|
||||
// Trivially delete the entity from the renderer
|
||||
haloo3d_easyrender_deleteinstance(die->render, die->obj);
|
||||
// Delete ourselves from existence
|
||||
mecs_deleteentity(*ecs, id);
|
||||
}
|
||||
}
|
||||
|
||||
void sys_world(ecs_world *w, mecs **ecs) {
|
||||
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);
|
||||
// We don't need to free anything created from previous runs; they delete
|
||||
// themselves
|
||||
maze_generate(w->state->maze, w->state->size, &w->state->start,
|
||||
&w->state->end);
|
||||
maze_wall_generate(w->state->maze, w->state->size, w->wallmodel,
|
||||
w->instancer, *ecs, w);
|
||||
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;
|
||||
@ -441,18 +464,6 @@ enum {
|
||||
SAI_GAMEPLAY,
|
||||
};
|
||||
|
||||
// State for tracking a smart ai moving through the maze.
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
// uint8_t rotstate;
|
||||
uint8_t dir;
|
||||
uint32_t timer;
|
||||
mfloat_t rotchange;
|
||||
struct vec2i mpos;
|
||||
worldstate *ws;
|
||||
haloo3d_obj_instance *startmarker;
|
||||
} ecs_smartai;
|
||||
|
||||
int smartai_mazeend(ecs_smartai *smartai) {
|
||||
if (smartai->mpos.x == smartai->ws->end.x &&
|
||||
smartai->mpos.y == smartai->ws->end.y) {
|
||||
@ -464,8 +475,8 @@ int smartai_mazeend(ecs_smartai *smartai) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sys_smartai(ecs_smartai *smartai, ecs_placement *p,
|
||||
ecs_autonav *anav, ecs_autorotate *arot) {
|
||||
void sys_smartai(ecs_smartai *smartai, ecs_placement *p, ecs_autonav *anav,
|
||||
ecs_autorotate *arot) {
|
||||
const int actiontime = smartai->ws->fps / (2 * speed);
|
||||
const int rotdelaytime = actiontime / 2; // 2 * actiontime / 5;
|
||||
switch (smartai->state) {
|
||||
@ -475,8 +486,8 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p,
|
||||
if (smartai->ws->state == WSTATE_SPINUP) {
|
||||
smartai->mpos = smartai->ws->start;
|
||||
smartai->dir =
|
||||
maze_longesthallway(smartai->ws->maze, MAZESIZE, smartai->ws->start.x,
|
||||
smartai->ws->start.y);
|
||||
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);
|
||||
p->rot.x = dirtoyaw(smartai->dir);
|
||||
// Move startmarker to in front of player.
|
||||
@ -527,7 +538,7 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p,
|
||||
}
|
||||
// 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,
|
||||
MAZESIZE, smartai->dir)) {
|
||||
smartai->ws->size, smartai->dir)) {
|
||||
struct vec2i movement = dirtovec(smartai->dir);
|
||||
smartai->mpos.x += movement.x;
|
||||
smartai->mpos.y += movement.y;
|
||||
@ -538,12 +549,12 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p,
|
||||
// Figure out if a rotation should be scheduled
|
||||
if (!(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.
|
||||
// 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);
|
||||
uint8_t leftdir = TURNLEFT(smartai->dir);
|
||||
if (maze_connected(smartai->ws->maze, smartai->mpos.x, smartai->mpos.y,
|
||||
MAZESIZE, rightdir)) {
|
||||
smartai->ws->size, rightdir)) {
|
||||
// Always choose right over left
|
||||
smartai->rotchange += MPI_2;
|
||||
smartai->timer = rotdelaytime;
|
||||
@ -553,7 +564,8 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p,
|
||||
// This while loop lets us turn around if necessary, so reaching a
|
||||
// dead end isn't super painful waiting for two rotations
|
||||
while (!maze_connected(smartai->ws->maze, smartai->mpos.x,
|
||||
smartai->mpos.y, MAZESIZE, smartai->dir)) {
|
||||
smartai->mpos.y, smartai->ws->size,
|
||||
smartai->dir)) {
|
||||
// We seem to have reached a wall. Do we need to turn ALL the way
|
||||
// around? We only move left if the player can't move forward or
|
||||
// right
|
||||
@ -570,30 +582,8 @@ static void sys_smartai(ecs_smartai *smartai, ecs_placement *p,
|
||||
}
|
||||
}
|
||||
|
||||
// Setup ECS system for our game
|
||||
ECS_START(mecs)
|
||||
ECS_COMPONENT(ecs_world);
|
||||
ECS_COMPONENT(ecs_autonav);
|
||||
ECS_COMPONENT(ecs_autorotate);
|
||||
ECS_COMPONENT(ecs_placement);
|
||||
ECS_COMPONENT(ecs_camera);
|
||||
ECS_COMPONENT(ecs_smartai);
|
||||
ECS_COMPONENT(ecs_syncgrow);
|
||||
ECS_COMPONENT(ecs_billboard);
|
||||
ECS_END(mecs)
|
||||
|
||||
// And then a copy of the components here... that sucksssss
|
||||
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_CID(ecs_smartai, 6);
|
||||
ECS_CID(ecs_syncgrow, 7);
|
||||
ECS_CID(ecs_billboard, 8);
|
||||
|
||||
ECS_SYSTEM1(mecs, sys_world, ecs_world);
|
||||
ECS_SYSTEM2(mecs, sys_world, ecs_world, mecs);
|
||||
ECS_SYSTEM2(mecs, sys_dieoninit, ecs_dieoninit, mecs);
|
||||
ECS_SYSTEM1(mecs, sys_syncgrow, ecs_syncgrow);
|
||||
ECS_SYSTEM1(mecs, sys_billboard, ecs_billboard);
|
||||
ECS_SYSTEM2(mecs, sys_autonav, ecs_autonav, ecs_placement);
|
||||
@ -602,6 +592,41 @@ ECS_SYSTEM2(mecs, sys_camera, ecs_camera, ecs_placement);
|
||||
ECS_SYSTEM4(mecs, sys_smartai, ecs_smartai, ecs_placement, ecs_autonav,
|
||||
ecs_autorotate);
|
||||
|
||||
// typedef struct {
|
||||
// haloo3d_easyrender *render;
|
||||
// haloo3d_obj_instance *paintings[MAXPAINTINGS];
|
||||
// ecs_eid paintingecs[MAXPAINTINGS];
|
||||
// haloo3d_fb *texture;
|
||||
// haloo3d_obj *model;
|
||||
// mecs *ecs;
|
||||
// mfloat_t *scaleto;
|
||||
// int *scaletimer;
|
||||
// int numpaintings;
|
||||
// } paintingmanager;
|
||||
//
|
||||
// void pm_add_painting(paintingmanager *pm) {
|
||||
// if (pm->numpaintings < MAXPAINTINGS) {
|
||||
// pm->paintings[pm->numpaintings] =
|
||||
// haloo3d_easyrender_addinstance(pm->render, pm->model, pm->texture);
|
||||
// ecs_eid id = mecs_newentity(pm->ecs, 0);
|
||||
// ECS_SETCOMPONENT(pm->ecs, id,
|
||||
// ecs_syncgrow){.obj = pm->paintings[pm->numpaintings],
|
||||
// .scale = pm->scaleto,
|
||||
// .basescale = 1,
|
||||
// .timer = pm->scaletimer};
|
||||
// pm->paintingecs[pm->numpaintings] = id;
|
||||
// pm->numpaintings++;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void pm_clear_all(paintingmanager * pm) {
|
||||
// for(int i = 0; i < pm->numpaintings; i++) {
|
||||
// mecs_deleteentity(pm->ecs, pm->paintingecs[i]);
|
||||
// haloo3d_easyrender_deleteinstance(pm->render, pm->paintings[i]);
|
||||
// }
|
||||
// pm->numpaintings = 0;
|
||||
// }
|
||||
|
||||
void init_floortexture(haloo3d_fb *floort) {
|
||||
uint16_t cols[1] = {0xFD93};
|
||||
haloo3d_fb_init_tex(floort, 64, 64);
|
||||
@ -679,6 +704,10 @@ void init_endtexture(haloo3d_fb *endt) {
|
||||
haloo3d_img_totransparent(endt, haloo3d_fb_get(endt, 0, 0));
|
||||
}
|
||||
|
||||
void init_paintingtexture(haloo3d_fb *endt) {
|
||||
haloo3d_img_loadppmfile(endt, PAINTINGTEXTURE);
|
||||
}
|
||||
|
||||
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
|
||||
@ -711,6 +740,56 @@ void init_mazeinstances(haloo3d_obj_instance *floori,
|
||||
ceili->pos.y = 1;
|
||||
}
|
||||
|
||||
// Given a pointer into an obj, fill it with everything required to make
|
||||
// the painting that clips with the wall (it's a cube)
|
||||
void create_paintingobj(haloo3d_obj *obj) {
|
||||
// 2 for each face; we have 4 faces (top and bottom don't need anything)
|
||||
haloo3d_gen_obj_prealloc(obj, 8, 8, 8);
|
||||
// ppm is 128x128 but 1 pixel along the top is the wall side
|
||||
const mfloat_t ptextop = 1.0 / 128.0;
|
||||
const mfloat_t thickness = 1.0 / 64.0;
|
||||
// box will be aligned along x/y axis, so it will be "facing" the negative z
|
||||
// dir like most other models. Box is topleft, topright, bottomleft,
|
||||
// bottomright, then same on other side. Box is not centered around 0,
|
||||
// intstead it is the same as a wall where iti starts from y=0 and goes to
|
||||
// y=1
|
||||
vec4(obj->vertices[0].v, 0, 1, thickness, 1);
|
||||
vec4(obj->vertices[1].v, 1, 1, thickness, 1);
|
||||
vec4(obj->vertices[2].v, 0, 0, thickness, 1);
|
||||
vec4(obj->vertices[3].v, 1, 0, thickness, 1);
|
||||
vec4(obj->vertices[4].v, 0, 1, -thickness, 1);
|
||||
vec4(obj->vertices[5].v, 1, 1, -thickness, 1);
|
||||
vec4(obj->vertices[6].v, 0, 0, -thickness, 1);
|
||||
vec4(obj->vertices[7].v, 1, 0, -thickness, 1);
|
||||
// Now, the vtexture points. Some might be dupes, I don't care. First 4 are
|
||||
// the painting texture, next 4 are the wall texture
|
||||
vec3(obj->vtexture[0].v, 0.001, 0.999 - ptextop, 0);
|
||||
vec3(obj->vtexture[1].v, 0.999, 0.999 - ptextop, 0);
|
||||
vec3(obj->vtexture[2].v, 0.001, 0.001, 0);
|
||||
vec3(obj->vtexture[3].v, 0.999, 0.001, 0);
|
||||
vec3(obj->vtexture[4].v, 0.001, 0.999, 0);
|
||||
vec3(obj->vtexture[5].v, 0.999, 0.999, 0);
|
||||
vec3(obj->vtexture[6].v, 0.001, 1.0 - ptextop, 0);
|
||||
vec3(obj->vtexture[7].v, 0.999, 1.0 - ptextop, 0);
|
||||
// Preconstruct the simplified format of the face vertices and vtexture.
|
||||
// First 3 are vertices, next are vtexture
|
||||
// clang-format: off
|
||||
const uint8_t f[8][6] = {
|
||||
{0, 2, 3, 0, 2, 3}, // front face
|
||||
{0, 3, 1, 0, 3, 1}, {5, 7, 6, 0, 2, 3}, // back face
|
||||
{5, 6, 4, 0, 3, 1}, {1, 3, 7, 4, 6, 7}, // front side
|
||||
{1, 7, 5, 4, 7, 5}, {4, 6, 2, 4, 6, 7}, // back side
|
||||
{4, 2, 0, 4, 7, 5},
|
||||
};
|
||||
// clang-format: on
|
||||
for (int fi = 0; fi < obj->numfaces; fi++) {
|
||||
for (int v = 0; v < 3; v++) {
|
||||
obj->faces[fi][v].posi = f[fi][v];
|
||||
obj->faces[fi][v].texi = f[fi][v + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main() { // int argc, char **argv) {
|
||||
|
||||
haloo3d_easystore storage;
|
||||
@ -725,6 +804,8 @@ int main() { // int argc, char **argv) {
|
||||
render.tprint.fb = &screen;
|
||||
eprintf("Initialized renderer\n");
|
||||
|
||||
haloo3d_easyinstancer instancer = {.storage = &storage, .render = &render};
|
||||
|
||||
haloo3d_easytimer frametimer, sdltimer, filltimer, logictimer;
|
||||
haloo3d_easytimer_init(&frametimer, AVGWEIGHT);
|
||||
haloo3d_easytimer_init(&sdltimer, AVGWEIGHT);
|
||||
@ -736,31 +817,40 @@ 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 *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 *paintingt = haloo3d_easystore_addtex(&storage, PAINTINGNAME);
|
||||
|
||||
haloo3d_gen_plane(planeo, MAZESIZE);
|
||||
haloo3d_gen_grid(wallo, MAZESIZE, 0);
|
||||
create_paintingobj(paintingo);
|
||||
init_floortexture(floort);
|
||||
init_ceilingtexture(ceilt);
|
||||
init_walltexture(wallt);
|
||||
init_starttexture(startt);
|
||||
init_endtexture(endt);
|
||||
init_paintingtexture(paintingt);
|
||||
|
||||
eprintf("Initialized models and textures\n");
|
||||
|
||||
worldstate wstate;
|
||||
memset(&wstate, 0, sizeof(worldstate));
|
||||
// The maze won't change size (for now), so we can set it here to some
|
||||
// constant array
|
||||
uint8_t maze[MAZESIZE * MAZESIZE];
|
||||
wstate.size = MAZESIZE;
|
||||
wstate.maze = maze;
|
||||
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
|
||||
// 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
|
||||
// lighting vector, which can easily be rotated in the opposite direction of
|
||||
// the model
|
||||
struct vec3 light;
|
||||
@ -779,7 +869,7 @@ int main() { // int argc, char **argv) {
|
||||
init_mazeinstances(floori, ceili, walli);
|
||||
init_billboard(starti, 1.0);
|
||||
init_billboard(endi, 0.25);
|
||||
eprintf("Setup all object instances\n");
|
||||
eprintf("Setup all static object instances\n");
|
||||
|
||||
unigi_type_event event;
|
||||
unigi_type_resolution res;
|
||||
@ -817,11 +907,15 @@ int main() { // int argc, char **argv) {
|
||||
// Set up ECS entities. For this game, we mostly have global entities.
|
||||
mecs ecs;
|
||||
mecs_init(&ecs);
|
||||
eprintf("ECS sys size: %zu\n", sizeof(mecs));
|
||||
|
||||
ecs_eid worldid = mecs_newentity(&ecs, 0);
|
||||
eprintf("World eid: %d\n", worldid);
|
||||
ECS_SETCOMPONENT(&ecs, worldid, ecs_world){
|
||||
.state = &wstate, .wallmodel = wallo, .endobj = endi, .scaletimer = 0};
|
||||
ECS_SETCOMPONENT(&ecs, worldid, ecs_world){.state = &wstate,
|
||||
.wallmodel = wallo,
|
||||
.endobj = endi,
|
||||
.scaletimer = 0,
|
||||
.instancer = &instancer};
|
||||
ecs_world *eworld = ecs.c_ecs_world + worldid;
|
||||
|
||||
// Setup some dynamic objects
|
||||
@ -909,6 +1003,7 @@ int main() { // int argc, char **argv) {
|
||||
sys_autorotate_run(&ecs, i);
|
||||
sys_camera_run(&ecs, i);
|
||||
sys_billboard_run(&ecs, i);
|
||||
sys_dieoninit_run(&ecs, i);
|
||||
}
|
||||
haloo3d_easytimer_end(&logictimer);
|
||||
|
||||
|
125
maze_ecstypes.h
Normal file
125
maze_ecstypes.h
Normal file
@ -0,0 +1,125 @@
|
||||
#ifndef __MAZE_ECSTYPES
|
||||
#define __MAZE_ECSTYPES
|
||||
|
||||
#include "ecs2.h"
|
||||
#include "haloo3d/haloo3d.h"
|
||||
#include "haloo3d/haloo3dex_easy.h"
|
||||
|
||||
// Turning into a blob? IDK. Maybe certain things should be
|
||||
// global state, which is this.
|
||||
typedef struct {
|
||||
// float timedelta;
|
||||
int fps;
|
||||
uint8_t state;
|
||||
uint8_t *maze; //[MAZESIZE * MAZESIZE];
|
||||
int size; // The length of an edge, guaranteed to be a square
|
||||
// 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;
|
||||
|
||||
// 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 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;
|
||||
|
||||
// Component which enables synchronized scale y from 0 to 1 or 1 to 0. It is
|
||||
// expected that an external source is modifying the value
|
||||
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;
|
||||
|
||||
// A billboard for OUR system, which does not look up or down at the target. As
|
||||
// such, no matter what the lookat is set to, y is always going to be equal to
|
||||
// the y of the instance, so it appears to be looking "straight"
|
||||
typedef struct {
|
||||
haloo3d_obj_instance *obj;
|
||||
struct vec3 *lookat;
|
||||
} ecs_billboard;
|
||||
|
||||
// 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 *wallmodel;
|
||||
haloo3d_obj_instance *endobj;
|
||||
haloo3d_easyinstancer *instancer;
|
||||
// paintingmanager * pm;
|
||||
int scaletimer;
|
||||
mfloat_t scaleto;
|
||||
} ecs_world;
|
||||
|
||||
// State for tracking a smart ai moving through the maze.
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t dir;
|
||||
uint32_t timer;
|
||||
mfloat_t rotchange;
|
||||
struct vec2i mpos;
|
||||
worldstate *ws;
|
||||
haloo3d_obj_instance *startmarker;
|
||||
} ecs_smartai;
|
||||
|
||||
// A component which allows an object instance to die
|
||||
// when the maze is initiailized.
|
||||
typedef struct {
|
||||
haloo3d_obj_instance *obj;
|
||||
haloo3d_easyrender *render;
|
||||
worldstate *ws;
|
||||
} ecs_dieoninit;
|
||||
|
||||
// Setup ECS system for our game
|
||||
ECS_START(mecs)
|
||||
ECS_COMPONENT(ecs_world);
|
||||
ECS_COMPONENT(ecs_autonav);
|
||||
ECS_COMPONENT(ecs_autorotate);
|
||||
ECS_COMPONENT(ecs_placement);
|
||||
ECS_COMPONENT(ecs_camera);
|
||||
ECS_COMPONENT(ecs_smartai);
|
||||
ECS_COMPONENT(ecs_syncgrow);
|
||||
ECS_COMPONENT(ecs_billboard);
|
||||
ECS_COMPONENT(ecs_dieoninit);
|
||||
ECS_END(mecs)
|
||||
|
||||
// And then a copy of the components here... that sucksssss
|
||||
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_CID(ecs_smartai, 6);
|
||||
ECS_CID(ecs_syncgrow, 7);
|
||||
ECS_CID(ecs_billboard, 8);
|
||||
ECS_CID(ecs_dieoninit, 9);
|
||||
|
||||
#endif
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user