Move rendering of tiles into rendering of entities

Downgraded background rendering to each tile individually (no batching)
temporarily such that we can render all entities in one function.
This commit is contained in:
Doyle Thai 2016-07-08 16:09:18 +10:00
parent 4b74bb9474
commit c9fc34aee1
5 changed files with 110 additions and 103 deletions

View File

@ -20,6 +20,10 @@ Texture *asset_getTexture(AssetManager *assetManager, const enum TexList type)
if (type < texlist_count) if (type < texlist_count)
return &assetManager->textures[type]; return &assetManager->textures[type];
#ifdef WT_DEBUG
ASSERT(INVALID_CODE_PATH);
#endif
return NULL; return NULL;
} }
@ -28,6 +32,9 @@ TexAtlas *asset_getTextureAtlas(AssetManager *assetManager, const enum TexList t
if (type < texlist_count) if (type < texlist_count)
return &assetManager->texAtlas[type]; return &assetManager->texAtlas[type];
#ifdef WT_DEBUG
ASSERT(INVALID_CODE_PATH);
#endif
return NULL; return NULL;
} }
@ -60,6 +67,9 @@ Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type)
if (type < shaderlist_count) if (type < shaderlist_count)
return &assetManager->shaders[type]; return &assetManager->shaders[type];
#ifdef WT_DEBUG
ASSERT(INVALID_CODE_PATH);
#endif
return NULL; return NULL;
} }
@ -234,7 +244,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath)
printf( printf(
"asset_loadTTFont() warning: The target font height creates a " "asset_loadTTFont() warning: The target font height creates a "
"glyph sheet that exceeds the available space!"); "glyph sheet that exceeds the available space!");
ASSERT(1);
ASSERT(INVALID_CODE_PATH);
} }
#endif #endif

View File

@ -19,37 +19,6 @@ INTERNAL void updateBufferObject(Renderer *const renderer,
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
#if 0
void renderer_backgroundTiles(Renderer *const renderer, const v2 tileSize,
World *const world, TexAtlas *const atlas,
Texture *const tex)
{
RenderQuad worldQuads[ARRAY_COUNT(world->tiles)] = {0};
i32 quadIndex = 0;
for (i32 i = 0; i < ARRAY_COUNT(world->tiles); i++)
{
Tile tile = world->tiles[i];
v2 tilePosInPixel = v2_scale(tile.pos, tileSize.x);
if ((tilePosInPixel.x < renderer->size.w && tilePosInPixel.x >= 0) &&
(tilePosInPixel.y < renderer->size.h && tilePosInPixel.y >= 0))
{
const v4 texRect = atlas->texRect[terraincoords_ground];
const v4 tileRect = getRect(tilePosInPixel, tileSize);
RenderQuad tileQuad =
renderer_createQuad(renderer, tileRect, texRect, tex);
worldQuads[quadIndex++] = tileQuad;
}
}
updateBufferObject(renderer, worldQuads, quadIndex);
renderer_object(renderer, V2(0.0f, 0.0f), renderer->size, 0.0f,
V3(0, 0, 0), tex);
}
#endif
void renderer_string(Renderer *const renderer, Font *const font, void renderer_string(Renderer *const renderer, Font *const font,
const char *const string, v2 pos, f32 rotate, const char *const string, v2 pos, f32 rotate,
v3 color) v3 color)
@ -114,29 +83,33 @@ void renderer_debugString(Renderer *const renderer, Font *const font,
void renderer_entity(Renderer *renderer, Entity *entity, f32 dt, f32 rotate, void renderer_entity(Renderer *renderer, Entity *entity, f32 dt, f32 rotate,
v3 color) v3 color)
{ {
SpriteAnim *anim = &entity->anim[entity->currAnimIndex]; if ((entity->pos.x < renderer->size.w && entity->pos.x >= 0) &&
v4 texRect = anim->rect[anim->currRectIndex]; (entity->pos.y < renderer->size.h && entity->pos.y >= 0))
anim->currDuration -= dt;
if (anim->currDuration <= 0.0f)
{ {
anim->currRectIndex++; SpriteAnim *anim = &entity->anim[entity->currAnimIndex];
anim->currRectIndex = anim->currRectIndex % anim->numRects; v4 texRect = anim->rect[anim->currRectIndex];
texRect = anim->rect[anim->currRectIndex];
anim->currDuration = anim->duration; anim->currDuration -= dt;
if (anim->currDuration <= 0.0f)
{
anim->currRectIndex++;
anim->currRectIndex = anim->currRectIndex % anim->numRects;
texRect = anim->rect[anim->currRectIndex];
anim->currDuration = anim->duration;
}
if (entity->direction == direction_east)
{
// NOTE(doyle): Flip the x coordinates to flip the tex
renderer_flipTexCoord(&texRect, TRUE, FALSE);
}
RenderQuad entityQuad =
renderer_createDefaultQuad(renderer, texRect, entity->tex);
updateBufferObject(renderer, &entityQuad, 1);
renderer_object(renderer, entity->pos, entity->size, rotate, color,
entity->tex);
} }
if (entity->direction == direction_east)
{
// NOTE(doyle): Flip the x coordinates to flip the tex
renderer_flipTexCoord(&texRect, TRUE, FALSE);
}
RenderQuad entityQuad =
renderer_createDefaultQuad(renderer, texRect, entity->tex);
updateBufferObject(renderer, &entityQuad, 1);
renderer_object(renderer, entity->pos, entity->size, rotate, color,
entity->tex);
} }
void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v3 color, void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v3 color,

View File

@ -30,33 +30,59 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
glCheckError(); glCheckError();
state->state = state_active; state->state = state_active;
state->tileSize = 64;
state->currWorldIndex = 0; state->currWorldIndex = 0;
state->tileSize = 64;
/* Init world tiles */ /* Init world */
i32 highestSquaredValue = 1; const i32 targetWorldWidth = 500 * METERS_TO_PIXEL;
while (squared(highestSquaredValue) < ARRAY_COUNT(state->world[0].tiles)) const i32 targetWorldHeight = 15 * METERS_TO_PIXEL;
highestSquaredValue++; v2i worldDimensionInTiles = V2i(targetWorldWidth / state->tileSize,
targetWorldHeight / state->tileSize);
const i32 worldSize = highestSquaredValue - 1;
// NOTE(doyle): Origin is center of the world
for (i32 i = 0; i < ARRAY_COUNT(state->world); i++) for (i32 i = 0; i < ARRAY_COUNT(state->world); i++)
{ {
for (i32 y = 0; y < worldSize; y++) World *const world = &state->world[i];
{ world->maxEntities = 8192;
for (i32 x = 0; x < worldSize; x++) world->entities =
{ CAST(Entity *) calloc(world->maxEntities, sizeof(Entity));
i32 packedDimension = y * worldSize + x; world->texType = texlist_terrain;
World *world = state->world;
world[i].texType = texlist_terrain; TexAtlas *const atlas =
world[i].tiles[packedDimension].pos = asset_getTextureAtlas(assetManager, world->texType);
V2(CAST(f32) x, CAST(f32) y);
for (i32 y = 0; y < worldDimensionInTiles.y; y++)
{
for (i32 x = 0; x < worldDimensionInTiles.x; x++)
{
#ifdef WT_DEBUG
ASSERT(worldDimensionInTiles.x * worldDimensionInTiles.y <
world->maxEntities);
#endif
world->texType = texlist_terrain;
Entity *entity = &world->entities[world->freeEntityIndex++];
entity->pos =
V2(CAST(f32) x * state->tileSize,
CAST(f32) y * state->tileSize);
entity->dPos = V2(0.0f, 0.0f);
entity->size =
V2(CAST(f32) state->tileSize, CAST(f32) state->tileSize);
entity->tex = asset_getTexture(assetManager, world->texType);
entity->collides = FALSE;
entity->freeAnimIndex = 0;
entity->currAnimIndex = 0;
SpriteAnim worldAnimIdle = {NULL, 1, 0, 1.0f, 1.0f};
worldAnimIdle.rect = (v4 *)calloc(1, sizeof(v4));
worldAnimIdle.rect[0] = atlas->texRect[terraincoords_ground];
entity->anim[entity->freeAnimIndex++] = worldAnimIdle;
} }
} }
} }
World *const world = &state->world[state->currWorldIndex];
/* Init hero */ /* Init hero */
Entity heroEnt = {V2(0.0f, 0.0f), Entity heroEnt = {V2(0.0f, 0.0f),
V2(0.0f, 0.0f), V2(0.0f, 0.0f),
@ -83,9 +109,9 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
heroEnt.anim[heroEnt.freeAnimIndex++] = heroAnimWalk; heroEnt.anim[heroEnt.freeAnimIndex++] = heroAnimWalk;
heroEnt.currAnimIndex = 0; heroEnt.currAnimIndex = 0;
state->heroIndex = state->freeEntityIndex; world->heroIndex = world->freeEntityIndex;
state->entityList[state->freeEntityIndex++] = heroEnt; world->entities[world->freeEntityIndex++] = heroEnt;
Entity *hero = &state->entityList[state->heroIndex]; Entity *hero = &world->entities[world->heroIndex];
Texture *heroSheet = hero->tex; Texture *heroSheet = hero->tex;
v2 sheetSize = V2(CAST(f32)heroSheet->width, CAST(f32)heroSheet->height); v2 sheetSize = V2(CAST(f32)heroSheet->width, CAST(f32)heroSheet->height);
@ -114,7 +140,7 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
0, 0,
0}; 0};
npcEnt.anim[npcEnt.freeAnimIndex++] = npcAnim; npcEnt.anim[npcEnt.freeAnimIndex++] = npcAnim;
state->entityList[state->freeEntityIndex++] = npcEnt; world->entities[world->freeEntityIndex++] = npcEnt;
/* Init renderer */ /* Init renderer */
Renderer *renderer = &state->renderer; Renderer *renderer = &state->renderer;
@ -168,7 +194,8 @@ INTERNAL void parseInput(GameState *state, const f32 dt)
f (t) = (a/2)*t^2 + v*t + p, where p is a constant, old position f (t) = (a/2)*t^2 + v*t + p, where p is a constant, old position
*/ */
Entity *hero = &state->entityList[state->heroIndex]; World *const world = &state->world[state->currWorldIndex];
Entity *hero = &world->entities[world->heroIndex];
v2 ddPos = V2(0, 0); v2 ddPos = V2(0, 0);
if (state->keys[GLFW_KEY_SPACE]) if (state->keys[GLFW_KEY_SPACE])
@ -203,7 +230,8 @@ INTERNAL void parseInput(GameState *state, const f32 dt)
ddPos = v2_scale(ddPos, 0.70710678118f); ddPos = v2_scale(ddPos, 0.70710678118f);
} }
f32 epsilon = 20.0f; // NOTE(doyle): Clipping threshold for snapping velocity to 0
f32 epsilon = 15.0f;
v2 epsilonDpos = v2_sub(V2(epsilon, epsilon), v2 epsilonDpos = v2_sub(V2(epsilon, epsilon),
V2(absolute(hero->dPos.x), absolute(hero->dPos.y))); V2(absolute(hero->dPos.x), absolute(hero->dPos.y)));
if (epsilonDpos.x >= 0.0f && epsilonDpos.y >= 0.0f) if (epsilonDpos.x >= 0.0f && epsilonDpos.y >= 0.0f)
@ -248,13 +276,15 @@ INTERNAL void parseInput(GameState *state, const f32 dt)
v2 dPos = v2_scale(hero->dPos, dt); v2 dPos = v2_scale(hero->dPos, dt);
v2 newHeroP = v2_add(v2_add(ddPosNew, dPos), hero->pos); v2 newHeroP = v2_add(v2_add(ddPosNew, dPos), hero->pos);
// TODO(doyle): Only check collision for entities within small bounding box
// of the hero
b32 heroCollided = FALSE; b32 heroCollided = FALSE;
if (hero->collides == TRUE) if (hero->collides == TRUE)
{ {
for (i32 i = 0; i < ARRAY_COUNT(state->entityList); i++) for (i32 i = 0; i < world->maxEntities; i++)
{ {
if (i == state->heroIndex) continue; if (i == world->heroIndex) continue;
Entity entity = state->entityList[i]; Entity entity = world->entities[i];
if (entity.collides) if (entity.collides)
{ {
v4 heroRect = v4 heroRect =
@ -295,20 +325,13 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
AssetManager *assetManager = &state->assetManager; AssetManager *assetManager = &state->assetManager;
Renderer *renderer = &state->renderer; Renderer *renderer = &state->renderer;
/* Render background tiles */
#if 0
World *const world = &state->world[state->currWorldIndex]; World *const world = &state->world[state->currWorldIndex];
TexAtlas *const worldAtlas =
asset_getTextureAtlas(assetManager, world->texType);
Texture *const worldTex = asset_getTexture(assetManager, world->texType);
v2 tileSize = (CAST(f32)state->tileSize.w, CAST(f32)state->tileSize.h);
renderer_backgroundTiles(&state->renderer, tileSize, world, atlas, tex);
#endif
/* Render entities */ /* Render entities */
ASSERT(state->freeEntityIndex < ARRAY_COUNT(state->entityList)); ASSERT(world->freeEntityIndex < world->maxEntities);
for (i32 i = 0; i < state->freeEntityIndex; i++) for (i32 i = 0; i < world->freeEntityIndex; i++)
{ {
Entity *const entity = &state->entityList[i]; Entity *const entity = &world->entities[i];
renderer_entity(&state->renderer, entity, dt, 0.0f, V3(0, 0, 0)); renderer_entity(&state->renderer, entity, dt, 0.0f, V3(0, 0, 0));
} }
@ -323,7 +346,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
Font *font = &assetManager->font; Font *font = &assetManager->font;
if (debugUpdateCounter <= 0) if (debugUpdateCounter <= 0)
{ {
Entity *hero = &state->entityList[state->heroIndex]; Entity *const hero = &world->entities[world->heroIndex];
snprintf(debugStrings[0], ARRAY_COUNT(debugStrings[0]), snprintf(debugStrings[0], ARRAY_COUNT(debugStrings[0]),
"Hero Pos: %06.2f,%06.2f", hero->pos.x, hero->pos.y); "Hero Pos: %06.2f,%06.2f", hero->pos.x, hero->pos.y);
numDebugStrings++; numDebugStrings++;
@ -333,7 +356,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
numDebugStrings++; numDebugStrings++;
snprintf(debugStrings[2], ARRAY_COUNT(debugStrings[2]), snprintf(debugStrings[2], ARRAY_COUNT(debugStrings[2]),
"FreeEntityIndex: %d", state->freeEntityIndex); "FreeEntityIndex: %d", world->freeEntityIndex);
numDebugStrings++; numDebugStrings++;
const f32 debugUpdateRate = 0.15f; const f32 debugUpdateRate = 0.15f;

View File

@ -28,4 +28,8 @@ typedef double f64;
i32 common_strlen(const char *const string); i32 common_strlen(const char *const string);
#ifdef WT_DEBUG
#define INVALID_CODE_PATH TRUE
#endif
#endif #endif

View File

@ -6,7 +6,7 @@
#include "Dengine/Renderer.h" #include "Dengine/Renderer.h"
#define NUM_KEYS 1024 #define NUM_KEYS 1024
#define METERS_TO_PIXEL 100 #define METERS_TO_PIXEL 64
enum State enum State
{ {
@ -15,15 +15,16 @@ enum State
state_win, state_win,
}; };
typedef struct Tile
{
v2 pos;
} Tile;
typedef struct World typedef struct World
{ {
Tile tiles[2048]; Entity *entities;
i32 maxEntities;
enum TexList texType; enum TexList texType;
i32 heroIndex;
i32 freeEntityIndex;
} World; } World;
typedef struct GameState typedef struct GameState
@ -32,16 +33,11 @@ typedef struct GameState
b32 keys[NUM_KEYS]; b32 keys[NUM_KEYS];
Renderer renderer; Renderer renderer;
i32 heroIndex;
World world[4]; World world[4];
i32 currWorldIndex; i32 currWorldIndex;
i32 tileSize; i32 tileSize;
// TODO(doyle): Make size of list dynamic
Entity entityList[256];
i32 freeEntityIndex;
AssetManager assetManager; AssetManager assetManager;
} GameState; } GameState;