Change start screen to pre-init the world

This commit is contained in:
Doyle Thai 2016-11-28 16:11:53 +11:00
parent 6df92e7aed
commit 15b4ff59f7
3 changed files with 179 additions and 121 deletions

View File

@ -7,9 +7,17 @@ INTERNAL void loadGameAssets(GameState *state)
MemoryArena_ *arena = &state->persistentArena;
{ // Init font assets
#if 0
i32 result =
asset_fontLoadTTF(assetManager, arena, &state->transientArena,
"C:/Windows/Fonts/Arialbd.ttf", "Arial", 15);
#endif
asset_fontLoadTTF(assetManager, arena, &state->transientArena,
"F:/Workspace/Dropbox/Apps/Fonts/"
"league-spartan-master/_webfonts/"
"leaguespartan-bold.ttf",
"Arial", 15);
}
{ // Init shaders assets
@ -64,7 +72,7 @@ INTERNAL void loadGameAssets(GameState *state)
#include <stdlib.h>
#include <time.h>
v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations,
INTERNAL v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations,
i32 asteroidRadius)
{
f32 iterationAngle = 360.0f / iterations;
@ -120,7 +128,7 @@ v2 *createAsteroidVertexList(MemoryArena_ *arena, i32 iterations,
return result;
}
v2 *createNormalEdgeList(MemoryArena_ *transientArena, v2 *vertexList,
INTERNAL v2 *createNormalEdgeList(MemoryArena_ *transientArena, v2 *vertexList,
i32 vertexListSize)
{
v2 *result = memory_pushBytes(transientArena, sizeof(v2) * vertexListSize);
@ -140,7 +148,7 @@ v2 *createNormalEdgeList(MemoryArena_ *transientArena, v2 *vertexList,
return result;
}
v2 calculateProjectionRangeForEdge(v2 *vertexList, i32 vertexListSize,
INTERNAL v2 calculateProjectionRangeForEdge(v2 *vertexList, i32 vertexListSize,
v2 edgeNormal)
{
v2 result = {0};
@ -160,7 +168,7 @@ v2 calculateProjectionRangeForEdge(v2 *vertexList, i32 vertexListSize,
return result;
}
b32 checkEdgeProjectionOverlap(v2 *vertexList, i32 listSize,
INTERNAL b32 checkEdgeProjectionOverlap(v2 *vertexList, i32 listSize,
v2 *checkVertexList, i32 checkListSize,
v2 *edgeList, i32 totalNumEdges)
{
@ -443,18 +451,60 @@ INTERNAL void setCollisionRule(World *world, enum EntityType a,
world->collisionTable[b][a] = rule;
}
INTERNAL AudioRenderer *getFreeAudioRenderer(World *world)
INTERNAL AudioRenderer *getFreeAudioRenderer(World *world, AudioVorbis *vorbis,
i32 maxSimultaneousPlayers)
{
i32 freeIndex = -1;
i32 sameAudioPlayingCount = 0;
AudioRenderer *result = NULL;
for (i32 i = 0; i < world->numAudioRenderers; i++)
{
AudioRenderer *renderer = &world->audioRenderer[i];
if (renderer->state == audiostate_stopped)
if (renderer->state == audiostate_playing &&
common_strcmp(renderer->audio->key, vorbis->key) == 0)
{
return renderer;
sameAudioPlayingCount++;
}
else if (renderer->state == audiostate_stopped && freeIndex == -1)
{
freeIndex = i;
}
}
return NULL;
if (sameAudioPlayingCount < maxSimultaneousPlayers && freeIndex != -1)
{
result = &world->audioRenderer[freeIndex];
}
return result;
}
INTERNAL void addPlayer(World *world)
{
Entity *ship = &world->entityList[world->entityIndex++];
ship->id = world->entityIdCounter++;
ship->pos = math_rectGetCentre(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(&world->entityArena,
sizeof(v2) * ship->numVertexPoints);
v2 triangleBaseP = V2(0, 0);
v2 triangleTopP = V2(ship->size.w * 0.5f, ship->size.h);
v2 triangleRightP = V2(ship->size.w, triangleBaseP.y);
ship->vertexPoints[0] = triangleBaseP;
ship->vertexPoints[1] = triangleRightP;
ship->vertexPoints[2] = triangleTopP;
ship->scale = 1;
ship->type = entitytype_ship;
ship->renderMode = rendermode_polygon;
ship->color = V4(1.0f, 0.5f, 0.5f, 1.0f);
}
INTERNAL void deleteEntity(World *world, i32 entityIndex)
@ -497,37 +547,11 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
}
{ // Init audio renderer
world->numAudioRenderers = 6;
world->numAudioRenderers = 8;
world->audioRenderer = MEMORY_PUSH_ARRAY(
&world->entityArena, world->numAudioRenderers, AudioRenderer);
}
{ // Init ship entity
Entity *ship = &world->entityList[world->entityIndex++];
ship->id = world->entityIdCounter++;
ship->pos = math_rectGetCentre(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(
&world->entityArena, sizeof(v2) * ship->numVertexPoints);
v2 triangleBaseP = V2(0, 0);
v2 triangleTopP = V2(ship->size.w * 0.5f, ship->size.h);
v2 triangleRightP = V2(ship->size.w, triangleBaseP.y);
ship->vertexPoints[0] = triangleBaseP;
ship->vertexPoints[1] = triangleRightP;
ship->vertexPoints[2] = triangleTopP;
ship->scale = 1;
ship->type = entitytype_ship;
ship->renderMode = rendermode_polygon;
ship->color = V4(1.0f, 0.5f, 0.5f, 1.0f);
}
{ // Global Collision Rules
setCollisionRule(world, entitytype_ship, entitytype_asteroid_small,
TRUE);
@ -543,19 +567,32 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
entitytype_asteroid_large, TRUE);
}
world->numStarP = 100;
world->starPList =
MEMORY_PUSH_ARRAY(&state->persistentArena, world->numStarP, v2);
for (i32 i = 0; i < world->numStarP; i++)
{
i32 randX = rand() % (i32)world->worldSize.x;
i32 randY = rand() % (i32)world->worldSize.y;
world->starPList[i] = V2i(randX, randY);
}
world->init = TRUE;
world->onInitAsteroidSpawnTimer = 1.0f;
}
if (world->onInitAsteroidSpawnTimer > 0)
{
world->onInitAsteroidSpawnTimer -= dt;
}
else
{
for (u32 i = world->asteroidCounter; i < world->numAsteroids; i++)
addAsteroid(world, (rand() % asteroidsize_count));
Radians starRotation = DEGREES_TO_RADIANS(45.0f);
v2 starSize = V2(2, 2);
for (i32 i = 0; i < world->numStarP; i++)
{
renderer_rect(&state->renderer, world->camera, world->starPList[i],
starSize, V2(0, 0), starRotation, NULL,
V4(1.0f, 1.0f, 0, 0.5f),
renderflag_no_texture | renderflag_wireframe);
}
if (platform_queryKey(&state->input.keys[keycode_left_square_bracket],
@ -592,16 +629,17 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
{
addBullet(world, entity);
AudioRenderer *audioRenderer = getFreeAudioRenderer(world);
if (audioRenderer)
{
AudioVorbis *fire =
asset_vorbisGet(&state->assetManager, "fire");
AudioRenderer *audioRenderer =
getFreeAudioRenderer(world, fire, 2);
if (audioRenderer)
{
// 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);
}
}
@ -863,9 +901,6 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
ASSERT(world->asteroidCounter >= 0);
AudioRenderer *audioRenderer = getFreeAudioRenderer(world);
if (audioRenderer)
{
char *sound;
i32 choice = rand() % 3;
if (choice == 0)
@ -883,6 +918,10 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
AudioVorbis *explode =
asset_vorbisGet(&state->assetManager, sound);
AudioRenderer *audioRenderer =
getFreeAudioRenderer(world, explode, 3);
if (audioRenderer)
{
audio_vorbisPlay(&state->transientArena,
&state->audioManager, audioRenderer,
explode, 1);
@ -907,37 +946,60 @@ INTERNAL void gameUpdate(GameState *state, Memory *memory, f32 dt)
}
}
LOCAL_PERSIST f32 flashingGameStartTimerThreshold = 1.0f;
LOCAL_PERSIST f32 flashingGameStartTimer = 1.0f;
LOCAL_PERSIST b32 toggleShowGameStart = TRUE;
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;
Renderer *renderer = &state->renderer;
MemoryArena_ *transientArena = &state->transientArena;
UiState *uiState = &state->uiState;
World *world = &state->world;
Font *arial15 = asset_fontGetOrCreateOnDemand(
assetManager, &state->persistentArena, transientArena, "Arial", 15);
Font *arial25 = asset_fontGetOrCreateOnDemand(
assetManager, &state->persistentArena, transientArena, "Arial", 40);
f32 margin = 20.0f;
f32 padding = 20.0f;
v2 titleP = V2(margin, renderer->size.h - 100 + margin);
renderer_stringFixed(renderer, transientArena, arial25, "Asteroids",
titleP, V2(0, 0), 0, V4(1, 0, 0, 1), 0);
v2 screenCenter = v2_scale(renderer->size, 0.5f);
const char *const title = "Asteroids";
v2 titleDim = asset_fontStringDimInPixels(arial25, title);
v2 halfTitleDim = v2_scale(titleDim, 0.5f);
v2 titleP = v2_add(screenCenter, V2(0, 40));
titleP = v2_sub(titleP, halfTitleDim);
renderer_stringFixed(renderer, transientArena, arial25, title, titleP,
V2(0, 0), 0, V4(1, 0, 0, 1), 0);
ui_beginState(uiState);
Rect buttonRect = {0};
buttonRect.min = V2(margin, margin);
buttonRect.max = V2(margin + 100, margin + 40);
buttonRect = math_rectShift(buttonRect, V2(0, titleP.y - 100));
if (ui_button(uiState, transientArena, assetManager, renderer,
arial15, *inputBuffer, 1, buttonRect,
"Start Game"))
flashingGameStartTimer -= dt;
if (flashingGameStartTimer < 0)
{
toggleShowGameStart = (toggleShowGameStart) ? FALSE : TRUE;
flashingGameStartTimer = flashingGameStartTimerThreshold;
}
if (toggleShowGameStart)
{
const char *const gameStart = "Press enter to start";
v2 gameStartDim = asset_fontStringDimInPixels(arial25, gameStart);
v2 halfGameStartDim = v2_scale(gameStartDim, 0.5f);
v2 gameStartP = v2_add(screenCenter, V2(0, -40));
gameStartP = v2_sub(gameStartP, halfGameStartDim);
renderer_stringFixed(renderer, transientArena, arial25, gameStart,
gameStartP, V2(0, 0), 0, V4(1, 1, 0, 1), 0);
}
if (platform_queryKey(&inputBuffer->keys[keycode_enter],
readkeytype_one_shot, KEY_DELAY_NONE))
{
state->appState = appstate_game;
addPlayer(&state->world);
}
ui_endState(uiState, inputBuffer);
@ -976,10 +1038,10 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
{
case appstate_start_menu:
{
// NOTE(doyle): Let menu overlay the game menu. We add player on "enter"
// So fall through to appstate_game is valid here!
startMenuUpdate(state, memory, dt);
}
break;
case appstate_game:
{
gameUpdate(state, memory, dt);

View File

@ -49,10 +49,10 @@ Texture *asset_loadTextureImage(AssetManager *assetManager, MemoryArena_ *arena,
* Animation Asset Managing
*********************************
*/
void asset_animAdd(AssetManager *const assetManager,
MemoryArena_ *const arena, const char *const animName,
TexAtlas *const atlas, char **const subTextureNames,
const i32 numSubTextures, const f32 frameDuration);
void asset_animAdd(AssetManager *const assetManager, MemoryArena_ *const arena,
const char *const animName, TexAtlas *const atlas,
char **const subTextureNames, const i32 numSubTextures,
const f32 frameDuration);
Animation *asset_animGet(AssetManager *const assetManager,
const char *const key);
@ -85,8 +85,7 @@ Font *asset_fontGetOrCreateOnDemand(AssetManager *assetManager,
MemoryArena_ *persistentArena,
MemoryArena_ *transientArena, char *name,
i32 size);
Font *asset_fontGet(AssetManager *assetManager, char *name,
i32 size);
Font *asset_fontGet(AssetManager *assetManager, char *name, i32 size);
const i32 asset_fontLoadTTF(AssetManager *assetManager,
MemoryArena_ *persistentArena,
MemoryArena_ *transientArena, char *filePath,

View File

@ -20,11 +20,6 @@ enum AppState
typedef struct World
{
b32 init;
// NOTE(doyle): Grace period when game starts before asteroids start
// spawning
f32 onInitAsteroidSpawnTimer;
MemoryArena_ entityArena;
v2 *entityVertexListCache[entitytype_count];
@ -41,6 +36,9 @@ typedef struct World
v2 *bulletVertexCache;
v2 *particleVertexCache;
v2 *starPList;
i32 numStarP;
// TODO(doyle): Audio mixing instead of multiple renderers
AudioRenderer *audioRenderer;
i32 numAudioRenderers;
@ -68,7 +66,6 @@ typedef struct GameState {
UiState uiState;
World world;
} GameState;
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,