This commit is contained in:
John Alanbrook 2023-11-28 23:17:40 +00:00
parent 1d491e694a
commit e092599816
4 changed files with 101 additions and 56 deletions

60
source/engine/freelist.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef FREELIST_H
#define FREELIST_H
/* Given a pointer to a struct, create a free list
Struct must have a 'next' field
*/
struct freelistheader
{
unsigned int first;
unsigned int len;
};
#define freelist_header(p) ((struct freelistheader*)p-1)
static inline void *freelist_make(struct freelistheader *list, size_t elemsize, unsigned int n)
{
list = malloc(elemsize*n*sizeof(struct freelistheader));
list->first = 0;
list->len = n;
return list+1;
}
static inline unsigned int freelist_check(struct freelistheader *h, void *data, size_t elemsize)
{
if (h->first > h->len) return -1;
unsigned int id = h->first;
return id;
}
#define freelist_size(p,l) do{p = freelist_make(p,sizeof(*p),l); for(int i = 0; i < l; i++) { p[i].next = i+1; }}while(0)
#define freelist_len(p) (freelist_header(p)->len)
#define freelist_first(p) (freelist_header(p)->first)
#define freelist_grab(i,p) do{i=freelist_header(p)->first; freelist_header(p)->first = p[i].next; p[i].next = -1;}while(0)
#define freelist_kill(p,i) do{p[i].next = freelist_first(p);freelist_first(p)=i;}while(0)
#define freelist_free(p) (free(freelist_header(p)))
struct link_header
{
int len;
void *head;
void *last;
};
static inline void *add_link(struct link_header *h, size_t size)
{
void *n = malloc(size);
return n;
}
#define link_header(p) ((struct link_header*)p-1)
#define link_head(p) (link_header(p)->head)
#define link_last(p) (link_header(p)->last)
#define link_add(p,v) do{
#define link_each(p,fn) do {void *f = p; while (link_header(p)->head != NULL) { fn(p); p = p->next; }; p = f; }while(0)
#define link_e(p,i) (
#define stack_size(p,n) (p = malloc(sizeof(p)*n))
#define stack_push(p,v) ()
#define stack_pop(p) ()
#endif

View file

@ -1,20 +1,10 @@
#include "particle.h" #include "particle.h"
#include "stb_ds.h" #include "stb_ds.h"
#include "freelist.h"
struct emitter make_emitter() { struct emitter make_emitter() {
struct emitter e = {0}; struct emitter e = {0};
return e; arrsetcap(e.particles, 200);
}
struct emitter set_emitter(struct emitter e) {
arrsetlen(e.particles, e.max);
e.first = &e.particles[0];
for (int i = 0; i < arrlen(e.particles) - 1; i++) {
e.particles[i].next = &e.particles[i + 1];
}
return e; return e;
} }
@ -23,26 +13,24 @@ void free_emitter(struct emitter e) {
} }
void start_emitter(struct emitter e) { void start_emitter(struct emitter e) {
} }
void pause_emitter(struct emitter e) { void pause_emitter(struct emitter e) {
} }
void stop_emitter(struct emitter e) { void stop_emitter(struct emitter e) {
} }
void emitter_step(struct emitter e, double dt) { void emitter_step(struct emitter e, double dt) {
for (int i = 0; i < arrlen(e.particles); i++) { for (int i = 0; i < arrlen(e.particles); i++) {
if (e.particles[i].life <= 0) e.particles[i].pos = HMM_AddV3(e.particles[i].pos, HMM_MulV3F(e.particles[i].v, dt));
continue; e.particles[i].angle = HMM_MulQ(e.particles[i].angle, HMM_MulQF(e.particles[i].angle, dt));
e.particles[i].life -= dt;
e.particles[i].pos = cpvadd(e.particles[i].pos, cpvmult(e.particles[i].v, dt)); if (e.particles[i].life <= 0)
e.particles[i].angle += e.particles[i].av * dt; arrdelswap(e.particles, i);
e.particles[i].life -= dt;
if (e.particles[i].life <= 0) {
e.particles[i].next = e.first;
e.first = &e.particles[i];
}
} }
} }

View file

@ -1,27 +1,25 @@
#ifndef PARTICLE_H #ifndef PARTICLE_H
#define PARTICLE_H #define PARTICLE_H
#include <chipmunk/chipmunk.h> #include "HandmadeMath.h"
struct particle { struct particle {
cpVect pos; HMM_Vec3 pos;
cpVect v; /* velocity */ HMM_Vec3 v; /* velocity */
double angle; HMM_Quat angle;
double av; /* angular velocity */ HMM_Quat av; /* angular velocity */
union {
union { double life;
double life; unsigned int next;
struct particle *next; };
};
}; };
struct emitter { struct emitter {
struct particle *particles; struct particle *particles;
struct particle *first; int max;
int max; double life;
double life; void (*seeder)(struct particle *p); /* Called to initialize each particle */
void (*seeder)(struct particle *p); /* Called to initialize each particle */
}; };
struct emitter make_emitter(); struct emitter make_emitter();
@ -33,4 +31,4 @@ void stop_emitter(struct emitter e);
void emitter_step(struct emitter e, double dt); void emitter_step(struct emitter e, double dt);
#endif #endif

View file

@ -13,14 +13,14 @@
#include <ctype.h> #include <ctype.h>
#include <limits.h> #include <limits.h>
#include "HandmadeMath.h" #include "HandmadeMath.h"
#include "freelist.h"
#include "sprite.sglsl.h" #include "sprite.sglsl.h"
#include "9slice.sglsl.h" #include "9slice.sglsl.h"
struct TextureOptions TEX_SPRITE = {1, 0, 0}; struct TextureOptions TEX_SPRITE = {1, 0, 0};
static struct sprite *sprites; static struct sprite *sprites = NULL;
static int first = -1;
static sg_shader shader_sprite; static sg_shader shader_sprite;
static sg_pipeline pip_sprite; static sg_pipeline pip_sprite;
@ -59,29 +59,21 @@ int make_sprite(int go) {
.size = {1.f, 1.f}, .size = {1.f, 1.f},
.tex = texture_loadfromfile(NULL), .tex = texture_loadfromfile(NULL),
.go = go, .go = go,
.next = -1,
.layer = 0, .layer = 0,
.next = -1,
.enabled = 1}; .enabled = 1};
int slot = 0; int id;
if (first < 0) { freelist_grab(id, sprites);
arrput(sprites, sprite); sprites[id] = sprite;
slot = arrlen(sprites)-1; return id;
} else {
slot = first;
first = id2sprite(first)->next;
*id2sprite(slot) = sprite;
}
return slot;
} }
void sprite_delete(int id) { void sprite_delete(int id) {
struct sprite *sp = id2sprite(id); struct sprite *sp = id2sprite(id);
sp->go = -1; sp->go = -1;
sp->enabled = 0; sp->enabled = 0;
sp->next = first; freelist_kill(sprites,id);
first = id;
} }
void sprite_enabled(int id, int e) { void sprite_enabled(int id, int e) {
@ -132,8 +124,9 @@ void sprite_draw_all() {
static int *layers; static int *layers;
if (layers) arrfree(layers); if (layers) arrfree(layers);
for (int i = 0; i < arrlen(sprites); i++) for (int i = 0; i < freelist_len(sprites); i++)
if (sprites[i].go >= 0 && sprites[i].enabled) arrpush(layers, i); if (sprites[i].next == -1 && sprites[i].go >= 0 && sprites[i].enabled)
arrpush(layers, i);
if (arrlen(layers) == 0) return; if (arrlen(layers) == 0) return;
if (arrlen(layers) > 1) if (arrlen(layers) > 1)
@ -144,6 +137,10 @@ void sprite_draw_all() {
} }
void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) { void sprite_loadtex(struct sprite *sprite, const char *path, struct glrect frame) {
if (!sprite) {
YughWarn("NO SPRITE!");
return;
}
sprite->tex = texture_loadfromfile(path); sprite->tex = texture_loadfromfile(path);
sprite_setframe(sprite, &frame); sprite_setframe(sprite, &frame);
} }
@ -154,6 +151,8 @@ void sprite_settex(struct sprite *sprite, struct Texture *tex) {
} }
void sprite_initialize() { void sprite_initialize() {
freelist_size(sprites, 500);
shader_sprite = sg_make_shader(sprite_shader_desc(sg_query_backend())); shader_sprite = sg_make_shader(sprite_shader_desc(sg_query_backend()));
pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){ pip_sprite = sg_make_pipeline(&(sg_pipeline_desc){