diff --git a/src/AssetManager.c b/src/AssetManager.c index 5c0eaac..29f6090 100644 --- a/src/AssetManager.c +++ b/src/AssetManager.c @@ -22,6 +22,34 @@ #include "Dengine/OpenGL.h" #include "Dengine/Platform.h" +void asset_init(AssetManager *assetManager, MemoryArena_ *arena) +{ + i32 texAtlasEntries = 8; + assetManager->texAtlas.size = texAtlasEntries; + assetManager->texAtlas.entries = + memory_pushBytes(arena, texAtlasEntries * sizeof(HashTableEntry)); + + i32 animEntries = 1024; + assetManager->anims.size = animEntries; + assetManager->anims.entries = + memory_pushBytes(arena, animEntries * sizeof(HashTableEntry)); + + i32 texEntries = 32; + assetManager->textures.size = texEntries; + assetManager->textures.entries = + memory_pushBytes(arena, texEntries * sizeof(HashTableEntry)); + + /* Create empty 1x1 4bpp black texture */ + u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0); + Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex"); + *tex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap)); + + i32 audioEntries = 32; + assetManager->audio.size = audioEntries; + assetManager->audio.entries = + memory_pushBytes(arena, audioEntries * sizeof(HashTableEntry)); +} + /* ********************************* * Hash Table Operations diff --git a/src/Asteroid.c b/src/Asteroid.c index dd2ad5f..c6b42c8 100644 --- a/src/Asteroid.c +++ b/src/Asteroid.c @@ -1,32 +1,12 @@ #include "Dengine/Asteroid.h" #include "Dengine/Debug.h" -void initAssetManager(GameState *state) +INTERNAL void loadGameAssets(GameState *state) { AssetManager *assetManager = &state->assetManager; MemoryArena_ *arena = &state->persistentArena; - i32 texAtlasEntries = 8; - assetManager->texAtlas.size = texAtlasEntries; - assetManager->texAtlas.entries = - memory_pushBytes(arena, texAtlasEntries * sizeof(HashTableEntry)); - - i32 animEntries = 1024; - assetManager->anims.size = animEntries; - assetManager->anims.entries = - memory_pushBytes(arena, animEntries * sizeof(HashTableEntry)); - - { // Init texture assets - i32 texEntries = 32; - assetManager->textures.size = texEntries; - assetManager->textures.entries = - memory_pushBytes(arena, texEntries * sizeof(HashTableEntry)); - - /* Create empty 1x1 4bpp black texture */ - u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0); - Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex"); - *tex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap)); - + { // Init font assets i32 result = asset_loadTTFont(assetManager, arena, &state->transientArena, "C:/Windows/Fonts/Arialbd.ttf", "Arial", 15); @@ -43,12 +23,6 @@ void initAssetManager(GameState *state) } { // Init audio assets - - i32 audioEntries = 32; - assetManager->audio.size = audioEntries; - assetManager->audio.entries = - memory_pushBytes(arena, audioEntries * sizeof(HashTableEntry)); - i32 result = asset_loadVorbis(assetManager, arena, "data/audio/Asteroids/bang_large.ogg", "bang_large"); @@ -88,66 +62,6 @@ void initAssetManager(GameState *state) } } -void initRenderer(GameState *state, v2 windowSize) -{ - AssetManager *assetManager = &state->assetManager; - Renderer *renderer = &state->renderer; - renderer->size = windowSize; - - // NOTE(doyle): Value to map a screen coordinate to NDC coordinate - renderer->vertexNdcFactor = - V2(1.0f / renderer->size.w, 1.0f / renderer->size.h); - renderer->groupIndexForVertexBatch = -1; - - const mat4 projection = - mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f); - for (i32 i = 0; i < shaderlist_count; i++) - { - renderer->shaderList[i] = asset_getShader(assetManager, i); - shader_use(renderer->shaderList[i]); - shader_uniformSetMat4fv(renderer->shaderList[i], "projection", - projection); - GL_CHECK_ERROR(); - } - - renderer->activeShaderId = renderer->shaderList[shaderlist_default]; - GL_CHECK_ERROR(); - - /* Create buffers */ - glGenVertexArrays(ARRAY_COUNT(renderer->vao), renderer->vao); - glGenBuffers(ARRAY_COUNT(renderer->vbo), renderer->vbo); - GL_CHECK_ERROR(); - - // Bind buffers and configure vao, vao automatically intercepts - // glBindCalls and associates the state with that buffer for us - for (enum RenderMode mode = 0; mode < rendermode_count; mode++) - { - glBindVertexArray(renderer->vao[mode]); - glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo[mode]); - - glEnableVertexAttribArray(0); - u32 numVertexElements = 4; - u32 stride = sizeof(RenderVertex); - - glVertexAttribPointer(0, numVertexElements, GL_FLOAT, - GL_FALSE, stride, (GLvoid *)0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - - /* Unbind */ - GL_CHECK_ERROR(); - - // TODO(doyle): Lazy allocate render group capacity - renderer->groupCapacity = 4096; - for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++) - { - renderer->groups[i].vertexList = - memory_pushBytes(&state->persistentArena, - renderer->groupCapacity * sizeof(RenderVertex)); - } -} - #include #include v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations, @@ -434,19 +348,19 @@ INTERNAL void addAsteroidWithSpec(World *world, enum AsteroidSize asteroidSize, // generated // to float back into game space v2 newP = V2i(randX, randY); - if (math_pointInRect(topLeftQuadrant, newP)) + if (math_rect_contains_p(topLeftQuadrant, newP)) { newP.y += midpoint.y; } - else if (math_pointInRect(botLeftQuadrant, newP)) + else if (math_rect_contains_p(botLeftQuadrant, newP)) { newP.x -= midpoint.x; } - else if (math_pointInRect(topRightQuadrant, newP)) + else if (math_rect_contains_p(topRightQuadrant, newP)) { newP.y -= midpoint.y; } - else if (math_pointInRect(botRightQuadrant, newP)) + else if (math_rect_contains_p(botRightQuadrant, newP)) { newP.x += midpoint.x; } @@ -556,22 +470,11 @@ INTERNAL void deleteEntity(World *world, i32 entityIndex) world->entityList[--world->entityIndex] = emptyEntity; } -void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, - v2 windowSize, f32 dt) +INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt) { - MemoryIndex globalTransientArenaSize = - (MemoryIndex)((f32)memory->transientSize * 0.5f); - memory_arenaInit(&state->transientArena, memory->transient, - globalTransientArenaSize); - World *world = &state->world; - if (!state->init) + if (!world->init) { - srand((u32)time(NULL)); - initAssetManager(state); - initRenderer(state, windowSize); - audio_init(&state->audioManager); - world->pixelsPerMeter = 70.0f; MemoryIndex entityArenaSize = @@ -580,6 +483,10 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, u8 *arenaBase = state->transientArena.base + state->transientArena.size; memory_arenaInit(&world->entityArena, arenaBase, entityArenaSize); + world->camera.min = V2(0, 0); + world->camera.max = state->renderer.size; + world->worldSize = state->renderer.size; + { // Init null entity Entity *nullEntity = &world->entityList[world->entityIndex++]; nullEntity->id = world->entityIdCounter++; @@ -596,12 +503,12 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, } { // Init ship entity - Entity *ship = &world->entityList[world->entityIndex++]; - ship->id = world->entityIdCounter++; - ship->pos = V2(100, 100); - ship->size = V2(25.0f, 50.0f); - ship->hitbox = ship->size; - ship->offset = v2_scale(ship->size, -0.5f); + Entity *ship = &world->entityList[world->entityIndex++]; + ship->id = world->entityIdCounter++; + ship->pos = math_rect_get_centre(world->camera); + ship->size = V2(25.0f, 50.0f); + ship->hitbox = ship->size; + ship->offset = v2_scale(ship->size, -0.5f); ship->numVertexPoints = 3; ship->vertexPoints = memory_pushBytes( @@ -636,20 +543,20 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, entitytype_asteroid_large, TRUE); } - world->camera.min = V2(0, 0); - world->camera.max = state->renderer.size; - world->worldSize = windowSize; + world->init = TRUE; + world->onInitAsteroidSpawnTimer = 1.0f; - state->init = TRUE; - - Font *arial15 = asset_getFont(&state->assetManager, "Arial", 15); - debug_init(&state->persistentArena, windowSize, *arial15); } - for (u32 i = world->asteroidCounter; i < world->numAsteroids; i++) - addAsteroid(world, (rand() % asteroidsize_count)); - - platform_processInputBuffer(&state->input, dt); + if (world->onInitAsteroidSpawnTimer > 0) + { + world->onInitAsteroidSpawnTimer -= dt; + } + else + { + for (u32 i = world->asteroidCounter; i < world->numAsteroids; i++) + addAsteroid(world, (rand() % asteroidsize_count)); + } if (platform_queryKey(&state->input.keys[keycode_left_square_bracket], readkeytype_repeat, 0.2f)) @@ -804,7 +711,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, } else if (entity->type == entitytype_bullet) { - if (!math_pointInRect(world->camera, entity->pos)) + if (!math_rect_contains_p(world->camera, entity->pos)) { deleteEntity(world, i--); continue; @@ -991,39 +898,6 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, collideColor, flags); } - { // Draw Ui - UiState *uiState = &state->uiState; - MemoryArena_ *transientArena = &state->transientArena; - AssetManager *assetManager = &state->assetManager; - Renderer *renderer = &state->renderer; - InputBuffer *inputBuffer = &state->input; - - renderer_rect(renderer, world->camera, V2(0, 0), renderer->size, - V2(0, 0), 0, NULL, V4(0, 0, 0, 0.5f), - renderflag_no_texture); - - Font *arial15 = asset_getFontCreateSizeOnDemand( - assetManager, &state->persistentArena, transientArena, "Arial", 15); - Font *arial25 = asset_getFontCreateSizeOnDemand( - assetManager, &state->persistentArena, transientArena, "Arial", 40); - - v2 titleP = V2(20, renderer->size.h - 100); - renderer_staticString(renderer, transientArena, arial25, - "Asteroids", titleP, V2(0, 0), 0, V4(1, 0, 0, 1), - 0); - - userInterface_beginState(uiState); - - Rect buttonRect = {V2(20, 20), V2(40, 40)}; - -#if 1 - userInterface_button(uiState, transientArena, assetManager, renderer, - arial15, *inputBuffer, 0, buttonRect, - "test button"); -#endif - - userInterface_endState(uiState, inputBuffer); - } for (i32 i = 0; i < world->numAudioRenderers; i++) { @@ -1031,11 +905,94 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, audio_updateAndPlay(&state->transientArena, &state->audioManager, audioRenderer); } +} + +INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt) +{ + UiState *uiState = &state->uiState; + MemoryArena_ *transientArena = &state->transientArena; + AssetManager *assetManager = &state->assetManager; + Renderer *renderer = &state->renderer; + World *world = &state->world; + InputBuffer *inputBuffer = &state->input; + + Font *arial15 = asset_getFontCreateSizeOnDemand( + assetManager, &state->persistentArena, transientArena, "Arial", 15); + Font *arial25 = asset_getFontCreateSizeOnDemand( + assetManager, &state->persistentArena, transientArena, "Arial", 40); + + f32 margin = 20.0f; + f32 padding = 20.0f; + v2 titleP = V2(margin, renderer->size.h - 100 + margin); + renderer_staticString(renderer, transientArena, arial25, "Asteroids", + titleP, V2(0, 0), 0, V4(1, 0, 0, 1), 0); + + userInterface_beginState(uiState); + + Rect buttonRect = {0}; + buttonRect.min = V2(margin, margin); + buttonRect.max = V2(margin + 100, margin + 40); + buttonRect = math_rect_shift(buttonRect, V2(0, titleP.y - 100)); + if (userInterface_button(uiState, transientArena, assetManager, renderer, + arial15, *inputBuffer, 1, buttonRect, + "Start Game")) + { + state->appState = appstate_game; + } + + userInterface_endState(uiState, inputBuffer); +} + +void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, + v2 windowSize, f32 dt) +{ + MemoryIndex globalTransientArenaSize = + (MemoryIndex)((f32)memory->transientSize * 0.5f); + memory_arenaInit(&state->transientArena, memory->transient, + globalTransientArenaSize); + + if (!state->init) + { + srand((u32)time(NULL)); + asset_init(&state->assetManager, &state->persistentArena); + audio_init(&state->audioManager); + + // NOTE(doyle): Load game assets must be before init_renderer so that + // shaders are available for the renderer configuration + loadGameAssets(state); + renderer_init(&state->renderer, &state->assetManager, + &state->persistentArena, windowSize); + + Font *arial15 = asset_getFont(&state->assetManager, "Arial", 15); + debug_init(&state->persistentArena, windowSize, *arial15); + + state->appState = appstate_start_menu; + state->init = TRUE; + } + + platform_processInputBuffer(&state->input, dt); + + switch (state->appState) + { + case appstate_start_menu: + { + startMenuUpdate(state, memory, dt); + } + break; + + case appstate_game: + { + gameUpdate(state, memory, dt); + } + break; + + default: + { + ASSERT(INVALID_CODE_PATH); + } + break; + } -#if 1 debug_drawUi(state, dt); - debug_clearCounter(); -#endif - renderer_renderGroups(&state->renderer); } diff --git a/src/Debug.c b/src/Debug.c index f1e34fc..ecae6cd 100644 --- a/src/Debug.c +++ b/src/Debug.c @@ -95,12 +95,6 @@ void debug_countIncrement(i32 id) GLOBAL_debug.callCount[id]++; } -void debug_clearCounter() -{ - for (i32 i = 0; i < debugcount_num; i++) - GLOBAL_debug.callCount[i] = 0; -} - void debug_consoleLog(char *string, char *file, int lineNum) { @@ -260,7 +254,7 @@ INTERNAL void renderConsole(Renderer *renderer, MemoryArena_ *arena) for (i32 i = 0; i < maxConsoleLines; i++) { f32 rotate = 0; - v4 color = V4(0, 0, 0, 1); + v4 color = V4(1.0f, 1.0f, 1.0f, 1.0f); renderer_staticString(renderer, arena, &GLOBAL_debug.font, GLOBAL_debug.console[i], consoleStrP, V2(0, 0), rotate, color, 0); @@ -270,9 +264,6 @@ INTERNAL void renderConsole(Renderer *renderer, MemoryArena_ *arena) void debug_drawUi(GameState *state, f32 dt) { - updateAndRenderDebugStack(&state->renderer, &state->transientArena, dt); - renderConsole(&state->renderer, &state->transientArena); - { // Print Memory Arena Info DEBUG_PUSH_STRING("== MEMORY ARENAS =="); MemoryArena_ *transient = &state->transientArena; @@ -298,5 +289,10 @@ void debug_drawUi(GameState *state, f32 dt) DEBUG_PUSH_VAR("Num Vertex: %d", GLOBAL_debug.callCount[debugcount_numVertex], "i32"); - debug_clearCounter(); + updateAndRenderDebugStack(&state->renderer, &state->transientArena, dt); + renderConsole(&state->renderer, &state->transientArena); + + { // Clear debug call counters + for (i32 i = 0; i < debugcount_num; i++) GLOBAL_debug.callCount[i] = 0; + } } diff --git a/src/Renderer.c b/src/Renderer.c index 158b2d8..2ae70e8 100644 --- a/src/Renderer.c +++ b/src/Renderer.c @@ -8,6 +8,64 @@ #include "Dengine/Shader.h" #include "Dengine/Texture.h" +void renderer_init(Renderer *renderer, AssetManager *assetManager, + MemoryArena_ *persistentArena, v2 windowSize) +{ + renderer->size = windowSize; + // NOTE(doyle): Value to map a screen coordinate to NDC coordinate + renderer->vertexNdcFactor = + V2(1.0f / renderer->size.w, 1.0f / renderer->size.h); + renderer->groupIndexForVertexBatch = -1; + + const mat4 projection = + mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f); + for (i32 i = 0; i < shaderlist_count; i++) + { + renderer->shaderList[i] = asset_getShader(assetManager, i); + shader_use(renderer->shaderList[i]); + shader_uniformSetMat4fv(renderer->shaderList[i], "projection", + projection); + GL_CHECK_ERROR(); + } + + renderer->activeShaderId = renderer->shaderList[shaderlist_default]; + GL_CHECK_ERROR(); + + /* Create buffers */ + glGenVertexArrays(ARRAY_COUNT(renderer->vao), renderer->vao); + glGenBuffers(ARRAY_COUNT(renderer->vbo), renderer->vbo); + GL_CHECK_ERROR(); + + // Bind buffers and configure vao, vao automatically intercepts + // glBindCalls and associates the state with that buffer for us + for (enum RenderMode mode = 0; mode < rendermode_count; mode++) + { + glBindVertexArray(renderer->vao[mode]); + glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo[mode]); + + glEnableVertexAttribArray(0); + u32 numVertexElements = 4; + u32 stride = sizeof(RenderVertex); + + glVertexAttribPointer(0, numVertexElements, GL_FLOAT, + GL_FALSE, stride, (GLvoid *)0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + /* Unbind */ + GL_CHECK_ERROR(); + + // TODO(doyle): Lazy allocate render group capacity + renderer->groupCapacity = 4096; + for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++) + { + renderer->groups[i].vertexList = memory_pushBytes( + persistentArena, renderer->groupCapacity * sizeof(RenderVertex)); + } +} + + typedef struct RenderQuad { RenderVertex vertexList[4]; @@ -300,10 +358,10 @@ INTERNAL RenderQuad createRenderQuad(Renderer *renderer, v2 pos, v2 size, * */ - v4 vertexPair = {0}; - vertexPair.vec2[0] = pos; - vertexPair.vec2[1] = v2_add(pos, size); - v4 texRectNdc = getTexRectNormaliseDeviceCoords(renderTex); + v4 vertexPair = {0}; + vertexPair.vec2[0] = pos; + vertexPair.vec2[1] = v2_add(pos, size); + v4 texRectNdc = getTexRectNormaliseDeviceCoords(renderTex); // NOTE(doyle): Create a quad composed of 4 vertexes to be rendered as // a triangle strip using vertices v0, v1, v2, then v2, v1, v3 (note the @@ -548,8 +606,8 @@ void renderer_string(Renderer *const renderer, MemoryArena_ *arena, Rect camera, v2_add(pos, V2((CAST(f32) font->maxSize.w * CAST(f32) strLen), CAST(f32) font->maxSize.h)); v2 leftAlignedP = pos; - if (math_pointInRect(camera, leftAlignedP) || - math_pointInRect(camera, rightAlignedP)) + if (math_rect_contains_p(camera, leftAlignedP) || + math_rect_contains_p(camera, rightAlignedP)) { i32 vertexIndex = 0; i32 numVertexPerQuad = 4; @@ -659,6 +717,7 @@ void renderer_entity(Renderer *renderer, MemoryArena_ *transientArena, } } +// TODO(doyle): We have no notion of sort order!! void renderer_renderGroups(Renderer *renderer) { for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++) diff --git a/src/UserInterface.c b/src/UserInterface.c index 22de67a..624a5d9 100644 --- a/src/UserInterface.c +++ b/src/UserInterface.c @@ -34,7 +34,7 @@ i32 userInterface_button(UiState *const uiState, MemoryArena_ *const arena, const InputBuffer input, const i32 id, const Rect rect, const char *const label) { - if (math_pointInRect(rect, input.mouseP)) + if (math_rect_contains_p(rect, input.mouseP)) { uiState->hotItem = id; if (uiState->activeItem == 0) @@ -55,41 +55,39 @@ i32 userInterface_button(UiState *const uiState, MemoryArena_ *const arena, #endif v2 buttonOffset = V2(0, 0); - v4 buttonColor = V4(1, 1, 1, 1); + v4 buttonColor = V4(0, 0, 0, 1); if (uiState->hotItem == id) { if (uiState->activeItem == id) { buttonOffset = V2(1, 1); - buttonColor = V4(1.0f, 0, 0, 1); + buttonColor = V4(0.8f, 0.8f, 0.8f, 1); } else { - // TODO(doyle): Optional add effect on button hover - buttonColor = V4(1.0f, 0, 0, 1); + // NOTE(doyle): Hover effect + buttonColor = V4(0.05f, 0.05f, 0.05f, 1); } } - else - { - buttonColor = V4(1.0f, 0, 0, 1); - } /* If no widget has keyboard focus, take it */ if (uiState->kbdItem == 0) uiState->kbdItem = id; + v2 rectSize = math_rect_get_size(rect); /* If we have keyboard focus, show it */ if (uiState->kbdItem == id) { // Draw outline renderer_staticRect(renderer, v2_add(V2(-2, -2), v2_add(buttonOffset, rect.min)), - v2_add(V2(4, 4), rect.max), V2(0, 0), 0, NULL, + v2_add(V2(4, 4), rectSize), V2(0, 0), 0, NULL, buttonColor, renderflag_no_texture); } - renderer_staticRect(renderer, v2_add(buttonOffset, rect.min), rect.max, - V2(0, 0), 0, NULL, buttonColor, renderflag_no_texture); + renderer_staticRect(renderer, v2_add(buttonOffset, rect.min), + rectSize, V2(0, 0), 0, NULL, + buttonColor, renderflag_no_texture); if (label) { @@ -97,21 +95,23 @@ i32 userInterface_button(UiState *const uiState, MemoryArena_ *const arena, v2 labelPos = rect.min; // Initially position the label to half the width of the button - labelPos.x += (rect.max.w * 0.5f); + labelPos.x += (rectSize.w * 0.5f); // Move the label pos back half the length of the string (i.e. // center it) labelPos.x -= (CAST(f32) labelDim.w * 0.5f); - if (labelDim.h < rect.max.h) + if (labelDim.h < rectSize.h) { - labelPos.y += (rect.max.h * 0.5f); + labelPos.y += (rectSize.h * 0.5f); labelPos.y -= (CAST(f32)labelDim.h * 0.5f); } + // TODO(doyle): We're using odd colors to overcome z-sorting by forcing + // button text into another render group labelPos = v2_add(labelPos, buttonOffset); renderer_staticString(renderer, arena, font, label, labelPos, V2(0, 0), - 0, V4(0, 0, 0, 1), 0); + 0, V4(0.9f, 0.9f, 0.9f, 0.9f), 0); } // After renderering before click check, see if we need to process keys @@ -159,7 +159,7 @@ i32 userInterface_scrollbar(UiState *const uiState, ASSERT(*value <= maxValue); #endif - if (math_pointInRect(scrollBarRect, input.mouseP)) + if (math_rect_contains_p(scrollBarRect, input.mouseP)) { uiState->hotItem = id; if (uiState->activeItem == 0) @@ -178,17 +178,18 @@ i32 userInterface_scrollbar(UiState *const uiState, if (uiState->kbdItem == 0) uiState->kbdItem = id; + v2 rectSize = math_rect_get_size(scrollBarRect); /* If we have keyboard focus, show it */ if (uiState->kbdItem == id) { // Draw outline renderer_staticRect(renderer, v2_add(V2(-2, -2), scrollBarRect.min), - v2_add(V2(4, 4), scrollBarRect.max), V2(0, 0), 0, + v2_add(V2(4, 4), rectSize), V2(0, 0), 0, &renderTex, V4(1, 0, 0, 1), 0); } // Render scroll bar background - renderer_staticRect(renderer, scrollBarRect.min, scrollBarRect.max, + renderer_staticRect(renderer, scrollBarRect.min, rectSize, V2(0, 0), 0, &renderTex, V4(0.75f, 0.5f, 0.5f, 1), 0); // Render scroll bar slider @@ -197,7 +198,7 @@ i32 userInterface_scrollbar(UiState *const uiState, f32 sliderPercentageOffset = (CAST(f32) *value / CAST(f32) maxValue); f32 sliderYOffsetToBar = - (scrollBarRect.max.h - sliderSize.h) * sliderPercentageOffset; + (rectSize.h - sliderSize.h) * sliderPercentageOffset; v2 sliderPos = v2_add(scrollBarRect.min, V2(0, sliderYOffsetToBar)); if (uiState->hotItem == id || uiState->activeItem == id) @@ -247,11 +248,11 @@ i32 userInterface_scrollbar(UiState *const uiState, // Bounds check if (mouseYRelToRect < 0) mouseYRelToRect = 0; - else if (mouseYRelToRect > scrollBarRect.max.h) - mouseYRelToRect = scrollBarRect.max.h; + else if (mouseYRelToRect > rectSize.h) + mouseYRelToRect = rectSize.h; f32 newSliderPercentOffset = - (CAST(f32) mouseYRelToRect / scrollBarRect.max.h); + (CAST(f32) mouseYRelToRect / rectSize.h); i32 newValue = CAST(i32)(newSliderPercentOffset * CAST(f32)maxValue); if (newValue != *value) @@ -273,7 +274,7 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena_ *const arena, i32 strLen = common_strlen(string); b32 changed = FALSE; - if (math_pointInRect(rect, input.mouseP)) + if (math_rect_contains_p(rect, input.mouseP)) { uiState->hotItem = id; if (uiState->activeItem == 0) @@ -290,27 +291,28 @@ i32 userInterface_textField(UiState *const uiState, MemoryArena_ *const arena, if (uiState->kbdItem == 0) uiState->kbdItem = id; + v2 rectSize = math_rect_get_size(rect); /* If we have keyboard focus, show it */ if (uiState->kbdItem == id) { // Draw outline renderer_staticRect(renderer, v2_add(V2(-2, -2), rect.min), - v2_add(V2(4, 4), rect.max), V2(0, 0), 0, + v2_add(V2(4, 4), rectSize), V2(0, 0), 0, NULL, V4(1.0f, 0, 0, 1), 0); } // Render text field - renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, NULL, + renderer_staticRect(renderer, rect.min, rectSize, V2(0, 0), 0, NULL, V4(0.75f, 0.5f, 0.5f, 1), 0); if (uiState->activeItem == id || uiState->hotItem == id) { - renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, + renderer_staticRect(renderer, rect.min, rectSize, V2(0, 0), 0, NULL, V4(0.75f, 0.75f, 0.0f, 1), 0); } else { - renderer_staticRect(renderer, rect.min, rect.max, V2(0, 0), 0, + renderer_staticRect(renderer, rect.min, rectSize, V2(0, 0), 0, NULL, V4(0.5f, 0.5f, 0.5f, 1), 0); } diff --git a/src/include/Dengine/AssetManager.h b/src/include/Dengine/AssetManager.h index ff61f3d..1701894 100644 --- a/src/include/Dengine/AssetManager.h +++ b/src/include/Dengine/AssetManager.h @@ -25,6 +25,9 @@ typedef struct AssetManager } AssetManager; #define MAX_TEXTURE_SIZE 1024 + +void asset_init(AssetManager *assetManager, MemoryArena_ *arena); + /* ********************************* * Texture Operations diff --git a/src/include/Dengine/Asteroid.h b/src/include/Dengine/Asteroid.h index bb54f19..b1f5757 100644 --- a/src/include/Dengine/Asteroid.h +++ b/src/include/Dengine/Asteroid.h @@ -10,8 +10,21 @@ #include "Dengine/Renderer.h" #include "Dengine/UserInterface.h" +enum AppState +{ + appstate_start_menu, + appstate_game, + appstate_count, +}; + typedef struct World { + b32 init; + + // NOTE(doyle): Grace period when game starts before asteroids start + // spawning + f32 onInitAsteroidSpawnTimer; + MemoryArena_ entityArena; v2 *entityVertexListCache[entitytype_count]; @@ -42,6 +55,8 @@ typedef struct World typedef struct GameState { b32 init; + + enum AppState appState; MemoryArena_ transientArena; MemoryArena_ persistentArena; diff --git a/src/include/Dengine/Debug.h b/src/include/Dengine/Debug.h index ba117d5..edac015 100644 --- a/src/include/Dengine/Debug.h +++ b/src/include/Dengine/Debug.h @@ -26,7 +26,6 @@ void debug_init(MemoryArena_ *arena, v2 windowSize, Font font); void debug_recursivePrintXmlTree(XmlNode *root, i32 levelsDeep); void debug_countIncrement(enum DebugCount id); -void debug_clearCounter(); #define DEBUG_LOG(string) debug_consoleLog(string, __FILE__, __LINE__); void debug_consoleLog(char *string, char *file, int lineNum); diff --git a/src/include/Dengine/Math.h b/src/include/Dengine/Math.h index e5032d0..11a23f5 100644 --- a/src/include/Dengine/Math.h +++ b/src/include/Dengine/Math.h @@ -347,14 +347,14 @@ INTERNAL inline v4 mat4_mul_v4(const mat4 a, const v4 b) return result; } -INTERNAL inline b32 math_pointInRect(Rect rect, v2 point) +INTERNAL inline b32 math_rect_contains_p(Rect rect, v2 p) { b32 outsideOfRectX = FALSE; - if (point.x < rect.min.x || point.x > (rect.min.x + rect.max.w)) + if (p.x < rect.min.x || p.x > rect.max.w) outsideOfRectX = TRUE; b32 outsideOfRectY = FALSE; - if (point.y < rect.min.y || point.y > (rect.min.y + rect.max.h)) + if (p.y < rect.min.y || p.y > rect.max.h) outsideOfRectY = TRUE; if (outsideOfRectX || outsideOfRectY) return FALSE; @@ -362,24 +362,43 @@ INTERNAL inline b32 math_pointInRect(Rect rect, v2 point) } -INTERNAL inline v4 math_getRect(v2 origin, v2 size) +INTERNAL inline Rect math_rect_create(v2 origin, v2 size) { - v2 upperRightBound = v2_add(origin, V2(size.x, size.y)); - v4 result = V4(origin.x, origin.y, upperRightBound.x, upperRightBound.y); + Rect result = {0}; + result.min = origin; + result.max = v2_add(origin, size); return result; } -INTERNAL inline v2 math_getRectSize(v4 rect) +INTERNAL inline v2 math_rect_get_size(Rect rect) { - f32 width = ABS(rect.x - rect.z); - f32 height = ABS(rect.y - rect.w); + f32 width = ABS(rect.max.x - rect.min.x); + f32 height = ABS(rect.max.y - rect.min.y); v2 result = V2(width, height); return result; } +INTERNAL inline v2 math_rect_get_centre(Rect rect) +{ + f32 sumX = rect.min.x + rect.max.x; + f32 sumY = rect.min.y + rect.max.y; + v2 result = v2_scale(V2(sumX, sumY), 0.5f); + + return result; +} + +INTERNAL inline Rect math_rect_shift(Rect rect, v2 shift) +{ + Rect result = {0}; + result.min = v2_add(rect.min, shift); + result.max = v2_add(rect.max, shift); + + return result; +} + INTERNAL inline void math_applyRotationToVertexes(v2 pos, v2 pivotPoint, Radians rotate, v2 *vertexList, diff --git a/src/include/Dengine/Renderer.h b/src/include/Dengine/Renderer.h index c02fe93..085b4c3 100644 --- a/src/include/Dengine/Renderer.h +++ b/src/include/Dengine/Renderer.h @@ -85,6 +85,8 @@ typedef struct Renderer i32 groupCapacity; } Renderer; +void renderer_init(Renderer *renderer, AssetManager *assetManager, + MemoryArena_ *persistentArena, v2 windowSize); RenderTex renderer_createNullRenderTex(AssetManager *const assetManager);