Add resolution changer in options menu
This commit is contained in:
parent
eb4b0e1714
commit
10891ab56e
168
src/Asteroid.c
168
src/Asteroid.c
@ -240,15 +240,14 @@ INTERNAL u32 moveEntity(GameWorldState *world, MemoryArena_ *transientArena,
|
||||
ASSERT(checkEntity->vertexPoints);
|
||||
|
||||
/* Create entity edge lists */
|
||||
v2 *entityVertexListOffsetToP = entity_generateUpdatedVertexList(
|
||||
transientArena, entity);
|
||||
v2 *entityVertexListOffsetToP =
|
||||
entity_generateUpdatedVertexList(transientArena, entity);
|
||||
|
||||
v2 *checkEntityVertexListOffsetToP =
|
||||
entity_generateUpdatedVertexList(transientArena,
|
||||
checkEntity);
|
||||
entity_generateUpdatedVertexList(transientArena, checkEntity);
|
||||
|
||||
v2 *entityEdgeList = createNormalEdgeList(transientArena,
|
||||
entityVertexListOffsetToP,
|
||||
v2 *entityEdgeList =
|
||||
createNormalEdgeList(transientArena, entityVertexListOffsetToP,
|
||||
entity->numVertexPoints);
|
||||
|
||||
v2 *checkEntityEdgeList = createNormalEdgeList(
|
||||
@ -296,7 +295,8 @@ enum AsteroidSize
|
||||
asteroidsize_count,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
v2 pos;
|
||||
v2 dP;
|
||||
} AsteroidSpec;
|
||||
@ -512,7 +512,7 @@ INTERNAL void addPlayer(GameWorldState *world)
|
||||
INTERNAL void deleteEntity(GameWorldState *world, i32 entityIndex)
|
||||
{
|
||||
ASSERT(entityIndex > 0);
|
||||
ASSERT(entityIndex < ARRAY_COUNT(world->entityList));
|
||||
ASSERT(entityIndex < world->entityListSize);
|
||||
|
||||
/* Last entity replaces the entity to delete */
|
||||
world->entityList[entityIndex] = world->entityList[world->entityIndex - 1];
|
||||
@ -581,6 +581,10 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
world->camera.max = state->renderer.size;
|
||||
world->size = state->renderer.size;
|
||||
|
||||
world->entityListSize = 1024;
|
||||
world->entityList = MEMORY_PUSH_ARRAY(&world->entityArena,
|
||||
world->entityListSize, Entity);
|
||||
|
||||
{ // Init null entity
|
||||
Entity *nullEntity = &world->entityList[world->entityIndex++];
|
||||
nullEntity->id = world->entityIdCounter++;
|
||||
@ -613,7 +617,7 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
|
||||
world->numStarP = 100;
|
||||
world->starPList =
|
||||
MEMORY_PUSH_ARRAY(&state->persistentArena, world->numStarP, v2);
|
||||
MEMORY_PUSH_ARRAY(&world->entityArena, world->numStarP, v2);
|
||||
|
||||
for (i32 i = 0; i < world->numStarP; i++)
|
||||
{
|
||||
@ -682,8 +686,8 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
// TODO(doyle): Atm transient arena is not used, this is
|
||||
// just to fill out the arguments
|
||||
audio_vorbisPlay(&state->transientArena,
|
||||
&state->audioManager, audioRenderer,
|
||||
fire, 1);
|
||||
&state->audioManager, audioRenderer, fire,
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -768,11 +772,15 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
// direction by extrapolating from it's current dp
|
||||
else
|
||||
{
|
||||
if (entity->dP.x >= 0) localDp.x = 1.0f;
|
||||
else localDp.x = -1.0f;
|
||||
if (entity->dP.x >= 0)
|
||||
localDp.x = 1.0f;
|
||||
else
|
||||
localDp.x = -1.0f;
|
||||
|
||||
if (entity->dP.y >= 0) localDp.y = 1.0f;
|
||||
else localDp.y = -1.0f;
|
||||
if (entity->dP.y >= 0)
|
||||
localDp.y = 1.0f;
|
||||
else
|
||||
localDp.y = -1.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -817,7 +825,6 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
f32 maxDp = MAX(entity->dP.x, entity->dP.y);
|
||||
|
||||
entity->color.a = maxDp / divisor;
|
||||
|
||||
}
|
||||
|
||||
/* Loop entity around world */
|
||||
@ -977,11 +984,9 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
|
||||
RenderFlags flags = renderflag_wireframe | renderflag_no_texture;
|
||||
renderer_entity(&state->renderer, &state->transientArena, world->camera,
|
||||
entity, V2(0, 0), 0,
|
||||
collideColor, flags);
|
||||
entity, V2(0, 0), 0, collideColor, flags);
|
||||
}
|
||||
|
||||
|
||||
for (i32 i = 0; i < world->numAudioRenderers; i++)
|
||||
{
|
||||
AudioRenderer *audioRenderer = &world->audioRenderer[i];
|
||||
@ -1000,6 +1005,45 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
StartMenuState *menuState =
|
||||
GET_STATE_DATA(state, &state->persistentArena, StartMenuState);
|
||||
|
||||
if (!menuState->init)
|
||||
{
|
||||
MemoryArena_ *persistentArena = &state->persistentArena;
|
||||
OptimalArrayV2 *resolutionArray = inputBuffer->resolutionList;
|
||||
v2 currRes = renderer->size;
|
||||
i32 resIndex = -1;
|
||||
|
||||
menuState->resStrings = memory_pushBytes(
|
||||
persistentArena, resolutionArray->index * sizeof(String *));
|
||||
|
||||
for (i32 i = 0; i < resolutionArray->index; i++)
|
||||
{
|
||||
v2 res = resolutionArray->ptr[i];
|
||||
if (v2_equals(res, currRes)) resIndex = i;
|
||||
|
||||
char widthString[8] = {0};
|
||||
char heightString[8] = {0};
|
||||
common_itoa((i32)res.w, widthString, ARRAY_COUNT(widthString));
|
||||
common_itoa((i32)res.h, heightString, ARRAY_COUNT(heightString));
|
||||
|
||||
String *resString = common_stringMake(transientArena, widthString);
|
||||
resString = common_stringAppend(transientArena, resString, "x", 1);
|
||||
resString =
|
||||
common_stringAppend(transientArena, resString, heightString,
|
||||
ARRAY_COUNT(heightString));
|
||||
|
||||
menuState->resStrings[i] = MEMORY_PUSH_ARRAY(
|
||||
persistentArena, common_stringLen(resString), char);
|
||||
common_strncpy(menuState->resStrings[i], resString,
|
||||
common_stringLen(resString));
|
||||
}
|
||||
|
||||
if (resIndex == -1) ASSERT(INVALID_CODE_PATH);
|
||||
|
||||
menuState->init = TRUE;
|
||||
menuState->numResStrings = resolutionArray->index;
|
||||
menuState->resStringDisplayIndex = resIndex;
|
||||
}
|
||||
|
||||
Font *arial15 = asset_fontGetOrCreateOnDemand(
|
||||
assetManager, &state->persistentArena, transientArena, "Arial", 15);
|
||||
Font *arial25 = asset_fontGetOrCreateOnDemand(
|
||||
@ -1008,7 +1052,6 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
v2 screenCenter = v2_scale(renderer->size, 0.5f);
|
||||
|
||||
ui_beginState(uiState);
|
||||
|
||||
if (menuState->optionsShow)
|
||||
{
|
||||
if (platform_queryKey(&inputBuffer->keys[keycode_o],
|
||||
@ -1020,39 +1063,78 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
}
|
||||
else
|
||||
{
|
||||
f32 textYOffset = arial25->size * 1.5f;;
|
||||
if (platform_queryKey(&inputBuffer->keys[keycode_enter],
|
||||
readkeytype_one_shot, KEY_DELAY_NONE))
|
||||
{
|
||||
OptimalArrayV2 *resolutionArray = inputBuffer->resolutionList;
|
||||
|
||||
menuState->newResolutionRequest = TRUE;
|
||||
v2 newSize =
|
||||
resolutionArray->ptr[menuState->resStringDisplayIndex];
|
||||
|
||||
GameWorldState *world = GET_STATE_DATA(
|
||||
state, &state->persistentArena, GameWorldState);
|
||||
|
||||
renderer_updateSize(renderer, &state->assetManager, newSize);
|
||||
|
||||
// TODO(doyle): reset world arena instead of zeroing out struct
|
||||
common_memset((u8 *)world, 0, sizeof(GameWorldState));
|
||||
debug_init(newSize, *arial15);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (platform_queryKey(&inputBuffer->keys[keycode_left],
|
||||
readkeytype_one_shot, KEY_DELAY_NONE))
|
||||
{
|
||||
menuState->resStringDisplayIndex--;
|
||||
}
|
||||
else if (platform_queryKey(&inputBuffer->keys[keycode_right],
|
||||
readkeytype_one_shot,
|
||||
KEY_DELAY_NONE))
|
||||
{
|
||||
menuState->resStringDisplayIndex++;
|
||||
}
|
||||
|
||||
if (menuState->resStringDisplayIndex < 0)
|
||||
{
|
||||
menuState->resStringDisplayIndex = 0;
|
||||
}
|
||||
else if (menuState->resStringDisplayIndex >=
|
||||
menuState->numResStrings)
|
||||
{
|
||||
menuState->resStringDisplayIndex =
|
||||
menuState->numResStrings - 1;
|
||||
}
|
||||
}
|
||||
|
||||
f32 textYOffset = arial25->size * 1.5f;
|
||||
{ // Options Title String Display
|
||||
const char *const title = "Options";
|
||||
|
||||
v2 p = v2_add(screenCenter, V2(0, textYOffset));
|
||||
renderer_stringFixedCentered(renderer, transientArena, arial25,
|
||||
title, p, V2(0, 0), 0, V4(1, 0, 1, 1),
|
||||
0);
|
||||
title, p, V2(0, 0), 0,
|
||||
V4(1, 0, 1, 1), 0);
|
||||
}
|
||||
|
||||
{ // Resolution String Display
|
||||
|
||||
/* Draw label */
|
||||
const char *const resolutionLabel = "Resolution";
|
||||
p = v2_add(screenCenter, V2(0, 0));
|
||||
|
||||
v2 p = v2_add(screenCenter, V2(0, 0));
|
||||
renderer_stringFixedCentered(renderer, transientArena, arial25,
|
||||
resolutionLabel, p, V2(0, 0), 0,
|
||||
V4(1, 0, 1, 1), 0);
|
||||
|
||||
const char *const resSizeLabel = "< 800x600 >";
|
||||
/* Draw label value */
|
||||
char *resStringToDisplay =
|
||||
menuState->resStrings[menuState->resStringDisplayIndex];
|
||||
|
||||
p = v2_add(screenCenter, V2(0, -textYOffset));
|
||||
|
||||
renderer_stringFixedCentered(renderer, transientArena, arial25,
|
||||
resSizeLabel, p, V2(0, 0), 0,
|
||||
resStringToDisplay, p, V2(0, 0), 0,
|
||||
V4(1, 0, 1, 1), 0);
|
||||
|
||||
if (platform_queryKey(&inputBuffer->keys[keycode_enter],
|
||||
readkeytype_one_shot, KEY_DELAY_NONE))
|
||||
{
|
||||
menuState->newResolutionRequest = TRUE;
|
||||
menuState->newResolution = V2(800, 600);
|
||||
|
||||
renderer->size = menuState->newResolution;
|
||||
|
||||
GameWorldState *world = GET_STATE_DATA(
|
||||
state, &state->persistentArena, GameWorldState);
|
||||
world->size = menuState->newResolution;
|
||||
world->camera.max = menuState->newResolution;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1086,8 +1168,8 @@ INTERNAL void startMenuUpdate(GameState *state, Memory *memory, f32 dt)
|
||||
const char *const optionPrompt = "Press [o] for options ";
|
||||
v2 p = v2_add(screenCenter, V2(0, -120));
|
||||
renderer_stringFixedCentered(renderer, transientArena, arial25,
|
||||
optionPrompt, p, V2(0, 0), 0, V4(1, 1, 0, 1),
|
||||
0);
|
||||
optionPrompt, p, V2(0, 0), 0,
|
||||
V4(1, 1, 0, 1), 0);
|
||||
}
|
||||
|
||||
if (platform_queryKey(&inputBuffer->keys[keycode_enter],
|
||||
@ -1139,7 +1221,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
||||
&state->persistentArena, windowSize);
|
||||
|
||||
Font *arial15 = asset_fontGet(&state->assetManager, "Arial", 15);
|
||||
debug_init(&state->persistentArena, windowSize, *arial15);
|
||||
debug_init(windowSize, *arial15);
|
||||
|
||||
state->currState = appstate_StartMenuState;
|
||||
state->init = TRUE;
|
||||
|
189
src/Common.c
189
src/Common.c
@ -1,10 +1,173 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Dengine/Common.h"
|
||||
#include "Dengine/Math.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
|
||||
void common_optimalArrayV2Create(OptimalArrayV2 *array)
|
||||
{
|
||||
array->ptr = array->fastStorage;
|
||||
array->size = ARRAY_COUNT(array->fastStorage);
|
||||
}
|
||||
|
||||
i32 common_optimalArrayV2Push(OptimalArrayV2 *array, v2 data)
|
||||
{
|
||||
if (array->index + 1 > array->size)
|
||||
{
|
||||
array->size += ARRAY_COUNT(array->fastStorage);
|
||||
i32 newSizeInBytes = array->size * sizeof(v2);
|
||||
|
||||
/* If first time expanding, we need to manually malloc and copy */
|
||||
if (array->ptr == array->fastStorage)
|
||||
{
|
||||
array->ptr = malloc(newSizeInBytes);
|
||||
for (i32 i = 0; i < ARRAY_COUNT(array->fastStorage); i++)
|
||||
{
|
||||
array->ptr[i] = array->fastStorage[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
array->ptr = realloc(array->ptr, newSizeInBytes);
|
||||
}
|
||||
|
||||
if (!array->ptr) return optimalarrayerror_out_of_memory;
|
||||
}
|
||||
|
||||
array->ptr[array->index++] = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void common_optimalArrayV2Destroy(OptimalArrayV2 *array)
|
||||
{
|
||||
if (array->ptr != array->fastStorage)
|
||||
{
|
||||
free(array->ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* +-------------------------------------+
|
||||
* | Header | C-String | Null Terminator |
|
||||
* +-------------------------------------+
|
||||
* |
|
||||
* +--> Functions return the c-string for compatibility with other
|
||||
* string libraries
|
||||
*
|
||||
* Headers are retrieved using pointer arithmetric from the C string. These
|
||||
* strings are typechecked by their own typedef char String.
|
||||
*/
|
||||
|
||||
typedef struct StringHeader
|
||||
{
|
||||
i32 len;
|
||||
|
||||
// NOTE(doyle): A string is stored as one contiguous chunk of memory. We
|
||||
// don't use a pointer for storing the string as this'd require an extra
|
||||
// 4 bytes to store the pointer, which we don't need if everything is
|
||||
// contiguous. The string follows on from the len, and we return the address
|
||||
// of the string to simulate a pointer.
|
||||
String string;
|
||||
} StringHeader;
|
||||
|
||||
// TODO(doyle): string capacity- append if already enough space
|
||||
INTERNAL StringHeader *stringGetHeader(String *const string)
|
||||
{
|
||||
StringHeader *result = NULL;
|
||||
|
||||
// NOTE(doyle): C-String must be located at end of struct type for offset to
|
||||
// be correct! We cannot just subtract the string-header since we start at
|
||||
// the string ptr position
|
||||
if (string)
|
||||
{
|
||||
i32 byteOffsetToHeader = sizeof(StringHeader) - sizeof(String *);
|
||||
result = CAST(StringHeader *)((CAST(u8 *) string) - byteOffsetToHeader);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
i32 common_stringLen(String *const string)
|
||||
{
|
||||
if (!string) return -1;
|
||||
|
||||
StringHeader *header = stringGetHeader(string);
|
||||
i32 result = header->len;
|
||||
return result;
|
||||
}
|
||||
|
||||
String *const common_stringAppend(MemoryArena_ *const arena, String *oldString,
|
||||
char *appendString, i32 appendLen)
|
||||
|
||||
{
|
||||
if (!oldString || !appendString || !arena) return oldString;
|
||||
|
||||
/* Calculate size of new string */
|
||||
StringHeader *oldHeader = stringGetHeader(oldString);
|
||||
i32 newLen = oldHeader->len + appendLen;
|
||||
String *newString = common_stringMakeLen(arena, newLen);
|
||||
|
||||
/* Append strings together */
|
||||
String *insertPtr = newString;
|
||||
common_strncpy(insertPtr, oldString, oldHeader->len);
|
||||
insertPtr += oldHeader->len;
|
||||
common_strncpy(insertPtr, appendString, appendLen);
|
||||
|
||||
/* Free old string */
|
||||
common_stringFree(arena, oldString);
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
void common_stringFree(MemoryArena_ *arena, String *string)
|
||||
{
|
||||
if (!string || !arena) return;
|
||||
|
||||
StringHeader *header = stringGetHeader(string);
|
||||
i32 bytesToFree = sizeof(StringHeader) + header->len;
|
||||
|
||||
common_memset((u8 *)header, 0, bytesToFree);
|
||||
|
||||
// TODO(doyle): Mem free
|
||||
// PLATFORM_MEM_FREE(arena, header, bytesToFree);
|
||||
|
||||
string = NULL;
|
||||
}
|
||||
|
||||
String *const common_stringMake(MemoryArena_ *const arena, char *string)
|
||||
{
|
||||
if (!arena) return NULL;
|
||||
|
||||
i32 len = common_strlen(string);
|
||||
String *result = common_stringMakeLen(arena, len);
|
||||
common_strncpy(result, string, len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String *const common_stringMakeLen(MemoryArena_ *const arena, i32 len)
|
||||
{
|
||||
if (!arena) return NULL;
|
||||
|
||||
// NOTE(doyle): Allocate the string header size plus the len. But _note_
|
||||
// that StringHeader contains a single String character. This has
|
||||
// a side-effect of already preallocating a byte for the null-terminating
|
||||
// character. Whilst the len of a string counts up to the last character
|
||||
// _not_ including null-terminator.
|
||||
i32 bytesToAllocate = sizeof(StringHeader) + len;
|
||||
void *chunk = memory_pushBytes(arena, bytesToAllocate * sizeof(u8));
|
||||
if (!chunk) return NULL;
|
||||
|
||||
StringHeader *header = CAST(StringHeader *) chunk;
|
||||
header->len = len;
|
||||
return &header->string;
|
||||
}
|
||||
|
||||
i32 common_strlen(const char *const string)
|
||||
{
|
||||
i32 result = 0;
|
||||
while (string[result]) result++;
|
||||
while (string[result])
|
||||
result++;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -12,8 +175,7 @@ i32 common_strcmp(const char *a, const char *b)
|
||||
{
|
||||
while (*a == *b)
|
||||
{
|
||||
if (!*a)
|
||||
return 0;
|
||||
if (!*a) return 0;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
@ -55,8 +217,8 @@ INTERNAL void reverseString(char *const buf, const i32 bufSize)
|
||||
for (i32 i = 0; i < mid; i++)
|
||||
{
|
||||
char tmp = buf[i];
|
||||
buf[i] = buf[(bufSize-1) - i];
|
||||
buf[(bufSize-1) - i] = tmp;
|
||||
buf[i] = buf[(bufSize - 1) - i];
|
||||
buf[(bufSize - 1) - i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,9 +299,9 @@ u32 common_murmurHash2(const void *key, i32 len, u32 seed)
|
||||
|
||||
// Mix 4 bytes at a time into the hash
|
||||
|
||||
const unsigned char * data = (const unsigned char *)key;
|
||||
const unsigned char *data = (const unsigned char *)key;
|
||||
|
||||
while(len >= 4)
|
||||
while (len >= 4)
|
||||
{
|
||||
u32 k = *(u32 *)data;
|
||||
|
||||
@ -156,11 +318,14 @@ u32 common_murmurHash2(const void *key, i32 len, u32 seed)
|
||||
|
||||
// Handle the last few bytes of the input array
|
||||
|
||||
switch(len)
|
||||
switch (len)
|
||||
{
|
||||
case 3: h ^= data[2] << 16;
|
||||
case 2: h ^= data[1] << 8;
|
||||
case 1: h ^= data[0];
|
||||
case 3:
|
||||
h ^= data[2] << 16;
|
||||
case 2:
|
||||
h ^= data[1] << 8;
|
||||
case 1:
|
||||
h ^= data[0];
|
||||
h *= m;
|
||||
};
|
||||
|
||||
|
12
src/Debug.c
12
src/Debug.c
@ -9,7 +9,7 @@ typedef struct DebugState
|
||||
{
|
||||
b32 init;
|
||||
Font font;
|
||||
i32 *callCount;
|
||||
i32 callCount[debugcount_num];
|
||||
f32 stringLineGap;
|
||||
|
||||
/* Debug strings rendered in top left corner */
|
||||
@ -28,11 +28,12 @@ typedef struct DebugState
|
||||
|
||||
GLOBAL_VAR DebugState GLOBAL_debug;
|
||||
|
||||
void debug_init(MemoryArena_ *arena, v2 windowSize, Font font)
|
||||
void debug_init(v2 windowSize, Font font)
|
||||
{
|
||||
GLOBAL_debug.font = font;
|
||||
GLOBAL_debug.callCount =
|
||||
memory_pushBytes(arena, debugcount_num * sizeof(i32));
|
||||
|
||||
for (i32 i = 0; i < debugcount_num; i++) GLOBAL_debug.callCount[i] = 0;
|
||||
|
||||
GLOBAL_debug.stringLineGap = CAST(f32) font.verticalSpacing;
|
||||
|
||||
/* Init debug string stack */
|
||||
@ -40,8 +41,7 @@ void debug_init(MemoryArena_ *arena, v2 windowSize, Font font)
|
||||
GLOBAL_debug.stringUpdateTimer = 0.0f;
|
||||
GLOBAL_debug.stringUpdateRate = 0.15f;
|
||||
|
||||
GLOBAL_debug.initialStringP =
|
||||
V2(0.0f, (windowSize.h - 1.8f * GLOBAL_debug.stringLineGap));
|
||||
GLOBAL_debug.initialStringP = V2(0.0f, (windowSize.h - 1.8f * GLOBAL_debug.stringLineGap));
|
||||
GLOBAL_debug.currStringP = GLOBAL_debug.initialStringP;
|
||||
|
||||
/* Init gui console */
|
||||
|
@ -32,8 +32,7 @@ void shaderUniformSetVec4f(u32 shaderId, const GLchar *name,
|
||||
|
||||
void shaderUse(u32 shaderId) { glUseProgram(shaderId); }
|
||||
|
||||
void renderer_init(Renderer *renderer, AssetManager *assetManager,
|
||||
MemoryArena_ *persistentArena, v2 windowSize)
|
||||
void renderer_updateSize(Renderer *renderer, AssetManager *assetManager, v2 windowSize)
|
||||
{
|
||||
renderer->size = windowSize;
|
||||
// NOTE(doyle): Value to map a screen coordinate to NDC coordinate
|
||||
@ -43,6 +42,7 @@ void renderer_init(Renderer *renderer, AssetManager *assetManager,
|
||||
|
||||
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_shaderGet(assetManager, i);
|
||||
@ -54,6 +54,12 @@ void renderer_init(Renderer *renderer, AssetManager *assetManager,
|
||||
|
||||
renderer->activeShaderId = renderer->shaderList[shaderlist_default];
|
||||
GL_CHECK_ERROR();
|
||||
}
|
||||
|
||||
void renderer_init(Renderer *renderer, AssetManager *assetManager,
|
||||
MemoryArena_ *persistentArena, v2 windowSize)
|
||||
{
|
||||
renderer_updateSize(renderer, assetManager, windowSize);
|
||||
|
||||
/* Create buffers */
|
||||
glGenVertexArrays(ARRAY_COUNT(renderer->vao), renderer->vao);
|
||||
|
117
src/String.c
117
src/String.c
@ -1,120 +1,3 @@
|
||||
#include "Dengine/String.h"
|
||||
#include "Dengine/MemoryArena.h"
|
||||
|
||||
/*
|
||||
* +-------------------------------------+
|
||||
* | Header | C-String | Null Terminator |
|
||||
* +-------------------------------------+
|
||||
* |
|
||||
* +--> Functions return the c-string for compatibility with other
|
||||
* string libraries
|
||||
*
|
||||
* Headers are retrieved using pointer arithmetric from the C string. These
|
||||
* strings are typechecked by their own typedef char String.
|
||||
*/
|
||||
|
||||
typedef struct StringHeader
|
||||
{
|
||||
i32 len;
|
||||
|
||||
// NOTE(doyle): A string is stored as one contiguous chunk of memory. We
|
||||
// don't use a pointer for storing the string as this'd require an extra
|
||||
// 4 bytes to store the pointer, which we don't need if everything is
|
||||
// contiguous. The string follows on from the len, and we return the address
|
||||
// of the string to simulate a pointer.
|
||||
String string;
|
||||
} StringHeader;
|
||||
|
||||
// TODO(doyle): string capacity- append if already enough space
|
||||
INTERNAL StringHeader *string_getHeader(String *const string)
|
||||
{
|
||||
StringHeader *result = NULL;
|
||||
|
||||
// NOTE(doyle): C-String must be located at end of struct type for offset to
|
||||
// be correct! We cannot just subtract the string-header since we start at
|
||||
// the string ptr position
|
||||
if (string)
|
||||
{
|
||||
i32 byteOffsetToHeader = sizeof(StringHeader) - sizeof(String *);
|
||||
result = CAST(StringHeader *)((CAST(u8 *) string) - byteOffsetToHeader);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
i32 string_len(String *const string)
|
||||
{
|
||||
if (!string) return -1;
|
||||
|
||||
StringHeader *header = string_getHeader(string);
|
||||
i32 result = header->len;
|
||||
return result;
|
||||
}
|
||||
|
||||
String *const string_append(MemoryArena_ *const arena, String *oldString,
|
||||
char *appendString, i32 appendLen)
|
||||
|
||||
{
|
||||
if (!oldString || !appendString || !arena) return oldString;
|
||||
|
||||
/* Calculate size of new string */
|
||||
StringHeader *oldHeader = string_getHeader(oldString);
|
||||
i32 newLen = oldHeader->len + appendLen;
|
||||
String *newString = string_makeLen(arena, newLen);
|
||||
|
||||
/* Append strings together */
|
||||
String *insertPtr = newString;
|
||||
common_strncpy(insertPtr, oldString, oldHeader->len);
|
||||
insertPtr += oldHeader->len;
|
||||
common_strncpy(insertPtr, appendString, appendLen);
|
||||
|
||||
/* Free old string */
|
||||
string_free(arena, oldString);
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
void string_free(MemoryArena_ *arena, String *string)
|
||||
{
|
||||
if (!string || !arena) return;
|
||||
|
||||
StringHeader *header = string_getHeader(string);
|
||||
i32 bytesToFree = sizeof(StringHeader) + header->len;
|
||||
|
||||
common_memset((u8 *)header, 0, bytesToFree);
|
||||
|
||||
// TODO(doyle): Mem free
|
||||
// PLATFORM_MEM_FREE(arena, header, bytesToFree);
|
||||
|
||||
string = NULL;
|
||||
}
|
||||
|
||||
String *const string_make(MemoryArena_ *const arena, char *string)
|
||||
{
|
||||
if (!arena) return NULL;
|
||||
|
||||
i32 len = common_strlen(string);
|
||||
String *result = string_makeLen(arena, len);
|
||||
common_strncpy(result, string, len);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String *const string_makeLen(MemoryArena_ *const arena, i32 len)
|
||||
{
|
||||
if (!arena) return NULL;
|
||||
|
||||
// NOTE(doyle): Allocate the string header size plus the len. But _note_
|
||||
// that StringHeader contains a single String character. This has
|
||||
// a side-effect of already preallocating a byte for the null-terminating
|
||||
// character. Whilst the len of a string counts up to the last character
|
||||
// _not_ including null-terminator.
|
||||
i32 bytesToAllocate = sizeof(StringHeader) + len;
|
||||
void *chunk = memory_pushBytes(arena, bytesToAllocate * sizeof(u8));
|
||||
if (!chunk) return NULL;
|
||||
|
||||
StringHeader *header = CAST(StringHeader *) chunk;
|
||||
header->len = len;
|
||||
return &header->string;
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ INTERNAL void mouseButtonCallback(GLFWwindow *window, int button, int action,
|
||||
{
|
||||
GameState *game = CAST(GameState *)(glfwGetWindowUserPointer(window));
|
||||
|
||||
switch(button)
|
||||
switch (button)
|
||||
{
|
||||
case GLFW_MOUSE_BUTTON_LEFT:
|
||||
processKey(&game->input.keys[keycode_mouseLeft], action);
|
||||
@ -115,8 +115,73 @@ i32 main(void)
|
||||
glfwInit();
|
||||
setGlfwWindowHints();
|
||||
|
||||
i32 windowWidth = 1600;
|
||||
i32 windowHeight = 900;
|
||||
OptimalArrayV2 vidList = {0};
|
||||
common_optimalArrayV2Create(&vidList);
|
||||
|
||||
i32 windowWidth = 0;
|
||||
i32 windowHeight = 0;
|
||||
{ // Query Computer Video Resolutions
|
||||
|
||||
i32 numMonitors;
|
||||
GLFWmonitor **monitors = glfwGetMonitors(&numMonitors);
|
||||
GLFWmonitor *primaryMonitor = monitors[0];
|
||||
|
||||
i32 numModes;
|
||||
const GLFWvidmode *modes = glfwGetVideoModes(primaryMonitor, &numModes);
|
||||
|
||||
i32 targetRefreshHz = 60;
|
||||
f32 targetWindowRatio = 16.0f / 9.0f;
|
||||
|
||||
i32 targetPixelDensity = 1280 * 720;
|
||||
i32 minPixelDensityDelta = 100000000;
|
||||
|
||||
printf("== Supported video modes ==\n");
|
||||
for (i32 i = 0; i < numModes; i++)
|
||||
{
|
||||
GLFWvidmode mode = modes[i];
|
||||
printf("width: %d, height: %d, rgb: %d, %d, %d, refresh: %d\n",
|
||||
mode.width, mode.height, mode.redBits, mode.greenBits,
|
||||
mode.blueBits, mode.refreshRate);
|
||||
|
||||
if (mode.refreshRate == targetRefreshHz)
|
||||
{
|
||||
i32 result = common_optimalArrayV2Push(
|
||||
&vidList, V2i(mode.width, mode.height));
|
||||
|
||||
if (result)
|
||||
{
|
||||
printf(
|
||||
"common_optimalArrayV2Push(): Failed error code %d\n",
|
||||
result);
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
}
|
||||
|
||||
f32 sizeRatio = (f32)mode.width / (f32)mode.height;
|
||||
f32 delta = targetWindowRatio - sizeRatio;
|
||||
if (delta < 0.1f)
|
||||
{
|
||||
i32 pixelDensity = mode.width * mode.height;
|
||||
i32 densityDelta = ABS((pixelDensity - targetPixelDensity));
|
||||
|
||||
if (densityDelta < minPixelDensityDelta)
|
||||
{
|
||||
minPixelDensityDelta = densityDelta;
|
||||
windowWidth = mode.width;
|
||||
windowHeight = mode.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("== ==\n");
|
||||
ASSERT(vidList.index > 0);
|
||||
}
|
||||
|
||||
if (windowWidth == 0 || windowHeight == 0)
|
||||
{
|
||||
// NOTE(doyle): In this case just fallback to some value we hope is safe
|
||||
windowWidth = 800;
|
||||
windowHeight = 600;
|
||||
}
|
||||
|
||||
GLFWwindow *window =
|
||||
glfwCreateWindow(windowWidth, windowHeight, "Dengine", NULL, NULL);
|
||||
@ -186,7 +251,7 @@ i32 main(void)
|
||||
|
||||
glfwSetWindowUserPointer(window, CAST(void *)(gameState));
|
||||
|
||||
{
|
||||
{ // Load game icon
|
||||
i32 width, height;
|
||||
char *iconPath = "data/textures/Asteroids/icon.png";
|
||||
u8 *pixels = asset_imageLoad(&width, &height, NULL, iconPath, FALSE);
|
||||
@ -198,6 +263,7 @@ i32 main(void)
|
||||
asset_imageFree(pixels);
|
||||
}
|
||||
}
|
||||
gameState->input.resolutionList = &vidList;
|
||||
|
||||
/*
|
||||
*******************
|
||||
@ -209,7 +275,6 @@ i32 main(void)
|
||||
|
||||
#if 0
|
||||
// TODO(doyle): Get actual monitor refresh rate
|
||||
i32 monitorRefreshHz = 60;
|
||||
f32 targetSecondsPerFrame = 1.0f / CAST(f32)(monitorRefreshHz);
|
||||
#else
|
||||
// TODO(doyle): http://gafferongames.com/game-physics/fix-your-timestep/
|
||||
@ -234,7 +299,7 @@ i32 main(void)
|
||||
/* Swap the buffers */
|
||||
glfwSwapBuffers(window);
|
||||
|
||||
f32 endTime = CAST(f32)glfwGetTime();
|
||||
f32 endTime = CAST(f32) glfwGetTime();
|
||||
secondsElapsed = endTime - startTime;
|
||||
|
||||
#if 0
|
||||
@ -277,8 +342,11 @@ i32 main(void)
|
||||
{
|
||||
if (menuState->newResolutionRequest)
|
||||
{
|
||||
windowSize = menuState->newResolution;
|
||||
i32 index = menuState->resStringDisplayIndex;
|
||||
windowSize = gameState->input.resolutionList->ptr[index];
|
||||
|
||||
glfwSetWindowSize(window, (i32)windowSize.w, (i32)windowSize.h);
|
||||
glViewport(0, 0, (i32)windowSize.w, (i32)windowSize.h);
|
||||
|
||||
menuState->newResolutionRequest = FALSE;
|
||||
}
|
||||
|
@ -24,7 +24,8 @@ typedef struct GameWorldState
|
||||
MemoryArena_ entityArena;
|
||||
|
||||
v2 *entityVertexListCache[entitytype_count];
|
||||
Entity entityList[1024];
|
||||
Entity *entityList;
|
||||
i32 entityListSize;
|
||||
i32 entityIndex;
|
||||
u32 entityIdCounter;
|
||||
|
||||
@ -54,19 +55,23 @@ typedef struct GameWorldState
|
||||
|
||||
typedef struct StartMenuState
|
||||
{
|
||||
b32 init;
|
||||
|
||||
f32 startPromptBlinkTimer;
|
||||
b32 startPromptShow;
|
||||
|
||||
b32 optionsShow;
|
||||
char **resStrings;
|
||||
i32 numResStrings;
|
||||
i32 resStringDisplayIndex;
|
||||
|
||||
b32 newResolutionRequest;
|
||||
v2 newResolution;
|
||||
|
||||
b32 optionsShow;
|
||||
} StartMenuState;
|
||||
|
||||
typedef struct GameState
|
||||
{
|
||||
b32 init;
|
||||
|
||||
enum AppState currState;
|
||||
void *appStateData[appstate_count];
|
||||
|
||||
@ -81,8 +86,7 @@ typedef struct GameState
|
||||
UiState uiState;
|
||||
} GameState;
|
||||
|
||||
#define ASTEROID_GET_STATE_DATA(state, type) \
|
||||
(type *)asteroid_getStateData_(state, appstate_##type)
|
||||
#define ASTEROID_GET_STATE_DATA(state, type) (type *)asteroid_getStateData_(state, appstate_##type)
|
||||
void *asteroid_getStateData_(GameState *state, enum AppState appState);
|
||||
|
||||
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
||||
|
@ -15,6 +15,9 @@ typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
typedef size_t MemoryIndex;
|
||||
typedef char String;
|
||||
|
||||
typedef struct MemoryArena MemoryArena_;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
@ -34,6 +37,44 @@ typedef size_t MemoryIndex;
|
||||
|
||||
#define DENGINE_DEBUG
|
||||
|
||||
#include "Dengine/Math.h"
|
||||
|
||||
/*
|
||||
NOTE(doyle): Small sized optimised dynamic array that grows as required. The
|
||||
array uses the stack first, only if it runs out of space does it rely on
|
||||
memory allocated from the machine.
|
||||
|
||||
The array->ptr is initially set to fast storage. Once we are out of space
|
||||
we allocate space on the heap for the ptr and copy over the elements in
|
||||
fast storage.
|
||||
|
||||
The default behaviour expands the array storage by the size of fastStorage.
|
||||
*/
|
||||
|
||||
enum OptimalArrayError
|
||||
{
|
||||
optimalarrayerror_out_of_memory = 1,
|
||||
optimalarrayerror_count,
|
||||
};
|
||||
|
||||
typedef struct OptimalArrayV2
|
||||
{
|
||||
v2 fastStorage[16];
|
||||
v2 *ptr;
|
||||
i32 index;
|
||||
i32 size;
|
||||
} OptimalArrayV2;
|
||||
void common_optimalArrayV2Create(OptimalArrayV2 *array);
|
||||
i32 common_optimalArrayV2Push(OptimalArrayV2 *array, v2 data);
|
||||
void common_optimalArrayV2Destroy(OptimalArrayV2 *array);
|
||||
|
||||
i32 common_stringLen(String *const string);
|
||||
String *const common_stringAppend(MemoryArena_ *const arena, String *oldString,
|
||||
String *appendString, i32 appendLen);
|
||||
void common_stringFree(MemoryArena_ *arena, String *string);
|
||||
String *const common_stringMake(MemoryArena_ *const arena, char *string);
|
||||
String *const common_stringMakeLen(MemoryArena_ *const arena, i32 len);
|
||||
|
||||
i32 common_strlen(const char *const string);
|
||||
i32 common_strcmp(const char *a, const char *b);
|
||||
void common_strncat(char *dest, const char *src, i32 numChars);
|
||||
|
@ -20,7 +20,7 @@ enum DebugCount
|
||||
debugcount_num,
|
||||
};
|
||||
|
||||
void debug_init(MemoryArena_ *arena, v2 windowSize, Font font);
|
||||
void debug_init(v2 windowSize, Font font);
|
||||
|
||||
#define DEBUG_RECURSIVE_PRINT_XML_TREE(sig) debug_recursivePrintXmlTree(sig, 1)
|
||||
void debug_recursivePrintXmlTree(XmlNode *root, i32 levelsDeep);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define DENGINE_MATH_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "Dengine/Common.h"
|
||||
|
||||
#define MATH_PI 3.14159265359f
|
||||
|
@ -143,6 +143,8 @@ typedef struct KeyState
|
||||
|
||||
typedef struct InputBuffer
|
||||
{
|
||||
OptimalArrayV2 *resolutionList;
|
||||
|
||||
v2 mouseP;
|
||||
KeyState keys[keycode_count];
|
||||
} InputBuffer;
|
||||
|
@ -84,6 +84,7 @@ typedef struct Renderer
|
||||
i32 groupCapacity;
|
||||
} Renderer;
|
||||
|
||||
void renderer_updateSize(Renderer *renderer, AssetManager *assetManager, v2 windowSize);
|
||||
void renderer_init(Renderer *renderer, AssetManager *assetManager,
|
||||
MemoryArena_ *persistentArena, v2 windowSize);
|
||||
|
||||
|
@ -1,16 +1,5 @@
|
||||
#ifndef DENGINE_STRING_H
|
||||
#define DENGINE_STRING_H
|
||||
|
||||
#include "Dengine/Common.h"
|
||||
|
||||
typedef struct MemoryArena MemoryArena_;
|
||||
typedef char String;
|
||||
|
||||
i32 string_len(String *const string);
|
||||
String *const string_append(MemoryArena_ *const arena, String *oldString,
|
||||
String *appendString, i32 appendLen);
|
||||
void string_free(MemoryArena_ *arena, String *string);
|
||||
String *const string_make(MemoryArena_ *const arena, char *string);
|
||||
String *const string_makeLen(MemoryArena_ *const arena, i32 len);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user