Switch developing game to asteroids, start project
Switch to something of smaller scope in aim to be able to finish a project from start to finish. Also allow refreshed eyes to review the existing API and see what can be improved on after taking a short break from the project.
This commit is contained in:
parent
ed6b961b61
commit
4795fe1cb1
@ -121,18 +121,17 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\AssetManager.c" />
|
||||
<ClCompile Include="src\Asteroid.c" />
|
||||
<ClCompile Include="src\Audio.c" />
|
||||
<ClCompile Include="src\Common.c" />
|
||||
<ClCompile Include="src\Debug.c" />
|
||||
<ClCompile Include="src\dengine.c" />
|
||||
<ClCompile Include="src\Entity.c" />
|
||||
<ClCompile Include="src\MemoryArena.c" />
|
||||
<ClCompile Include="src\Platform.c" />
|
||||
<ClCompile Include="src\Renderer.c" />
|
||||
<ClCompile Include="src\Shader.c" />
|
||||
<ClCompile Include="src\String.c" />
|
||||
<ClCompile Include="src\UserInterface.c" />
|
||||
<ClCompile Include="src\WorldTraveller.c" />
|
||||
<ClCompile Include="src\Texture.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -143,14 +142,15 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\include\Dengine\Assets.h" />
|
||||
<ClInclude Include="src\include\Dengine\Asteroid.h" />
|
||||
<ClInclude Include="src\include\Dengine\Audio.h" />
|
||||
<ClInclude Include="src\include\Dengine\Debug.h" />
|
||||
<ClInclude Include="src\include\Dengine\Entity.h" />
|
||||
<ClInclude Include="src\include\Dengine\MemoryArena.h" />
|
||||
<ClInclude Include="src\include\Dengine\Platform.h" />
|
||||
<ClInclude Include="src\include\Dengine\AssetManager.h" />
|
||||
<ClInclude Include="src\include\Dengine\Common.h" />
|
||||
<ClInclude Include="src\include\Breakout\Game.h" />
|
||||
<ClInclude Include="src\include\Dengine\Entity.h" />
|
||||
<ClInclude Include="src\include\Dengine\Math.h" />
|
||||
<ClInclude Include="src\include\Dengine\OpenGL.h" />
|
||||
<ClInclude Include="src\include\Dengine\Renderer.h" />
|
||||
|
@ -15,9 +15,6 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\WorldTraveller.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Texture.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -42,9 +39,6 @@
|
||||
<ClCompile Include="src\Audio.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Entity.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dengine.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -57,6 +51,9 @@
|
||||
<ClCompile Include="src\MemoryArena.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Asteroid.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="data\shaders\default.vert.glsl" />
|
||||
@ -86,9 +83,6 @@
|
||||
<ClInclude Include="src\include\Dengine\Renderer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\include\Dengine\Entity.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\include\Dengine\Math.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -116,5 +110,11 @@
|
||||
<ClInclude Include="src\include\Dengine\String.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\include\Dengine\Asteroid.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\include\Dengine\Entity.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
241
src/Asteroid.c
Normal file
241
src/Asteroid.c
Normal file
@ -0,0 +1,241 @@
|
||||
#include "Dengine/Asteroid.h"
|
||||
#include "Dengine/Debug.h"
|
||||
|
||||
void initAssetManager(GameState *state)
|
||||
{
|
||||
AssetManager *assetManager = &state->assetManager;
|
||||
MemoryArena_ *arena = &state->persistentArena;
|
||||
|
||||
i32 audioEntries = 32;
|
||||
assetManager->audio.size = audioEntries;
|
||||
assetManager->audio.entries =
|
||||
memory_pushBytes(arena, audioEntries * sizeof(HashTableEntry));
|
||||
|
||||
i32 texAtlasEntries = 8;
|
||||
assetManager->texAtlas.size = texAtlasEntries;
|
||||
assetManager->texAtlas.entries =
|
||||
memory_pushBytes(arena, texAtlasEntries * sizeof(HashTableEntry));
|
||||
|
||||
i32 texEntries = 32;
|
||||
assetManager->textures.size = texEntries;
|
||||
assetManager->textures.entries =
|
||||
memory_pushBytes(arena, texEntries * sizeof(HashTableEntry));
|
||||
|
||||
i32 animEntries = 1024;
|
||||
assetManager->anims.size = animEntries;
|
||||
assetManager->anims.entries =
|
||||
memory_pushBytes(arena, animEntries * sizeof(HashTableEntry));
|
||||
|
||||
/* Create empty 1x1 4bpp black texture */
|
||||
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
|
||||
Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex");
|
||||
*tex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap));
|
||||
|
||||
/* Load shaders */
|
||||
asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl",
|
||||
"data/shaders/sprite.frag.glsl",
|
||||
shaderlist_sprite);
|
||||
|
||||
i32 result =
|
||||
asset_loadTTFont(assetManager, arena, "C:/Windows/Fonts/Arialbd.ttf");
|
||||
|
||||
if (result) {
|
||||
ASSERT(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void initRenderer(GameState *state, v2 windowSize) {
|
||||
AssetManager *assetManager = &state->assetManager;
|
||||
Renderer *renderer = &state->renderer;
|
||||
renderer->size = windowSize;
|
||||
|
||||
// NOTE(doyle): Value to map a screen coordinate to NDC coordinate
|
||||
renderer->vertexNdcFactor =
|
||||
V2(1.0f / renderer->size.w, 1.0f / renderer->size.h);
|
||||
renderer->shader = asset_getShader(assetManager, shaderlist_sprite);
|
||||
shader_use(renderer->shader);
|
||||
|
||||
const mat4 projection =
|
||||
mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f);
|
||||
shader_uniformSetMat4fv(renderer->shader, "projection", projection);
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
/* Create buffers */
|
||||
glGenVertexArrays(1, &renderer->vao);
|
||||
glGenBuffers(1, &renderer->vbo);
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
/* Bind buffers */
|
||||
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo);
|
||||
glBindVertexArray(renderer->vao);
|
||||
|
||||
/* Configure VAO */
|
||||
u32 numVertexElements = 4;
|
||||
u32 stride = sizeof(Vertex);
|
||||
glVertexAttribPointer(0, numVertexElements, GL_FLOAT, GL_FALSE, stride,
|
||||
(GLvoid *)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
/* Unbind */
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
// TODO(doyle): Lazy allocate render group capacity
|
||||
renderer->groupCapacity = 4096;
|
||||
for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++)
|
||||
{
|
||||
renderer->groups[i].vertexList = memory_pushBytes(
|
||||
&state->persistentArena, renderer->groupCapacity * sizeof(Vertex));
|
||||
}
|
||||
}
|
||||
|
||||
enum ReadKeyType
|
||||
{
|
||||
readkeytype_oneShot,
|
||||
readkeytype_delayedRepeat,
|
||||
readkeytype_repeat,
|
||||
readkeytype_count,
|
||||
};
|
||||
|
||||
#define KEY_DELAY_NONE 0.0f
|
||||
INTERNAL b32 getKeyStatus(KeyState *key, enum ReadKeyType readType,
|
||||
f32 delayInterval, f32 dt)
|
||||
{
|
||||
|
||||
if (!key->endedDown) return FALSE;
|
||||
|
||||
switch(readType)
|
||||
{
|
||||
case readkeytype_oneShot:
|
||||
{
|
||||
if (key->newHalfTransitionCount > key->oldHalfTransitionCount)
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
case readkeytype_repeat:
|
||||
case readkeytype_delayedRepeat:
|
||||
{
|
||||
if (key->newHalfTransitionCount > key->oldHalfTransitionCount)
|
||||
{
|
||||
if (readType == readkeytype_delayedRepeat)
|
||||
{
|
||||
// TODO(doyle): Let user set arbitrary delay after initial input
|
||||
key->delayInterval = 2 * delayInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
key->delayInterval = delayInterval;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if (key->delayInterval <= 0.0f)
|
||||
{
|
||||
key->delayInterval = delayInterval;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
key->delayInterval -= dt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#ifdef DENGINE_DEBUG
|
||||
DEBUG_LOG("getKeyStatus() error: Invalid ReadKeyType enum");
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
||||
v2 windowSize, f32 dt)
|
||||
{
|
||||
if (!state->init) {
|
||||
|
||||
memory_arenaInit(&state->persistentArena, memory->persistent,
|
||||
memory->persistentSize);
|
||||
memory_arenaInit(&state->transientArena, memory->transient,
|
||||
memory->transientSize);
|
||||
|
||||
initAssetManager(state);
|
||||
initRenderer(state, windowSize);
|
||||
|
||||
{ // Init ship entity
|
||||
Entity *ship = &state->entityList[state->entityIndex++];
|
||||
ship->id = 0;
|
||||
ship->pos = V2(100.0f, 100.0f);
|
||||
ship->hitbox = V2(100.0f, 100.0f);
|
||||
ship->size = V2(100.0f, 100.0f);
|
||||
ship->scale = 1;
|
||||
ship->type = entitytype_ship;
|
||||
ship->direction = direction_null;
|
||||
ship->tex = asset_getTex(&state->assetManager, "nullTex");
|
||||
ship->collides = FALSE;
|
||||
}
|
||||
|
||||
state->camera.pos = V2(0, 0);
|
||||
state->camera.size = state->renderer.size;
|
||||
|
||||
state->init = TRUE;
|
||||
}
|
||||
{
|
||||
KeyState *keys = state->input.keys;
|
||||
for (enum KeyCode code = 0; code < keycode_count; code++)
|
||||
{
|
||||
KeyState *keyState = &keys[code];
|
||||
|
||||
u32 halfTransitionCount = keyState->newHalfTransitionCount -
|
||||
keyState->oldHalfTransitionCount;
|
||||
|
||||
if (halfTransitionCount > 0)
|
||||
{
|
||||
b32 transitionCountIsOdd = ((halfTransitionCount & 1) == 1);
|
||||
|
||||
if (transitionCountIsOdd)
|
||||
{
|
||||
if (keyState->endedDown) keyState->endedDown = FALSE;
|
||||
else keyState->endedDown = TRUE;
|
||||
}
|
||||
|
||||
keyState->oldHalfTransitionCount =
|
||||
keyState->newHalfTransitionCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < state->entityIndex; i++)
|
||||
{
|
||||
Entity *entity = &state->entityList[i];
|
||||
ASSERT(entity->type != entitytype_invalid);
|
||||
|
||||
if (entity->type == entitytype_ship) {
|
||||
|
||||
{ // Parse input
|
||||
if (getKeyStatus(&state->input.keys[keycode_up],
|
||||
readkeytype_repeat, 0.0f, dt))
|
||||
{
|
||||
entity->pos.y += 10.0f;
|
||||
}
|
||||
|
||||
if (getKeyStatus(&state->input.keys[keycode_down],
|
||||
readkeytype_repeat, 0.0f, dt))
|
||||
{
|
||||
entity->pos.y -= 10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
renderer_entity(&state->renderer, state->camera, entity, V2(0, 0), 0,
|
||||
V4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
renderer_renderGroups(&state->renderer);
|
||||
}
|
282
src/Debug.c
282
src/Debug.c
@ -1,10 +1,9 @@
|
||||
#include "Dengine/Debug.h"
|
||||
#include "Dengine/AssetManager.h"
|
||||
#include "Dengine/Entity.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/Platform.h"
|
||||
#include "Dengine/Renderer.h"
|
||||
#include "Dengine/WorldTraveller.h"
|
||||
#include "Dengine/Asteroid.h"
|
||||
|
||||
typedef struct DebugState
|
||||
{
|
||||
@ -29,52 +28,6 @@ typedef struct DebugState
|
||||
|
||||
GLOBAL_VAR DebugState GLOBAL_debug;
|
||||
|
||||
inline char *debug_entitystate_string(i32 val)
|
||||
{
|
||||
char *string;
|
||||
switch(val)
|
||||
{
|
||||
case entitystate_idle:
|
||||
string = "EntityState_Idle";
|
||||
break;
|
||||
case entitystate_battle:
|
||||
string = "EntityState_Battle";
|
||||
break;
|
||||
case entitystate_attack:
|
||||
string = "EntityState_Attack";
|
||||
break;
|
||||
case entitystate_dead:
|
||||
string = "EntityState_Dead";
|
||||
break;
|
||||
case entitystate_count:
|
||||
string = "EntityState_Count (Error!)";
|
||||
break;
|
||||
case entitystate_invalid:
|
||||
string = "EntityState_Invalid (Error!)";
|
||||
break;
|
||||
default:
|
||||
string = "EntityState Unknown (NOT DEFINED)";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
inline char *debug_entityattack_string(i32 val)
|
||||
{
|
||||
char *string;
|
||||
switch(val)
|
||||
{
|
||||
case entityattack_count:
|
||||
string = "EntityAttack_Count (Error!)";
|
||||
break;
|
||||
case entityattack_invalid:
|
||||
string = "EntityAttack_Invalid";
|
||||
break;
|
||||
default:
|
||||
string = "EntityAttack Unknown (NOT DEFINED)";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
void debug_init(MemoryArena_ *arena, v2 windowSize, Font font)
|
||||
{
|
||||
GLOBAL_debug.font = font;
|
||||
@ -317,238 +270,5 @@ INTERNAL void renderConsole(Renderer *renderer, MemoryArena_ *arena)
|
||||
|
||||
void debug_drawUi(GameState *state, f32 dt)
|
||||
{
|
||||
AssetManager *assetManager = &state->assetManager;
|
||||
Renderer *renderer = &state->renderer;
|
||||
World *const world = &state->world[state->currWorldIndex];
|
||||
Entity *hero = &world->entities[entity_getIndex(world, world->heroId)];
|
||||
MemoryArena_ *transientArena = &state->transientArena;
|
||||
|
||||
// TODO(doyle): Dumb copy function from game so we don't expose api
|
||||
Rect camera = {world->cameraPos, renderer->size};
|
||||
// NOTE(doyle): Lock camera if it passes the bounds of the world
|
||||
if (camera.pos.x <= world->bounds.x)
|
||||
camera.pos.x = world->bounds.x;
|
||||
|
||||
// TODO(doyle): Allow Y panning when we need it
|
||||
f32 cameraTopBoundInPixels = camera.pos.y + camera.size.h;
|
||||
if (cameraTopBoundInPixels >= world->bounds.w)
|
||||
camera.pos.y = (world->bounds.w - camera.size.h);
|
||||
|
||||
f32 cameraRightBoundInPixels = camera.pos.x + camera.size.w;
|
||||
if (cameraRightBoundInPixels >= world->bounds.z)
|
||||
camera.pos.x = (world->bounds.z - camera.size.w);
|
||||
|
||||
if (camera.pos.y <= world->bounds.y) camera.pos.y = world->bounds.y;
|
||||
|
||||
Font *font = &GLOBAL_debug.font;
|
||||
if (world->numEntitiesInBattle > 0)
|
||||
{
|
||||
v4 color = V4(1.0f, 0, 0, 1);
|
||||
char *battleStr = "IN-BATTLE RANGE";
|
||||
f32 strLenInPixels =
|
||||
CAST(f32)(font->maxSize.w * common_strlen(battleStr));
|
||||
v2 strPos = V2((renderer->size.w * 0.5f) - (strLenInPixels * 0.5f),
|
||||
renderer->size.h - 300.0f);
|
||||
renderer_staticString(&state->renderer, transientArena, font, battleStr,
|
||||
strPos, V2(0, 0), 0, color);
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < world->freeEntityIndex; i++)
|
||||
{
|
||||
Entity *const entity = &world->entities[i];
|
||||
if (entity->state == entitystate_dead) continue;
|
||||
|
||||
/* Render debug markers on entities */
|
||||
v4 color = V4(1, 1, 1, 1);
|
||||
char *debugString = NULL;
|
||||
switch (entity->type)
|
||||
{
|
||||
case entitytype_mob:
|
||||
color = V4(1, 0, 0, 1);
|
||||
debugString = "MOB";
|
||||
break;
|
||||
|
||||
case entitytype_hero:
|
||||
color = V4(0, 0, 1.0f, 1);
|
||||
debugString = "HERO";
|
||||
break;
|
||||
|
||||
case entitytype_npc:
|
||||
color = V4(0, 1.0f, 0, 1);
|
||||
debugString = "NPC";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (debugString)
|
||||
{
|
||||
v2 strPos = v2_add(entity->pos, entity->hitbox);
|
||||
i32 indexOfLowerAInMetrics = 'a' - CAST(i32) font->codepointRange.x;
|
||||
strPos.y += font->charMetrics[indexOfLowerAInMetrics].offset.y;
|
||||
|
||||
renderer_string(&state->renderer, transientArena, camera, font,
|
||||
debugString, strPos, V2(0, 0), 0, color);
|
||||
|
||||
f32 stringLineGap = 1.1f * font->verticalSpacing;
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
|
||||
char entityPosStr[128];
|
||||
snprintf(entityPosStr, ARRAY_COUNT(entityPosStr), "%06.2f, %06.2f",
|
||||
entity->pos.x, entity->pos.y);
|
||||
renderer_string(&state->renderer, transientArena, camera, font,
|
||||
entityPosStr, strPos, V2(0, 0), 0, color);
|
||||
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
char entityIDStr[32];
|
||||
snprintf(entityIDStr, ARRAY_COUNT(entityIDStr), "ID: %4d/%d", entity->id,
|
||||
world->uniqueIdAccumulator-1);
|
||||
renderer_string(&state->renderer, transientArena, camera, font,
|
||||
entityIDStr, strPos, V2(0, 0), 0, color);
|
||||
|
||||
if (entity->stats)
|
||||
{
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
char entityHealth[32];
|
||||
snprintf(entityHealth, ARRAY_COUNT(entityHealth), "HP: %3.0f/%3.0f",
|
||||
entity->stats->health, entity->stats->maxHealth);
|
||||
renderer_string(&state->renderer, transientArena, camera,
|
||||
font, entityHealth, strPos, V2(0, 0), 0, color);
|
||||
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
char entityTimer[32];
|
||||
snprintf(entityTimer, ARRAY_COUNT(entityTimer), "ATB: %3.0f/%3.0f",
|
||||
entity->stats->actionTimer, entity->stats->actionRate);
|
||||
renderer_string(&state->renderer, transientArena, camera,
|
||||
font, entityTimer, strPos, V2(0, 0), 0, color);
|
||||
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
char entityIdTarget[32];
|
||||
snprintf(entityIdTarget, ARRAY_COUNT(entityIdTarget),
|
||||
"Targetting ID: %d", entity->stats->entityIdToAttack);
|
||||
renderer_string(&state->renderer, transientArena, camera,
|
||||
font, entityIdTarget, strPos, V2(0, 0), 0, color);
|
||||
}
|
||||
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
char *entityStateStr = debug_entitystate_string(entity->state);
|
||||
renderer_string(&state->renderer, transientArena, camera, font,
|
||||
entityStateStr, strPos, V2(0, 0), 0, color);
|
||||
|
||||
if (entity->audioRenderer)
|
||||
{
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
char entityAudioSourceIndex[32];
|
||||
snprintf(entityAudioSourceIndex,
|
||||
ARRAY_COUNT(entityAudioSourceIndex),
|
||||
"AudioSource Index: %d",
|
||||
entity->audioRenderer->sourceIndex);
|
||||
renderer_string(&state->renderer, transientArena, camera,
|
||||
font, entityAudioSourceIndex, strPos, V2(0, 0),
|
||||
0, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Render debug info stack */
|
||||
DEBUG_PUSH_STRING("== Controls ==");
|
||||
DEBUG_PUSH_STRING(" [: Spawn a mob");
|
||||
DEBUG_PUSH_STRING("<TAB>: Switch UI element");
|
||||
DEBUG_PUSH_STRING("<ESC>: Close program");
|
||||
DEBUG_PUSH_STRING("");
|
||||
|
||||
DEBUG_PUSH_STRING("== Config == ");
|
||||
DEBUG_PUSH_VAR("Toggle World Audio: %d", state->config.playWorldAudio,
|
||||
"i32");
|
||||
DEBUG_PUSH_VAR("Toggle Debug Display: %d", state->config.showDebugDisplay,
|
||||
"i32");
|
||||
DEBUG_PUSH_STRING("");
|
||||
|
||||
DEBUG_PUSH_STRING("== Hero Properties == ");
|
||||
DEBUG_PUSH_VAR("Hero Pos: %06.2f, %06.2f", hero->pos, "v2");
|
||||
DEBUG_PUSH_VAR("Hero dPos: %06.2f, %06.2f", hero->dPos, "v2");
|
||||
DEBUG_PUSH_VAR("Hero Busy Duration: %05.3f", hero->stats->busyDuration, "f32");
|
||||
char *heroStateString = debug_entitystate_string(hero->state);
|
||||
DEBUG_PUSH_VAR("Hero State: %s", *heroStateString, "char");
|
||||
char *heroQueuedAttackStr =
|
||||
debug_entityattack_string(hero->stats->queuedAttack);
|
||||
DEBUG_PUSH_VAR("Hero QueuedAttack: %s", *heroQueuedAttackStr, "char");
|
||||
DEBUG_PUSH_STRING("");
|
||||
|
||||
DEBUG_PUSH_STRING("== State Properties == ");
|
||||
DEBUG_PUSH_VAR("FreeEntityIndex: %d", world->freeEntityIndex, "i32");
|
||||
DEBUG_PUSH_VAR("GLDrawArray Calls: %d",
|
||||
GLOBAL_debug.callCount[debugcount_drawArrays], "i32");
|
||||
DEBUG_PUSH_VAR("PlatformMemAlloc Calls: %d",
|
||||
GLOBAL_debug.callCount[debugcount_platformMemAlloc], "i32");
|
||||
DEBUG_PUSH_VAR("PlatformMemFree Calls: %d",
|
||||
GLOBAL_debug.callCount[debugcount_platformMemFree], "i32");
|
||||
|
||||
i32 vertexesUsed = GLOBAL_debug.callCount[debugcount_numVertex];
|
||||
i32 vertexesAvail =
|
||||
(ARRAY_COUNT(state->renderer.groups) * state->renderer.groupCapacity);
|
||||
i32 vertexesLeft = vertexesAvail - vertexesUsed;
|
||||
v2 vertexData = V2i(vertexesUsed, vertexesAvail);
|
||||
DEBUG_PUSH_VAR("Vertexes Rendered: %1.0f/%1.0f", vertexData, "v2");
|
||||
DEBUG_PUSH_VAR("Vertexes Left: %d", vertexesLeft, "i32");
|
||||
|
||||
i32 groupsUsed = GLOBAL_debug.callCount[debugcount_renderGroups];
|
||||
i32 groupsAvail = ARRAY_COUNT(state->renderer.groups);
|
||||
v2 groupData = V2i(groupsUsed, groupsAvail);
|
||||
DEBUG_PUSH_VAR("Render Groups Used: %1.0f/%1.0f", groupData, "v2");
|
||||
|
||||
DEBUG_PUSH_VAR("Mouse Pos: %06.2f, %06.2f", state->input.mouseP, "v2");
|
||||
|
||||
/*
|
||||
*****************
|
||||
* MEMORY DISPLAY
|
||||
*****************
|
||||
*/
|
||||
i32 debug_bAllocated = transientArena->used;
|
||||
i32 debug_kbAllocated = debug_bAllocated / 1024;
|
||||
i32 debug_mbAllocated = debug_kbAllocated / 1024;
|
||||
DEBUG_PUSH_VAR("TransientArena Used: %db", debug_bAllocated, "i32");
|
||||
DEBUG_PUSH_VAR("TransientArena Used: %dkb", debug_kbAllocated, "i32");
|
||||
DEBUG_PUSH_VAR("TransientArena Used: %dmb", debug_mbAllocated, "i32");
|
||||
DEBUG_PUSH_STRING("");
|
||||
|
||||
debug_bAllocated = state->arena_.used;
|
||||
debug_kbAllocated = debug_bAllocated / 1024;
|
||||
debug_mbAllocated = debug_kbAllocated / 1024;
|
||||
DEBUG_PUSH_VAR("PersistentArena Used: %db", debug_bAllocated, "i32");
|
||||
DEBUG_PUSH_VAR("PersistentArena Used: %dkb", debug_kbAllocated, "i32");
|
||||
DEBUG_PUSH_VAR("PersistentArena Used: %dmb", debug_mbAllocated, "i32");
|
||||
DEBUG_PUSH_STRING("");
|
||||
|
||||
AudioManager *audioManager = &state->audioManager;
|
||||
DEBUG_PUSH_STRING("== Audio System ==");
|
||||
for (i32 i = 0; i < ARRAY_COUNT(audioManager->sourceList); i++)
|
||||
{
|
||||
if (audioManager->sourceList[i].isFree) continue;
|
||||
v3 tmp = V3i(i, audioManager->sourceList[i].id,
|
||||
audioManager->sourceList[i].isFree);
|
||||
DEBUG_PUSH_VAR("Source ID[%02.0f].id[%02.0f].isFree: %1.0f", tmp, "v3");
|
||||
}
|
||||
DEBUG_PUSH_STRING("");
|
||||
|
||||
DEBUG_PUSH_STRING("== EntityIDs in Battle List == ");
|
||||
DEBUG_PUSH_VAR("NumEntitiesInBattle: %d", world->numEntitiesInBattle,
|
||||
"i32");
|
||||
if (world->numEntitiesInBattle > 0)
|
||||
{
|
||||
for (i32 i = 0; i < world->maxEntities; i++)
|
||||
{
|
||||
if (world->entityIdInBattle[i])
|
||||
DEBUG_PUSH_VAR("Entity ID: %d", i, "i32");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_PUSH_STRING("-none-");
|
||||
}
|
||||
|
||||
updateAndRenderDebugStack(&state->renderer, transientArena, dt);
|
||||
renderConsole(&state->renderer, transientArena);
|
||||
debug_clearCounter();
|
||||
}
|
||||
|
160
src/Entity.c
160
src/Entity.c
@ -1,12 +1,10 @@
|
||||
#include "Dengine/Entity.h"
|
||||
#include "Dengine/AssetManager.h"
|
||||
#include "Dengine/Debug.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/WorldTraveller.h"
|
||||
|
||||
SubTexture entity_getActiveSubTexture(Entity *const entity)
|
||||
{
|
||||
EntityAnim *entityAnim = &entity->animList[entity->currAnimId];
|
||||
EntityAnim *entityAnim = &entity->animList[entity->animListIndex];
|
||||
Animation *anim = entityAnim->anim;
|
||||
char *frameName = anim->frameList[entityAnim->currFrame];
|
||||
|
||||
@ -14,11 +12,10 @@ SubTexture entity_getActiveSubTexture(Entity *const entity)
|
||||
return result;
|
||||
}
|
||||
|
||||
void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity,
|
||||
const char *const animName)
|
||||
void entity_setActiveAnim(Entity *const entity, const char *const animName)
|
||||
{
|
||||
/* Reset current anim data */
|
||||
EntityAnim *currEntityAnim = &entity->animList[entity->currAnimId];
|
||||
EntityAnim *currEntityAnim = &entity->animList[entity->animListIndex];
|
||||
currEntityAnim->currDuration = currEntityAnim->anim->frameDuration;
|
||||
currEntityAnim->currFrame = 0;
|
||||
currEntityAnim->timesCompleted = 0;
|
||||
@ -32,14 +29,11 @@ void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity,
|
||||
// TODO(doyle): Linear search, but not a problem if list is small
|
||||
if (common_strcmp(anim->key, animName) == 0)
|
||||
{
|
||||
entity->currAnimId = i;
|
||||
entity->animListIndex = i;
|
||||
EntityAnim *newEntityAnim = &entity->animList[i];
|
||||
newEntityAnim->currDuration =
|
||||
newEntityAnim->anim->frameDuration;
|
||||
newEntityAnim->currFrame = 0;
|
||||
|
||||
worldTraveller_registerEvent(eventQueue, eventtype_start_anim,
|
||||
newEntityAnim);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -48,13 +42,12 @@ void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity,
|
||||
DEBUG_LOG("Entity does not have access to desired anim");
|
||||
}
|
||||
|
||||
void entity_updateAnim(EventQueue *eventQueue, Entity *const entity,
|
||||
const f32 dt)
|
||||
void entity_updateAnim(Entity *const entity, const f32 dt)
|
||||
{
|
||||
if (!entity->tex)
|
||||
return;
|
||||
|
||||
EntityAnim *currEntityAnim = &entity->animList[entity->currAnimId];
|
||||
EntityAnim *currEntityAnim = &entity->animList[entity->animListIndex];
|
||||
Animation *anim = currEntityAnim->anim;
|
||||
|
||||
currEntityAnim->currDuration -= dt;
|
||||
@ -64,30 +57,15 @@ void entity_updateAnim(EventQueue *eventQueue, Entity *const entity,
|
||||
currEntityAnim->currFrame = currEntityAnim->currFrame % anim->numFrames;
|
||||
if (currEntityAnim->currFrame == 0)
|
||||
{
|
||||
worldTraveller_registerEvent(eventQueue, eventtype_end_anim,
|
||||
currEntityAnim);
|
||||
currEntityAnim->timesCompleted++;
|
||||
}
|
||||
|
||||
currEntityAnim->currDuration = anim->frameDuration;
|
||||
}
|
||||
|
||||
// NOTE(doyle): If humanoid entity, let animation dictate render size which
|
||||
// may exceed the hitbox size of the entity
|
||||
switch (entity->type)
|
||||
{
|
||||
case entitytype_hero:
|
||||
case entitytype_mob:
|
||||
case entitytype_npc:
|
||||
case entitytype_weapon:
|
||||
case entitytype_projectile:
|
||||
char *frameName = anim->frameList[currEntityAnim->currFrame];
|
||||
SubTexture texRect =
|
||||
asset_getAtlasSubTex(anim->atlas, frameName);
|
||||
SubTexture texRect = asset_getAtlasSubTex(anim->atlas, frameName);
|
||||
entity->size = v2_scale(texRect.rect.size, entity->scale);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void entity_addAnim(AssetManager *const assetManager, Entity *const entity,
|
||||
@ -108,127 +86,3 @@ void entity_addAnim(AssetManager *const assetManager, Entity *const entity,
|
||||
|
||||
DEBUG_LOG("No more free entity animation slots");
|
||||
}
|
||||
|
||||
Entity *const entity_add(MemoryArena_ *const arena, World *const world,
|
||||
const v2 pos, const v2 size, const f32 scale,
|
||||
const enum EntityType type,
|
||||
const enum Direction direction, Texture *const tex,
|
||||
const b32 collides)
|
||||
{
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(world);
|
||||
ASSERT(world->freeEntityIndex < world->maxEntities);
|
||||
ASSERT(type < entitytype_count);
|
||||
#endif
|
||||
|
||||
Entity entity = {0};
|
||||
entity.id = world->uniqueIdAccumulator++;
|
||||
entity.pos = pos;
|
||||
entity.size = size;
|
||||
entity.hitbox = size;
|
||||
entity.scale = scale;
|
||||
entity.type = type;
|
||||
entity.direction = direction;
|
||||
entity.tex = tex;
|
||||
entity.collides = collides;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case entitytype_hero:
|
||||
entity.stats = MEMORY_PUSH_STRUCT(arena, EntityStats);
|
||||
entity.stats->maxHealth = 100;
|
||||
entity.stats->health = entity.stats->maxHealth;
|
||||
entity.stats->actionRate = 100;
|
||||
entity.stats->actionTimer = entity.stats->actionRate;
|
||||
entity.stats->actionSpdMul = 100;
|
||||
entity.stats->entityIdToAttack = -1;
|
||||
entity.stats->queuedAttack = entityattack_invalid;
|
||||
entity.state = entitystate_idle;
|
||||
entity.collidesWith[entitytype_mob] = TRUE;
|
||||
break;
|
||||
case entitytype_mob:
|
||||
{
|
||||
entity.stats = MEMORY_PUSH_STRUCT(arena, EntityStats);
|
||||
entity.stats->maxHealth = 100;
|
||||
entity.stats->health = entity.stats->maxHealth;
|
||||
entity.stats->actionRate = 80;
|
||||
entity.stats->actionTimer = entity.stats->actionRate;
|
||||
entity.stats->actionSpdMul = 100;
|
||||
entity.stats->entityIdToAttack = -1;
|
||||
entity.stats->queuedAttack = entityattack_invalid;
|
||||
entity.state = entitystate_idle;
|
||||
entity.collidesWith[entitytype_hero] = TRUE;
|
||||
break;
|
||||
}
|
||||
case entitytype_projectile:
|
||||
case entitytype_attackObject:
|
||||
entity.stats = MEMORY_PUSH_STRUCT(arena, EntityStats);
|
||||
entity.stats->maxHealth = 100;
|
||||
entity.stats->health = entity.stats->maxHealth;
|
||||
entity.stats->actionRate = 100;
|
||||
entity.stats->actionTimer = entity.stats->actionRate;
|
||||
entity.stats->actionSpdMul = 100;
|
||||
entity.stats->entityIdToAttack = -1;
|
||||
entity.stats->queuedAttack = entityattack_invalid;
|
||||
entity.state = entitystate_idle;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
world->entities[world->freeEntityIndex++] = entity;
|
||||
Entity *result = &world->entities[world->freeEntityIndex - 1];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void entity_clearData(MemoryArena_ *const arena, World *const world,
|
||||
Entity *const entity)
|
||||
{
|
||||
// TODO(doyle): Mem free// memory leak!!
|
||||
|
||||
/*
|
||||
if (entity->stats)
|
||||
PLATFORM_MEM_FREE(arena, entity->stats, sizeof(EntityStats));
|
||||
|
||||
if (entity->audioRenderer)
|
||||
PLATFORM_MEM_FREE(arena, entity->audioRenderer,
|
||||
sizeof(AudioRenderer) * entity->numAudioRenderers);
|
||||
*/
|
||||
|
||||
entity->type = entitytype_null;
|
||||
}
|
||||
|
||||
i32 entity_getIndex(World *const world, const i32 entityId)
|
||||
{
|
||||
i32 first = 0;
|
||||
i32 last = world->freeEntityIndex - 1;
|
||||
|
||||
while (first <= last)
|
||||
{
|
||||
i32 middle = (first + last) / 2;
|
||||
|
||||
if (world->entities[middle].id > entityId)
|
||||
last = middle - 1;
|
||||
else if (world->entities[middle].id < entityId)
|
||||
first = middle + 1;
|
||||
else
|
||||
return middle;
|
||||
}
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
Entity *entity_get(World *const world, const i32 entityId)
|
||||
{
|
||||
Entity *result = NULL;
|
||||
i32 worldIndex = entity_getIndex(world, entityId);
|
||||
if (worldIndex != -1) result = &world->entities[worldIndex];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "Dengine/Debug.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
|
||||
void platform_memoryFree(MemoryArena_ *arena, void *data, i32 numBytes)
|
||||
void platform_memoryFree(MemoryArena_ *arena, void *data, size_t numBytes)
|
||||
{
|
||||
if (data) free(data);
|
||||
|
||||
@ -16,7 +16,7 @@ void platform_memoryFree(MemoryArena_ *arena, void *data, i32 numBytes)
|
||||
#endif
|
||||
}
|
||||
|
||||
void *platform_memoryAlloc(MemoryArena_ *arena, i32 numBytes)
|
||||
void *platform_memoryAlloc(MemoryArena_ *arena, size_t numBytes)
|
||||
{
|
||||
void *result = calloc(1, numBytes);
|
||||
|
||||
|
@ -381,23 +381,31 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
||||
if (math_pointInRect(camera, leftAlignedP) ||
|
||||
math_pointInRect(camera, rightAlignedP))
|
||||
{
|
||||
EntityAnim *entityAnim = &entity->animList[entity->currAnimId];
|
||||
EntityAnim *entityAnim = &entity->animList[entity->animListIndex];
|
||||
|
||||
v4 texRect = {0};
|
||||
if (entityAnim->anim)
|
||||
{
|
||||
Animation *anim = entityAnim->anim;
|
||||
char *frameName = anim->frameList[entityAnim->currFrame];
|
||||
SubTexture animRect = asset_getAtlasSubTex(anim->atlas, frameName);
|
||||
SubTexture subTex = asset_getAtlasSubTex(anim->atlas, frameName);
|
||||
|
||||
v4 animTexRect = {0};
|
||||
animTexRect.vec2[0] = animRect.rect.pos;
|
||||
animTexRect.vec2[1] = v2_add(animRect.rect.pos, animRect.rect.size);
|
||||
|
||||
flipTexCoord(&animTexRect, entity->flipX, entity->flipY);
|
||||
texRect.vec2[0] = subTex.rect.pos;
|
||||
texRect.vec2[1] = v2_add(subTex.rect.pos, subTex.rect.size);
|
||||
flipTexCoord(&texRect, entity->flipX, entity->flipY);
|
||||
}
|
||||
else
|
||||
{
|
||||
texRect = V4(0.0f, 0.0f, (f32)entity->tex->width,
|
||||
(f32)entity->tex->height);
|
||||
}
|
||||
|
||||
if (entity->direction == direction_east)
|
||||
{
|
||||
flipTexCoord(&animTexRect, TRUE, FALSE);
|
||||
flipTexCoord(&texRect, TRUE, FALSE);
|
||||
}
|
||||
|
||||
RenderTex renderTex = {entity->tex, animTexRect};
|
||||
RenderTex renderTex = {entity->tex, texRect};
|
||||
renderer_rect(renderer, camera, entity->pos, entity->size, pivotPoint,
|
||||
entity->rotation + rotate, renderTex, color);
|
||||
}
|
||||
|
2477
src/WorldTraveller.c
2477
src/WorldTraveller.c
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,13 @@
|
||||
@echo OFF
|
||||
|
||||
REM Build tags file
|
||||
ctags -R
|
||||
|
||||
REM Check if build tool is on path
|
||||
REM >nul, 2>nul will remove the output text from the where command
|
||||
where cl.exe >nul 2>nul
|
||||
if %errorlevel%==1 call msvc86.bat
|
||||
|
||||
REM Drop compilation files into build folder
|
||||
IF NOT EXIST ..\bin mkdir ..\bin
|
||||
pushd ..\bin
|
||||
|
@ -3,7 +3,8 @@
|
||||
#include "Dengine/Debug.h"
|
||||
#include "Dengine/Math.h"
|
||||
#include "Dengine/OpenGL.h"
|
||||
#include "Dengine/WorldTraveller.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/Asteroid.h"
|
||||
|
||||
INTERNAL inline void processKey(KeyState *state, int action)
|
||||
{
|
||||
@ -142,6 +143,7 @@ i32 main(void)
|
||||
i32 frameBufferWidth, frameBufferHeight;
|
||||
glfwGetFramebufferSize(window, &frameBufferWidth, &frameBufferHeight);
|
||||
glViewport(0, 0, frameBufferWidth, frameBufferHeight);
|
||||
v2 windowSize = V2i(frameBufferWidth, frameBufferHeight);
|
||||
|
||||
glfwSetKeyCallback(window, keyCallback);
|
||||
glfwSetCursorPosCallback(window, mouseCallback);
|
||||
@ -161,9 +163,8 @@ i32 main(void)
|
||||
*******************
|
||||
*/
|
||||
Memory memory = {0};
|
||||
|
||||
size_t persistentSize = MEGABYTES(128);
|
||||
size_t transientSize = MEGABYTES(128);
|
||||
MemoryIndex persistentSize = MEGABYTES(128);
|
||||
MemoryIndex transientSize = MEGABYTES(128);
|
||||
|
||||
memory.persistentSize = persistentSize;
|
||||
memory.persistent = PLATFORM_MEM_ALLOC_(NULL, persistentSize, u8);
|
||||
@ -171,15 +172,8 @@ i32 main(void)
|
||||
memory.transientSize = transientSize;
|
||||
memory.transient = PLATFORM_MEM_ALLOC_(NULL, transientSize, u8);
|
||||
|
||||
GameState worldTraveller = {0};
|
||||
worldTraveller_gameInit(&worldTraveller,
|
||||
V2i(frameBufferWidth, frameBufferHeight), &memory);
|
||||
#ifdef DENGINE_DEBUG
|
||||
debug_init(&worldTraveller.arena_, V2i(windowWidth, windowHeight),
|
||||
worldTraveller.assetManager.font);
|
||||
#endif
|
||||
|
||||
glfwSetWindowUserPointer(window, CAST(void *)(&worldTraveller));
|
||||
GameState gameState = {0};
|
||||
glfwSetWindowUserPointer(window, CAST(void *)(&gameState));
|
||||
|
||||
/*
|
||||
*******************
|
||||
@ -206,10 +200,11 @@ i32 main(void)
|
||||
glfwPollEvents();
|
||||
|
||||
/* Rendering commands here*/
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
worldTraveller_gameUpdateAndRender(&worldTraveller, secondsElapsed);
|
||||
asteroid_gameUpdateAndRender(&gameState, &memory, windowSize,
|
||||
secondsElapsed);
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
/* Swap the buffers */
|
||||
@ -235,14 +230,10 @@ i32 main(void)
|
||||
f32 msPerFrame = secondsElapsed * 1000.0f;
|
||||
f32 framesPerSecond = 1.0f / secondsElapsed;
|
||||
|
||||
i32 entityCount =
|
||||
worldTraveller.world[worldTraveller.currWorldIndex]
|
||||
.freeEntityIndex;
|
||||
|
||||
char textBuffer[256];
|
||||
snprintf(textBuffer, ARRAY_COUNT(textBuffer),
|
||||
"Dengine | %f ms/f | %f fps | Entity Count: %d",
|
||||
msPerFrame, framesPerSecond, entityCount);
|
||||
msPerFrame, framesPerSecond, 0);
|
||||
|
||||
glfwSetWindowTitle(window, textBuffer);
|
||||
titleUpdateFrequencyInSeconds = 0.5f;
|
||||
|
@ -94,7 +94,6 @@ typedef struct AudioVorbis
|
||||
* Texture Assets
|
||||
*********************************
|
||||
*/
|
||||
|
||||
typedef struct SubTexture
|
||||
{
|
||||
Rect rect;
|
||||
|
31
src/include/Dengine/Asteroid.h
Normal file
31
src/include/Dengine/Asteroid.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef ASTEROID_H
|
||||
#define ASTEROID_H
|
||||
|
||||
#include "Dengine/AssetManager.h"
|
||||
#include "Dengine/Common.h"
|
||||
#include "Dengine/Entity.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/Platform.h"
|
||||
#include "Dengine/Renderer.h"
|
||||
|
||||
typedef struct GameState {
|
||||
b32 init;
|
||||
|
||||
Entity entityList[1024];
|
||||
i32 entityIndex;
|
||||
|
||||
Rect camera;
|
||||
|
||||
AssetManager assetManager;
|
||||
KeyInput input;
|
||||
|
||||
MemoryArena_ transientArena;
|
||||
MemoryArena_ persistentArena;
|
||||
|
||||
Renderer renderer;
|
||||
} GameState;
|
||||
|
||||
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
||||
v2 windowSize, f32 dt);
|
||||
|
||||
#endif
|
@ -14,6 +14,8 @@ typedef i32 b32;
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
typedef size_t MemoryIndex;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
|
@ -1,17 +1,10 @@
|
||||
#ifndef DENGINE_ENTITY_H
|
||||
#define DENGINE_ENTITY_H
|
||||
#ifndef ENTITY_H
|
||||
#define ENTITY_H
|
||||
|
||||
#include "Dengine/Common.h"
|
||||
#include "Dengine/Math.h"
|
||||
#include "Dengine/Assets.h"
|
||||
#include "Dengine/Common.h"
|
||||
|
||||
typedef struct AssetManager AssetManager;
|
||||
typedef struct AudioRenderer AudioRenderer;
|
||||
typedef struct MemoryArena MemoryArena_;
|
||||
typedef struct World World;
|
||||
typedef struct EventQueue EventQueue;
|
||||
|
||||
typedef struct Entity Entity;
|
||||
|
||||
enum Direction
|
||||
{
|
||||
@ -19,63 +12,17 @@ enum Direction
|
||||
direction_west,
|
||||
direction_south,
|
||||
direction_east,
|
||||
direction_num,
|
||||
direction_null,
|
||||
direction_num,
|
||||
};
|
||||
|
||||
enum EntityType
|
||||
{
|
||||
entitytype_null,
|
||||
entitytype_hero,
|
||||
entitytype_weapon,
|
||||
entitytype_projectile,
|
||||
entitytype_attackObject,
|
||||
entitytype_npc,
|
||||
entitytype_mob,
|
||||
entitytype_tile,
|
||||
entitytype_soundscape,
|
||||
entitytype_invalid,
|
||||
entitytype_ship,
|
||||
entitytype_count,
|
||||
};
|
||||
|
||||
enum EntityState
|
||||
{
|
||||
entitystate_idle,
|
||||
entitystate_battle,
|
||||
entitystate_attack,
|
||||
entitystate_dead,
|
||||
entitystate_count,
|
||||
entitystate_invalid,
|
||||
};
|
||||
|
||||
enum EntityAttack
|
||||
{
|
||||
entityattack_claudeAttack,
|
||||
entityattack_claudeAttackUp,
|
||||
entityattack_claudeAttackDown,
|
||||
entityattack_claudeDragonHowl,
|
||||
entityattack_claudeEnergySword,
|
||||
entityattack_claudeRipperBlast,
|
||||
entityattack_claudeAirSlash,
|
||||
entityattack_count,
|
||||
entityattack_invalid,
|
||||
};
|
||||
|
||||
typedef struct EntityStats
|
||||
{
|
||||
f32 maxHealth;
|
||||
f32 health;
|
||||
|
||||
f32 actionRate;
|
||||
f32 actionTimer;
|
||||
f32 actionSpdMul;
|
||||
|
||||
f32 busyDuration;
|
||||
i32 entityIdToAttack;
|
||||
enum EntityAttack queuedAttack;
|
||||
|
||||
Entity *weapon;
|
||||
} EntityStats;
|
||||
|
||||
typedef struct EntityAnim
|
||||
{
|
||||
Animation *anim;
|
||||
@ -85,7 +32,7 @@ typedef struct EntityAnim
|
||||
u32 timesCompleted;
|
||||
} EntityAnim;
|
||||
|
||||
struct Entity
|
||||
typedef struct Entity
|
||||
{
|
||||
i32 id;
|
||||
|
||||
@ -102,7 +49,6 @@ struct Entity
|
||||
|
||||
b32 invisible;
|
||||
|
||||
enum EntityState state;
|
||||
enum EntityType type;
|
||||
enum Direction direction;
|
||||
|
||||
@ -116,32 +62,13 @@ struct Entity
|
||||
// allow for early-exit in collision check if the entity doesn't collide at
|
||||
// all
|
||||
b32 collides;
|
||||
enum EntityType collidesWith[entitytype_count];
|
||||
|
||||
EntityAnim animList[16];
|
||||
i32 currAnimId;
|
||||
|
||||
EntityStats *stats;
|
||||
i32 animListIndex;
|
||||
|
||||
// TODO(doyle): Audio mixing instead of multiple renderers
|
||||
AudioRenderer *audioRenderer;
|
||||
i32 numAudioRenderers;
|
||||
};
|
||||
} Entity;
|
||||
|
||||
SubTexture entity_getActiveSubTexture(Entity *const entity);
|
||||
void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity,
|
||||
const char *const animName);
|
||||
void entity_updateAnim(EventQueue *eventQueue, Entity *const entity,
|
||||
const f32 dt);
|
||||
void entity_addAnim(AssetManager *const assetManager, Entity *const entity,
|
||||
const char *const animName);
|
||||
Entity *const entity_add(MemoryArena_ *const arena, World *const world,
|
||||
const v2 pos, const v2 size, const f32 scale,
|
||||
const enum EntityType type,
|
||||
const enum Direction direction, Texture *const tex,
|
||||
const b32 collides);
|
||||
void entity_clearData(MemoryArena_ *const arena, World *const world,
|
||||
Entity *const entity);
|
||||
Entity *entity_get(World *const world, const i32 entityId);
|
||||
i32 entity_getIndex(World *const world, const i32 entityId);
|
||||
#endif
|
||||
|
@ -5,25 +5,25 @@
|
||||
|
||||
typedef struct MemoryArena
|
||||
{
|
||||
size_t size;
|
||||
size_t used;
|
||||
MemoryIndex size;
|
||||
MemoryIndex used;
|
||||
u8 *base;
|
||||
} MemoryArena_;
|
||||
|
||||
typedef struct Memory
|
||||
{
|
||||
void *persistent;
|
||||
size_t persistentSize;
|
||||
MemoryIndex persistentSize;
|
||||
|
||||
void *transient;
|
||||
size_t transientSize;
|
||||
MemoryIndex transientSize;
|
||||
|
||||
b32 init;
|
||||
} Memory;
|
||||
|
||||
#define MEMORY_PUSH_STRUCT(arena, type) (type *)memory_pushBytes(arena, sizeof(type))
|
||||
#define MEMORY_PUSH_ARRAY(arena, count, type) (type *)memory_pushBytes(arena, (count)*sizeof(type))
|
||||
inline void *memory_pushBytes(MemoryArena_ *arena, size_t size)
|
||||
inline void *memory_pushBytes(MemoryArena_ *arena, MemoryIndex size)
|
||||
{
|
||||
ASSERT((arena->used + size) <= arena->size);
|
||||
void *result = arena->base + arena->used;
|
||||
@ -32,6 +32,6 @@ inline void *memory_pushBytes(MemoryArena_ *arena, size_t size)
|
||||
return result;
|
||||
}
|
||||
|
||||
void memory_arenaInit(MemoryArena_ *arena, void *base, size_t size);
|
||||
void memory_arenaInit(MemoryArena_ *arena, void *base, MemoryIndex size);
|
||||
|
||||
#endif
|
||||
|
@ -140,14 +140,16 @@ typedef struct PlatformFileRead
|
||||
} PlatformFileRead;
|
||||
|
||||
// TODO(doyle): Create own custom memory allocator
|
||||
#define PLATFORM_MEM_FREE_(arena, ptr, bytes) platform_memoryFree(arena, CAST(void *) ptr, bytes)
|
||||
#define PLATFORM_MEM_FREE_(arena, ptr, bytes) \
|
||||
platform_memoryFree(arena, CAST(void *) ptr, bytes)
|
||||
// TODO(doyle): numBytes in mem free is temporary until we create custom
|
||||
// allocator since we haven't put in a system to track memory usage per
|
||||
// allocation
|
||||
void platform_memoryFree(MemoryArena_ *arena, void *data, i32 numBytes);
|
||||
void platform_memoryFree(MemoryArena_ *arena, void *data, MemoryIndex numBytes);
|
||||
|
||||
#define PLATFORM_MEM_ALLOC_(arena, num, type) CAST(type *) platform_memoryAlloc(arena, num * sizeof(type))
|
||||
void *platform_memoryAlloc(MemoryArena_ *arena, i32 numBytes);
|
||||
#define PLATFORM_MEM_ALLOC_(arena, num, type) \
|
||||
CAST(type *) platform_memoryAlloc(arena, num * sizeof(type))
|
||||
void *platform_memoryAlloc(MemoryArena_ *arena, MemoryIndex numBytes);
|
||||
|
||||
void platform_closeFileRead(MemoryArena_ *arena, PlatformFileRead *file);
|
||||
i32 platform_readFileToBuffer(MemoryArena_ *arena, const char *const filePath,
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
/* Forward Declaration */
|
||||
typedef struct AssetManager AssetManager;
|
||||
typedef struct Entity Entity;
|
||||
typedef struct Font Font;
|
||||
typedef struct Entity Entity;
|
||||
typedef struct MemoryArena MemoryArena_;
|
||||
typedef struct Shader Shader;
|
||||
typedef struct Texture Texture;
|
||||
|
@ -1,109 +0,0 @@
|
||||
#ifndef WORLDTRAVELLER_GAME_H
|
||||
#define WORLDTRAVELLER_GAME_H
|
||||
|
||||
#include "Dengine/AssetManager.h"
|
||||
#include "Dengine/Audio.h"
|
||||
#include "Dengine/Common.h"
|
||||
#include "Dengine/Math.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/Platform.h"
|
||||
#include "Dengine/Renderer.h"
|
||||
#include "Dengine/UserInterface.h"
|
||||
|
||||
#define NUM_KEYS 1024
|
||||
#define METERS_TO_PIXEL 240
|
||||
|
||||
/* Forward declaration */
|
||||
typedef struct Entity Entity;
|
||||
|
||||
enum EventType
|
||||
{
|
||||
eventtype_null = 0,
|
||||
eventtype_start_attack,
|
||||
eventtype_end_attack,
|
||||
eventtype_start_anim,
|
||||
eventtype_end_anim,
|
||||
eventtype_entity_died,
|
||||
eventtype_count,
|
||||
};
|
||||
|
||||
typedef struct Event
|
||||
{
|
||||
enum EventType type;
|
||||
void *data;
|
||||
} Event;
|
||||
|
||||
typedef struct EventQueue
|
||||
{
|
||||
Event queue[1024];
|
||||
i32 numEvents;
|
||||
} EventQueue;
|
||||
|
||||
enum RectBaseline
|
||||
{
|
||||
rectbaseline_top,
|
||||
rectbaseline_topLeft,
|
||||
rectbaseline_topRight,
|
||||
rectbaseline_bottom,
|
||||
rectbaseline_bottomRight,
|
||||
rectbaseline_bottomLeft,
|
||||
rectbaseline_left,
|
||||
rectbaseline_right,
|
||||
rectbaseline_center,
|
||||
rectbaseline_count,
|
||||
|
||||
};
|
||||
|
||||
typedef struct Config
|
||||
{
|
||||
b32 playWorldAudio;
|
||||
b32 showStatMenu;
|
||||
b32 showDebugDisplay;
|
||||
} Config;
|
||||
|
||||
typedef struct World
|
||||
{
|
||||
Entity *entities;
|
||||
i32 maxEntities;
|
||||
b32 *entityIdInBattle;
|
||||
i32 numEntitiesInBattle;
|
||||
|
||||
i32 cameraFollowingId;
|
||||
v2 cameraPos; // In pixels
|
||||
v4 bounds; // In pixels
|
||||
|
||||
i32 heroId;
|
||||
i32 freeEntityIndex;
|
||||
u32 uniqueIdAccumulator;
|
||||
|
||||
Entity *soundscape;
|
||||
} World;
|
||||
|
||||
typedef struct GameState
|
||||
{
|
||||
Memory *memory;
|
||||
MemoryArena_ arena_;
|
||||
MemoryArena_ transientArena;
|
||||
|
||||
enum State state;
|
||||
KeyInput input;
|
||||
v2 mouse;
|
||||
|
||||
Renderer renderer;
|
||||
|
||||
World world[4];
|
||||
i32 currWorldIndex;
|
||||
i32 tileSize;
|
||||
|
||||
AssetManager assetManager;
|
||||
AudioManager audioManager;
|
||||
Config config;
|
||||
UiState uiState;
|
||||
EventQueue eventQueue;
|
||||
} GameState;
|
||||
|
||||
void worldTraveller_gameInit(GameState *state, v2 windowSize, Memory *memory);
|
||||
void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt);
|
||||
void worldTraveller_registerEvent(EventQueue *eventQueue, enum EventType type,
|
||||
void *data);
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user