#include #include #include #include #include #include "dat.h" #define SPEED 100 static EntityCollisionProc bulletcollproc; static EntityCollisionProc ghostcollproc; static EntityCollisionProc teleportercollproc; static EntityCollisionProc goalcollproc; static EntityUpdateProc playerproc; static EntityUpdateProc ghostproc; static EntityUpdateProc bulletproc; static EntityCollisionProc *collisionProcs[LASTEntity] = { [EBULLET] = bulletcollproc, [EGHOST] = ghostcollproc, [ETELEPORTER] = teleportercollproc, [EGOAL] = goalcollproc, }; 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() { Entity *e; 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; e = allocentity(); e->type = EGOAL; e->body.pos[0] = goalx * ENTITY_SIZE * 2; e->body.pos[1] = goaly * ENTITY_SIZE * 2; e->body.size[0] = ENTITY_SIZE; e->body.size[1] = ENTITY_SIZE; 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; } for(int i = 0; i < telessize; i++) { Entity *e = allocentity(); e->type = ETELEPORTER; e->body.pos[0] = teles[i].x * ENTITY_SIZE * 2; e->body.pos[1] = teles[i].y * ENTITY_SIZE * 2; e->body.size[0] = ENTITY_SIZE; e->body.size[1] = ENTITY_SIZE; e->telex = floorf(teles[i].x); e->teley = floorf(teles[i].y); } } 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 teleportercollproc(Entity *self, Entity *target) { if(target->type == EPLAYER && target->alive) { for(int i = 0; i < telemapsize; i++) { if(self->telex == telemap[i].ftx && self->teley == telemap[i].fty) { target->body.pos[0] = telemap[i].ttx * ENTITY_SIZE * 2; target->body.pos[1] = telemap[i].tty * ENTITY_SIZE * 2; break; } } } } void goalcollproc(Entity *self, Entity *target) { static int goal = 0; if(goal) return; if(target->type == EPLAYER && target->alive) { goal = 1; printf("GOAL!\n"); for(int i = 0; i < ebufi; i++) { Entity *e = entitybuffer + i; if(!e->active) continue; if(e->type == EGHOST) e->alive = 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; } }