Add basic sound effects to game

This commit is contained in:
Doyle Thai 2016-11-24 22:54:07 +11:00
parent be1c009dfb
commit ea6ea02404
4 changed files with 150 additions and 38 deletions

View File

@ -6,46 +6,89 @@ void initAssetManager(GameState *state)
AssetManager *assetManager = &state->assetManager; AssetManager *assetManager = &state->assetManager;
MemoryArena_ *arena = &state->persistentArena; MemoryArena_ *arena = &state->persistentArena;
i32 audioEntries = 32;
assetManager->audio.size = audioEntries;
assetManager->audio.entries =
memory_pushBytes(arena, audioEntries * sizeof(HashTableEntry));
i32 texAtlasEntries = 8; i32 texAtlasEntries = 8;
assetManager->texAtlas.size = texAtlasEntries; assetManager->texAtlas.size = texAtlasEntries;
assetManager->texAtlas.entries = assetManager->texAtlas.entries =
memory_pushBytes(arena, texAtlasEntries * sizeof(HashTableEntry)); 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; i32 animEntries = 1024;
assetManager->anims.size = animEntries; assetManager->anims.size = animEntries;
assetManager->anims.entries = assetManager->anims.entries =
memory_pushBytes(arena, animEntries * sizeof(HashTableEntry)); memory_pushBytes(arena, animEntries * sizeof(HashTableEntry));
/* Create empty 1x1 4bpp black texture */ { // Init texture assets
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0); i32 texEntries = 32;
Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex"); assetManager->textures.size = texEntries;
*tex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap)); assetManager->textures.entries =
memory_pushBytes(arena, texEntries * sizeof(HashTableEntry));
/* Load shaders */ /* Create empty 1x1 4bpp black texture */
asset_loadShaderFiles( u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
assetManager, arena, "data/shaders/default_tex.vert.glsl", Texture *tex = asset_getFreeTexSlot(assetManager, arena, "nullTex");
"data/shaders/default_tex.frag.glsl", shaderlist_default); *tex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap));
asset_loadShaderFiles( i32 result = asset_loadTTFont(assetManager, arena,
assetManager, arena, "data/shaders/default_no_tex.vert.glsl", "C:/Windows/Fonts/Arialbd.ttf");
"data/shaders/default_no_tex.frag.glsl", shaderlist_default_no_tex); }
i32 result = { // Init shaders assets
asset_loadTTFont(assetManager, arena, "C:/Windows/Fonts/Arialbd.ttf"); asset_loadShaderFiles(
if (result) ASSERT(TRUE); assetManager, arena, "data/shaders/default_tex.vert.glsl",
"data/shaders/default_tex.frag.glsl", shaderlist_default);
asset_loadShaderFiles(
assetManager, arena, "data/shaders/default_no_tex.vert.glsl",
"data/shaders/default_no_tex.frag.glsl", shaderlist_default_no_tex);
}
{ // 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");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/bang_medium.ogg",
"bang_medium");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/bang_small.ogg",
"bang_small");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/beat1.ogg", "beat1");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/beat2.ogg", "beat2");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/extra_ship.ogg",
"extra_ship");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/fire.ogg", "fire");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/saucer_big.ogg",
"saucer_big");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/saucer_small.ogg",
"saucer_small");
ASSERT(!result);
result = asset_loadVorbis(assetManager, arena,
"data/audio/Asteroids/thrust.ogg", "thrust");
ASSERT(!result);
}
} }
void initRenderer(GameState *state, v2 windowSize) { void initRenderer(GameState *state, v2 windowSize)
{
AssetManager *assetManager = &state->assetManager; AssetManager *assetManager = &state->assetManager;
Renderer *renderer = &state->renderer; Renderer *renderer = &state->renderer;
renderer->size = windowSize; renderer->size = windowSize;
@ -446,6 +489,20 @@ INTERNAL void setCollisionRule(World *world, enum EntityType a,
world->collisionTable[b][a] = rule; world->collisionTable[b][a] = rule;
} }
INTERNAL AudioRenderer *getFreeAudioRenderer(World *world)
{
for (i32 i = 0; i < world->numAudioRenderers; i++)
{
AudioRenderer *renderer = &world->audioRenderer[i];
if (renderer->state == audiostate_stopped)
{
return renderer;
}
}
return NULL;
}
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
v2 windowSize, f32 dt) v2 windowSize, f32 dt)
{ {
@ -460,6 +517,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
srand((u32)time(NULL)); srand((u32)time(NULL));
initAssetManager(state); initAssetManager(state);
initRenderer(state, windowSize); initRenderer(state, windowSize);
audio_init(&state->audioManager);
world->pixelsPerMeter = 70.0f; world->pixelsPerMeter = 70.0f;
@ -473,10 +531,17 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
Entity *nullEntity = &world->entityList[world->entityIndex++]; Entity *nullEntity = &world->entityList[world->entityIndex++];
nullEntity->id = world->entityIdCounter++; nullEntity->id = world->entityIdCounter++;
} }
{ // Init asteroid entities { // Init asteroid entities
world->numAsteroids = 15; world->numAsteroids = 15;
} }
{ // Init audio renderer
world->numAudioRenderers = 6;
world->audioRenderer = MEMORY_PUSH_ARRAY(
&world->entityArena, world->numAudioRenderers, AudioRenderer);
}
{ // Init ship entity { // Init ship entity
Entity *ship = &world->entityList[world->entityIndex++]; Entity *ship = &world->entityList[world->entityIndex++];
ship->id = world->entityIdCounter++; ship->id = world->entityIdCounter++;
@ -595,6 +660,18 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
readkeytype_delayedRepeat, 0.05f, dt)) readkeytype_delayedRepeat, 0.05f, dt))
{ {
addBullet(world, entity); addBullet(world, entity);
AudioRenderer *audioRenderer = getFreeAudioRenderer(world);
if (audioRenderer)
{
AudioVorbis *fire =
asset_getVorbis(&state->assetManager, "fire");
// TODO(doyle): Atm transient arena is not used, this is
// just to fill out the arguments
audio_playVorbis(&state->transientArena,
&state->audioManager, audioRenderer, fire,
1);
}
} }
if (ddP.x > 0.0f && ddP.y > 0.0f) if (ddP.x > 0.0f && ddP.y > 0.0f)
@ -704,7 +781,7 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
continue; continue;
} }
ddPSpeedInMs = 25; ddPSpeedInMs = 10;
Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f)); Radians rotation = DEGREES_TO_RADIANS((entity->rotation + 90.0f));
ddP = V2(math_cosf(rotation), math_sinf(rotation)); ddP = V2(math_cosf(rotation), math_sinf(rotation));
entity->dP = v2_scale(ddP, world->pixelsPerMeter * ddPSpeedInMs); entity->dP = v2_scale(ddP, world->pixelsPerMeter * ddPSpeedInMs);
@ -749,16 +826,39 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
if (colliderA->type == entitytype_asteroid) if (colliderA->type == entitytype_asteroid)
{ {
ASSERT(colliderB->type == entitytype_bullet); ASSERT(colliderB->type == entitytype_bullet);
world->entityList[collisionIndex] = world->entityList[collisionIndex] =
world->entityList[--world->entityIndex]; world->entityList[--world->entityIndex];
world->entityList[i--] = world->entityList[i--] =
world->entityList[--world->entityIndex]; world->entityList[--world->entityIndex];
world->asteroidCounter--; world->asteroidCounter--;
ASSERT(world->asteroidCounter >= 0); ASSERT(world->asteroidCounter >= 0);
AudioRenderer *audioRenderer = getFreeAudioRenderer(world);
if (audioRenderer)
{
char *sound;
i32 choice = rand() % 3;
if (choice == 0)
{
sound = "bang_small";
}
else if (choice == 1)
{
sound = "bang_medium";
}
else
{
sound = "bang_large";
}
AudioVorbis *explode =
asset_getVorbis(&state->assetManager, sound);
audio_playVorbis(&state->transientArena,
&state->audioManager, audioRenderer,
explode, 1);
}
continue; continue;
} }
} }
@ -769,6 +869,13 @@ void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,
collideColor, flags); collideColor, flags);
} }
for (i32 i = 0; i < world->numAudioRenderers; i++)
{
AudioRenderer *audioRenderer = &world->audioRenderer[i];
audio_updateAndPlay(&state->transientArena, &state->audioManager,
audioRenderer);
}
#if 1 #if 1
debug_drawUi(state, dt); debug_drawUi(state, dt);
debug_clearCounter(); debug_clearCounter();

View File

@ -299,6 +299,9 @@ const i32 audio_streamPlayVorbis(MemoryArena_ *arena, AudioManager *audioManager
AudioVorbis *vorbis, i32 numPlays) AudioVorbis *vorbis, i32 numPlays)
{ {
// TODO(doyle): Streaming leaks memory, we don't free the "copy audio"
ASSERT(INVALID_CODE_PATH);
i32 result = initRendererForPlayback(arena, audioManager, audioRenderer, i32 result = initRendererForPlayback(arena, audioManager, audioRenderer,
vorbis, numPlays); vorbis, numPlays);
// NOTE(doyle): We make a copy of the audio vorbis file using all the same // NOTE(doyle): We make a copy of the audio vorbis file using all the same

View File

@ -2,6 +2,7 @@
#define ASTEROID_H #define ASTEROID_H
#include "Dengine/AssetManager.h" #include "Dengine/AssetManager.h"
#include "Dengine/Audio.h"
#include "Dengine/Common.h" #include "Dengine/Common.h"
#include "Dengine/Entity.h" #include "Dengine/Entity.h"
#include "Dengine/MemoryArena.h" #include "Dengine/MemoryArena.h"
@ -23,6 +24,10 @@ typedef struct World
v2 *asteroidVertexCache[10]; v2 *asteroidVertexCache[10];
v2 *bulletVertexCache; v2 *bulletVertexCache;
// TODO(doyle): Audio mixing instead of multiple renderers
AudioRenderer *audioRenderer;
i32 numAudioRenderers;
f32 pixelsPerMeter; f32 pixelsPerMeter;
v2 worldSize; v2 worldSize;
Rect camera; Rect camera;
@ -34,14 +39,15 @@ typedef struct World
typedef struct GameState { typedef struct GameState {
b32 init; b32 init;
World world;
AssetManager assetManager;
KeyInput input;
MemoryArena_ transientArena; MemoryArena_ transientArena;
MemoryArena_ persistentArena; MemoryArena_ persistentArena;
AudioManager audioManager;
AssetManager assetManager;
KeyInput input;
Renderer renderer; Renderer renderer;
World world;
} GameState; } GameState;
void asteroid_gameUpdateAndRender(GameState *state, Memory *memory, void asteroid_gameUpdateAndRender(GameState *state, Memory *memory,

View File

@ -77,10 +77,6 @@ typedef struct Entity
EntityAnim animList[16]; EntityAnim animList[16];
i32 animListIndex; i32 animListIndex;
// TODO(doyle): Audio mixing instead of multiple renderers
AudioRenderer *audioRenderer;
i32 numAudioRenderers;
} Entity; } Entity;
SubTexture entity_getActiveSubTexture(Entity *const entity); SubTexture entity_getActiveSubTexture(Entity *const entity);