Add asteroid collision handling

This commit is contained in:
Doyle Thai 2016-11-24 21:05:14 +11:00
parent 42ba86f05a
commit be1c009dfb
3 changed files with 101 additions and 67 deletions

View File

@ -286,7 +286,7 @@ b32 checkEdgeProjectionOverlap(v2 *vertexList, i32 listSize,
return result;
}
INTERNAL b32 moveEntity(World *world, MemoryArena_ *transientArena,
INTERNAL u32 moveEntity(World *world, MemoryArena_ *transientArena,
Entity *entity, i32 entityIndex, v2 ddP, f32 dt,
f32 ddPSpeed)
{
@ -312,12 +312,12 @@ INTERNAL b32 moveEntity(World *world, MemoryArena_ *transientArena,
v2 newPos = v2_add(v2_add(ddPHalfDtSquared, oldDpDt), oldPos);
b32 willCollide = FALSE;
i32 collisionIndex = -1;
// TODO(doyle): Collision for rects, (need to create vertex list for it)
#if 1
for (i32 i = entityIndex + 1; i < world->entityIndex; i++)
for (i32 i = 1; i < world->entityIndex; i++)
{
if (i == entityIndex) continue;
Entity *checkEntity = &world->entityList[i];
ASSERT(checkEntity->id != entity->id);
@ -362,38 +362,23 @@ INTERNAL b32 moveEntity(World *world, MemoryArena_ *transientArena,
checkEntityVertexListOffsetToP,
checkEntity->numVertexPoints, edgeList, totalNumEdges))
{
willCollide = TRUE;
collisionIndex = i;
}
}
if (willCollide)
{
break;
}
}
#endif
#if 0
if (!willCollide)
{
entity->dP = newDp;
entity->pos = newPos;
}
else
{
entity->dP = v2_scale(newDp, -1.0f);
if (collisionIndex != -1) break;
}
#else
entity->dP = newDp;
entity->pos = newPos;
#endif
return willCollide;
return collisionIndex;
}
INTERNAL void addAsteroid(World *world, v2 windowSize)
{
world->asteroidCounter++;
Entity *asteroid = &world->entityList[world->entityIndex++];
asteroid->id = world->entityIdCounter++;
@ -410,10 +395,16 @@ INTERNAL void addAsteroid(World *world, v2 windowSize)
asteroid->renderMode = rendermode_polygon;
asteroid->numVertexPoints = 10;
asteroid->vertexPoints = createAsteroidVertexList(
&world->entityArena, asteroid->numVertexPoints,
(i32)(asteroid->size.w * 0.5f));
i32 cacheIndex = randValue % ARRAY_COUNT(world->asteroidVertexCache);
if (!world->asteroidVertexCache[cacheIndex])
{
world->asteroidVertexCache[cacheIndex] = createAsteroidVertexList(
&world->entityArena, asteroid->numVertexPoints,
(i32)(asteroid->size.w * 0.5f));
}
asteroid->vertexPoints = world->asteroidVertexCache[cacheIndex];
asteroid->color = V4(0.0f, 0.5f, 0.5f, 1.0f);
}
@ -429,14 +420,17 @@ INTERNAL void addBullet(World *world, Entity *shooter)
bullet->rotation = shooter->rotation;
bullet->renderMode = rendermode_quad;
// TODO(doyle): Figure out how to free this memory on entity delete. A free list?
bullet->vertexPoints =
memory_pushBytes(&world->entityArena, sizeof(v2) * 4);
bullet->vertexPoints[0] = V2(0, bullet->size.h);
bullet->vertexPoints[1] = V2(0, 0);
bullet->vertexPoints[2] = V2(bullet->size.w, 0);
bullet->vertexPoints[3] = bullet->size;
if (!world->bulletVertexCache)
{
world->bulletVertexCache =
memory_pushBytes(&world->entityArena, sizeof(v2) * 4);
world->bulletVertexCache[0] = V2(0, bullet->size.h);
world->bulletVertexCache[1] = V2(0, 0);
world->bulletVertexCache[2] = V2(bullet->size.w, 0);
world->bulletVertexCache[3] = bullet->size;
}
bullet->vertexPoints = world->bulletVertexCache;
bullet->numVertexPoints = 4;
bullet->type = entitytype_bullet;
@ -475,10 +469,12 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
u8 *arenaBase = state->transientArena.base + state->transientArena.size;
memory_arenaInit(&world->entityArena, arenaBase, entityArenaSize);
{ // Init null entity
Entity *nullEntity = &world->entityList[world->entityIndex++];
nullEntity->id = world->entityIdCounter++;
}
{ // Init asteroid entities
i32 numAsteroids = 15;
for (i32 i = 0; i < numAsteroids; i++)
addAsteroid(world, windowSize);
world->numAsteroids = 15;
}
{ // Init ship entity
@ -524,6 +520,9 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
state->assetManager.font);
}
for (u32 i = world->asteroidCounter; i < world->numAsteroids; i++)
addAsteroid(world, windowSize);
{
KeyState *keys = state->input.keys;
for (enum KeyCode code = 0; code < keycode_count; code++)
@ -555,24 +554,13 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
addAsteroid(world, windowSize);
}
for (i32 i = 0; i < world->entityIndex; i++)
ASSERT(world->entityList[0].id == NULL_ENTITY_ID);
for (i32 i = 1; i < world->entityIndex; i++)
{
Entity *entity = &world->entityList[i];
ASSERT(entity->type != entitytype_invalid);
v2 pivotPoint = {0};
// Loop entity around world
if (entity->pos.y >= world->worldSize.h)
entity->pos.y = 0;
else if (entity->pos.y < 0)
entity->pos.y = world->worldSize.h;
if (entity->pos.x >= world->worldSize.w)
entity->pos.x = 0;
else if (entity->pos.x < 0)
entity->pos.x = world->worldSize.w;
f32 ddPSpeedInMs = 0;
v2 ddP = {0};
if (entity->type == entitytype_ship)
@ -604,7 +592,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
}
if (getKeyStatus(&state->input.keys[keycode_space],
readkeytype_delayedRepeat, 0.0f, dt))
readkeytype_delayedRepeat, 0.05f, dt))
{
addBullet(world, entity);
}
@ -637,7 +625,6 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
}
v2 ddP = {0};
#if 1
switch (entity->direction)
{
case direction_north:
@ -707,30 +694,71 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
ddPSpeedInMs = 1;
entity->dP = v2_scale(ddP, world->pixelsPerMeter * ddPSpeedInMs);
entity->rotation += (60 * dt);
#endif
}
else if (entity->type == entitytype_bullet)
{
ddPSpeedInMs = 5;
if (!math_pointInRect(world->camera, entity->pos))
{
world->entityList[i--] =
world->entityList[--world->entityIndex];
continue;
}
ddPSpeedInMs = 25;
Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f));
ddP = V2(math_cosf(rotation), math_sinf(rotation));
entity->dP = v2_scale(ddP, world->pixelsPerMeter * ddPSpeedInMs);
}
b32 willCollide = moveEntity(world, &state->transientArena, entity, i,
ddP, dt, ddPSpeedInMs);
// Loop entity around world
if (entity->pos.y >= world->worldSize.h)
entity->pos.y = 0;
else if (entity->pos.y < 0)
entity->pos.y = world->worldSize.h;
if (entity->pos.x >= world->worldSize.w)
entity->pos.x = 0;
else if (entity->pos.x < 0)
entity->pos.x = world->worldSize.w;
i32 collisionIndex = moveEntity(world, &state->transientArena, entity,
i, ddP, dt, ddPSpeedInMs);
v4 collideColor = {0};
if (willCollide)
if (collisionIndex != -1)
{
collideColor = V4(1.0f, 0, 0, 0.5f);
}
ASSERT(collisionIndex < world->entityIndex);
if (entity->type == entitytype_bullet)
{
if (!math_pointInRect(world->camera, entity->pos))
Entity *collideEntity = &world->entityList[collisionIndex];
Entity *colliderA;
Entity *colliderB;
if (collideEntity->type < entity->type)
{
world->entityList[i] = world->entityList[--world->entityIndex];
i--;
colliderA = collideEntity;
colliderB = entity;
}
else
{
colliderA = entity;
colliderB = collideEntity;
}
if (colliderA->type == entitytype_asteroid)
{
ASSERT(colliderB->type == entitytype_bullet);
world->entityList[collisionIndex] =
world->entityList[--world->entityIndex];
world->entityList[i--] =
world->entityList[--world->entityIndex];
world->asteroidCounter--;
ASSERT(world->asteroidCounter >= 0);
continue;
}
}

View File

@ -15,9 +15,14 @@ typedef struct World
v2 *entityVertexListCache[entitytype_count];
Entity entityList[1024];
i32 entityIndex;
u32 entityIdCounter;
u32 asteroidCounter;
u32 numAsteroids;
v2 *asteroidVertexCache[10];
v2 *bulletVertexCache;
f32 pixelsPerMeter;
v2 worldSize;
Rect camera;
@ -36,7 +41,6 @@ typedef struct GameState {
MemoryArena_ transientArena;
MemoryArena_ persistentArena;
Renderer renderer;
} GameState;

View File

@ -23,9 +23,11 @@ enum Direction
direction_num,
};
#define NULL_ENTITY_ID 0
enum EntityType
{
entitytype_invalid,
entitytype_null,
entitytype_ship,
entitytype_asteroid,
entitytype_bullet,