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

View File

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

View File

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