Add entity attack audio cue
This commit is contained in:
parent
9ec87fc8be
commit
190822c1f6
@ -131,7 +131,6 @@
|
|||||||
<ClCompile Include="src\Shader.c" />
|
<ClCompile Include="src\Shader.c" />
|
||||||
<ClCompile Include="src\WorldTraveller.c" />
|
<ClCompile Include="src\WorldTraveller.c" />
|
||||||
<ClCompile Include="src\Texture.c" />
|
<ClCompile Include="src\Texture.c" />
|
||||||
<ClCompile Include="src\Tutorial.cpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="data\shaders\default.frag.glsl" />
|
<None Include="data\shaders\default.frag.glsl" />
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\Tutorial.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="src\WorldTraveller.c">
|
<ClCompile Include="src\WorldTraveller.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -80,6 +80,7 @@ const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
|
|||||||
|
|
||||||
i32 error;
|
i32 error;
|
||||||
AudioVorbis audio = {0};
|
AudioVorbis audio = {0};
|
||||||
|
audio.type = type;
|
||||||
audio.file =
|
audio.file =
|
||||||
stb_vorbis_open_memory(fileRead.buffer, fileRead.size, &error, NULL);
|
stb_vorbis_open_memory(fileRead.buffer, fileRead.size, &error, NULL);
|
||||||
|
|
||||||
@ -94,6 +95,8 @@ const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
|
|||||||
audio.info = stb_vorbis_get_info(audio.file);
|
audio.info = stb_vorbis_get_info(audio.file);
|
||||||
audio.lengthInSamples = stb_vorbis_stream_length_in_samples(audio.file);
|
audio.lengthInSamples = stb_vorbis_stream_length_in_samples(audio.file);
|
||||||
audio.lengthInSeconds = stb_vorbis_stream_length_in_seconds(audio.file);
|
audio.lengthInSeconds = stb_vorbis_stream_length_in_seconds(audio.file);
|
||||||
|
audio.data = CAST(u8 *) fileRead.buffer;
|
||||||
|
audio.size = fileRead.size;
|
||||||
|
|
||||||
assetManager->audio[type] = audio;
|
assetManager->audio[type] = audio;
|
||||||
|
|
||||||
|
125
src/Audio.c
125
src/Audio.c
@ -6,6 +6,8 @@
|
|||||||
#include "Dengine/Assets.h"
|
#include "Dengine/Assets.h"
|
||||||
#include "Dengine/Audio.h"
|
#include "Dengine/Audio.h"
|
||||||
#include "Dengine/Debug.h"
|
#include "Dengine/Debug.h"
|
||||||
|
#include "Dengine/MemoryArena.h"
|
||||||
|
#include "dengine/Platform.h"
|
||||||
|
|
||||||
#define AL_CHECK_ERROR() alCheckError_(__FILE__, __LINE__);
|
#define AL_CHECK_ERROR() alCheckError_(__FILE__, __LINE__);
|
||||||
void alCheckError_(const char *file, int line)
|
void alCheckError_(const char *file, int line)
|
||||||
@ -101,13 +103,8 @@ const i32 audio_init(AudioManager *audioManager)
|
|||||||
alGenSources(1, &audioManager->sourceList[i].id);
|
alGenSources(1, &audioManager->sourceList[i].id);
|
||||||
AL_CHECK_ERROR();
|
AL_CHECK_ERROR();
|
||||||
|
|
||||||
// NOTE(doyle): If last entry, loop the free source to front of list
|
audioManager->sourceList[i].isFree = TRUE;
|
||||||
if (i + 1 >= ARRAY_COUNT(audioManager->sourceList))
|
|
||||||
audioManager->sourceList[i].nextFreeIndex = 0;
|
|
||||||
else
|
|
||||||
audioManager->sourceList[i].nextFreeIndex = i+1;
|
|
||||||
}
|
}
|
||||||
audioManager->freeSourceIndex = 0;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -119,44 +116,41 @@ INTERNAL inline u32 getSourceId(AudioManager *audioManager,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL i32 rendererAcquire(AudioManager *audioManager,
|
INTERNAL i32 rendererAcquire(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer)
|
AudioRenderer *audioRenderer)
|
||||||
{
|
{
|
||||||
|
|
||||||
i32 vacantSource = audioManager->freeSourceIndex;
|
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(audioManager && audioRenderer);
|
ASSERT(arena && audioManager && audioRenderer);
|
||||||
ASSERT(vacantSource >= 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (audioManager->sourceList[vacantSource].nextFreeIndex ==
|
|
||||||
AUDIO_NO_FREE_SOURCE)
|
|
||||||
{
|
|
||||||
// TODO(doyle): Error messaging return paths
|
|
||||||
DEBUG_LOG("rendererAcquire(): Failed to acquire free source, all busy");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 checkSource = getSourceId(audioManager, audioRenderer);
|
u32 checkSource = getSourceId(audioManager, audioRenderer);
|
||||||
if (alIsSource(checkSource) == AL_TRUE)
|
if (alIsSource(checkSource) == AL_TRUE)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(
|
DEBUG_LOG(
|
||||||
"rendererAcquire(): Renderer has not been released before "
|
"rendererAcquire(): Renderer has not been released before "
|
||||||
"acquiring, force release by stopping stream");
|
"acquiring, force release by stopping stream");
|
||||||
audio_streamStopVorbis(audioManager, audioRenderer);
|
audio_streamStopVorbis(arena, audioManager, audioRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(doyle): Super bad linear O(n) search for every audio-enabled entity
|
||||||
|
i32 vacantSource = AUDIO_SOURCE_UNASSIGNED;
|
||||||
|
for (i32 i = 0; i < ARRAY_COUNT(audioManager->sourceList); i++)
|
||||||
|
{
|
||||||
|
if (audioManager->sourceList[i].isFree)
|
||||||
|
{
|
||||||
|
vacantSource = i;
|
||||||
|
audioManager->sourceList[i].isFree = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vacantSource == AUDIO_SOURCE_UNASSIGNED)
|
||||||
|
{
|
||||||
|
DEBUG_LOG("rendererAcquire(): Failed to acquire free source, all busy");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assign a vacant source slot to renderer */
|
|
||||||
audioRenderer->sourceIndex = vacantSource;
|
audioRenderer->sourceIndex = vacantSource;
|
||||||
|
|
||||||
/* Update the immediate free source index */
|
|
||||||
audioManager->freeSourceIndex =
|
|
||||||
audioManager->sourceList[vacantSource].nextFreeIndex;
|
|
||||||
|
|
||||||
/* Mark current source as in use */
|
|
||||||
audioManager->sourceList[vacantSource].nextFreeIndex = AUDIO_NO_FREE_SOURCE;
|
|
||||||
|
|
||||||
/* Generate audio data buffers */
|
/* Generate audio data buffers */
|
||||||
alGenBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId);
|
alGenBuffers(ARRAY_COUNT(audioRenderer->bufferId), audioRenderer->bufferId);
|
||||||
AL_CHECK_ERROR();
|
AL_CHECK_ERROR();
|
||||||
@ -166,7 +160,7 @@ INTERNAL i32 rendererAcquire(AudioManager *audioManager,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL const i32 rendererRelease(AudioManager *audioManager,
|
INTERNAL const i32 rendererRelease(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer)
|
AudioRenderer *audioRenderer)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -181,8 +175,29 @@ INTERNAL const i32 rendererRelease(AudioManager *audioManager,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
alSourceUnqueueBuffers(alSourceId, ARRAY_COUNT(audioRenderer->bufferId),
|
/*
|
||||||
|
NOTE(doyle): Doing an alSourceRewind will result in the source going to
|
||||||
|
the AL_INITIAL state, but the properties of the source (position,
|
||||||
|
velocity, etc.) will not change.
|
||||||
|
*/
|
||||||
|
alSourceRewind(alSourceId);
|
||||||
|
AL_CHECK_ERROR();
|
||||||
|
|
||||||
|
// TODO(doyle): We can possible remove this by just attaching the null buffer ..
|
||||||
|
ALint numProcessedBuffers;
|
||||||
|
alGetSourcei(alSourceId, AL_BUFFERS_PROCESSED, &numProcessedBuffers);
|
||||||
|
if (numProcessedBuffers > 0)
|
||||||
|
{
|
||||||
|
alSourceUnqueueBuffers(alSourceId, numProcessedBuffers,
|
||||||
audioRenderer->bufferId);
|
audioRenderer->bufferId);
|
||||||
|
}
|
||||||
|
AL_CHECK_ERROR();
|
||||||
|
|
||||||
|
// NOTE(doyle): Any buffer queued up that has not been played cannot be
|
||||||
|
// deleted without being played once. We can set the source buffers to NULL
|
||||||
|
// (0) to free up the buffer, since we still hold the reference ids for the
|
||||||
|
// buffer in our audio structure we can delete it afterwards ..
|
||||||
|
alSourcei(alSourceId, AL_BUFFER, 0);
|
||||||
alDeleteBuffers(ARRAY_COUNT(audioRenderer->bufferId),
|
alDeleteBuffers(ARRAY_COUNT(audioRenderer->bufferId),
|
||||||
audioRenderer->bufferId);
|
audioRenderer->bufferId);
|
||||||
AL_CHECK_ERROR();
|
AL_CHECK_ERROR();
|
||||||
@ -192,21 +207,22 @@ INTERNAL const i32 rendererRelease(AudioManager *audioManager,
|
|||||||
audioRenderer->bufferId[i] = 0;
|
audioRenderer->bufferId[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stb_vorbis_close(audioRenderer->audio->file);
|
||||||
|
PLATFORM_MEM_FREE(arena, audioRenderer->audio, sizeof(AudioVorbis));
|
||||||
|
|
||||||
audioRenderer->audio = NULL;
|
audioRenderer->audio = NULL;
|
||||||
audioRenderer->numPlays = 0;
|
audioRenderer->numPlays = 0;
|
||||||
|
|
||||||
u32 sourceIndexToFree = audioRenderer->sourceIndex;
|
u32 sourceIndexToFree = audioRenderer->sourceIndex;
|
||||||
audioRenderer->sourceIndex = AUDIO_SOURCE_UNASSIGNED;
|
audioRenderer->sourceIndex = AUDIO_SOURCE_UNASSIGNED;
|
||||||
|
|
||||||
audioManager->sourceList[sourceIndexToFree].nextFreeIndex =
|
audioManager->sourceList[sourceIndexToFree].isFree = TRUE;
|
||||||
audioManager->freeSourceIndex;
|
|
||||||
audioManager->freeSourceIndex = sourceIndexToFree;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define AUDIO_CHUNK_SIZE_ 65536
|
#define AUDIO_CHUNK_SIZE_ 65536
|
||||||
const i32 audio_streamPlayVorbis(AudioManager *audioManager,
|
const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer,
|
AudioRenderer *audioRenderer,
|
||||||
AudioVorbis *vorbis, i32 numPlays)
|
AudioVorbis *vorbis, i32 numPlays)
|
||||||
{
|
{
|
||||||
@ -218,7 +234,7 @@ const i32 audio_streamPlayVorbis(AudioManager *audioManager,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
i32 result = rendererAcquire(audioManager, audioRenderer);
|
i32 result = rendererAcquire(arena, audioManager, audioRenderer);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("audio_streamPlayVorbis() failed: Could not acquire renderer");
|
DEBUG_LOG("audio_streamPlayVorbis() failed: Could not acquire renderer");
|
||||||
@ -237,13 +253,30 @@ const i32 audio_streamPlayVorbis(AudioManager *audioManager,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
audioRenderer->audio = vorbis;
|
// NOTE(doyle): We make a copy of the audio vorbis file using all the same
|
||||||
|
// data except the file pointer. If the same sound is playing twice
|
||||||
|
// simultaneously, we need unique file pointers into the data to track song
|
||||||
|
// position uniquely
|
||||||
|
AudioVorbis *copyAudio = PLATFORM_MEM_ALLOC(arena, 1, AudioVorbis);
|
||||||
|
copyAudio->type = vorbis->type;
|
||||||
|
copyAudio->info = vorbis->info;
|
||||||
|
copyAudio->lengthInSamples = vorbis->lengthInSamples;
|
||||||
|
copyAudio->lengthInSeconds = vorbis->lengthInSeconds;
|
||||||
|
|
||||||
|
copyAudio->data = vorbis->data;
|
||||||
|
copyAudio->size = vorbis->size;
|
||||||
|
|
||||||
|
i32 error;
|
||||||
|
copyAudio->file =
|
||||||
|
stb_vorbis_open_memory(copyAudio->data, copyAudio->size, &error, NULL);
|
||||||
|
|
||||||
|
audioRenderer->audio = copyAudio;
|
||||||
audioRenderer->numPlays = numPlays;
|
audioRenderer->numPlays = numPlays;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const i32 audio_streamStopVorbis(AudioManager *audioManager,
|
const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer)
|
AudioRenderer *audioRenderer)
|
||||||
{
|
{
|
||||||
i32 result = 0;
|
i32 result = 0;
|
||||||
@ -252,7 +285,7 @@ const i32 audio_streamStopVorbis(AudioManager *audioManager,
|
|||||||
{
|
{
|
||||||
alSourceStop(alSourceId);
|
alSourceStop(alSourceId);
|
||||||
AL_CHECK_ERROR();
|
AL_CHECK_ERROR();
|
||||||
result = rendererRelease(audioManager, audioRenderer);
|
result = rendererRelease(arena, audioManager, audioRenderer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -300,18 +333,20 @@ const i32 audio_streamResumeVorbis(AudioManager *audioManager,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const i32 audio_updateAndPlay(AudioManager *audioManager,
|
const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer)
|
AudioRenderer *audioRenderer)
|
||||||
{
|
{
|
||||||
AudioVorbis *audio = audioRenderer->audio;
|
AudioVorbis *audio = audioRenderer->audio;
|
||||||
if (!audio) return 0;
|
if (!audio) return 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (audioRenderer->numPlays != AUDIO_REPEAT_INFINITE &&
|
if (audioRenderer->numPlays != AUDIO_REPEAT_INFINITE &&
|
||||||
audioRenderer->numPlays <= 0)
|
audioRenderer->numPlays <= 0)
|
||||||
{
|
{
|
||||||
i32 result = rendererRelease(audioManager, audioRenderer);
|
i32 result = rendererRelease(arena, audioManager, audioRenderer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 alSourceId = getSourceId(audioManager, audioRenderer);
|
u32 alSourceId = getSourceId(audioManager, audioRenderer);
|
||||||
if (alIsSource(alSourceId) == AL_FALSE)
|
if (alIsSource(alSourceId) == AL_FALSE)
|
||||||
@ -345,13 +380,12 @@ const i32 audio_updateAndPlay(AudioManager *audioManager,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
i32 result = rendererRelease(audioManager, audioRenderer);
|
i32 result =
|
||||||
|
rendererRelease(arena, audioManager, audioRenderer);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(doyle): Possible bug! Multiple sources playing same file seeking
|
|
||||||
// file ptr to start may interrupt other stream
|
|
||||||
stb_vorbis_seek_start(audio->file);
|
stb_vorbis_seek_start(audio->file);
|
||||||
for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++)
|
for (i32 i = 0; i < ARRAY_COUNT(audioRenderer->bufferId); i++)
|
||||||
{
|
{
|
||||||
@ -380,6 +414,7 @@ const i32 audio_updateAndPlay(AudioManager *audioManager,
|
|||||||
AL_CHECK_ERROR();
|
AL_CHECK_ERROR();
|
||||||
if (numProcessedBuffers > 0)
|
if (numProcessedBuffers > 0)
|
||||||
{
|
{
|
||||||
|
// TODO(doyle): Possibly wrong, we should pass in all processed buffers?
|
||||||
ALint numBuffersToUnqueue = 1;
|
ALint numBuffersToUnqueue = 1;
|
||||||
ALuint emptyBufferId;
|
ALuint emptyBufferId;
|
||||||
alSourceUnqueueBuffers(alSourceId, numBuffersToUnqueue,
|
alSourceUnqueueBuffers(alSourceId, numBuffersToUnqueue,
|
||||||
|
29
src/Debug.c
29
src/Debug.c
@ -189,6 +189,13 @@ void debug_pushString(char *formatString, void *data, char *dataType)
|
|||||||
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
||||||
formatString, val.x, val.y);
|
formatString, val.x, val.y);
|
||||||
}
|
}
|
||||||
|
else if (common_strcmp(dataType, "v3") == 0)
|
||||||
|
{
|
||||||
|
v3 val = *(CAST(v3 *) data);
|
||||||
|
snprintf(GLOBAL_debug.debugStrings[numDebugStrings],
|
||||||
|
ARRAY_COUNT(GLOBAL_debug.debugStrings[0]),
|
||||||
|
formatString, val.x, val.y, val.z);
|
||||||
|
}
|
||||||
else if (common_strcmp(dataType, "i32") == 0)
|
else if (common_strcmp(dataType, "i32") == 0)
|
||||||
{
|
{
|
||||||
i32 val = *(CAST(i32 *) data);
|
i32 val = *(CAST(i32 *) data);
|
||||||
@ -394,6 +401,19 @@ void debug_drawUi(GameState *state, f32 dt)
|
|||||||
char *entityStateStr = debug_entitystate_string(entity->state);
|
char *entityStateStr = debug_entitystate_string(entity->state);
|
||||||
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
|
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
|
||||||
entityStateStr, strPos, V2(0, 0), 0, color);
|
entityStateStr, strPos, V2(0, 0), 0, color);
|
||||||
|
|
||||||
|
if (entity->audioRenderer)
|
||||||
|
{
|
||||||
|
strPos.y -= GLOBAL_debug.stringLineGap;
|
||||||
|
char entityAudioSourceIndex[32];
|
||||||
|
snprintf(entityAudioSourceIndex,
|
||||||
|
ARRAY_COUNT(entityAudioSourceIndex),
|
||||||
|
"AudioSource Index: %d",
|
||||||
|
entity->audioRenderer->sourceIndex);
|
||||||
|
renderer_string(&state->renderer, &state->arena, cameraBounds,
|
||||||
|
font, entityAudioSourceIndex, strPos, V2(0, 0),
|
||||||
|
0, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,6 +438,15 @@ void debug_drawUi(GameState *state, f32 dt)
|
|||||||
i32 debug_kbAllocated = state->arena.bytesAllocated / 1024;
|
i32 debug_kbAllocated = state->arena.bytesAllocated / 1024;
|
||||||
DEBUG_PUSH_VAR("TotalMemoryAllocated: %dkb", debug_kbAllocated, "i32");
|
DEBUG_PUSH_VAR("TotalMemoryAllocated: %dkb", debug_kbAllocated, "i32");
|
||||||
|
|
||||||
|
AudioManager *audioManager = &state->audioManager;
|
||||||
|
DEBUG_PUSH_STRING("== Audio System ==");
|
||||||
|
for (i32 i = 0; i < ARRAY_COUNT(audioManager->sourceList); i++)
|
||||||
|
{
|
||||||
|
v3 tmp = V3i(i, audioManager->sourceList[i].id,
|
||||||
|
audioManager->sourceList[i].isFree);
|
||||||
|
DEBUG_PUSH_VAR("Source ID[%02.0f].id[%02.0f].isFree: %1.0f", tmp, "v3");
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_PUSH_STRING("== EntityIDs in Battle List == ");
|
DEBUG_PUSH_STRING("== EntityIDs in Battle List == ");
|
||||||
DEBUG_PUSH_VAR("NumEntitiesInBattle: %d", world->numEntitiesInBattle,
|
DEBUG_PUSH_VAR("NumEntitiesInBattle: %d", world->numEntitiesInBattle,
|
||||||
"i32");
|
"i32");
|
||||||
|
10
src/Entity.c
10
src/Entity.c
@ -77,6 +77,9 @@ void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager,
|
|||||||
b32 collides = TRUE;
|
b32 collides = TRUE;
|
||||||
Entity *mob = entity_add(arena, world, pos, size, type, dir, tex, collides);
|
Entity *mob = entity_add(arena, world, pos, size, type, dir, tex, collides);
|
||||||
|
|
||||||
|
mob->audioRenderer = PLATFORM_MEM_ALLOC(arena, 1, AudioRenderer);
|
||||||
|
mob->audioRenderer->sourceIndex = AUDIO_SOURCE_UNASSIGNED;
|
||||||
|
|
||||||
/* Populate mob animation references */
|
/* Populate mob animation references */
|
||||||
entity_addAnim(assetManager, mob, animlist_hero_idle);
|
entity_addAnim(assetManager, mob, animlist_hero_idle);
|
||||||
entity_addAnim(assetManager, mob, animlist_hero_walk);
|
entity_addAnim(assetManager, mob, animlist_hero_walk);
|
||||||
@ -125,7 +128,7 @@ Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size,
|
|||||||
entity.stats = PLATFORM_MEM_ALLOC(arena, 1, EntityStats);
|
entity.stats = PLATFORM_MEM_ALLOC(arena, 1, EntityStats);
|
||||||
entity.stats->maxHealth = 100;
|
entity.stats->maxHealth = 100;
|
||||||
entity.stats->health = entity.stats->maxHealth;
|
entity.stats->health = entity.stats->maxHealth;
|
||||||
entity.stats->actionRate = 100;
|
entity.stats->actionRate = 80;
|
||||||
entity.stats->actionTimer = entity.stats->actionRate;
|
entity.stats->actionTimer = entity.stats->actionRate;
|
||||||
entity.stats->actionSpdMul = 100;
|
entity.stats->actionSpdMul = 100;
|
||||||
entity.stats->entityIdToAttack = -1;
|
entity.stats->entityIdToAttack = -1;
|
||||||
@ -147,8 +150,13 @@ Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size,
|
|||||||
void entity_delete(MemoryArena *arena, World *world, i32 entityIndex)
|
void entity_delete(MemoryArena *arena, World *world, i32 entityIndex)
|
||||||
{
|
{
|
||||||
Entity *entity = &world->entities[entityIndex];
|
Entity *entity = &world->entities[entityIndex];
|
||||||
|
|
||||||
|
if (entity->stats)
|
||||||
PLATFORM_MEM_FREE(arena, entity->stats, sizeof(EntityStats));
|
PLATFORM_MEM_FREE(arena, entity->stats, sizeof(EntityStats));
|
||||||
|
|
||||||
|
if (entity->audioRenderer)
|
||||||
|
PLATFORM_MEM_FREE(arena, entity->audioRenderer, sizeof(AudioRenderer));
|
||||||
|
|
||||||
// TODO(doyle): Inefficient shuffle down all elements
|
// TODO(doyle): Inefficient shuffle down all elements
|
||||||
for (i32 i = entityIndex; i < world->freeEntityIndex - 1; i++)
|
for (i32 i = entityIndex; i < world->freeEntityIndex - 1; i++)
|
||||||
world->entities[i] = world->entities[i + 1];
|
world->entities[i] = world->entities[i + 1];
|
||||||
|
@ -187,6 +187,8 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
|||||||
asset_loadVorbis(assetManager, arena, audioPath, audiolist_battle);
|
asset_loadVorbis(assetManager, arena, audioPath, audiolist_battle);
|
||||||
audioPath = "data/audio/Yuki Kajiura - Swordland.ogg";
|
audioPath = "data/audio/Yuki Kajiura - Swordland.ogg";
|
||||||
asset_loadVorbis(assetManager, arena, audioPath, audiolist_overworld);
|
asset_loadVorbis(assetManager, arena, audioPath, audiolist_overworld);
|
||||||
|
audioPath = "data/audio/nuindependent_hit22.ogg";
|
||||||
|
asset_loadVorbis(assetManager, arena, audioPath, audiolist_tackle);
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
DEBUG_LOG("Sound assets initialised");
|
DEBUG_LOG("Sound assets initialised");
|
||||||
@ -278,6 +280,8 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
|||||||
tex = asset_getTexture(assetManager, texlist_hero);
|
tex = asset_getTexture(assetManager, texlist_hero);
|
||||||
collides = TRUE;
|
collides = TRUE;
|
||||||
Entity *hero = entity_add(arena, world, pos, size, type, dir, tex, collides);
|
Entity *hero = entity_add(arena, world, pos, size, type, dir, tex, collides);
|
||||||
|
hero->audioRenderer = PLATFORM_MEM_ALLOC(arena, 1, AudioRenderer);
|
||||||
|
hero->audioRenderer->sourceIndex = AUDIO_SOURCE_UNASSIGNED;
|
||||||
|
|
||||||
/* Populate hero animation references */
|
/* Populate hero animation references */
|
||||||
entity_addAnim(assetManager, hero, animlist_hero_idle);
|
entity_addAnim(assetManager, hero, animlist_hero_idle);
|
||||||
@ -579,7 +583,6 @@ INTERNAL inline void resetEntityState(World *world, Entity *entity)
|
|||||||
|
|
||||||
INTERNAL void beginAttack(World *world, Entity *attacker)
|
INTERNAL void beginAttack(World *world, Entity *attacker)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
||||||
ASSERT(attacker->state == entitystate_battle);
|
ASSERT(attacker->state == entitystate_battle);
|
||||||
@ -596,17 +599,18 @@ INTERNAL void beginAttack(World *world, Entity *attacker)
|
|||||||
attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
|
attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
|
||||||
else
|
else
|
||||||
attacker->dPos.x -= (1.0f * METERS_TO_PIXEL);
|
attacker->dPos.x -= (1.0f * METERS_TO_PIXEL);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(INVALID_CODE_PATH);
|
ASSERT(INVALID_CODE_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
INTERNAL void endAttack(MemoryArena *arena, AssetManager *assetManager,
|
||||||
|
AudioManager *audioManager, World *world,
|
||||||
INTERNAL void endAttack(World *world, Entity *attacker)
|
Entity *attacker)
|
||||||
{
|
{
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
||||||
@ -621,11 +625,18 @@ INTERNAL void endAttack(World *world, Entity *attacker)
|
|||||||
else
|
else
|
||||||
attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
|
attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
audio_streamPlayVorbis(arena, audioManager, attacker->audioRenderer,
|
||||||
|
asset_getVorbis(assetManager, audiolist_tackle),
|
||||||
|
1);
|
||||||
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(INVALID_CODE_PATH);
|
ASSERT(INVALID_CODE_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute attack damage */
|
/* Compute attack damage */
|
||||||
@ -681,8 +692,9 @@ INTERNAL void endAttack(World *world, Entity *attacker)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
INTERNAL void entityStateSwitch(MemoryArena *arena, AssetManager *assetManager,
|
||||||
enum EntityState newState)
|
AudioManager *audioManager, World *world,
|
||||||
|
Entity *entity, enum EntityState newState)
|
||||||
{
|
{
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(world && entity)
|
ASSERT(world && entity)
|
||||||
@ -718,6 +730,7 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
|||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(INVALID_CODE_PATH);
|
ASSERT(INVALID_CODE_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case entitystate_battle:
|
case entitystate_battle:
|
||||||
@ -736,13 +749,14 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
|||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(INVALID_CODE_PATH);
|
ASSERT(INVALID_CODE_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case entitystate_attack:
|
case entitystate_attack:
|
||||||
switch (newState)
|
switch (newState)
|
||||||
{
|
{
|
||||||
case entitystate_battle:
|
case entitystate_battle:
|
||||||
endAttack(world, entity);
|
endAttack(arena, assetManager, audioManager, world, entity);
|
||||||
entity_setActiveAnim(entity, animlist_hero_battlePose);
|
entity_setActiveAnim(entity, animlist_hero_battlePose);
|
||||||
entity->stats->actionTimer = entity->stats->actionRate;
|
entity->stats->actionTimer = entity->stats->actionRate;
|
||||||
entity->stats->busyDuration = 0;
|
entity->stats->busyDuration = 0;
|
||||||
@ -756,6 +770,7 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
|||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(INVALID_CODE_PATH);
|
ASSERT(INVALID_CODE_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case entitystate_dead:
|
case entitystate_dead:
|
||||||
@ -768,12 +783,14 @@ INTERNAL void entityStateSwitch(World *world, Entity *entity,
|
|||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(INVALID_CODE_PATH);
|
ASSERT(INVALID_CODE_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(INVALID_CODE_PATH);
|
ASSERT(INVALID_CODE_PATH);
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity->state = newState;
|
entity->state = newState;
|
||||||
@ -790,6 +807,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
Renderer *renderer = &state->renderer;
|
Renderer *renderer = &state->renderer;
|
||||||
World *const world = &state->world[state->currWorldIndex];
|
World *const world = &state->world[state->currWorldIndex];
|
||||||
Font *font = &assetManager->font;
|
Font *font = &assetManager->font;
|
||||||
|
MemoryArena *arena = &state->arena;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
******************************
|
******************************
|
||||||
@ -798,37 +816,55 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
*/
|
*/
|
||||||
Entity *hero = getHeroEntity(world);
|
Entity *hero = getHeroEntity(world);
|
||||||
v4 cameraBounds = createCameraBounds(world, renderer->size);
|
v4 cameraBounds = createCameraBounds(world, renderer->size);
|
||||||
|
AudioManager *audioManager = &state->audioManager;
|
||||||
ASSERT(world->freeEntityIndex < world->maxEntities);
|
ASSERT(world->freeEntityIndex < world->maxEntities);
|
||||||
for (i32 i = 0; i < world->freeEntityIndex; i++)
|
for (i32 i = 0; i < world->freeEntityIndex; i++)
|
||||||
{
|
{
|
||||||
Entity *const entity = &world->entities[i];
|
Entity *const entity = &world->entities[i];
|
||||||
|
|
||||||
if (entity->audioRenderer)
|
if (entity->type == entitytype_soundscape)
|
||||||
{
|
{
|
||||||
AudioRenderer *audioRenderer = entity->audioRenderer;
|
AudioRenderer *audioRenderer = entity->audioRenderer;
|
||||||
if (world->numEntitiesInBattle > 0)
|
if (world->numEntitiesInBattle > 0)
|
||||||
{
|
{
|
||||||
AudioVorbis *battleTheme =
|
AudioVorbis *battleTheme =
|
||||||
asset_getVorbis(assetManager, audiolist_battle);
|
asset_getVorbis(assetManager, audiolist_battle);
|
||||||
if (audioRenderer->audio != battleTheme)
|
if (audioRenderer->audio)
|
||||||
{
|
{
|
||||||
audio_streamPlayVorbis(&state->audioManager, audioRenderer,
|
if (audioRenderer->audio->type != audiolist_battle)
|
||||||
battleTheme, AUDIO_REPEAT_INFINITE);
|
{
|
||||||
|
audio_streamPlayVorbis(arena, &state->audioManager,
|
||||||
|
audioRenderer, battleTheme,
|
||||||
|
AUDIO_REPEAT_INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audio_streamPlayVorbis(arena, &state->audioManager,
|
||||||
|
audioRenderer, battleTheme,
|
||||||
|
AUDIO_REPEAT_INFINITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AudioVorbis *overworldTheme =
|
AudioVorbis *overworldTheme =
|
||||||
asset_getVorbis(assetManager, audiolist_overworld);
|
asset_getVorbis(assetManager, audiolist_overworld);
|
||||||
if (audioRenderer->audio != overworldTheme)
|
if (audioRenderer->audio)
|
||||||
{
|
{
|
||||||
audio_streamPlayVorbis(&state->audioManager, audioRenderer,
|
if (audioRenderer->audio->type != audiolist_overworld)
|
||||||
overworldTheme,
|
{
|
||||||
|
audio_streamPlayVorbis(arena, &state->audioManager,
|
||||||
|
audioRenderer, overworldTheme,
|
||||||
|
AUDIO_REPEAT_INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
audio_streamPlayVorbis(arena, &state->audioManager,
|
||||||
|
audioRenderer, overworldTheme,
|
||||||
AUDIO_REPEAT_INFINITE);
|
AUDIO_REPEAT_INFINITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_updateAndPlay(&state->audioManager, entity->audioRenderer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entity->state == entitystate_dead)
|
if (entity->state == entitystate_dead)
|
||||||
@ -849,6 +885,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
// an entity dies
|
// an entity dies
|
||||||
#if 1
|
#if 1
|
||||||
i32 entityIndexInArray = i;
|
i32 entityIndexInArray = i;
|
||||||
|
audio_streamStopVorbis(arena, &state->audioManager,
|
||||||
|
entity->audioRenderer);
|
||||||
entity_delete(&state->arena, world, entityIndexInArray);
|
entity_delete(&state->arena, world, entityIndexInArray);
|
||||||
|
|
||||||
// TODO(doyle): DeleteEntity moves elements down 1, so account for i
|
// TODO(doyle): DeleteEntity moves elements down 1, so account for i
|
||||||
@ -888,7 +926,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
newState = entitystate_idle;
|
newState = entitystate_idle;
|
||||||
}
|
}
|
||||||
|
|
||||||
entityStateSwitch(world, entity, newState);
|
entityStateSwitch(arena, assetManager, audioManager, world, entity,
|
||||||
|
newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -911,7 +950,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
stats->queuedAttack = entityattack_tackle;
|
stats->queuedAttack = entityattack_tackle;
|
||||||
|
|
||||||
/* Launch up attack animation */
|
/* Launch up attack animation */
|
||||||
entityStateSwitch(world, entity, entitystate_attack);
|
entityStateSwitch(arena, assetManager, audioManager, world,
|
||||||
|
entity, entitystate_attack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (entity->state == entitystate_attack)
|
else if (entity->state == entitystate_attack)
|
||||||
@ -922,7 +962,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
if (stats->busyDuration <= 0)
|
if (stats->busyDuration <= 0)
|
||||||
{
|
{
|
||||||
/* Apply attack damage */
|
/* Apply attack damage */
|
||||||
entityStateSwitch(world, entity, entitystate_battle);
|
entityStateSwitch(arena, assetManager, audioManager, world,
|
||||||
|
entity, entitystate_battle);
|
||||||
|
|
||||||
/* Get target entity that was attacked */
|
/* Get target entity that was attacked */
|
||||||
Entity *defender = NULL;
|
Entity *defender = NULL;
|
||||||
@ -946,13 +987,21 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
DEBUG_LOG("Entity has died");
|
DEBUG_LOG("Entity has died");
|
||||||
#endif
|
#endif
|
||||||
entityStateSwitch(world, defender, entitystate_dead);
|
entityStateSwitch(arena, assetManager, audioManager, world, defender,
|
||||||
entityStateSwitch(world, attacker, entitystate_idle);
|
entitystate_dead);
|
||||||
|
entityStateSwitch(arena, assetManager, audioManager, world, attacker,
|
||||||
|
entitystate_idle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entity->audioRenderer)
|
||||||
|
{
|
||||||
|
audio_updateAndPlay(&state->arena, &state->audioManager,
|
||||||
|
entity->audioRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**************************************************
|
**************************************************
|
||||||
* Update animations and render entity
|
* Update animations and render entity
|
||||||
@ -973,10 +1022,10 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
// NOTE(doyle): If battle entities is 1 then only the hero left
|
// NOTE(doyle): If battle entities is 1 then only the hero left
|
||||||
if (hero->state == entitystate_battle &&
|
if (hero->state == entitystate_battle &&
|
||||||
world->numEntitiesInBattle == 1)
|
world->numEntitiesInBattle == 1)
|
||||||
entityStateSwitch(world, hero, entitystate_idle);
|
entityStateSwitch(arena, assetManager, audioManager, world, hero, entitystate_idle);
|
||||||
else if (hero->state != entitystate_attack)
|
else if (hero->state != entitystate_attack)
|
||||||
{
|
{
|
||||||
entityStateSwitch(world, hero, entitystate_battle);
|
entityStateSwitch(arena, assetManager, audioManager, world, hero, entitystate_battle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -62,17 +62,22 @@ enum AudioList
|
|||||||
{
|
{
|
||||||
audiolist_battle,
|
audiolist_battle,
|
||||||
audiolist_overworld,
|
audiolist_overworld,
|
||||||
|
audiolist_tackle,
|
||||||
audiolist_count,
|
audiolist_count,
|
||||||
audiolist_invalid,
|
audiolist_invalid,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct AudioVorbis
|
typedef struct AudioVorbis
|
||||||
{
|
{
|
||||||
|
enum AudioList type;
|
||||||
stb_vorbis *file;
|
stb_vorbis *file;
|
||||||
stb_vorbis_info info;
|
stb_vorbis_info info;
|
||||||
|
|
||||||
u32 lengthInSamples;
|
u32 lengthInSamples;
|
||||||
f32 lengthInSeconds;
|
f32 lengthInSeconds;
|
||||||
|
|
||||||
|
u8 *data;
|
||||||
|
i32 size;
|
||||||
} AudioVorbis;
|
} AudioVorbis;
|
||||||
|
|
||||||
typedef struct TexAtlas
|
typedef struct TexAtlas
|
||||||
|
@ -5,20 +5,22 @@
|
|||||||
|
|
||||||
#include "Dengine/Common.h"
|
#include "Dengine/Common.h"
|
||||||
|
|
||||||
|
/* Forward Declaration */
|
||||||
|
typedef struct MemoryArena MemoryArena;
|
||||||
|
|
||||||
#define AUDIO_NO_FREE_SOURCE -1
|
#define AUDIO_NO_FREE_SOURCE -1
|
||||||
typedef struct AudioSourceEntry
|
typedef struct AudioSourceEntry
|
||||||
{
|
{
|
||||||
u32 id;
|
u32 id;
|
||||||
i32 nextFreeIndex;
|
b32 isFree;
|
||||||
} AudioSourceEntry;
|
} AudioSourceEntry;
|
||||||
|
|
||||||
|
// TODO(doyle): Incorporate memory arena into managers?
|
||||||
#define AUDIO_MAX_SOURCES 32
|
#define AUDIO_MAX_SOURCES 32
|
||||||
typedef struct AudioManager
|
typedef struct AudioManager
|
||||||
{
|
{
|
||||||
// NOTE(doyle): Source entries point to the next free index
|
// NOTE(doyle): Source entries point to the next free index
|
||||||
AudioSourceEntry sourceList[AUDIO_MAX_SOURCES];
|
AudioSourceEntry sourceList[AUDIO_MAX_SOURCES];
|
||||||
i32 freeSourceIndex;
|
|
||||||
|
|
||||||
} AudioManager;
|
} AudioManager;
|
||||||
|
|
||||||
|
|
||||||
@ -36,15 +38,15 @@ typedef struct AudioRenderer
|
|||||||
|
|
||||||
|
|
||||||
const i32 audio_init(AudioManager *audioManager);
|
const i32 audio_init(AudioManager *audioManager);
|
||||||
const i32 audio_streamPlayVorbis(AudioManager *audioManager,
|
const i32 audio_streamPlayVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer,
|
AudioRenderer *audioRenderer,
|
||||||
AudioVorbis *vorbis, i32 numPlays);
|
AudioVorbis *vorbis, i32 numPlays);
|
||||||
const i32 audio_streamStopVorbis(AudioManager *audioManager,
|
const i32 audio_streamStopVorbis(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer);
|
AudioRenderer *audioRenderer);
|
||||||
const i32 audio_streamPauseVorbis(AudioManager *audioManager,
|
const i32 audio_streamPauseVorbis(AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer);
|
AudioRenderer *audioRenderer);
|
||||||
const i32 audio_streamResumeVorbis(AudioManager *audioManager,
|
const i32 audio_streamResumeVorbis(AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer);
|
AudioRenderer *audioRenderer);
|
||||||
const i32 audio_updateAndPlay(AudioManager *audioManager,
|
const i32 audio_updateAndPlay(MemoryArena *arena, AudioManager *audioManager,
|
||||||
AudioRenderer *audioRenderer);
|
AudioRenderer *audioRenderer);
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,6 +55,11 @@ INTERNAL inline v2 V2(const f32 x, const f32 y)
|
|||||||
v2 result = {x, y};
|
v2 result = {x, y};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
INTERNAL inline v3 V3i(const i32 x, const i32 y, const i32 z)
|
||||||
|
{
|
||||||
|
v3 result = {CAST(f32)x, CAST(f32)y, CAST(f32)z};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
INTERNAL inline v3 V3(const f32 x, const f32 y, const f32 z)
|
INTERNAL inline v3 V3(const f32 x, const f32 y, const f32 z)
|
||||||
{
|
{
|
||||||
v3 result = {x, y, z};
|
v3 result = {x, y, z};
|
||||||
|
@ -15,7 +15,6 @@ typedef struct MemoryArena MemoryArena;
|
|||||||
#define NUM_KEYS 1024
|
#define NUM_KEYS 1024
|
||||||
#define METERS_TO_PIXEL 240
|
#define METERS_TO_PIXEL 240
|
||||||
|
|
||||||
|
|
||||||
typedef struct World
|
typedef struct World
|
||||||
{
|
{
|
||||||
Entity *entities;
|
Entity *entities;
|
||||||
|
Loading…
Reference in New Issue
Block a user