diff options
Diffstat (limited to 'game.c')
| -rw-r--r-- | game.c | 190 |
1 files changed, 190 insertions, 0 deletions
@@ -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; +} |
