Add basic entity death code for singular entity

This commit is contained in:
Doyle Thai 2016-07-20 02:23:11 +10:00
parent 3e2287e13a
commit 3aaad2fba3
2 changed files with 112 additions and 58 deletions

View File

@ -175,7 +175,7 @@ void debug_drawUi(GameState *state, f32 dt)
strPos, 0, color); strPos, 0, color);
} }
for (i32 i = 0; i < world->maxEntities; i++) for (i32 i = 0; i < world->freeEntityIndex; i++)
{ {
Entity *const entity = &world->entities[i]; Entity *const entity = &world->entities[i];
/* Render debug markers on entities */ /* Render debug markers on entities */

View File

@ -58,6 +58,18 @@ INTERNAL Entity *addEntity(MemoryArena *arena, World *world, v2 pos, v2 size,
return result; return result;
} }
INTERNAL void deleteEntity(MemoryArena *arena, World *world, i32 entityIndex)
{
Entity *entity = &world->entities[entityIndex];
PLATFORM_MEM_FREE(arena, entity->stats, sizeof(EntityStats));
// TODO(doyle): Inefficient shuffle down all elements
for (i32 i = entityIndex; i < world->freeEntityIndex-1; i++)
world->entities[i] = world->entities[i+1];
world->freeEntityIndex--;
}
INTERNAL void rendererInit(GameState *state, v2 windowSize) INTERNAL void rendererInit(GameState *state, v2 windowSize)
{ {
AssetManager *assetManager = &state->assetManager; AssetManager *assetManager = &state->assetManager;
@ -105,6 +117,35 @@ INTERNAL void addAnim(AssetManager *assetManager, i32 animId, Entity *entity)
entity->anim[animId].currDuration = anim->frameDuration; entity->anim[animId].currDuration = anim->frameDuration;
} }
INTERNAL void addGenericMob(MemoryArena *arena, AssetManager *assetManager,
World *world, v2 pos)
{
#ifdef DENGINE_DEBUG
DEBUG_LOG("Mob entity spawned");
#endif
Entity *hero = &world->entities[world->heroIndex];
v2 size = V2(58.0f, 98.0f);
enum EntityType type = entitytype_mob;
enum Direction dir = direction_west;
Texture *tex = asset_getTexture(assetManager, texlist_hero);
b32 collides = TRUE;
Entity *mob = addEntity(arena, world, pos, size, type, dir, tex, collides);
/* Populate mob animation references */
addAnim(assetManager, animlist_hero_idle, mob);
addAnim(assetManager, animlist_hero_walk, mob);
addAnim(assetManager, animlist_hero_wave, mob);
addAnim(assetManager, animlist_hero_battlePose, mob);
addAnim(assetManager, animlist_hero_tackle, mob);
mob->currAnimId = animlist_hero_idle;
}
// TODO(doyle): Remove and implement own random generator!
#include <time.h>
#include <stdlib.h>
void worldTraveller_gameInit(GameState *state, v2 windowSize) void worldTraveller_gameInit(GameState *state, v2 windowSize)
{ {
AssetManager *assetManager = &state->assetManager; AssetManager *assetManager = &state->assetManager;
@ -304,24 +345,12 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
/* Create a Mob */ /* Create a Mob */
pos = V2(renderer->size.w - (renderer->size.w / 3.0f), pos = V2(renderer->size.w - (renderer->size.w / 3.0f),
CAST(f32) state->tileSize); CAST(f32) state->tileSize);
size = hero->hitboxSize; addGenericMob(arena, assetManager, world, pos);
type = entitytype_mob;
dir = direction_west;
tex = hero->tex;
collides = TRUE;
Entity *mob = addEntity(arena, world, pos, size, type, dir, tex, collides);
/* Populate mob animation references */
addAnim(assetManager, animlist_hero_idle, mob);
addAnim(assetManager, animlist_hero_walk, mob);
addAnim(assetManager, animlist_hero_battlePose, mob);
addAnim(assetManager, animlist_hero_tackle, mob);
hero->currAnimId = animlist_hero_idle;
#ifdef DENGINE_DEBUG #ifdef DENGINE_DEBUG
DEBUG_LOG("World populated"); DEBUG_LOG("World populated");
#endif #endif
srand(CAST(u32)(time(NULL)));
} }
INTERNAL inline void setActiveEntityAnim(Entity *entity, INTERNAL inline void setActiveEntityAnim(Entity *entity,
@ -405,20 +434,20 @@ INTERNAL void parseInput(GameState *state, const f32 dt)
} }
// TODO(doyle): Revisit key input with state checking for last ended down // TODO(doyle): Revisit key input with state checking for last ended down
#if 0
if (state->keys[GLFW_KEY_SPACE] && !spaceBarWasDown) if (state->keys[GLFW_KEY_SPACE] && !spaceBarWasDown)
{ {
if (!(hero->currAnimId == entityanimid_tackle && Renderer *renderer = &state->renderer;
hero->currAnimCyclesCompleted == 0)) f32 yPos = CAST(f32)(rand() % CAST(i32)renderer->size.h);
{ f32 xModifier = 5.0f - CAST(f32)(rand() % 3);
v2 pos = V2(renderer->size.w - (renderer->size.w / xModifier), yPos);
addGenericMob(&state->arena, &state->assetManager, world, pos);
spaceBarWasDown = TRUE; spaceBarWasDown = TRUE;
} }
}
else if (!state->keys[GLFW_KEY_SPACE]) else if (!state->keys[GLFW_KEY_SPACE])
{ {
spaceBarWasDown = FALSE; spaceBarWasDown = FALSE;
} }
#endif
} }
// NOTE(doyle): Clipping threshold for snapping velocity to 0 // NOTE(doyle): Clipping threshold for snapping velocity to 0
@ -462,7 +491,7 @@ INTERNAL void parseInput(GameState *state, const f32 dt)
b32 heroCollided = FALSE; b32 heroCollided = FALSE;
if (hero->collides == TRUE) if (hero->collides == TRUE)
{ {
for (i32 i = 0; i < world->maxEntities; i++) for (i32 i = 0; i < world->freeEntityIndex; i++)
{ {
if (i == world->heroIndex) continue; if (i == world->heroIndex) continue;
Entity entity = world->entities[i]; Entity entity = world->entities[i];
@ -600,7 +629,14 @@ INTERNAL void endAttack(World *world, Entity *attacker)
setActiveEntityAnim(attacker, animlist_hero_battlePose); setActiveEntityAnim(attacker, animlist_hero_battlePose);
Entity *defender = &world->entities[attacker->stats->entityIdToAttack]; Entity *defender = &world->entities[attacker->stats->entityIdToAttack];
if (attacker->type == entitytype_hero)
{
defender->stats->health -= 50;
}
else
{
defender->stats->health--; defender->stats->health--;
}
} }
// TODO(doyle): Exposed because of debug .. rework debug system so it we don't // TODO(doyle): Exposed because of debug .. rework debug system so it we don't
@ -727,8 +763,14 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
break; break;
case entitystate_attack: case entitystate_attack:
break;
case entitystate_dead: case entitystate_dead:
return; updateWorldBattleEntities(world, entity, ENTITY_NOT_IN_BATTLE);
setActiveEntityAnim(entity, animlist_hero_wave);
entity->stats->actionTimer = entity->stats->actionRate;
entity->stats->queuedAttack = entityattack_invalid;
entity->stats->entityIdToAttack = ENTITY_NULL_ID;
break;
default: default:
#ifdef DENGINE_DEBUG #ifdef DENGINE_DEBUG
ASSERT(INVALID_CODE_PATH); ASSERT(INVALID_CODE_PATH);
@ -743,6 +785,13 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
return; return;
case entitystate_dead: case entitystate_dead:
// TODO(doyle): Repeated logic with battle -> dead
updateWorldBattleEntities(world, entity, ENTITY_NOT_IN_BATTLE);
setActiveEntityAnim(entity, animlist_hero_wave);
entity->stats->actionTimer = entity->stats->actionRate;
entity->stats->queuedAttack = entityattack_invalid;
entity->stats->entityIdToAttack = ENTITY_NULL_ID;
break;
default: default:
#ifdef DENGINE_DEBUG #ifdef DENGINE_DEBUG
ASSERT(INVALID_CODE_PATH); ASSERT(INVALID_CODE_PATH);
@ -770,7 +819,8 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
entity->state = newState; entity->state = newState;
} }
INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt) INTERNAL void updateEntityAndRender(MemoryArena *arena, Renderer *renderer,
World *world, f32 dt)
{ {
Entity *hero = &world->entities[world->heroIndex]; Entity *hero = &world->entities[world->heroIndex];
for (i32 i = 0; i < world->freeEntityIndex; i++) for (i32 i = 0; i < world->freeEntityIndex; i++)
@ -780,6 +830,16 @@ INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt)
{ {
case entitytype_mob: case entitytype_mob:
{ {
if (entity->state == entitystate_dead)
{
// TODO(doyle): Accumulate all dead entities and delete at the
// end. Hence resort/organise entity array once, not every time
// an entity dies
i32 entityIndexInArray = i;
deleteEntity(arena, world, entityIndexInArray);
continue;
}
// TODO(doyle): Currently calculated in pixels, how about meaningful // TODO(doyle): Currently calculated in pixels, how about meaningful
// game units? // game units?
f32 battleThreshold = 500.0f; f32 battleThreshold = 500.0f;
@ -795,13 +855,8 @@ INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt)
} }
// NOTE(doyle): Let entitytype_mob fall through to entitytype_hero here // NOTE(doyle): Let entitytype_mob fall through to entitytype_hero here
case entitytype_hero: case entitytype_hero:
{
if (entity->state == entitystate_battle ||
entity->state == entitystate_attack)
{ {
EntityStats *stats = entity->stats; EntityStats *stats = entity->stats;
if (stats->health > 0)
{
if (entity->state == entitystate_battle) if (entity->state == entitystate_battle)
{ {
if (stats->actionTimer > 0) if (stats->actionTimer > 0)
@ -816,22 +871,21 @@ INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt)
beginAttack(entity); beginAttack(entity);
} }
} }
else else if (entity->state == entitystate_attack)
{ {
// TODO(doyle): Untested if the attacker and the defender same
Entity *attacker = entity;
stats->busyDuration -= dt; stats->busyDuration -= dt;
if (stats->busyDuration <= 0) if (stats->busyDuration <= 0) endAttack(world, attacker);
endAttack(world, entity);
} Entity *defender =
} &world->entities[attacker->stats->entityIdToAttack];
else if (defender->stats->health <= 0)
{ {
#ifdef DENGINE_DEBUG #ifdef DENGINE_DEBUG
ASSERT(INVALID_CODE_PATH); DEBUG_LOG("Entity has died");
#endif #endif
// TODO(doyle): Generalise for all entities entityStateSwitch(world, defender, entitystate_dead);
hero->stats->entityIdToAttack = ENTITY_NULL_ID;
hero->state = entitystate_idle;
entity->state = entitystate_dead;
} }
} }
break; break;
@ -884,7 +938,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
Font *font = &assetManager->font; Font *font = &assetManager->font;
ASSERT(world->freeEntityIndex < world->maxEntities); ASSERT(world->freeEntityIndex < world->maxEntities);
updateEntityAndRender(renderer, world, dt); updateEntityAndRender(&state->arena, renderer, world, dt);
/* Draw ui */ /* Draw ui */
TexAtlas *heroAtlas = asset_getTextureAtlas(assetManager, texlist_hero); TexAtlas *heroAtlas = asset_getTextureAtlas(assetManager, texlist_hero);