summaryrefslogtreecommitdiff
path: root/game.c
diff options
context:
space:
mode:
Diffstat (limited to 'game.c')
-rw-r--r--game.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/game.c b/game.c
new file mode 100644
index 0000000..fc126a1
--- /dev/null
+++ b/game.c
@@ -0,0 +1,190 @@
+#include <stdlib.h>
+#include <stdbool.h>
+#include <math.h>
+
+#include <SDL3/SDL.h>
+
+#include "dat.h"
+
+#define SPEED 100
+
+static EntityCollisionProc bulletcollproc;
+static EntityUpdateProc playerproc;
+static EntityUpdateProc ghostproc;
+
+static EntityCollisionProc *collisionProcs[LASTEntity] = {
+ [EBULLET] = bulletcollproc,
+};
+
+static EntityUpdateProc *updateprocs[LASTEntity] = {
+ [EPLAYER] = playerproc,
+ [EGHOST] = ghostproc,
+};
+
+Entity entitybuffer[2048];
+int ebufi;
+
+Entity *player;
+
+void
+entinit()
+{
+ player = allocentity();
+ player->type = EPLAYER;
+ player->body.size[0] = ENTITY_SIZE;
+ player->body.size[1] = ENTITY_SIZE;
+ for(int i = 0; i < 10; i++) {
+ Entity *e = allocentity();
+ e->type = EGHOST;
+ e->body.pos[0] = rand() % 800;
+ e->body.pos[1] = rand() % 600;
+ e->body.size[0] = ENTITY_SIZE;
+ e->body.size[1] = ENTITY_SIZE;
+ }
+}
+
+void
+entupdate(float delta)
+{
+ EntityCollision *coll;
+ while((coll = deqcoll())) {
+ Entity *self = coll->self;
+ Entity *target = coll->target;
+
+ if(collisionProcs[self->type])
+ collisionProcs[self->type](self, target);
+
+ if(collisionProcs[target->type])
+ collisionProcs[target->type](target, self);
+ }
+
+ for(int ei = 0; ei < ebufi; ei++) {
+ Entity *e = entitybuffer + ei;
+ if(!e->active)
+ continue;
+
+ if(updateprocs[e->type])
+ updateprocs[e->type](e, delta);
+ }
+}
+
+void
+bulletcollproc(Entity *self, Entity *target)
+{
+ if(target->type == EGHOST) {
+ self->active = false;
+ target->active = false;
+ }
+}
+
+void
+playerproc(Entity *e, float delta)
+{
+ Entity *bullet;
+ const _Bool *kstate = SDL_GetKeyboardState(NULL);
+
+ e->body.vel[0] = 0;
+ e->body.vel[1] = 0;
+
+ if(kstate[SDL_SCANCODE_W])
+ e->body.vel[1] -= SPEED;
+ if(kstate[SDL_SCANCODE_A])
+ e->body.vel[0] -= SPEED;
+ if(kstate[SDL_SCANCODE_S])
+ e->body.vel[1] += SPEED;
+ if(kstate[SDL_SCANCODE_D])
+ e->body.vel[0] += SPEED;
+
+ if(shot) {
+ shot = false;
+ int i;
+
+ float dx = shotx - e->body.pos[0];
+ float dy = shoty - e->body.pos[1];
+ float dd = sqrtf(dx * dx + dy * dy);
+
+ dx /= dd;
+ dy /= dd;
+
+ bullet = allocentity();
+ bullet->type = EBULLET;
+ bullet->time = 0.5;
+ bullet->body.vel[0] = dx * SPEED * 5.0;
+ bullet->body.vel[1] = dy * SPEED * 5.0;
+ bullet->body.pos[0] = e->body.pos[0];
+ bullet->body.pos[1] = e->body.pos[1];
+ bullet->body.size[0] = BULLET_SIZE;
+ bullet->body.size[1] = BULLET_SIZE;
+ bullet->active = true;
+ }
+}
+
+void
+ghostproc(Entity *e, float delta)
+{
+ Entity *other;
+ float vx, vy;
+
+ vx = 0;
+ vy = 0;
+
+ float dx = player->body.pos[0] - e->body.pos[0];
+ float dy = player->body.pos[1] - e->body.pos[1];
+ float dd = sqrtf(dx * dx + dy * dy);
+
+ dx /= dd;
+ dy /= dd;
+
+ vx += dx * SPEED;
+ vy += dy * SPEED;
+
+ for(int j = 0; j < 1024; j++) {
+ other = entitybuffer + j;
+ if(!other->active || other == e || other->type != EGHOST)
+ continue;
+
+ float dx = other->body.pos[0] - e->body.pos[0];
+ float dy = other->body.pos[1] - e->body.pos[1];
+ float dd = sqrtf(dx * dx + dy * dy);
+
+ dx /= dd;
+ dy /= dd;
+
+ if(dd < 40) {
+ vx -= dx * 100;
+ vy -= dy * 100;
+ }
+ }
+
+ e->body.vel[0] = vx;
+ e->body.vel[1] = vy;
+}
+
+Entity *
+allocentity(void)
+{
+ Entity *e;
+
+ for(e = entitybuffer; e < entitybuffer + ebufi; e++) {
+ if(!e->active)
+ break;
+ }
+
+ if(e >= entitybuffer + ebufi) {
+ if(ebufi >= 2048)
+ return NULL;
+ e = entitybuffer + ebufi;
+ ebufi++;
+ }
+
+ memset(e, 0, sizeof(*e));
+ e->active = true;
+
+ return e;
+}
+
+void
+freeentity(Entity *e)
+{
+ e->active = false;
+}