Switch developing game to asteroids, start project
Switch to something of smaller scope in aim to be able to finish a project from start to finish. Also allow refreshed eyes to review the existing API and see what can be improved on after taking a short break from the project.
This commit is contained in:
+241
@@ -0,0 +1,241 @@
|
||||
#include "Dengine/Asteroid.h"
|
||||
#include "Dengine/Debug.h"
|
||||
|
||||
void initAssetManager(GameState *state)
|
||||
{
|
||||
AssetManager *assetManager = &state->assetManager;
|
||||
MemoryArena_ *arena = &state->persistentArena;
|
||||
|
||||
i32 audioEntries = 32;
|
||||
assetManager->audio.size = audioEntries;
|
||||
assetManager->audio.entries =
|
||||
memory_pushBytes(arena, audioEntries * sizeof(HashTableEntry));
|
||||
|
||||
i32 texAtlasEntries = 8;
|
||||
assetManager->texAtlas.size = texAtlasEntries;
|
||||
assetManager->texAtlas.entries =
|
||||
memory_pushBytes(arena, texAtlasEntries * sizeof(HashTableEntry));
|
||||
|
||||
i32 texEntries = 32;
|
||||
assetManager->textures.size = texEntries;
|
||||
assetManager->textures.entries =
|
||||
memory_pushBytes(arena, texEntries * sizeof(HashTableEntry));
|
||||
|
||||
i32 animEntries = 1024;
|
||||
assetManager->anims.size = animEntries;
|
||||
assetManager->anims.entries =
|
||||
memory_pushBytes(arena, animEntries * 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));
|
||||
|
||||
/* Load shaders */
|
||||
asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl",
|
||||
"data/shaders/sprite.frag.glsl",
|
||||
shaderlist_sprite);
|
||||
|
||||
i32 result =
|
||||
asset_loadTTFont(assetManager, arena, "C:/Windows/Fonts/Arialbd.ttf");
|
||||
|
||||
if (result) {
|
||||
ASSERT(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
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->shader = asset_getShader(assetManager, shaderlist_sprite);
|
||||
shader_use(renderer->shader);
|
||||
|
||||
const mat4 projection =
|
||||
mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f);
|
||||
shader_uniformSetMat4fv(renderer->shader, "projection", projection);
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
/* Create buffers */
|
||||
glGenVertexArrays(1, &renderer->vao);
|
||||
glGenBuffers(1, &renderer->vbo);
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
/* Bind buffers */
|
||||
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo);
|
||||
glBindVertexArray(renderer->vao);
|
||||
|
||||
/* Configure VAO */
|
||||
u32 numVertexElements = 4;
|
||||
u32 stride = sizeof(Vertex);
|
||||
glVertexAttribPointer(0, numVertexElements, GL_FLOAT, GL_FALSE, stride,
|
||||
(GLvoid *)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
GL_CHECK_ERROR();
|
||||
|
||||
/* Unbind */
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
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(Vertex));
|
||||
}
|
||||
}
|
||||
|
||||
enum ReadKeyType
|
||||
{
|
||||
readkeytype_oneShot,
|
||||
readkeytype_delayedRepeat,
|
||||
readkeytype_repeat,
|
||||
readkeytype_count,
|
||||
};
|
||||
|
||||
#define KEY_DELAY_NONE 0.0f
|
||||
INTERNAL b32 getKeyStatus(KeyState *key, enum ReadKeyType readType,
|
||||
f32 delayInterval, f32 dt)
|
||||
{
|
||||
|
||||
if (!key->endedDown) return FALSE;
|
||||
|
||||
switch(readType)
|
||||
{
|
||||
case readkeytype_oneShot:
|
||||
{
|
||||
if (key->newHalfTransitionCount > key->oldHalfTransitionCount)
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
case readkeytype_repeat:
|
||||
case readkeytype_delayedRepeat:
|
||||
{
|
||||
if (key->newHalfTransitionCount > key->oldHalfTransitionCount)
|
||||
{
|
||||
if (readType == readkeytype_delayedRepeat)
|
||||
{
|
||||
// TODO(doyle): Let user set arbitrary delay after initial input
|
||||
key->delayInterval = 2 * delayInterval;
|
||||
}
|
||||
else
|
||||
{
|
||||
key->delayInterval = delayInterval;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if (key->delayInterval <= 0.0f)
|
||||
{
|
||||
key->delayInterval = delayInterval;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
key->delayInterval -= dt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#ifdef DENGINE_DEBUG
|
||||
DEBUG_LOG("getKeyStatus() error: Invalid ReadKeyType enum");
|
||||
ASSERT(INVALID_CODE_PATH);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
|
||||
v2 windowSize, f32 dt)
|
||||
{
|
||||
if (!state->init) {
|
||||
|
||||
memory_arenaInit(&state->persistentArena, memory->persistent,
|
||||
memory->persistentSize);
|
||||
memory_arenaInit(&state->transientArena, memory->transient,
|
||||
memory->transientSize);
|
||||
|
||||
initAssetManager(state);
|
||||
initRenderer(state, windowSize);
|
||||
|
||||
{ // Init ship entity
|
||||
Entity *ship = &state->entityList[state->entityIndex++];
|
||||
ship->id = 0;
|
||||
ship->pos = V2(100.0f, 100.0f);
|
||||
ship->hitbox = V2(100.0f, 100.0f);
|
||||
ship->size = V2(100.0f, 100.0f);
|
||||
ship->scale = 1;
|
||||
ship->type = entitytype_ship;
|
||||
ship->direction = direction_null;
|
||||
ship->tex = asset_getTex(&state->assetManager, "nullTex");
|
||||
ship->collides = FALSE;
|
||||
}
|
||||
|
||||
state->camera.pos = V2(0, 0);
|
||||
state->camera.size = state->renderer.size;
|
||||
|
||||
state->init = TRUE;
|
||||
}
|
||||
{
|
||||
KeyState *keys = state->input.keys;
|
||||
for (enum KeyCode code = 0; code < keycode_count; code++)
|
||||
{
|
||||
KeyState *keyState = &keys[code];
|
||||
|
||||
u32 halfTransitionCount = keyState->newHalfTransitionCount -
|
||||
keyState->oldHalfTransitionCount;
|
||||
|
||||
if (halfTransitionCount > 0)
|
||||
{
|
||||
b32 transitionCountIsOdd = ((halfTransitionCount & 1) == 1);
|
||||
|
||||
if (transitionCountIsOdd)
|
||||
{
|
||||
if (keyState->endedDown) keyState->endedDown = FALSE;
|
||||
else keyState->endedDown = TRUE;
|
||||
}
|
||||
|
||||
keyState->oldHalfTransitionCount =
|
||||
keyState->newHalfTransitionCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < state->entityIndex; i++)
|
||||
{
|
||||
Entity *entity = &state->entityList[i];
|
||||
ASSERT(entity->type != entitytype_invalid);
|
||||
|
||||
if (entity->type == entitytype_ship) {
|
||||
|
||||
{ // Parse input
|
||||
if (getKeyStatus(&state->input.keys[keycode_up],
|
||||
readkeytype_repeat, 0.0f, dt))
|
||||
{
|
||||
entity->pos.y += 10.0f;
|
||||
}
|
||||
|
||||
if (getKeyStatus(&state->input.keys[keycode_down],
|
||||
readkeytype_repeat, 0.0f, dt))
|
||||
{
|
||||
entity->pos.y -= 10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
renderer_entity(&state->renderer, state->camera, entity, V2(0, 0), 0,
|
||||
V4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
renderer_renderGroups(&state->renderer);
|
||||
}
|
||||
Reference in New Issue
Block a user