Mobs battle with hero, engine architect. changes
Mobs battle in real-time with the hero when in range. Start encapsulating logic into entityStateSwitch() to organise entity properties changing between different states. Introduce basic concept of memory management in MemoryArena. Begin passing around a memory object to track memory usage and eventually delegate memory allocations through. Remove the old memory tracker in the debug object and incorporate into engine primarily. Add a debug console for logging information and events to the screen in a console-like fashion. Debug is now initialised after the game, this is so that you can pass the game's memory arena and font file to the debug services. Debug services now properly initialise debug element positions from this information and not through the update routine.
This commit is contained in:
parent
5fc58ca643
commit
fd94eb5afd
@ -140,6 +140,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\include\Dengine\Assets.h" />
|
||||
<ClInclude Include="src\include\Dengine\Debug.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" />
|
||||
|
@ -92,5 +92,8 @@
|
||||
<ClInclude Include="src\include\Dengine\Assets.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\include\Dengine\MemoryArena.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -95,11 +95,11 @@ Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INTERNAL GLuint createShaderFromPath(const char *const path, GLuint shadertype)
|
||||
INTERNAL GLuint createShaderFromPath(MemoryArena *arena, const char *const path, GLuint shadertype)
|
||||
{
|
||||
PlatformFileRead file = {0};
|
||||
|
||||
i32 status = platform_readFileToBuffer(path, &file);
|
||||
i32 status = platform_readFileToBuffer(arena, path, &file);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@ -118,7 +118,7 @@ INTERNAL GLuint createShaderFromPath(const char *const path, GLuint shadertype)
|
||||
printf("glCompileShader() failed: %s\n", infoLog);
|
||||
}
|
||||
|
||||
platform_closeFileRead(&file);
|
||||
platform_closeFileRead(arena, &file);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -147,14 +147,14 @@ INTERNAL i32 shaderLoadProgram(Shader *const shader, const GLuint vertexShader,
|
||||
return 0;
|
||||
}
|
||||
|
||||
const i32 asset_loadShaderFiles(AssetManager *assetManager,
|
||||
const i32 asset_loadShaderFiles(AssetManager *assetManager, MemoryArena *arena,
|
||||
const char *const vertexPath,
|
||||
const char *const fragmentPath,
|
||||
const enum ShaderList type)
|
||||
{
|
||||
GLuint vertexShader = createShaderFromPath(vertexPath, GL_VERTEX_SHADER);
|
||||
GLuint vertexShader = createShaderFromPath(arena, vertexPath, GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader =
|
||||
createShaderFromPath(fragmentPath, GL_FRAGMENT_SHADER);
|
||||
createShaderFromPath(arena, fragmentPath, GL_FRAGMENT_SHADER);
|
||||
|
||||
Shader shader;
|
||||
i32 result = shaderLoadProgram(&shader, vertexShader, fragmentShader);
|
||||
@ -173,10 +173,11 @@ typedef struct GlyphBitmap
|
||||
i32 codepoint;
|
||||
} GlyphBitmap;
|
||||
|
||||
const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
||||
const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
||||
const char *filePath)
|
||||
{
|
||||
PlatformFileRead fontFileRead = {0};
|
||||
platform_readFileToBuffer(filePath, &fontFileRead);
|
||||
platform_readFileToBuffer(arena, filePath, &fontFileRead);
|
||||
|
||||
stbtt_fontinfo fontInfo = {0};
|
||||
stbtt_InitFont(&fontInfo, fontFileRead.buffer,
|
||||
@ -188,7 +189,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
||||
v2 codepointRange = font->codepointRange;
|
||||
const i32 numGlyphs = CAST(i32)(codepointRange.y - codepointRange.x);
|
||||
|
||||
GlyphBitmap *glyphBitmaps = PLATFORM_MEM_ALLOC(numGlyphs, GlyphBitmap);
|
||||
GlyphBitmap *glyphBitmaps =
|
||||
PLATFORM_MEM_ALLOC(arena, numGlyphs, GlyphBitmap);
|
||||
v2 largestGlyphDimension = V2(0, 0);
|
||||
|
||||
const f32 targetFontHeight = 15.0f;
|
||||
@ -203,7 +205,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
||||
|
||||
font->metrics = CAST(FontMetrics){ascent, descent, lineGap};
|
||||
|
||||
font->charMetrics = PLATFORM_MEM_ALLOC(numGlyphs, CharMetrics);
|
||||
font->charMetrics = PLATFORM_MEM_ALLOC(arena, numGlyphs, CharMetrics);
|
||||
|
||||
/* Use STB_TrueType to generate a series of bitmap characters */
|
||||
i32 glyphIndex = 0;
|
||||
@ -218,7 +220,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
||||
&height, &xOffset, &yOffset);
|
||||
|
||||
u8 *source = monoBitmap;
|
||||
u32 *colorBitmap = PLATFORM_MEM_ALLOC(width * height, u32);
|
||||
u32 *colorBitmap = PLATFORM_MEM_ALLOC(arena, width * height, u32);
|
||||
u32 *dest = colorBitmap;
|
||||
|
||||
// NOTE(doyle): STB generates 1 byte per pixel bitmaps, we use 4bpp, so
|
||||
@ -294,7 +296,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
||||
#endif
|
||||
|
||||
i32 bitmapSize = SQUARED(TARGET_TEXTURE_SIZE) * TARGET_BYTES_PER_PIXEL;
|
||||
u32 *fontBitmap = PLATFORM_MEM_ALLOC(bitmapSize, u32);
|
||||
u32 *fontBitmap = PLATFORM_MEM_ALLOC(arena, bitmapSize, u32);
|
||||
const i32 pitch = MAX_TEXTURE_SIZE * TARGET_BYTES_PER_PIXEL;
|
||||
|
||||
// Check value to determine when a row of glyphs is completely printed
|
||||
@ -394,7 +396,7 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
||||
stbi_write_png("out.png", MAX_TEXTURE_SIZE, MAX_TEXTURE_SIZE, 4, fontBitmap,
|
||||
MAX_TEXTURE_SIZE * 4);
|
||||
#endif
|
||||
PLATFORM_MEM_FREE(fontBitmap, bitmapSize);
|
||||
PLATFORM_MEM_FREE(arena, fontBitmap, bitmapSize);
|
||||
|
||||
font->tex = &assetManager->textures[texlist_font];
|
||||
font->atlas = &assetManager->texAtlas[texlist_font];
|
||||
@ -404,18 +406,18 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
|
||||
i32 glyphBitmapSizeInBytes = CAST(i32) glyphBitmaps[i].dimensions.w *
|
||||
CAST(i32) glyphBitmaps[i].dimensions.h *
|
||||
sizeof(u32);
|
||||
PLATFORM_MEM_FREE(glyphBitmaps[i].pixels, glyphBitmapSizeInBytes);
|
||||
PLATFORM_MEM_FREE(arena, glyphBitmaps[i].pixels, glyphBitmapSizeInBytes);
|
||||
}
|
||||
|
||||
PLATFORM_MEM_FREE(glyphBitmaps, numGlyphs * sizeof(GlyphBitmap));
|
||||
platform_closeFileRead(&fontFileRead);
|
||||
PLATFORM_MEM_FREE(arena, glyphBitmaps, numGlyphs * sizeof(GlyphBitmap));
|
||||
platform_closeFileRead(arena, &fontFileRead);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void asset_addAnimation(AssetManager *assetManager, i32 texId,
|
||||
i32 animId, i32 *frameIndex, i32 numFrames,
|
||||
f32 frameDuration)
|
||||
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
||||
i32 texId, i32 animId, i32 *frameIndex, i32 numFrames,
|
||||
f32 frameDuration)
|
||||
{
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(assetManager && frameIndex)
|
||||
@ -425,7 +427,7 @@ void asset_addAnimation(AssetManager *assetManager, i32 texId,
|
||||
Animation anim = {0};
|
||||
anim.atlas = asset_getTextureAtlas(assetManager, texId);
|
||||
|
||||
anim.frameIndex = PLATFORM_MEM_ALLOC(numFrames, i32);
|
||||
anim.frameIndex = PLATFORM_MEM_ALLOC(arena, numFrames, i32);
|
||||
for (i32 i = 0; i < numFrames; i++) anim.frameIndex[i] = frameIndex[i];
|
||||
|
||||
anim.numFrames = numFrames;
|
||||
|
24
src/Common.c
24
src/Common.c
@ -1,4 +1,5 @@
|
||||
#include "Dengine\Common.h"
|
||||
#include "Dengine/Common.h"
|
||||
#include "Dengine/Math.h"
|
||||
|
||||
i32 common_strlen(const char *const string)
|
||||
{
|
||||
@ -19,3 +20,24 @@ i32 common_strcmp(const char *a, const char *b)
|
||||
|
||||
return ((*a < *b) ? -1 : 1);
|
||||
}
|
||||
|
||||
void common_itoa(i32 value, char *buf, i32 bufSize)
|
||||
{
|
||||
if (!buf || bufSize == 0) return;
|
||||
|
||||
// NOTE(doyle): Max 32bit integer (+-)2147483647
|
||||
i32 charIndex = 0;
|
||||
|
||||
b32 negative = FALSE;
|
||||
if (value < 0) negative = TRUE;
|
||||
|
||||
if (negative) buf[charIndex++] = '-';
|
||||
|
||||
i32 val = ABS(value);
|
||||
while (val != 0 && charIndex < bufSize)
|
||||
{
|
||||
i32 rem = val % 10;
|
||||
buf[charIndex++] = rem + '0';
|
||||
val /= 10;
|
||||
}
|
||||
}
|
||||
|
146
src/Debug.c
146
src/Debug.c
@ -4,16 +4,30 @@
|
||||
|
||||
DebugState GLOBAL_debug;
|
||||
|
||||
void debug_init()
|
||||
void debug_init(MemoryArena *arena, v2 windowSize, Font font)
|
||||
{
|
||||
GLOBAL_debug.totalMemoryAllocated = 0;
|
||||
GLOBAL_debug.callCount = PLATFORM_MEM_ALLOC(debugcallcount_num, i32);
|
||||
GLOBAL_debug.font = font;
|
||||
GLOBAL_debug.callCount = PLATFORM_MEM_ALLOC(arena, debugcallcount_num, i32);
|
||||
GLOBAL_debug.stringLineGap = 1.1f * asset_getVFontSpacing(font.metrics);
|
||||
|
||||
/* Init debug string stack */
|
||||
GLOBAL_debug.numDebugStrings = 0;
|
||||
GLOBAL_debug.stringUpdateTimer = 0.0f;
|
||||
GLOBAL_debug.stringUpdateRate = 0.15f;
|
||||
|
||||
GLOBAL_debug.stringLineGap = -1;
|
||||
GLOBAL_debug.initialStringP =
|
||||
V2(0.0f, (windowSize.h - 1.8f * GLOBAL_debug.stringLineGap));
|
||||
GLOBAL_debug.currStringP = GLOBAL_debug.initialStringP;
|
||||
|
||||
/* Init gui console */
|
||||
i32 maxConsoleStrLen = ARRAY_COUNT(GLOBAL_debug.console[0]);
|
||||
GLOBAL_debug.consoleIndex = 0;
|
||||
|
||||
// TODO(doyle): Font max size not entirely correct? using 1 * font.maxSize.w
|
||||
// reveals around 4 characters ..
|
||||
f32 consoleXPos = windowSize.x - (font.maxSize.w * 38);
|
||||
f32 consoleYPos = windowSize.h - 1.8f * GLOBAL_debug.stringLineGap;
|
||||
GLOBAL_debug.initialConsoleP = V2(consoleXPos, consoleYPos);
|
||||
}
|
||||
|
||||
void debug_pushString(char *formatString, void *data, char *dataType)
|
||||
@ -65,29 +79,22 @@ void debug_pushString(char *formatString, void *data, char *dataType)
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
}
|
||||
GLOBAL_debug.numDebugStrings++;
|
||||
ASSERT(GLOBAL_debug.numDebugStrings <
|
||||
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]));
|
||||
}
|
||||
}
|
||||
|
||||
void debug_stringUpdateAndRender(Renderer *renderer, Font *font, f32 dt)
|
||||
INTERNAL void updateAndRenderDebugStack(Renderer *renderer, MemoryArena *arena,
|
||||
f32 dt)
|
||||
{
|
||||
if (GLOBAL_debug.stringLineGap == -1)
|
||||
{
|
||||
GLOBAL_debug.stringLineGap =
|
||||
1.1f * asset_getVFontSpacing(font->metrics);
|
||||
GLOBAL_debug.initialStringPos =
|
||||
V2(0.0f,
|
||||
(renderer->size.y - 1.8f * GLOBAL_debug.stringLineGap));
|
||||
GLOBAL_debug.stringPos = GLOBAL_debug.initialStringPos;
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < GLOBAL_debug.numDebugStrings; i++)
|
||||
{
|
||||
f32 rotate = 0;
|
||||
v4 color = V4(0, 0, 0, 1);
|
||||
renderer_staticString(renderer, font, GLOBAL_debug.debugStrings[i],
|
||||
GLOBAL_debug.stringPos, rotate, color);
|
||||
GLOBAL_debug.stringPos.y -=
|
||||
(0.9f * GLOBAL_debug.stringLineGap);
|
||||
renderer_staticString(renderer, arena, &GLOBAL_debug.font,
|
||||
GLOBAL_debug.debugStrings[i],
|
||||
GLOBAL_debug.currStringP, rotate, color);
|
||||
GLOBAL_debug.currStringP.y -= (0.9f * GLOBAL_debug.stringLineGap);
|
||||
}
|
||||
|
||||
if (GLOBAL_debug.stringUpdateTimer <= 0)
|
||||
@ -104,7 +111,23 @@ void debug_stringUpdateAndRender(Renderer *renderer, Font *font, f32 dt)
|
||||
}
|
||||
}
|
||||
|
||||
GLOBAL_debug.stringPos = GLOBAL_debug.initialStringPos;
|
||||
GLOBAL_debug.currStringP = GLOBAL_debug.initialStringP;
|
||||
|
||||
}
|
||||
|
||||
INTERNAL void renderConsole(Renderer *renderer, MemoryArena *arena)
|
||||
{
|
||||
i32 maxConsoleLines = ARRAY_COUNT(GLOBAL_debug.console);
|
||||
v2 consoleStrP = GLOBAL_debug.initialConsoleP;
|
||||
for (i32 i = 0; i < maxConsoleLines; i++)
|
||||
{
|
||||
f32 rotate = 0;
|
||||
v4 color = V4(0, 0, 0, 1);
|
||||
renderer_staticString(renderer, arena, &GLOBAL_debug.font,
|
||||
GLOBAL_debug.console[i], consoleStrP,
|
||||
rotate, color);
|
||||
consoleStrP.y -= (0.9f * GLOBAL_debug.stringLineGap);
|
||||
}
|
||||
}
|
||||
|
||||
void debug_drawUi(GameState *state, f32 dt)
|
||||
@ -113,7 +136,6 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
Renderer *renderer = &state->renderer;
|
||||
World *const world = &state->world[state->currWorldIndex];
|
||||
Entity *hero = &world->entities[world->heroIndex];
|
||||
Font *font = &assetManager->font;
|
||||
|
||||
// TODO(doyle): Dumb copy function from game so we don't expose api
|
||||
v4 cameraBounds = math_getRect(world->cameraPos, renderer->size);
|
||||
@ -140,6 +162,7 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
V2(distance, 5.0f), 0, renderTex, V4(1, 0, 0, 0.25f));
|
||||
#endif
|
||||
|
||||
Font *font = &GLOBAL_debug.font;
|
||||
if (world->numEntitiesInBattle > 0)
|
||||
{
|
||||
v4 color = V4(1.0f, 0, 0, 1);
|
||||
@ -148,8 +171,8 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
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, font, battleStr, strPos, 0,
|
||||
color);
|
||||
renderer_staticString(&state->renderer, &state->arena, font, battleStr,
|
||||
strPos, 0, color);
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < world->maxEntities; i++)
|
||||
@ -185,8 +208,8 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
i32 indexOfLowerAInMetrics = 'a' - CAST(i32) font->codepointRange.x;
|
||||
strPos.y += font->charMetrics[indexOfLowerAInMetrics].offset.y;
|
||||
|
||||
renderer_string(&state->renderer, cameraBounds, font, debugString,
|
||||
strPos, 0, color);
|
||||
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
|
||||
debugString, strPos, 0, color);
|
||||
|
||||
f32 stringLineGap = 1.1f * asset_getVFontSpacing(font->metrics);
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
@ -194,15 +217,15 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
char entityPosStr[128];
|
||||
snprintf(entityPosStr, ARRAY_COUNT(entityPosStr), "%06.2f, %06.2f",
|
||||
entity->pos.x, entity->pos.y);
|
||||
renderer_string(&state->renderer, cameraBounds, font, entityPosStr,
|
||||
strPos, 0, color);
|
||||
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
|
||||
entityPosStr, strPos, 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, cameraBounds, font, entityIDStr,
|
||||
strPos, 0, color);
|
||||
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
|
||||
entityIDStr, strPos, 0, color);
|
||||
|
||||
if (entity->stats)
|
||||
{
|
||||
@ -210,20 +233,20 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
char entityHealth[32];
|
||||
snprintf(entityHealth, ARRAY_COUNT(entityHealth), "HP: %3.0f/%3.0f",
|
||||
entity->stats->health, entity->stats->maxHealth);
|
||||
renderer_string(&state->renderer, cameraBounds, font,
|
||||
entityHealth, strPos, 0, color);
|
||||
renderer_string(&state->renderer, &state->arena, cameraBounds,
|
||||
font, entityHealth, strPos, 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, cameraBounds, font,
|
||||
entityTimer, strPos, 0, color);
|
||||
renderer_string(&state->renderer, &state->arena, cameraBounds,
|
||||
font, entityTimer, strPos, 0, color);
|
||||
}
|
||||
|
||||
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||
char *entityStateStr = debug_entitystate_string(entity->state);
|
||||
renderer_string(&state->renderer, cameraBounds, font,
|
||||
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
|
||||
entityStateStr, strPos, 0, color);
|
||||
}
|
||||
}
|
||||
@ -243,7 +266,8 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
DEBUG_PUSH_VAR("FreeEntityIndex: %d", world->freeEntityIndex, "i32");
|
||||
DEBUG_PUSH_VAR("glDrawArray Calls: %d",
|
||||
GLOBAL_debug.callCount[debugcallcount_drawArrays], "i32");
|
||||
i32 debug_kbAllocated = GLOBAL_debug.totalMemoryAllocated / 1024;
|
||||
|
||||
i32 debug_kbAllocated = state->arena.bytesAllocated / 1024;
|
||||
DEBUG_PUSH_VAR("TotalMemoryAllocated: %dkb", debug_kbAllocated, "i32");
|
||||
|
||||
DEBUG_PUSH_STRING("== EntityIDs in Battle List == ");
|
||||
@ -262,6 +286,56 @@ void debug_drawUi(GameState *state, f32 dt)
|
||||
DEBUG_PUSH_STRING("-none-");
|
||||
}
|
||||
|
||||
debug_stringUpdateAndRender(&state->renderer, font, dt);
|
||||
updateAndRenderDebugStack(&state->renderer, &state->arena, dt);
|
||||
renderConsole(&state->renderer, &state->arena);
|
||||
debug_clearCallCounter();
|
||||
}
|
||||
|
||||
void debug_consoleLog(char *string, char *file, int lineNum)
|
||||
{
|
||||
i32 maxConsoleStrLen = ARRAY_COUNT(GLOBAL_debug.console[0]);
|
||||
|
||||
i32 strIndex = 0;
|
||||
i32 fileStrLen = common_strlen(file);
|
||||
for (i32 count = 0; strIndex < maxConsoleStrLen; strIndex++, count++)
|
||||
{
|
||||
if (fileStrLen <= count) break;
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex] = file[count];
|
||||
}
|
||||
|
||||
if (strIndex < maxConsoleStrLen)
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex++] = ':';
|
||||
|
||||
char line[12] = {0};
|
||||
common_itoa(lineNum, line, ARRAY_COUNT(line));
|
||||
i32 lineStrLen = common_strlen(line);
|
||||
for (i32 count = 0; strIndex < maxConsoleStrLen; strIndex++, count++)
|
||||
{
|
||||
if (lineStrLen <= count) break;
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex] = line[count];
|
||||
}
|
||||
|
||||
if (strIndex < maxConsoleStrLen)
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex++] = ':';
|
||||
|
||||
i32 stringStrLen = common_strlen(string);
|
||||
for (i32 count = 0; strIndex < maxConsoleStrLen; strIndex++, count++)
|
||||
{
|
||||
if (stringStrLen <= count) break;
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][strIndex] = string[count];
|
||||
}
|
||||
|
||||
if (strIndex >= maxConsoleStrLen)
|
||||
{
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-4] = '.';
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-3] = '.';
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-2] = '.';
|
||||
GLOBAL_debug.console[GLOBAL_debug.consoleIndex][maxConsoleStrLen-1] = 0;
|
||||
}
|
||||
|
||||
i32 maxConsoleLines = ARRAY_COUNT(GLOBAL_debug.console);
|
||||
GLOBAL_debug.consoleIndex++;
|
||||
|
||||
if (GLOBAL_debug.consoleIndex >= maxConsoleLines)
|
||||
GLOBAL_debug.consoleIndex = 0;
|
||||
}
|
||||
|
@ -5,32 +5,32 @@
|
||||
#include "Dengine/Platform.h"
|
||||
#include "Dengine/Debug.h"
|
||||
|
||||
void platform_memoryFree(void *data, i32 numBytes)
|
||||
void platform_memoryFree(MemoryArena *arena, void *data, i32 numBytes)
|
||||
{
|
||||
if (data) free(data);
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
GLOBAL_debug.totalMemoryAllocated -= numBytes;
|
||||
arena->bytesAllocated -= numBytes;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *platform_memoryAlloc(i32 numBytes)
|
||||
void *platform_memoryAlloc(MemoryArena *arena, i32 numBytes)
|
||||
{
|
||||
void *result = calloc(1, numBytes);
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
if (result)
|
||||
GLOBAL_debug.totalMemoryAllocated += numBytes;
|
||||
arena->bytesAllocated += numBytes;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void platform_closeFileRead(PlatformFileRead *file)
|
||||
void platform_closeFileRead(MemoryArena *arena, PlatformFileRead *file)
|
||||
{
|
||||
PLATFORM_MEM_FREE(file->buffer, file->size);
|
||||
PLATFORM_MEM_FREE(arena, file->buffer, file->size);
|
||||
}
|
||||
|
||||
i32 platform_readFileToBuffer(const char *const filePath,
|
||||
i32 platform_readFileToBuffer(MemoryArena *arena, const char *const filePath,
|
||||
PlatformFileRead *file)
|
||||
{
|
||||
HANDLE fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ,
|
||||
@ -52,7 +52,7 @@ i32 platform_readFileToBuffer(const char *const filePath,
|
||||
}
|
||||
|
||||
// TODO(doyle): Warning we assume files less than 4GB
|
||||
file->buffer = PLATFORM_MEM_ALLOC(fileSize.LowPart, char);
|
||||
file->buffer = PLATFORM_MEM_ALLOC(arena, fileSize.LowPart, char);
|
||||
file->size = fileSize.LowPart;
|
||||
|
||||
DWORD numBytesRead = 0;
|
||||
@ -63,7 +63,7 @@ i32 platform_readFileToBuffer(const char *const filePath,
|
||||
{
|
||||
printf("ReadFile() failed: %d error number\n",
|
||||
status);
|
||||
PLATFORM_MEM_FREE(file->buffer, file->size);
|
||||
PLATFORM_MEM_FREE(arena, file->buffer, file->size);
|
||||
return status;
|
||||
}
|
||||
else if (numBytesRead != file->size)
|
||||
@ -71,7 +71,7 @@ i32 platform_readFileToBuffer(const char *const filePath,
|
||||
printf(
|
||||
"ReadFile() failed: Number of bytes read doesn't match file "
|
||||
"size\n");
|
||||
PLATFORM_MEM_FREE(file->buffer, file->size);
|
||||
PLATFORM_MEM_FREE(arena, file->buffer, file->size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -152,9 +152,9 @@ void renderer_rect(Renderer *const renderer, v4 cameraBounds, v2 pos, v2 size,
|
||||
renderTex.tex);
|
||||
}
|
||||
|
||||
void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
||||
Font *const font, const char *const string, v2 pos,
|
||||
f32 rotate, v4 color)
|
||||
void renderer_string(Renderer *const renderer, MemoryArena *arena,
|
||||
v4 cameraBounds, Font *const font,
|
||||
const char *const string, v2 pos, f32 rotate, v4 color)
|
||||
{
|
||||
i32 strLen = common_strlen(string);
|
||||
// TODO(doyle): Scale, not too important .. but rudimentary infrastructure
|
||||
@ -172,7 +172,7 @@ void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
||||
(leftAlignedP.y < cameraBounds.y && rightAlignedP.y >= cameraBounds.w))
|
||||
{
|
||||
i32 quadIndex = 0;
|
||||
RenderQuad *stringQuads = PLATFORM_MEM_ALLOC(strLen, RenderQuad);
|
||||
RenderQuad *stringQuads = PLATFORM_MEM_ALLOC(arena, strLen, RenderQuad);
|
||||
|
||||
v2 offsetFromCamOrigin = V2(cameraBounds.x, cameraBounds.w);
|
||||
v2 entityRelativeToCamera = v2_sub(pos, offsetFromCamOrigin);
|
||||
@ -210,7 +210,7 @@ void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
||||
updateBufferObject(renderer, stringQuads, quadIndex);
|
||||
renderObject(renderer, V2(0.0f, 0.0f), renderer->size, rotate, color,
|
||||
font->tex);
|
||||
PLATFORM_MEM_FREE(stringQuads, strLen * sizeof(RenderQuad));
|
||||
PLATFORM_MEM_FREE(arena, stringQuads, strLen * sizeof(RenderQuad));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,9 @@ enum State
|
||||
state_win,
|
||||
};
|
||||
|
||||
INTERNAL Entity *addEntity(World *world, v2 pos, v2 size, enum EntityType type,
|
||||
enum Direction direction, Texture *tex, b32 collides)
|
||||
INTERNAL Entity *addEntity(MemoryArena *arena, World *world, v2 pos, v2 size,
|
||||
enum EntityType type, enum Direction direction,
|
||||
Texture *tex, b32 collides)
|
||||
{
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
@ -35,7 +36,7 @@ INTERNAL Entity *addEntity(World *world, v2 pos, v2 size, enum EntityType type,
|
||||
case entitytype_hero:
|
||||
case entitytype_mob:
|
||||
{
|
||||
entity.stats = PLATFORM_MEM_ALLOC(1, EntityStats);
|
||||
entity.stats = PLATFORM_MEM_ALLOC(arena, 1, EntityStats);
|
||||
entity.stats->maxHealth = 100;
|
||||
entity.stats->health = entity.stats->maxHealth;
|
||||
entity.stats->actionRate = 100;
|
||||
@ -107,6 +108,7 @@ INTERNAL void addAnim(AssetManager *assetManager, i32 animId, Entity *entity)
|
||||
void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
{
|
||||
AssetManager *assetManager = &state->assetManager;
|
||||
MemoryArena *arena = &state->arena;
|
||||
/* Initialise assets */
|
||||
/* Create empty 1x1 4bpp black texture */
|
||||
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
|
||||
@ -142,29 +144,33 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
texOrigin.y - atlasTileSize);
|
||||
|
||||
/* Load shaders */
|
||||
asset_loadShaderFiles(assetManager, "data/shaders/sprite.vert.glsl",
|
||||
asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl",
|
||||
"data/shaders/sprite.frag.glsl",
|
||||
shaderlist_sprite);
|
||||
|
||||
asset_loadTTFont(assetManager, "C:/Windows/Fonts/Arialbd.ttf");
|
||||
asset_loadTTFont(assetManager, arena, "C:/Windows/Fonts/Arialbd.ttf");
|
||||
glCheckError();
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
DEBUG_LOG("Assets loaded");
|
||||
#endif
|
||||
|
||||
/* Load animations */
|
||||
f32 duration = 1.0f;
|
||||
i32 numRects = 1;
|
||||
v4 *animRects = PLATFORM_MEM_ALLOC(numRects, v4);
|
||||
v4 *animRects = PLATFORM_MEM_ALLOC(arena, numRects, v4);
|
||||
i32 terrainAnimAtlasIndexes[1] = {terrainrects_ground};
|
||||
|
||||
// TODO(doyle): Optimise animation storage, we waste space having 1:1 with
|
||||
// animlist when some textures don't have certain animations
|
||||
asset_addAnimation(assetManager, texlist_terrain, animlist_terrain,
|
||||
asset_addAnimation(assetManager, arena, texlist_terrain, animlist_terrain,
|
||||
terrainAnimAtlasIndexes, numRects, duration);
|
||||
|
||||
// Idle animation
|
||||
duration = 1.0f;
|
||||
numRects = 1;
|
||||
i32 idleAnimAtlasIndexes[1] = {herorects_idle};
|
||||
asset_addAnimation(assetManager, texlist_hero, animlist_hero_idle,
|
||||
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_idle,
|
||||
idleAnimAtlasIndexes, numRects, duration);
|
||||
|
||||
// Walk animation
|
||||
@ -172,21 +178,21 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
numRects = 3;
|
||||
i32 walkAnimAtlasIndexes[3] = {herorects_walkA, herorects_idle,
|
||||
herorects_walkB};
|
||||
asset_addAnimation(assetManager, texlist_hero, animlist_hero_walk,
|
||||
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_walk,
|
||||
walkAnimAtlasIndexes, numRects, duration);
|
||||
|
||||
// Wave animation
|
||||
duration = 0.30f;
|
||||
numRects = 2;
|
||||
i32 waveAnimAtlasIndexes[2] = {herorects_waveA, herorects_waveB};
|
||||
asset_addAnimation(assetManager, texlist_hero, animlist_hero_wave,
|
||||
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_wave,
|
||||
waveAnimAtlasIndexes, numRects, duration);
|
||||
|
||||
// Battle Stance animation
|
||||
duration = 1.0f;
|
||||
numRects = 1;
|
||||
i32 battleStanceAnimAtlasIndexes[1] = {herorects_battlePose};
|
||||
asset_addAnimation(assetManager, texlist_hero, animlist_hero_battlePose,
|
||||
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_battlePose,
|
||||
battleStanceAnimAtlasIndexes, numRects, duration);
|
||||
|
||||
// Battle tackle animation
|
||||
@ -194,8 +200,11 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
numRects = 3;
|
||||
i32 tackleAnimAtlasIndexes[3] = {herorects_castA, herorects_castB,
|
||||
herorects_castC};
|
||||
asset_addAnimation(assetManager, texlist_hero, animlist_hero_tackle,
|
||||
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_tackle,
|
||||
tackleAnimAtlasIndexes, numRects, duration);
|
||||
#ifdef DENGINE_DEBUG
|
||||
DEBUG_LOG("Animations created");
|
||||
#endif
|
||||
|
||||
|
||||
state->state = state_active;
|
||||
@ -204,6 +213,9 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
|
||||
/* Init renderer */
|
||||
rendererInit(state, windowSize);
|
||||
#ifdef DENGINE_DEBUG
|
||||
DEBUG_LOG("Renderer initialised");
|
||||
#endif
|
||||
|
||||
/* Init world */
|
||||
const i32 targetWorldWidth = 100 * METERS_TO_PIXEL;
|
||||
@ -215,8 +227,9 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
{
|
||||
World *const world = &state->world[i];
|
||||
world->maxEntities = 16384;
|
||||
world->entities = PLATFORM_MEM_ALLOC(world->maxEntities, Entity);
|
||||
world->entityIdInBattle = PLATFORM_MEM_ALLOC(world->maxEntities, i32);
|
||||
world->entities = PLATFORM_MEM_ALLOC(arena, world->maxEntities, Entity);
|
||||
world->entityIdInBattle =
|
||||
PLATFORM_MEM_ALLOC(arena, world->maxEntities, i32);
|
||||
world->numEntitiesInBattle = 0;
|
||||
world->texType = texlist_terrain;
|
||||
world->bounds =
|
||||
@ -243,8 +256,8 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
enum Direction dir = direction_null;
|
||||
Texture *tex = asset_getTexture(assetManager, world->texType);
|
||||
b32 collides = FALSE;
|
||||
Entity *tile =
|
||||
addEntity(world, pos, size, type, dir, tex, collides);
|
||||
Entity *tile = addEntity(arena, world, pos, size, type, dir,
|
||||
tex, collides);
|
||||
|
||||
addAnim(assetManager, animlist_terrain, tile);
|
||||
tile->currAnimId = animlist_terrain;
|
||||
@ -265,7 +278,7 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
enum Direction dir = direction_east;
|
||||
Texture *tex = asset_getTexture(assetManager, texlist_hero);
|
||||
b32 collides = TRUE;
|
||||
Entity *hero = addEntity(world, pos, size, type, dir, tex, collides);
|
||||
Entity *hero = addEntity(arena, world, pos, size, type, dir, tex, collides);
|
||||
|
||||
/* Populate hero animation references */
|
||||
addAnim(assetManager, animlist_hero_idle, hero);
|
||||
@ -282,7 +295,7 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
dir = direction_null;
|
||||
tex = hero->tex;
|
||||
collides = FALSE;
|
||||
Entity *npc = addEntity(world, pos, size, type, dir, tex, collides);
|
||||
Entity *npc = addEntity(arena, world, pos, size, type, dir, tex, collides);
|
||||
|
||||
/* Populate npc animation references */
|
||||
addAnim(assetManager, animlist_hero_wave, npc);
|
||||
@ -296,7 +309,7 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
dir = direction_west;
|
||||
tex = hero->tex;
|
||||
collides = TRUE;
|
||||
Entity *mob = addEntity(world, pos, size, type, dir, tex, collides);
|
||||
Entity *mob = addEntity(arena, world, pos, size, type, dir, tex, collides);
|
||||
|
||||
/* Populate mob animation references */
|
||||
addAnim(assetManager, animlist_hero_idle, mob);
|
||||
@ -304,6 +317,11 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||
addAnim(assetManager, animlist_hero_battlePose, mob);
|
||||
addAnim(assetManager, animlist_hero_tackle, mob);
|
||||
hero->currAnimId = animlist_hero_idle;
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
DEBUG_LOG("World populated");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
INTERNAL inline void setActiveEntityAnim(Entity *entity,
|
||||
@ -519,8 +537,14 @@ INTERNAL void updateEntityAnim(Entity *entity, f32 dt)
|
||||
}
|
||||
}
|
||||
|
||||
#define ENTITY_NULL_ID -1
|
||||
INTERNAL void beginAttack(Entity *attacker)
|
||||
{
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
||||
#endif
|
||||
|
||||
attacker->state = entitystate_attack;
|
||||
switch (attacker->stats->queuedAttack)
|
||||
{
|
||||
@ -549,6 +573,10 @@ INTERNAL void beginAttack(Entity *attacker)
|
||||
// etc
|
||||
INTERNAL void endAttack(World *world, Entity *attacker)
|
||||
{
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
||||
#endif
|
||||
|
||||
switch (attacker->stats->queuedAttack)
|
||||
{
|
||||
case entityattack_tackle:
|
||||
@ -602,20 +630,69 @@ INTERNAL v4 createCameraBounds(World *world, v2 size)
|
||||
|
||||
#define ENTITY_IN_BATTLE TRUE
|
||||
#define ENTITY_NOT_IN_BATTLE FALSE
|
||||
INTERNAL i32 findBestEntityToAttack(World *world, Entity attacker)
|
||||
{
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(world);
|
||||
ASSERT(attacker.type == entitytype_hero || attacker.type == entitytype_mob);
|
||||
#endif
|
||||
i32 result = 0;
|
||||
|
||||
// TODO(doyle): If attacker is mob- retrieve hero entity id directly, change
|
||||
// when we have party members!
|
||||
if (attacker.type == entitytype_mob)
|
||||
{
|
||||
Entity hero = world->entities[world->heroIndex];
|
||||
result = hero.id;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Attacker is hero */
|
||||
Entity hero = attacker;
|
||||
for (i32 i = 0; i < world->maxEntities; i++)
|
||||
{
|
||||
|
||||
Entity targetEntity = world->entities[i];
|
||||
if (hero.id == targetEntity.id) continue;
|
||||
if (world->entityIdInBattle[targetEntity.id] == ENTITY_IN_BATTLE)
|
||||
{
|
||||
result = targetEntity.id;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(doyle): Not all "battling" entities have been enumerated yet in the
|
||||
// update loop, guard against when using function
|
||||
return ENTITY_NULL_ID;
|
||||
}
|
||||
|
||||
INTERNAL inline void updateWorldBattleEntities(World *world, Entity *entity,
|
||||
b32 isInBattle)
|
||||
{
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(isInBattle == ENTITY_IN_BATTLE ||
|
||||
isInBattle == ENTITY_NOT_IN_BATTLE);
|
||||
ASSERT(world && entity);
|
||||
#endif
|
||||
world->entityIdInBattle[entity->id] = isInBattle;
|
||||
|
||||
if (isInBattle)
|
||||
world->numEntitiesInBattle++;
|
||||
else
|
||||
world->numEntitiesInBattle--;
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(world->numEntitiesInBattle >= 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
||||
enum EntityState newState)
|
||||
{
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(world && entity)
|
||||
ASSERT(entity->type == entitytype_mob || entity->type == entitytype_hero)
|
||||
#endif
|
||||
if (entity->state == newState) return;
|
||||
|
||||
switch(entity->state)
|
||||
@ -625,11 +702,16 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
||||
{
|
||||
case entitystate_battle:
|
||||
updateWorldBattleEntities(world, entity, ENTITY_IN_BATTLE);
|
||||
entity->stats->entityIdToAttack =
|
||||
findBestEntityToAttack(world, *entity);
|
||||
break;
|
||||
|
||||
case entitystate_attack:
|
||||
case entitystate_dead:
|
||||
break;
|
||||
default:
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case entitystate_battle:
|
||||
@ -637,36 +719,52 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
||||
{
|
||||
case entitystate_idle:
|
||||
updateWorldBattleEntities(world, entity, ENTITY_NOT_IN_BATTLE);
|
||||
entity->stats->actionTimer = entity->stats->actionRate;
|
||||
entity->stats->queuedAttack = entityattack_invalid;
|
||||
setActiveEntityAnim(entity, animlist_hero_idle);
|
||||
|
||||
entity->stats->actionTimer = entity->stats->actionRate;
|
||||
entity->stats->queuedAttack = entityattack_invalid;
|
||||
entity->stats->entityIdToAttack = ENTITY_NULL_ID;
|
||||
|
||||
break;
|
||||
case entitystate_attack:
|
||||
case entitystate_dead:
|
||||
break;
|
||||
return;
|
||||
default:
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case entitystate_attack:
|
||||
switch (newState)
|
||||
{
|
||||
case entitystate_idle:
|
||||
case entitystate_battle:
|
||||
case entitystate_idle:
|
||||
return;
|
||||
|
||||
case entitystate_dead:
|
||||
break;
|
||||
default:
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case entitystate_dead:
|
||||
switch (newState)
|
||||
{
|
||||
case entitystate_idle:
|
||||
case entitystate_battle:
|
||||
case entitystate_attack:
|
||||
break;
|
||||
default:
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
}
|
||||
|
||||
entity->state = newState;
|
||||
@ -674,11 +772,10 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
||||
|
||||
INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt)
|
||||
{
|
||||
Entity *hero = &world->entities[world->heroIndex];
|
||||
for (i32 i = 0; i < world->freeEntityIndex; i++)
|
||||
{
|
||||
Entity *const entity = &world->entities[i];
|
||||
Entity *hero = &world->entities[world->heroIndex];
|
||||
|
||||
Entity *const entity = &world->entities[i];
|
||||
switch(entity->type)
|
||||
{
|
||||
case entitytype_mob:
|
||||
@ -696,7 +793,7 @@ INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt)
|
||||
|
||||
entityStateSwitch(world, entity, newState);
|
||||
}
|
||||
// NOTE(doyle): Allow fall through to entitytype_hero here
|
||||
// NOTE(doyle): Let entitytype_mob fall through to entitytype_hero here
|
||||
case entitytype_hero:
|
||||
{
|
||||
if (entity->state == entitystate_battle ||
|
||||
@ -728,8 +825,11 @@ INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DENGINE_DEBUG
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
// TODO(doyle): Generalise for all entities
|
||||
hero->stats->entityIdToAttack = -1;
|
||||
hero->stats->entityIdToAttack = ENTITY_NULL_ID;
|
||||
hero->state = entitystate_idle;
|
||||
entity->state = entitystate_dead;
|
||||
}
|
||||
@ -740,38 +840,37 @@ INTERNAL void updateEntityAndRender(Renderer *renderer, World *world, f32 dt)
|
||||
break;
|
||||
}
|
||||
|
||||
if (world->numEntitiesInBattle > 0)
|
||||
{
|
||||
if (hero->state == entitystate_idle)
|
||||
{
|
||||
hero->state = entitystate_battle;
|
||||
world->entityIdInBattle[hero->id] = TRUE;
|
||||
}
|
||||
|
||||
if (hero->stats->entityIdToAttack == -1)
|
||||
hero->stats->entityIdToAttack = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hero->state == entitystate_battle)
|
||||
{
|
||||
hero->state = entitystate_idle;
|
||||
world->entityIdInBattle[hero->id] = FALSE;
|
||||
setActiveEntityAnim(hero, animlist_hero_idle);
|
||||
}
|
||||
hero->stats->entityIdToAttack = -1;
|
||||
hero->stats->actionTimer = hero->stats->actionRate;
|
||||
hero->stats->busyDuration = 0;
|
||||
}
|
||||
|
||||
updateEntityAnim(entity, dt);
|
||||
|
||||
/* Calculate region to render */
|
||||
v4 cameraBounds = createCameraBounds(world, renderer->size);
|
||||
renderer_entity(renderer, cameraBounds, entity, 0, V4(1, 1, 1, 1));
|
||||
}
|
||||
|
||||
if (world->numEntitiesInBattle > 0)
|
||||
{
|
||||
// NOTE(doyle): If battle entities is 1 then only the hero is left
|
||||
if (hero->state == entitystate_battle &&
|
||||
world->numEntitiesInBattle == 1)
|
||||
entityStateSwitch(world, hero, entitystate_idle);
|
||||
else
|
||||
entityStateSwitch(world, hero, entitystate_battle);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hero->state == entitystate_battle)
|
||||
{
|
||||
hero->state = entitystate_idle;
|
||||
world->entityIdInBattle[hero->id] = FALSE;
|
||||
setActiveEntityAnim(hero, animlist_hero_idle);
|
||||
}
|
||||
hero->stats->entityIdToAttack = -1;
|
||||
hero->stats->actionTimer = hero->stats->actionRate;
|
||||
hero->stats->busyDuration = 0;
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_PERSIST b32 count = 0;
|
||||
void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
||||
{
|
||||
/* Update */
|
||||
@ -802,8 +901,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
||||
f32 strLenInPixels =
|
||||
CAST(f32)(font->maxSize.w * common_strlen(heroAvatarStr));
|
||||
v2 strPos = V2(heroAvatarP.x, heroAvatarP.y - (0.5f * heroAvatarSize.h));
|
||||
renderer_staticString(&state->renderer, font, heroAvatarStr, strPos, 0,
|
||||
V4(0, 0, 1, 1));
|
||||
renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr,
|
||||
strPos, 0, V4(0, 0, 1, 1));
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
debug_drawUi(state, dt);
|
||||
|
@ -78,14 +78,15 @@ int main()
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
debug_init();
|
||||
#endif
|
||||
|
||||
GameState worldTraveller = {0};
|
||||
worldTraveller_gameInit(&worldTraveller,
|
||||
V2i(frameBufferWidth, frameBufferHeight));
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
debug_init(&worldTraveller.arena, V2i(windowWidth, windowHeight),
|
||||
worldTraveller.assetManager.font);
|
||||
#endif
|
||||
|
||||
glfwSetWindowUserPointer(window, CAST(void *)(&worldTraveller));
|
||||
|
||||
f32 startTime = CAST(f32)(glfwGetTime());
|
||||
|
@ -2,8 +2,10 @@
|
||||
#define DENGINE_ASSET_MANAGER_H
|
||||
|
||||
#include "Dengine/Assets.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/Shader.h"
|
||||
#include "Dengine/Texture.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
|
||||
#define MAX_TEXTURE_SIZE 1024
|
||||
|
||||
@ -29,12 +31,13 @@ const i32 asset_loadTextureImage(AssetManager *assetManager,
|
||||
const char *const path,
|
||||
const enum TexList type);
|
||||
|
||||
const i32 asset_loadShaderFiles(AssetManager *assetManager,
|
||||
const i32 asset_loadShaderFiles(AssetManager *assetManager, MemoryArena *arena,
|
||||
const char *const vertexPath,
|
||||
const char *const fragmentPath,
|
||||
const enum ShaderList type);
|
||||
|
||||
const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath);
|
||||
const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
||||
const char *filePath);
|
||||
|
||||
inline i32 asset_getVFontSpacing(FontMetrics metrics)
|
||||
{
|
||||
@ -43,8 +46,8 @@ inline i32 asset_getVFontSpacing(FontMetrics metrics)
|
||||
return result;
|
||||
}
|
||||
|
||||
void asset_addAnimation(AssetManager *assetManager, i32 texId,
|
||||
i32 animId, i32 *atlasIndexes, i32 numFrames,
|
||||
f32 frameDuration);
|
||||
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
||||
i32 texId, i32 animId, i32 *atlasIndexes, i32 numFrames,
|
||||
f32 frameDuration);
|
||||
|
||||
#endif
|
||||
|
@ -28,5 +28,6 @@ typedef double f64;
|
||||
|
||||
i32 common_strlen(const char *const string);
|
||||
i32 common_strcmp(const char *a, const char *b);
|
||||
void common_itoa(i32 value, char *buf, i32 bufSize);
|
||||
|
||||
#endif
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "WorldTraveller/WorldTraveller.h"
|
||||
|
||||
#define INVALID_CODE_PATH TRUE
|
||||
#define INVALID_CODE_PATH 0
|
||||
enum DebugCallCount
|
||||
{
|
||||
debugcallcount_drawArrays,
|
||||
@ -18,19 +18,22 @@ enum DebugCallCount
|
||||
|
||||
typedef struct DebugState
|
||||
{
|
||||
i32 totalMemoryAllocated;
|
||||
Font font;
|
||||
i32 *callCount;
|
||||
f32 stringLineGap;
|
||||
|
||||
/* Debug strings rendered in top left corner */
|
||||
char debugStrings[256][64];
|
||||
char debugStrings[64][128];
|
||||
i32 numDebugStrings;
|
||||
f32 stringUpdateTimer;
|
||||
f32 stringUpdateRate;
|
||||
v2 initialStringP;
|
||||
v2 currStringP;
|
||||
|
||||
v2 initialStringPos;
|
||||
v2 stringPos;
|
||||
|
||||
f32 stringLineGap;
|
||||
/* Debug gui console log */
|
||||
char console[20][128];
|
||||
i32 consoleIndex;
|
||||
v2 initialConsoleP;
|
||||
} DebugState;
|
||||
|
||||
extern DebugState GLOBAL_debug;
|
||||
@ -97,14 +100,16 @@ inline char *debug_entityattack_string(i32 val)
|
||||
}
|
||||
|
||||
|
||||
void debug_init();
|
||||
void debug_init(MemoryArena *arena, v2 windowSize, Font font);
|
||||
|
||||
#define DEBUG_PUSH_STRING(string) debug_pushString(string, NULL, "char")
|
||||
#define DEBUG_PUSH_VAR(formatString, data, type) \
|
||||
debug_pushString(formatString, CAST(void *)&data, type)
|
||||
void debug_pushString(char *formatString, void *data, char *dataType);
|
||||
|
||||
void debug_stringUpdateAndRender(Renderer *renderer, Font *font, f32 dt);
|
||||
void debug_drawUi(GameState *state, f32 dt);
|
||||
|
||||
#define DEBUG_LOG(string) debug_consoleLog(string, __FILE__, __LINE__);
|
||||
void debug_consoleLog(char *string, char *file, int lineNum);
|
||||
|
||||
#endif
|
||||
|
@ -65,7 +65,7 @@ typedef struct EntityAnim_
|
||||
|
||||
typedef struct Entity
|
||||
{
|
||||
u32 id;
|
||||
i32 id;
|
||||
|
||||
v2 pos; // Position
|
||||
v2 dPos; // Velocity
|
||||
|
9
src/include/Dengine/MemoryArena.h
Normal file
9
src/include/Dengine/MemoryArena.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef DENGINE_MEMORY_ARENA_H
|
||||
#define DENGINE_MEMORY_ARENA_H
|
||||
|
||||
typedef struct MemoryArena
|
||||
{
|
||||
i32 bytesAllocated;
|
||||
} MemoryArena;
|
||||
|
||||
#endif
|
@ -2,6 +2,7 @@
|
||||
#define DENGINE_PLATFORM_H
|
||||
|
||||
#include "Dengine/Common.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
|
||||
typedef struct PlatformFileRead
|
||||
{
|
||||
@ -10,17 +11,17 @@ typedef struct PlatformFileRead
|
||||
} PlatformFileRead;
|
||||
|
||||
// TODO(doyle): Create own custom memory allocator
|
||||
#define PLATFORM_MEM_FREE(ptr, bytes) platform_memoryFree(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(void *data, i32 numBytes);
|
||||
void platform_memoryFree(MemoryArena *arena, void *data, i32 numBytes);
|
||||
|
||||
#define PLATFORM_MEM_ALLOC(num, type) CAST(type *) platform_memoryAlloc(num * sizeof(type))
|
||||
void *platform_memoryAlloc(i32 numBytes);
|
||||
#define PLATFORM_MEM_ALLOC(arena, num, type) CAST(type *) platform_memoryAlloc(arena, num * sizeof(type))
|
||||
void *platform_memoryAlloc(MemoryArena *arena, i32 numBytes);
|
||||
|
||||
void platform_closeFileRead(PlatformFileRead *file);
|
||||
i32 platform_readFileToBuffer(const char *const filePath,
|
||||
void platform_closeFileRead(MemoryArena *arena, PlatformFileRead *file);
|
||||
i32 platform_readFileToBuffer(MemoryArena *arena, const char *const filePath,
|
||||
PlatformFileRead *file);
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "Dengine/Entity.h"
|
||||
#include "Dengine/Math.h"
|
||||
#include "Dengine/Shader.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
|
||||
typedef struct Renderer
|
||||
{
|
||||
@ -36,18 +37,17 @@ inline void renderer_staticRect(Renderer *const renderer, v2 pos, v2 size,
|
||||
color);
|
||||
}
|
||||
|
||||
void renderer_string(Renderer *const renderer, MemoryArena *arena,
|
||||
v4 cameraBounds, Font *const font,
|
||||
const char *const string, v2 pos, f32 rotate, v4 color);
|
||||
|
||||
void renderer_string(Renderer *const renderer, v4 cameraBounds,
|
||||
Font *const font, const char *const string, v2 pos,
|
||||
f32 rotate, v4 color);
|
||||
|
||||
inline void renderer_staticString(Renderer *const renderer, Font *const font,
|
||||
const char *const string, v2 pos, f32 rotate,
|
||||
v4 color)
|
||||
inline void renderer_staticString(Renderer *const renderer, MemoryArena *arena,
|
||||
Font *const font, const char *const string,
|
||||
v2 pos, f32 rotate, v4 color)
|
||||
{
|
||||
v4 staticCameraBounds = math_getRect(V2(0, 0), renderer->size);
|
||||
renderer_string(renderer, staticCameraBounds, font, string, pos, rotate,
|
||||
color);
|
||||
renderer_string(renderer, arena, staticCameraBounds, font, string, pos,
|
||||
rotate, color);
|
||||
}
|
||||
|
||||
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Dengine/Common.h"
|
||||
#include "Dengine/Entity.h"
|
||||
#include "Dengine/Math.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
#include "Dengine/Renderer.h"
|
||||
|
||||
#define NUM_KEYS 1024
|
||||
@ -41,6 +42,7 @@ typedef struct GameState
|
||||
i32 tileSize;
|
||||
|
||||
AssetManager assetManager;
|
||||
MemoryArena arena;
|
||||
} GameState;
|
||||
|
||||
void worldTraveller_gameInit(GameState *state, v2 windowSize);
|
||||
|
Loading…
Reference in New Issue
Block a user