From e638724c758013a850cfec3cefe39dc9d394dd9f Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Sat, 25 Jun 2016 21:23:15 +1000 Subject: [PATCH] Add tile grid and atlas concept to game --- src/AssetManager.c | 10 +++- src/Renderer.c | 20 ++++++-- src/WorldTraveller.c | 56 ++++++++++++++++++++- src/dengine.c | 5 +- src/include/Dengine/AssetManager.h | 16 ++++++ src/include/Dengine/Entity.h | 1 - src/include/Dengine/Renderer.h | 3 ++ src/include/WorldTraveller/WorldTraveller.h | 17 ++++++- 8 files changed, 114 insertions(+), 14 deletions(-) diff --git a/src/AssetManager.c b/src/AssetManager.c index 282d5b3..1c00ee8 100644 --- a/src/AssetManager.c +++ b/src/AssetManager.c @@ -8,14 +8,20 @@ GLOBAL_VAR AssetManager assetManager; Texture *asset_getTexture(const enum TexList type) { - // NOTE(doyle): Since we're using a map, the count of an object can - // only be 1 or 0 if (type < texlist_count) return &assetManager.textures[type]; return NULL; } +TexAtlas *asset_getTextureAtlas(const enum TexList type) +{ + if (type < texlist_count) + return &assetManager.texAtlas[type]; + + return NULL; +} + const i32 asset_loadTextureImage(const char *const path, const enum TexList type) { /* Open the texture image */ diff --git a/src/Renderer.c b/src/Renderer.c index a5fbf24..323f6d8 100644 --- a/src/Renderer.c +++ b/src/Renderer.c @@ -2,16 +2,23 @@ #include void renderer_entity(Renderer *renderer, Entity *entity, f32 rotate, v3 color) +{ + renderer_object(renderer, entity->pos, entity->size, rotate, color, + entity->tex); +} + +void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v3 color, + Texture *tex) { shader_use(renderer->shader); - mat4 transMatrix = mat4_translate(entity->pos.x, entity->pos.y, 0.0f); + mat4 transMatrix = mat4_translate(pos.x, pos.y, 0.0f); mat4 rotateMatrix = mat4_rotate(rotate, 0.0f, 0.0f, 1.0f); // NOTE(doyle): We draw everything as a unit square in OGL. Scale it to size // TODO(doyle): We should have a notion of hitbox size and texture size // we're going to render so we can draw textures that may be bigger than the // entity, (slightly) but keep a consistent bounding box - mat4 scaleMatrix = mat4_scale(entity->size.x, entity->size.y, 1.0f); + mat4 scaleMatrix = mat4_scale(size.x, size.y, 1.0f); mat4 model = mat4_mul(transMatrix, mat4_mul(rotateMatrix, scaleMatrix)); shader_uniformSetMat4fv(renderer->shader, "model", model); @@ -21,9 +28,12 @@ void renderer_entity(Renderer *renderer, Entity *entity, f32 rotate, v3 color) // this->shader->uniformSetVec3f("spriteColor", color); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, entity->tex->id); - shader_uniformSet1i(renderer->shader, "tex", 0); - glCheckError(); + + if (tex) + { + glBindTexture(GL_TEXTURE_2D, tex->id); + shader_uniformSet1i(renderer->shader, "tex", 0); + } glBindVertexArray(renderer->vao); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/src/WorldTraveller.c b/src/WorldTraveller.c index 405517f..bd7b9f6 100644 --- a/src/WorldTraveller.c +++ b/src/WorldTraveller.c @@ -32,11 +32,45 @@ void worldTraveller_gameInit(GameState *state) /* Initialise assets */ asset_loadTextureImage( "data/textures/WorldTraveller/TerraSprite1024.png", texlist_hero); + + asset_loadTextureImage( + "data/textures/WorldTraveller/Terrain.png", texlist_terrain); + TexAtlas *terrainAtlas = asset_getTextureAtlas(texlist_terrain); + f32 atlasTileSize = 128.0f; + terrainAtlas->texRect[terraincoords_ground] = + V4(384.0f, 512.0f, 384.0f + atlasTileSize, 512.0f + atlasTileSize); + asset_loadShaderFiles("data/shaders/sprite.vert.glsl", "data/shaders/sprite.frag.glsl", shaderlist_sprite); glCheckError(); - state->state = state_active; + state->state = state_active; + state->tileSize = 32; + state->currWorldIndex = 0; + + /* Init world tiles */ + i32 highestSquaredValue = 1; + while (squared(highestSquaredValue) < ARRAY_COUNT(state->world[0].tiles)) + highestSquaredValue++; + + 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[i].texType = texlist_terrain; + world[i].tiles[packedDimension].pos = + V2(CAST(f32) x, CAST(f32) y); + } + } + } /* Init hero */ Entity heroEnt = {V2(0.0f, 0.0f), @@ -268,9 +302,27 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt) parseInput(state, dt); glCheckError(); + World *world = &state->world[state->currWorldIndex]; + TexAtlas *worldAtlas = asset_getTextureAtlas(world->texType); + Texture *worldTex = asset_getTexture(world->texType); + + f32 ndcFactor = 1.0f / CAST(f32)worldTex->width; + for (i32 i = 0; i < ARRAY_COUNT(world->tiles); i++) + { + Tile tile = world->tiles[i]; + v2 tileSize = V2(CAST(f32)state->tileSize, CAST(f32)state->tileSize); + v2 tilePosInPixel = v2_scale(tile.pos, tileSize.x); + + v4 texNDC = + v4_scale(worldAtlas->texRect[terraincoords_ground], ndcFactor); + updateBufferObject(state->renderer.vbo, texNDC); + renderer_object(&state->renderer, tilePosInPixel, tileSize, 0.0f, + V3(0, 0, 0), worldTex); + } + // NOTE(doyle): Factor to normalise sprite sheet rect coords to -1, 1 Entity *hero = &state->entityList[state->heroIndex]; - f32 ndcFactor = 1.0f / CAST(f32) hero->tex->width; + ndcFactor = 1.0f / CAST(f32) hero->tex->width; ASSERT(state->freeEntityIndex < ARRAY_COUNT(state->entityList)); for (i32 i = 0; i < state->freeEntityIndex; i++) diff --git a/src/dengine.c b/src/dengine.c index 12f98e2..fdc37c7 100644 --- a/src/dengine.c +++ b/src/dengine.c @@ -80,7 +80,6 @@ int main() glCullFace(GL_BACK); GameState worldTraveller = {0}; - worldTraveller.state = state_active; worldTraveller.width = CAST(i32)frameBufferSize.x; worldTraveller.height = CAST(i32)frameBufferSize.y; @@ -94,7 +93,7 @@ int main() #if 0 // TODO(doyle): Get actual monitor refresh rate i32 monitorRefreshHz = 60; - f32 targetSecondsPerFrame = 1.0f / static_cast(monitorRefreshHz); + f32 targetSecondsPerFrame = 1.0f / CAST(f32)(monitorRefreshHz); #else // TODO(doyle): http://gafferongames.com/game-physics/fix-your-timestep/ // NOTE(doyle): Prevent glfwSwapBuffer until a vertical retrace has @@ -125,7 +124,7 @@ int main() // TODO(doyle): Busy waiting, should sleep while (secondsElapsed < targetSecondsPerFrame) { - endTime = static_cast(glfwGetTime()); + endTime = CAST(f32)(glfwGetTime()); secondsElapsed = endTime - startTime; } #endif diff --git a/src/include/Dengine/AssetManager.h b/src/include/Dengine/AssetManager.h index e0a528f..f4fafce 100644 --- a/src/include/Dengine/AssetManager.h +++ b/src/include/Dengine/AssetManager.h @@ -7,6 +7,7 @@ enum TexList { texlist_hero, + texlist_terrain, texlist_count, }; @@ -16,10 +17,24 @@ enum ShaderList shaderlist_count, }; +enum TerrainCoords +{ + terraincoords_ground, + terraincoords_count, +}; + +typedef struct TexAtlas +{ + // TODO(doyle): String hash based lookup + v4 texRect[16]; + +} TexAtlas; + // TODO(doyle): Switch to hash based lookup typedef struct AssetManager { Texture textures[256]; + TexAtlas texAtlas[256]; Shader shaders[256]; } AssetManager; @@ -27,6 +42,7 @@ extern AssetManager assetManager; /* Texture */ Texture *asset_getTexture(const enum TexList type); +TexAtlas *asset_getTextureAtlas(const enum TexList type); const i32 asset_loadTextureImage(const char *const path, const enum TexList type); diff --git a/src/include/Dengine/Entity.h b/src/include/Dengine/Entity.h index 0923d56..516addd 100644 --- a/src/include/Dengine/Entity.h +++ b/src/include/Dengine/Entity.h @@ -37,7 +37,6 @@ typedef struct Entity SpriteAnim anim[16]; i32 freeAnimIndex; i32 currAnimIndex; - } Entity; INTERNAL inline v4 getEntityScreenRect(Entity entity) diff --git a/src/include/Dengine/Renderer.h b/src/include/Dengine/Renderer.h index 39660ba..aba1f6d 100644 --- a/src/include/Dengine/Renderer.h +++ b/src/include/Dengine/Renderer.h @@ -15,4 +15,7 @@ typedef struct Renderer void renderer_entity(Renderer *renderer, Entity *entity, f32 rotate, v3 color); +void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v3 color, + Texture *tex); + #endif diff --git a/src/include/WorldTraveller/WorldTraveller.h b/src/include/WorldTraveller/WorldTraveller.h index 74229f3..36c36c1 100644 --- a/src/include/WorldTraveller/WorldTraveller.h +++ b/src/include/WorldTraveller/WorldTraveller.h @@ -12,9 +12,20 @@ enum State { state_active, state_menu, - state_win + state_win, }; +typedef struct Tile +{ + v2 pos; +} Tile; + +typedef struct World +{ + Tile tiles[2048]; + enum TexList texType; +} World; + typedef struct GameState { enum State state; @@ -24,6 +35,10 @@ typedef struct GameState Renderer renderer; i32 heroIndex; + World world[4]; + i32 currWorldIndex; + i32 tileSize; + // TODO(doyle): Make size of list dynamic Entity entityList[256]; i32 freeEntityIndex;