From c9fc34aee16e5cd13ab598af52d6969c7ade08f6 Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Fri, 8 Jul 2016 16:09:18 +1000 Subject: [PATCH] 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. --- src/AssetManager.c | 13 ++- src/Renderer.c | 75 +++++---------- src/WorldTraveller.c | 101 ++++++++++++-------- src/include/Dengine/Common.h | 4 + src/include/WorldTraveller/WorldTraveller.h | 20 ++-- 5 files changed, 110 insertions(+), 103 deletions(-) diff --git a/src/AssetManager.c b/src/AssetManager.c index 3d76b72..f979ee4 100644 --- a/src/AssetManager.c +++ b/src/AssetManager.c @@ -20,6 +20,10 @@ Texture *asset_getTexture(AssetManager *assetManager, const enum TexList type) if (type < texlist_count) return &assetManager->textures[type]; +#ifdef WT_DEBUG + ASSERT(INVALID_CODE_PATH); +#endif + return NULL; } @@ -28,6 +32,9 @@ TexAtlas *asset_getTextureAtlas(AssetManager *assetManager, const enum TexList t if (type < texlist_count) return &assetManager->texAtlas[type]; +#ifdef WT_DEBUG + ASSERT(INVALID_CODE_PATH); +#endif return NULL; } @@ -60,6 +67,9 @@ Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type) if (type < shaderlist_count) return &assetManager->shaders[type]; +#ifdef WT_DEBUG + ASSERT(INVALID_CODE_PATH); +#endif return NULL; } @@ -234,7 +244,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, const char *filePath) printf( "asset_loadTTFont() warning: The target font height creates a " "glyph sheet that exceeds the available space!"); - ASSERT(1); + + ASSERT(INVALID_CODE_PATH); } #endif diff --git a/src/Renderer.c b/src/Renderer.c index 9531e06..ca5f089 100644 --- a/src/Renderer.c +++ b/src/Renderer.c @@ -19,37 +19,6 @@ INTERNAL void updateBufferObject(Renderer *const renderer, 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, const char *const string, v2 pos, f32 rotate, 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, v3 color) { - SpriteAnim *anim = &entity->anim[entity->currAnimIndex]; - v4 texRect = anim->rect[anim->currRectIndex]; - - anim->currDuration -= dt; - if (anim->currDuration <= 0.0f) + if ((entity->pos.x < renderer->size.w && entity->pos.x >= 0) && + (entity->pos.y < renderer->size.h && entity->pos.y >= 0)) { - anim->currRectIndex++; - anim->currRectIndex = anim->currRectIndex % anim->numRects; - texRect = anim->rect[anim->currRectIndex]; - anim->currDuration = anim->duration; + SpriteAnim *anim = &entity->anim[entity->currAnimIndex]; + v4 texRect = anim->rect[anim->currRectIndex]; + + 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, diff --git a/src/WorldTraveller.c b/src/WorldTraveller.c index 1e1868e..9d30532 100644 --- a/src/WorldTraveller.c +++ b/src/WorldTraveller.c @@ -30,33 +30,59 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize) glCheckError(); state->state = state_active; - state->tileSize = 64; state->currWorldIndex = 0; + state->tileSize = 64; - /* Init world tiles */ - i32 highestSquaredValue = 1; - while (squared(highestSquaredValue) < ARRAY_COUNT(state->world[0].tiles)) - highestSquaredValue++; + /* Init world */ + const i32 targetWorldWidth = 500 * METERS_TO_PIXEL; + const i32 targetWorldHeight = 15 * METERS_TO_PIXEL; + 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 y = 0; y < worldSize; y++) - { - for (i32 x = 0; x < worldSize; x++) - { - i32 packedDimension = y * worldSize + x; - World *world = state->world; + World *const world = &state->world[i]; + world->maxEntities = 8192; + world->entities = + CAST(Entity *) calloc(world->maxEntities, sizeof(Entity)); + world->texType = texlist_terrain; - world[i].texType = texlist_terrain; - world[i].tiles[packedDimension].pos = - V2(CAST(f32) x, CAST(f32) y); + TexAtlas *const atlas = + asset_getTextureAtlas(assetManager, world->texType); + + 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 */ Entity heroEnt = {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.currAnimIndex = 0; - state->heroIndex = state->freeEntityIndex; - state->entityList[state->freeEntityIndex++] = heroEnt; - Entity *hero = &state->entityList[state->heroIndex]; + world->heroIndex = world->freeEntityIndex; + world->entities[world->freeEntityIndex++] = heroEnt; + Entity *hero = &world->entities[world->heroIndex]; Texture *heroSheet = hero->tex; v2 sheetSize = V2(CAST(f32)heroSheet->width, CAST(f32)heroSheet->height); @@ -114,7 +140,7 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize) 0, 0}; npcEnt.anim[npcEnt.freeAnimIndex++] = npcAnim; - state->entityList[state->freeEntityIndex++] = npcEnt; + world->entities[world->freeEntityIndex++] = npcEnt; /* Init 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 */ - Entity *hero = &state->entityList[state->heroIndex]; + World *const world = &state->world[state->currWorldIndex]; + Entity *hero = &world->entities[world->heroIndex]; v2 ddPos = V2(0, 0); if (state->keys[GLFW_KEY_SPACE]) @@ -203,7 +230,8 @@ INTERNAL void parseInput(GameState *state, const f32 dt) 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(absolute(hero->dPos.x), absolute(hero->dPos.y))); 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 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; 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; - Entity entity = state->entityList[i]; + if (i == world->heroIndex) continue; + Entity entity = world->entities[i]; if (entity.collides) { v4 heroRect = @@ -295,20 +325,13 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt) AssetManager *assetManager = &state->assetManager; Renderer *renderer = &state->renderer; - /* Render background tiles */ -#if 0 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 */ - ASSERT(state->freeEntityIndex < ARRAY_COUNT(state->entityList)); - for (i32 i = 0; i < state->freeEntityIndex; i++) + ASSERT(world->freeEntityIndex < world->maxEntities); + 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)); } @@ -323,7 +346,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt) Font *font = &assetManager->font; if (debugUpdateCounter <= 0) { - Entity *hero = &state->entityList[state->heroIndex]; + Entity *const hero = &world->entities[world->heroIndex]; snprintf(debugStrings[0], ARRAY_COUNT(debugStrings[0]), "Hero Pos: %06.2f,%06.2f", hero->pos.x, hero->pos.y); numDebugStrings++; @@ -333,7 +356,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt) numDebugStrings++; snprintf(debugStrings[2], ARRAY_COUNT(debugStrings[2]), - "FreeEntityIndex: %d", state->freeEntityIndex); + "FreeEntityIndex: %d", world->freeEntityIndex); numDebugStrings++; const f32 debugUpdateRate = 0.15f; diff --git a/src/include/Dengine/Common.h b/src/include/Dengine/Common.h index 2fc2742..7840bfe 100644 --- a/src/include/Dengine/Common.h +++ b/src/include/Dengine/Common.h @@ -28,4 +28,8 @@ typedef double f64; i32 common_strlen(const char *const string); +#ifdef WT_DEBUG +#define INVALID_CODE_PATH TRUE +#endif + #endif diff --git a/src/include/WorldTraveller/WorldTraveller.h b/src/include/WorldTraveller/WorldTraveller.h index 4c41f65..8d572e4 100644 --- a/src/include/WorldTraveller/WorldTraveller.h +++ b/src/include/WorldTraveller/WorldTraveller.h @@ -6,7 +6,7 @@ #include "Dengine/Renderer.h" #define NUM_KEYS 1024 -#define METERS_TO_PIXEL 100 +#define METERS_TO_PIXEL 64 enum State { @@ -15,15 +15,16 @@ enum State state_win, }; -typedef struct Tile -{ - v2 pos; -} Tile; - typedef struct World { - Tile tiles[2048]; + Entity *entities; + i32 maxEntities; + enum TexList texType; + + i32 heroIndex; + i32 freeEntityIndex; + } World; typedef struct GameState @@ -32,16 +33,11 @@ typedef struct GameState b32 keys[NUM_KEYS]; Renderer renderer; - i32 heroIndex; World world[4]; i32 currWorldIndex; i32 tileSize; - // TODO(doyle): Make size of list dynamic - Entity entityList[256]; - i32 freeEntityIndex; - AssetManager assetManager; } GameState;