Playing around with ecs
This commit is contained in:
parent
e996e77c38
commit
9717b88e22
116
ecs.h
Normal file
116
ecs.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// A very simple library for constructing the basis of EXTREMELY simple ecs
|
||||||
|
// systems. Made mostly for fun
|
||||||
|
|
||||||
|
#ifndef __HALOO3D_ECS_H
|
||||||
|
#define __HALOO3D_ECS_H
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef HECS_MAXENTITIES
|
||||||
|
#define HECS_MAXENTITIES 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef uint64_t hecs_cidt;
|
||||||
|
typedef int hecs_eidt;
|
||||||
|
|
||||||
|
#define HECS_MAXCTYPES 63 // One minus the thing
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
hecs_cidt e_components[HECS_MAXENTITIES];
|
||||||
|
void *components[HECS_MAXCTYPES];
|
||||||
|
int numcomponents;
|
||||||
|
hecs_eidt entitytop;
|
||||||
|
} haloo_ecs;
|
||||||
|
|
||||||
|
static void haloo_ecs_init(haloo_ecs *ecs) {
|
||||||
|
memset(ecs, 0, sizeof(haloo_ecs));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an entity with given components to ecs system.
|
||||||
|
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]) {
|
||||||
|
// Utilize the very last bit to indicate that the entity is active
|
||||||
|
ecs->e_components[id] = (1ULL << HECS_MAXCTYPES) | basecomponents;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int haloo_ecs_match(haloo_ecs *ecs, hecs_eidt eid, hecs_cidt comps) {
|
||||||
|
hecs_cidt realcomps = (1ULL << HECS_MAXCTYPES) | comps;
|
||||||
|
return (ecs->e_components[eid] & realcomps) == realcomps;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void haloo_ecs_removeentity(haloo_ecs *ecs, int eid) {
|
||||||
|
if (eid >= 0 && eid < HECS_MAXENTITIES)
|
||||||
|
ecs->e_components[eid] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new component to ecs. Create the type or storage with
|
||||||
|
// HECS_NEWCOMPONENT(type, name)
|
||||||
|
static int haloo_ecs_newcomponent(haloo_ecs *ecs, void *component) {
|
||||||
|
int id = ecs->numcomponents++;
|
||||||
|
ecs->components[id] = 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); \
|
||||||
|
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.
|
||||||
|
// Example: HECS_SETCOMPONENT(mytype, &ecs, playerid) { .x = 1, .y = 2 }
|
||||||
|
#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!
|
||||||
|
#define HECS_RUNSYS(ecs, eid, func, ...) \
|
||||||
|
{ \
|
||||||
|
hecs_cidt _hecstemp[] = {__VA_ARGS__}; \
|
||||||
|
hecs_cidt _hecsflags = 0; \
|
||||||
|
for (int _hecsi = 0; _hecsi < sizeof(_hecstemp) / sizeof(hecs_cidt); \
|
||||||
|
_hecsi++) { \
|
||||||
|
_hecsflags |= _hecstemp[_hecsi]; \
|
||||||
|
} \
|
||||||
|
if (haloo_ecs_match(ecs, eid, _hecsflags)) { \
|
||||||
|
func(ecs, eid, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
61
ecs_comps.h
Normal file
61
ecs_comps.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// A bunch of component definitions that might not
|
||||||
|
// be useful in general, but who knows?
|
||||||
|
|
||||||
|
#ifndef __HALOO3D_ECSCOMP_H
|
||||||
|
#define __HALOO3D_ECSCOMP_H
|
||||||
|
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "haloo3d/haloo3d.h"
|
||||||
|
|
||||||
|
// A component that simply points back to an object instance. If combined
|
||||||
|
// with movement, will pull pos from objin at start of frame, then write
|
||||||
|
// pos back to obj at end of frame.
|
||||||
|
typedef haloo3d_obj_instance *ecs_objin;
|
||||||
|
|
||||||
|
// Like objin, this component simply points to a camera. It will set the
|
||||||
|
// position AND rotation at the start of the frame, and pull the pos/
|
||||||
|
// rotation back into the camera at the end.
|
||||||
|
typedef haloo3d_camera *ecs_camera;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct vec3 pos;
|
||||||
|
struct vec3 dst;
|
||||||
|
int timer;
|
||||||
|
} ecs_moveto;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct vec2 rot;
|
||||||
|
struct vec2 dstrot;
|
||||||
|
int timer;
|
||||||
|
} 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) {
|
||||||
|
ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs);
|
||||||
|
ecs_objin *oi = HECS_ENTITYCOMPONENT(ecs_objin *, id, oiid, ecs);
|
||||||
|
mt->pos = (*oi)->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sys_ecs_moveto(haloo_ecs *ecs, hecs_eidt id, hecs_cidt mtid) {
|
||||||
|
ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs);
|
||||||
|
if (mt->timer <= 0) {
|
||||||
|
mt->pos = mt->dst;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
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) {
|
||||||
|
ecs_moveto *mt = HECS_ENTITYCOMPONENT(ecs_moveto *, id, mtid, ecs);
|
||||||
|
ecs_objin *oi = HECS_ENTITYCOMPONENT(ecs_objin *, id, oiid, ecs);
|
||||||
|
(*oi)->pos = mt->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
92
maze.c
92
maze.c
@ -9,6 +9,8 @@
|
|||||||
#include "unigi/unigi.headers/src/main.h"
|
#include "unigi/unigi.headers/src/main.h"
|
||||||
#include "unigi/unigi.platform.sdl1/src/main.c"
|
#include "unigi/unigi.platform.sdl1/src/main.c"
|
||||||
|
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "ecs_comps.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -16,10 +18,10 @@
|
|||||||
// INteresting flags for performance comparisons
|
// INteresting flags for performance comparisons
|
||||||
#define FASTFILL
|
#define FASTFILL
|
||||||
|
|
||||||
#define WIDTH 320
|
#define WIDTH 640
|
||||||
#define HEIGHT 200
|
#define HEIGHT 400
|
||||||
#define ASPECT ((float)WIDTH / HEIGHT)
|
#define ASPECT ((float)WIDTH / HEIGHT)
|
||||||
#define SCREENSCALE 4
|
#define SCREENSCALE 1
|
||||||
#define SWIDTH (WIDTH * SCREENSCALE)
|
#define SWIDTH (WIDTH * SCREENSCALE)
|
||||||
#define SHEIGHT (HEIGHT * SCREENSCALE)
|
#define SHEIGHT (HEIGHT * SCREENSCALE)
|
||||||
#define NEARCLIP 0.01
|
#define NEARCLIP 0.01
|
||||||
@ -38,6 +40,55 @@
|
|||||||
|
|
||||||
#define STACKPUSH(s, t, v) s[t++] = v;
|
#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?
|
||||||
|
// Allows movement in 3 dimensions
|
||||||
|
// typedef struct {
|
||||||
|
// struct vec3 pos;
|
||||||
|
// struct vec3 vel;
|
||||||
|
// } ecs_movement;
|
||||||
|
|
||||||
|
// Allows rotational movement only with yaw and pitch (in that order)
|
||||||
|
// typedef struct {
|
||||||
|
// struct vec2 rot;
|
||||||
|
// struct vec2 rotvel;
|
||||||
|
// } ecs_rotmovement;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
int size;
|
||||||
|
struct vec2i pos; // tile position within maze
|
||||||
|
struct vec2i dir; // facing dir
|
||||||
|
} ecs_maze;
|
||||||
|
|
||||||
|
// A component which can track progress towards some destination. Each
|
||||||
|
// frame it is expected that the timer will decrease, and that on 0,
|
||||||
|
// the destination should be reached
|
||||||
|
// typedef struct {
|
||||||
|
// int timer;
|
||||||
|
// struct vec3 dst;
|
||||||
|
// } ecs_destination;
|
||||||
|
|
||||||
|
// // A component that simply points back to an object instance. If combined
|
||||||
|
// // with movement, will pull pos from objin at start of frame, then write
|
||||||
|
// // pos back to obj at end of frame.
|
||||||
|
// typedef haloo3d_obj_instance *ecs_objin;
|
||||||
|
//
|
||||||
|
// // Like objin, this component simply points to a camera. It will set the
|
||||||
|
// // position AND rotation at the start of the frame, and pull the pos/
|
||||||
|
// // rotation back into the camera at the end.
|
||||||
|
// typedef haloo3d_camera *ecs_camera;
|
||||||
|
|
||||||
|
// typedef struct vec2i ecs_cpos;
|
||||||
|
// typedef struct vec2i ecs_npos;
|
||||||
|
// typedef struct vec2i ecs_cdir;
|
||||||
|
// typedef struct vec2i ecs_ndir;
|
||||||
|
// typedef haloo3d_obj_instance *ecs_objin;
|
||||||
|
// typedef haloo3d_camera *ecs_cam;
|
||||||
|
|
||||||
int maze_visited(uint8_t *maze, int x, int y, int size) {
|
int maze_visited(uint8_t *maze, int x, int y, int size) {
|
||||||
return (maze[x + y * size] & MAZEVISIT) > 0;
|
return (maze[x + y * size] & MAZEVISIT) > 0;
|
||||||
}
|
}
|
||||||
@ -273,6 +324,25 @@ int main() { // int argc, char **argv) {
|
|||||||
|
|
||||||
haloo3d_debugconsole_set(&dc, "obj/ceil/pos_y.f", &ceili->pos.y);
|
haloo3d_debugconsole_set(&dc, "obj/ceil/pos_y.f", &ceili->pos.y);
|
||||||
|
|
||||||
|
// Set up the various systems
|
||||||
|
haloo_ecs ecs;
|
||||||
|
haloo_ecs_init(&ecs);
|
||||||
|
|
||||||
|
HECS_ADDNEWCOMPONENT(ecs_moveto, &ecs);
|
||||||
|
HECS_ADDNEWCOMPONENT(ecs_rotateto, &ecs);
|
||||||
|
HECS_ADDNEWCOMPONENT(ecs_maze, &ecs);
|
||||||
|
HECS_ADDNEWCOMPONENT(ecs_objin, &ecs);
|
||||||
|
HECS_ADDNEWCOMPONENT(ecs_camera, &ecs);
|
||||||
|
|
||||||
|
hecs_eidt playerid = haloo_ecs_newentity(&ecs, 0);
|
||||||
|
|
||||||
|
HECS_SETCOMPONENT(ecs_moveto, &ecs, playerid){
|
||||||
|
.pos = render.camera.pos, .dst = render.camera.pos, .timer = 0};
|
||||||
|
HECS_SETCOMPONENT(ecs_camera, &ecs, playerid) & render.camera;
|
||||||
|
// HECS_SETCOMPONENT(ecs_cpos, &ecs, playerid){.x = 1, .y = 1};
|
||||||
|
|
||||||
|
// ecs_ndir_f);
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// Actual rendering
|
// Actual rendering
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
@ -305,6 +375,22 @@ int main() { // int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------
|
||||||
|
// Game logic?
|
||||||
|
// ---------------------------
|
||||||
|
|
||||||
|
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);
|
||||||
|
// if (haloo_ecs_match(&ecs, i, ecs_moveto_f | ecs_objin_f)) {
|
||||||
|
// sys_ecs_objin_moveto(&ecs, i, ecs_objin_f, ecs_moveto_f);
|
||||||
|
// }
|
||||||
|
// if (haloo_ecs_match(&ecs, i, ecs_moveto_f)) {
|
||||||
|
// sys_ecs_moveto(&ecs, i, ecs_moveto_f);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
totaldrawn = 0;
|
totaldrawn = 0;
|
||||||
|
|
||||||
haloo3d_obj_instance *object = NULL;
|
haloo3d_obj_instance *object = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user