Additional debug string rendering infrastructure
Separate notion of rendering a static string, i.e. for debug display that is absolutely positioned, and rendering of a regular string that moves with the game camera.
This commit is contained in:
parent
d82afe49d0
commit
b1875077b7
@ -48,6 +48,15 @@ const i32 asset_loadTextureImage(AssetManager *assetManager,
|
||||
u8 *image =
|
||||
stbi_load(path, &imgWidth, &imgHeight, &bytesPerPixel, 0);
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
if (imgWidth != imgHeight)
|
||||
{
|
||||
printf(
|
||||
"worldTraveller_gameInit() warning: Sprite sheet is not square: "
|
||||
"%dx%dpx\n", imgWidth, imgHeight);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!image)
|
||||
{
|
||||
printf("stdbi_load() failed: %s\n", stbi_failure_reason());
|
||||
|
@ -58,8 +58,8 @@ void debug_stringUpdateAndRender(Renderer *renderer, Font *font, f32 dt)
|
||||
{
|
||||
f32 rotate = 0;
|
||||
v4 color = V4(0, 0, 0, 1);
|
||||
renderer_string(renderer, font, GLOBAL_debugState.debugStrings[i],
|
||||
GLOBAL_debugState.stringPos, rotate, color);
|
||||
renderer_staticString(renderer, font, GLOBAL_debugState.debugStrings[i],
|
||||
GLOBAL_debugState.stringPos, rotate, color);
|
||||
GLOBAL_debugState.stringPos.y -=
|
||||
(0.9f * GLOBAL_debugState.stringLineGap);
|
||||
}
|
||||
|
@ -18,50 +18,65 @@ INTERNAL void updateBufferObject(Renderer *const renderer,
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
void renderer_string(Renderer *const renderer, 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)
|
||||
{
|
||||
i32 quadIndex = 0;
|
||||
i32 strLen = common_strlen(string);
|
||||
RenderQuad *stringQuads = PLATFORM_MEM_ALLOC(strLen, RenderQuad);
|
||||
|
||||
f32 baseline = pos.y;
|
||||
for (i32 i = 0; i < strLen; i++)
|
||||
i32 strLen = common_strlen(string);
|
||||
// TODO(doyle): Slightly incorrect string length in pixels calculation,
|
||||
// because we use the advance metric of each character for length not
|
||||
// maximum character size in rendering
|
||||
v2 rightAlignedP =
|
||||
v2_add(pos, V2((CAST(f32) font->maxSize.w * CAST(f32) strLen),
|
||||
CAST(f32) font->maxSize.h));
|
||||
v2 leftAlignedP = pos;
|
||||
if ((leftAlignedP.x < cameraBounds.z && rightAlignedP.x >= cameraBounds.x) &&
|
||||
(leftAlignedP.y < cameraBounds.y && rightAlignedP.y >= cameraBounds.w))
|
||||
{
|
||||
// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint to
|
||||
// its actual atlas index, i.e. we skip the first 31 glyphs
|
||||
i32 codepoint = string[i];
|
||||
i32 relativeIndex = codepoint - font->codepointRange.x;
|
||||
CharMetrics charMetric = font->charMetrics[relativeIndex];
|
||||
pos.y = baseline - charMetric.offset.y;
|
||||
i32 quadIndex = 0;
|
||||
RenderQuad *stringQuads = PLATFORM_MEM_ALLOC(strLen, RenderQuad);
|
||||
|
||||
const v4 charRectOnScreen = getRect(
|
||||
pos, V2(CAST(f32) font->maxSize.w, CAST(f32) font->maxSize.h));
|
||||
v2 offsetFromCamOrigin = V2(cameraBounds.x, cameraBounds.w);
|
||||
v2 entityRelativeToCamera = v2_sub(pos, offsetFromCamOrigin);
|
||||
|
||||
pos.x += charMetric.advance;
|
||||
|
||||
/* Get texture out */
|
||||
v4 charTexRect = font->atlas->texRect[relativeIndex];
|
||||
renderer_flipTexCoord(&charTexRect, FALSE, TRUE);
|
||||
pos = entityRelativeToCamera;
|
||||
f32 baseline = pos.y;
|
||||
for (i32 i = 0; i < strLen; i++)
|
||||
{
|
||||
// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint
|
||||
// to
|
||||
// its actual atlas index, i.e. we skip the first 31 glyphs
|
||||
i32 codepoint = string[i];
|
||||
i32 relativeIndex = codepoint - font->codepointRange.x;
|
||||
CharMetrics charMetric = font->charMetrics[relativeIndex];
|
||||
pos.y = baseline - charMetric.offset.y;
|
||||
|
||||
RenderQuad charQuad = renderer_createQuad(renderer, charRectOnScreen,
|
||||
charTexRect, font->tex);
|
||||
stringQuads[quadIndex++] = charQuad;
|
||||
const v4 charRectOnScreen = getRect(
|
||||
pos, V2(CAST(f32) font->maxSize.w, CAST(f32) font->maxSize.h));
|
||||
|
||||
pos.x += charMetric.advance;
|
||||
|
||||
/* Get texture out */
|
||||
v4 charTexRect = font->atlas->texRect[relativeIndex];
|
||||
renderer_flipTexCoord(&charTexRect, FALSE, TRUE);
|
||||
|
||||
RenderQuad charQuad = renderer_createQuad(
|
||||
renderer, charRectOnScreen, charTexRect, font->tex);
|
||||
stringQuads[quadIndex++] = charQuad;
|
||||
}
|
||||
|
||||
// NOTE(doyle): We render at the renderer's size because we create quads
|
||||
// relative to the window size, hence we also render at the origin since
|
||||
// we're rendering a window sized buffer
|
||||
updateBufferObject(renderer, stringQuads, quadIndex);
|
||||
renderer_object(renderer, V2(0.0f, 0.0f), renderer->size, rotate, color,
|
||||
font->tex);
|
||||
PLATFORM_MEM_FREE(stringQuads, strLen * sizeof(RenderQuad));
|
||||
}
|
||||
|
||||
// NOTE(doyle): We render at the renderer's size because we create quads
|
||||
// relative to the window size, hence we also render at the origin since
|
||||
// we're rendering a window sized buffer
|
||||
updateBufferObject(renderer, stringQuads, quadIndex);
|
||||
renderer_object(renderer, V2(0.0f, 0.0f), renderer->size, rotate, color,
|
||||
font->tex);
|
||||
PLATFORM_MEM_FREE(stringQuads, strLen * sizeof(RenderQuad));
|
||||
|
||||
}
|
||||
|
||||
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity, f32 dt, f32 rotate,
|
||||
v4 color)
|
||||
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
|
||||
f32 dt, f32 rotate, v4 color)
|
||||
{
|
||||
// TODO(doyle): Batch into render groups
|
||||
|
||||
@ -101,7 +116,6 @@ void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity, f32 dt
|
||||
renderer_object(renderer, entityRelativeToCamera, entity->size, rotate,
|
||||
color, entity->tex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v4 color,
|
||||
|
@ -201,23 +201,13 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
||||
heroWalkRects[2] = V4(849.0f, 1018.0f, 904.0f, 920.0f);
|
||||
addAnim(hero, heroWalkRects, numRects, duration);
|
||||
|
||||
Texture *heroSheet = hero->tex;
|
||||
v2 sheetSize = V2(CAST(f32) heroSheet->width, CAST(f32) heroSheet->height);
|
||||
if (sheetSize.x != sheetSize.y)
|
||||
{
|
||||
printf(
|
||||
"worldTraveller_gameInit() warning: Sprite sheet is not square: "
|
||||
"%dx%dpx\n",
|
||||
CAST(i32) sheetSize.w, CAST(i32) sheetSize.h);
|
||||
}
|
||||
|
||||
/* Create a NPC */
|
||||
pos = V2(300.0f, 300.0f);
|
||||
pos = V2((renderer->size.w / 3.0f), CAST(f32) state->tileSize);
|
||||
size = hero->size;
|
||||
type = entitytype_hero;
|
||||
type = entitytype_npc;
|
||||
dir = direction_null;
|
||||
tex = hero->tex;
|
||||
collides = TRUE;
|
||||
collides = FALSE;
|
||||
Entity *npc = addEntity(world, pos, size, type, dir, tex, collides);
|
||||
|
||||
/* Add npc waving animation */
|
||||
@ -228,6 +218,32 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
||||
npcWavingRects[1] = V4(944.0f, 812.0f, 1010.0f, 710.0f);
|
||||
addAnim(npc, npcWavingRects, numRects, duration);
|
||||
|
||||
/* Create a Mob */
|
||||
pos = V2(renderer->size.w - (renderer->size.w / 3.0f),
|
||||
CAST(f32) state->tileSize);
|
||||
size = hero->size;
|
||||
type = entitytype_mob;
|
||||
dir = direction_west;
|
||||
tex = hero->tex;
|
||||
collides = TRUE;
|
||||
Entity *mob = addEntity(world, pos, size, type, dir, tex, collides);
|
||||
|
||||
/* Add mob idle animation */
|
||||
duration = 1.0f;
|
||||
numRects = 1;
|
||||
v4 *mobIdleRects = PLATFORM_MEM_ALLOC(numRects, v4);
|
||||
mobIdleRects[0] = heroIdleRects[0];
|
||||
addAnim(mob, mobIdleRects, numRects, duration);
|
||||
|
||||
/* Add mob walking animation */
|
||||
duration = 0.10f;
|
||||
numRects = 3;
|
||||
v4 *mobWalkRects = PLATFORM_MEM_ALLOC(numRects, v4);
|
||||
mobWalkRects[0] = heroWalkRects[0];
|
||||
mobWalkRects[1] = heroWalkRects[1];
|
||||
mobWalkRects[2] = heroWalkRects[2];
|
||||
addAnim(mob, mobWalkRects, numRects, duration);
|
||||
|
||||
}
|
||||
|
||||
INTERNAL void parseInput(GameState *state, const f32 dt)
|
||||
@ -406,18 +422,63 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
||||
|
||||
if (cameraBounds.w <= world->bounds.w) cameraBounds.w = world->bounds.w;
|
||||
|
||||
Font *font = &assetManager->font;
|
||||
for (i32 i = 0; i < world->freeEntityIndex; i++)
|
||||
{
|
||||
Entity *const entity = &world->entities[i];
|
||||
renderer_entity(&state->renderer, cameraBounds, entity, dt, 0.0f,
|
||||
V4(1, 1, 1, 1));
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
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->size);
|
||||
i32 indexOfLowerAInMetrics = 'a' - font->codepointRange.x;
|
||||
strPos.y += font->charMetrics[indexOfLowerAInMetrics].offset.y;
|
||||
|
||||
renderer_string(&state->renderer, cameraBounds, font, debugString,
|
||||
strPos, 0, color);
|
||||
|
||||
f32 stringLineGap = 1.1f * asset_getVFontSpacing(font->metrics);
|
||||
strPos.y -= GLOBAL_debugState.stringLineGap;
|
||||
|
||||
char entityPosStr[256];
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// TODO(doyle): Clean up lines
|
||||
// Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }
|
||||
|
||||
#ifdef DENGINE_DEBUG
|
||||
Font *font = &assetManager->font;
|
||||
Entity *hero = &world->entities[world->heroIndex];
|
||||
DEBUG_PUSH_STRING("Hero Pos: %06.2f, %06.2f", &hero->pos, "v2");
|
||||
DEBUG_PUSH_STRING("Hero dPos: %06.2f, %06.2f", &hero->dPos, "v2");
|
||||
|
@ -19,6 +19,7 @@ enum EntityType
|
||||
entitytype_null,
|
||||
entitytype_hero,
|
||||
entitytype_npc,
|
||||
entitytype_mob,
|
||||
entitytype_tile,
|
||||
entitytype_count,
|
||||
};
|
||||
|
@ -19,8 +19,17 @@ typedef struct RenderQuad
|
||||
v4 vertex[4];
|
||||
} RenderQuad;
|
||||
|
||||
void renderer_string(Renderer *const renderer, 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)
|
||||
{
|
||||
renderer_string(renderer, V4(0, renderer->size.h, renderer->size.w, 0),
|
||||
font, string, pos, rotate, color);
|
||||
}
|
||||
|
||||
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
|
||||
f32 dt, f32 rotate, v4 color);
|
||||
|
Loading…
Reference in New Issue
Block a user