#include #include #include #include #include #include "dat.h" #define SPEED 100 static EntityCollisionProc bulletcollproc; static EntityCollisionProc ghostcollproc; static EntityUpdateProc playerproc; static EntityUpdateProc ghostproc; static EntityUpdateProc bulletproc; static EntityCollisionProc *collisionProcs[LASTEntity] = { [EBULLET] = bulletcollproc, [EGHOST] = ghostcollproc, }; static EntityUpdateProc *updateprocs[LASTEntity] = { [EPLAYER] = playerproc, [EGHOST] = ghostproc, [EBULLET] = bulletproc, }; static void physics(float delta); Entity entitybuffer[2048]; int ebufi; Entity *player; void entrestart() { ebufi = 0; player = NULL; entinit(); } void entinit() { player = allocentity(); player->type = EPLAYER; player->body.pos[0] = player_x * ENTITY_SIZE * 2; player->body.pos[1] = player_y * ENTITY_SIZE * 2; player->body.size[0] = ENTITY_SIZE; player->body.size[1] = ENTITY_SIZE; player->life = 1; player->alive = true; for(int i = 0; i < ghostcount; i++) { Entity *e = allocentity(); e->type = EGHOST; e->body.pos[0] = ghostpositions[i][0] * ENTITY_SIZE * 2; e->body.pos[1] = ghostpositions[i][1] * ENTITY_SIZE * 2; e->body.size[0] = ENTITY_SIZE; e->body.size[1] = ENTITY_SIZE; e->life = 2; e->alive = true; } } void entupdate(float delta) { physics(delta); 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 && target->alive) { target->life -= 1; if(target->life <= 0) target->alive = false; self->active = false; } } void ghostcollproc(Entity *self, Entity *target) { if(!self->alive) return; if(target->type == EPLAYER && target->alive) { target->life -= 1; if(target->life <= 0) target->alive = false; self->active = false; } } void playerproc(Entity *e, float delta) { Entity *bullet; e->body.vel[0] = 0; e->body.vel[1] = 0; if(!e->alive) return; if(moveup) e->body.vel[1] -= SPEED; if(moveleft) e->body.vel[0] -= SPEED; if(movedown) e->body.vel[1] += SPEED; if(moveright) 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; if(e->alive) { 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); if(dd < 400.0) { 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 || !other->alive) 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 * SPEED * 2; vy -= dy * SPEED * 2; } } } e->body.vel[0] = vx; e->body.vel[1] = vy; } void bulletproc(Entity *e, float delta) { e->active = (e->time += delta) < 1.0; } 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; } void physics(float delta) { #define PHYSICS_TIME (1.0 / 480.0) EntityCollision *coll; static float time = 0; time += delta; while(time >= PHYSICS_TIME) { entphysics(PHYSICS_TIME); 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); } time -= PHYSICS_TIME; } }