Start merging hash table access into assets
Basic implementation with many pre-existing features disabled untill all parts of the system that interact with the assets transitions over.
This commit is contained in:
parent
b43754986f
commit
7ca42f781a
@ -21,6 +21,76 @@
|
|||||||
#include "Dengine/OpenGL.h"
|
#include "Dengine/OpenGL.h"
|
||||||
#include "Dengine/Platform.h"
|
#include "Dengine/Platform.h"
|
||||||
|
|
||||||
|
INTERNAL AtlasSubTexture *getAtlasSubTexture(TexAtlas *atlas, char *key)
|
||||||
|
{
|
||||||
|
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(atlas->subTex));
|
||||||
|
AtlasSubTexture *result = &atlas->subTex[hashIndex];
|
||||||
|
if (result->key)
|
||||||
|
{
|
||||||
|
while (result && common_strcmp(result->key, key) != 0)
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL AtlasSubTexture *makeAtlasSubTexture(TexAtlas *atlas,
|
||||||
|
MemoryArena *arena, char *key)
|
||||||
|
{
|
||||||
|
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(atlas->subTex));
|
||||||
|
AtlasSubTexture *result = &atlas->subTex[hashIndex];
|
||||||
|
if (result->key)
|
||||||
|
{
|
||||||
|
while (result->next)
|
||||||
|
{
|
||||||
|
if (common_strcmp(result->key, key) == 0)
|
||||||
|
{
|
||||||
|
// TODO(doyle): Error correction whereby if a tex atlas already
|
||||||
|
// exists
|
||||||
|
ASSERT(INVALID_CODE_PATH);
|
||||||
|
}
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->next = PLATFORM_MEM_ALLOC(arena, 1, AtlasSubTexture);
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL Animation *getFreeAnimSlot(Animation *table, u32 tableSize,
|
||||||
|
MemoryArena *arena, char *key)
|
||||||
|
{
|
||||||
|
u32 hashIndex = common_getHashIndex(key, tableSize);
|
||||||
|
Animation *result = &table[hashIndex];
|
||||||
|
if (result->key)
|
||||||
|
{
|
||||||
|
while (result->next)
|
||||||
|
{
|
||||||
|
if (common_strcmp(result->key, key) == 0)
|
||||||
|
{
|
||||||
|
// TODO(doyle): Error correction whereby if a tex atlas already
|
||||||
|
// exists
|
||||||
|
ASSERT(INVALID_CODE_PATH);
|
||||||
|
}
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->next = PLATFORM_MEM_ALLOC(arena, 1, Animation);
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect asset_getAtlasSubTexRect(TexAtlas *atlas, char *key)
|
||||||
|
{
|
||||||
|
AtlasSubTexture *subTex = getAtlasSubTexture(atlas, key);
|
||||||
|
Rect result = subTex->rect;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(doyle): Switch to hash based lookup
|
// TODO(doyle): Switch to hash based lookup
|
||||||
// TODO(doyle): Use pointers, so we can forward declare all assets?
|
// TODO(doyle): Use pointers, so we can forward declare all assets?
|
||||||
AudioVorbis *asset_getVorbis(AssetManager *assetManager,
|
AudioVorbis *asset_getVorbis(AssetManager *assetManager,
|
||||||
@ -49,27 +119,64 @@ Texture *asset_getTexture(AssetManager *const assetManager,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TexAtlas *asset_getTextureAtlas(AssetManager *assetManager, const enum TexList type)
|
TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager,
|
||||||
|
MemoryArena *arena, const char *const key)
|
||||||
{
|
{
|
||||||
if (type < texlist_count)
|
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->texAtlas));
|
||||||
return &assetManager->texAtlas[type];
|
TexAtlas *result = &assetManager->texAtlas[hashIndex];
|
||||||
|
if (result->key)
|
||||||
|
{
|
||||||
|
while (result->next)
|
||||||
|
{
|
||||||
|
if (common_strcmp(result->key, key) == 0)
|
||||||
|
{
|
||||||
|
// TODO(doyle): Error correction whereby if a tex atlas already
|
||||||
|
// exists
|
||||||
|
ASSERT(INVALID_CODE_PATH);
|
||||||
|
}
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
result->next = PLATFORM_MEM_ALLOC(arena, 1, TexAtlas);
|
||||||
ASSERT(INVALID_CODE_PATH);
|
result = result->next;
|
||||||
#endif
|
}
|
||||||
return NULL;
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation *asset_getAnim(AssetManager *assetManager, const enum AnimList type)
|
TexAtlas *asset_getTexAtlas(AssetManager *const assetManager,
|
||||||
|
const char *const key)
|
||||||
{
|
{
|
||||||
if (type < animlist_count)
|
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->texAtlas));
|
||||||
return &assetManager->anims[type];
|
TexAtlas *result = &assetManager->texAtlas[hashIndex];
|
||||||
|
if (result->key)
|
||||||
|
{
|
||||||
|
while (result && common_strcmp(result->key, key) != 0)
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
return result;
|
||||||
ASSERT(INVALID_CODE_PATH);
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return NULL;
|
Animation *asset_getAnim(AssetManager *assetManager, char *key)
|
||||||
|
{
|
||||||
|
u32 hashIndex = common_getHashIndex(key, ARRAY_COUNT(assetManager->anims));
|
||||||
|
Animation *result = &assetManager->anims[hashIndex];
|
||||||
|
if (result->key)
|
||||||
|
{
|
||||||
|
while (result && common_strcmp(result->key, key) != 0)
|
||||||
|
result = result->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
|
const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
|
||||||
@ -364,7 +471,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
|||||||
// TODO(doyle): We copy over the bitmap direct to the font sheet, should we
|
// TODO(doyle): We copy over the bitmap direct to the font sheet, should we
|
||||||
// align the baselines up so we don't need to do baseline adjusting at
|
// align the baselines up so we don't need to do baseline adjusting at
|
||||||
// render?
|
// render?
|
||||||
i32 atlasIndex = 0;
|
char charToEncode = CAST(char)codepointRange.x;
|
||||||
|
TexAtlas *fontAtlas = asset_makeTexAtlas(assetManager, arena, "font");
|
||||||
for (i32 row = 0; row < MAX_TEXTURE_SIZE; row++)
|
for (i32 row = 0; row < MAX_TEXTURE_SIZE; row++)
|
||||||
{
|
{
|
||||||
u32 *destRow = fontBitmap + (row * MAX_TEXTURE_SIZE);
|
u32 *destRow = fontBitmap + (row * MAX_TEXTURE_SIZE);
|
||||||
@ -378,23 +486,26 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
|||||||
/* Store the location of glyph into atlas */
|
/* Store the location of glyph into atlas */
|
||||||
if (verticalPixelsBlitted == 0)
|
if (verticalPixelsBlitted == 0)
|
||||||
{
|
{
|
||||||
TexAtlas *fontAtlas = &assetManager->texAtlas[texlist_font];
|
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(activeGlyph.codepoint < ARRAY_COUNT(fontAtlas->texRect));
|
ASSERT(activeGlyph.codepoint < ARRAY_COUNT(fontAtlas->subTex));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
v2 origin =
|
v2 origin =
|
||||||
V2(CAST(f32)(glyphIndex * font->maxSize.w), CAST(f32) row);
|
V2(CAST(f32)(glyphIndex * font->maxSize.w), CAST(f32) row);
|
||||||
#if 1
|
|
||||||
fontAtlas->texRect[atlasIndex++] =
|
// NOTE(doyle): Since charToEncode starts from 0 and we record
|
||||||
math_getRect(origin, V2(CAST(f32) font->maxSize.w,
|
// all ascii characters, charToEncode represents the character
|
||||||
CAST(f32) font->maxSize.h));
|
// 1:1
|
||||||
#else
|
char charTmp[2] = {0};
|
||||||
v2i fontSize =
|
charTmp[0] = charToEncode;
|
||||||
font->charMetrics[activeGlyph.codepoint - 32].trueSize;
|
AtlasSubTexture *subTex =
|
||||||
fontAtlas->texRect[atlasIndex++] = math_getRect(
|
makeAtlasSubTexture(fontAtlas, arena, charTmp);
|
||||||
origin, V2(CAST(f32) fontSize.x, CAST(f32) fontSize.y));
|
|
||||||
#endif
|
subTex->key = PLATFORM_MEM_ALLOC(arena, 1, char);
|
||||||
|
subTex->key[0] = charToEncode;
|
||||||
|
|
||||||
|
subTex->rect = CAST(Rect){origin, font->maxSize};
|
||||||
|
charToEncode++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy over exactly one row of pixels */
|
/* Copy over exactly one row of pixels */
|
||||||
@ -452,8 +563,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
|||||||
#endif
|
#endif
|
||||||
PLATFORM_MEM_FREE(arena, fontBitmap, bitmapSize);
|
PLATFORM_MEM_FREE(arena, fontBitmap, bitmapSize);
|
||||||
|
|
||||||
font->tex = &assetManager->textures[texlist_font];
|
fontAtlas->tex = &assetManager->textures[texlist_font];
|
||||||
font->atlas = &assetManager->texAtlas[texlist_font];
|
font->atlas = fontAtlas;
|
||||||
|
|
||||||
// NOTE(doyle): Formula derived from STB Font
|
// NOTE(doyle): Formula derived from STB Font
|
||||||
font->verticalSpacing =
|
font->verticalSpacing =
|
||||||
@ -472,26 +583,28 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
||||||
i32 texId, i32 animId, i32 *frameIndex, i32 numFrames,
|
char *animName, TexAtlas *atlas, char **subTextureNames,
|
||||||
f32 frameDuration)
|
i32 numSubTextures, f32 frameDuration)
|
||||||
{
|
{
|
||||||
#ifdef DENGINE_DEBUG
|
Animation *anim = getFreeAnimSlot(
|
||||||
ASSERT(assetManager && frameIndex)
|
assetManager->anims, ARRAY_COUNT(assetManager->anims), arena, animName);
|
||||||
ASSERT(!assetManager->anims[animId].frameIndex);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Animation anim = {0};
|
anim->atlas = atlas;
|
||||||
anim.atlas = asset_getTextureAtlas(assetManager, texId);
|
anim->frameDuration = frameDuration;
|
||||||
|
anim->numFrames = numSubTextures;
|
||||||
|
|
||||||
anim.frameIndex = PLATFORM_MEM_ALLOC(arena, numFrames, i32);
|
// NOTE(doyle): +1 for the null terminator
|
||||||
for (i32 i = 0; i < numFrames; i++) anim.frameIndex[i] = frameIndex[i];
|
anim->name = PLATFORM_MEM_ALLOC(arena, common_strlen(animName) + 1, char);
|
||||||
|
common_strncpy(anim->name, animName, common_strlen(animName));
|
||||||
|
|
||||||
anim.numFrames = numFrames;
|
anim->frameList = PLATFORM_MEM_ALLOC(arena, numSubTextures, char*);
|
||||||
anim.frameDuration = frameDuration;
|
for (i32 i = 0; i < numSubTextures; i++)
|
||||||
|
{
|
||||||
|
AtlasSubTexture *subTex = getAtlasSubTexture(atlas, subTextureNames[i]);
|
||||||
|
anim->frameList[i] = subTex->key;
|
||||||
|
}
|
||||||
|
|
||||||
assetManager->anims[animId] = anim;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v2 asset_stringDimInPixels(const Font *const font, const char *const string)
|
v2 asset_stringDimInPixels(const Font *const font, const char *const string)
|
||||||
|
79
src/Entity.c
79
src/Entity.c
@ -3,20 +3,28 @@
|
|||||||
#include "Dengine/Platform.h"
|
#include "Dengine/Platform.h"
|
||||||
#include "Dengine/WorldTraveller.h"
|
#include "Dengine/WorldTraveller.h"
|
||||||
|
|
||||||
void entity_setActiveAnim(Entity *entity, enum AnimList animId)
|
void entity_setActiveAnim(Entity *entity, char *animName)
|
||||||
{
|
{
|
||||||
#ifdef DENGINE_DEBUG
|
|
||||||
ASSERT(animId < animlist_count);
|
|
||||||
ASSERT(entity->anim[animId].anim);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Reset current anim data */
|
/* Reset current anim data */
|
||||||
EntityAnim_ *currAnim = &entity->anim[entity->currAnimId];
|
EntityAnim *currEntityAnim = &entity->animList[entity->currAnimId];
|
||||||
currAnim->currDuration = currAnim->anim->frameDuration;
|
currEntityAnim->currDuration = currEntityAnim->anim->frameDuration;
|
||||||
currAnim->currFrame = 0;
|
currEntityAnim->currFrame = 0;
|
||||||
|
|
||||||
/* Set entity active animation */
|
/* Set entity active animation */
|
||||||
entity->currAnimId = animId;
|
for (i32 i = 0; i < ARRAY_COUNT(entity->animList); i++)
|
||||||
|
{
|
||||||
|
Animation *anim = entity->animList[i].anim;
|
||||||
|
if (anim)
|
||||||
|
{
|
||||||
|
if (common_strcmp(anim->key, animName) == 0)
|
||||||
|
{
|
||||||
|
entity->currAnimId = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG("Entity does not have access to desired anim");
|
||||||
}
|
}
|
||||||
|
|
||||||
void entity_updateAnim(Entity *entity, f32 dt)
|
void entity_updateAnim(Entity *entity, f32 dt)
|
||||||
@ -24,20 +32,15 @@ void entity_updateAnim(Entity *entity, f32 dt)
|
|||||||
if (!entity->tex)
|
if (!entity->tex)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO(doyle): Recheck why we have this twice
|
EntityAnim *currEntityAnim = &entity->animList[entity->currAnimId];
|
||||||
EntityAnim_ *entityAnim = &entity->anim[entity->currAnimId];
|
Animation *anim = currEntityAnim->anim;
|
||||||
Animation anim = *entityAnim->anim;
|
|
||||||
i32 frameIndex = anim.frameIndex[entityAnim->currFrame];
|
|
||||||
v4 texRect = anim.atlas->texRect[frameIndex];
|
|
||||||
|
|
||||||
entityAnim->currDuration -= dt;
|
currEntityAnim->currDuration -= dt;
|
||||||
if (entityAnim->currDuration <= 0.0f)
|
if (currEntityAnim->currDuration <= 0.0f)
|
||||||
{
|
{
|
||||||
entityAnim->currFrame++;
|
currEntityAnim->currFrame++;
|
||||||
entityAnim->currFrame = entityAnim->currFrame % anim.numFrames;
|
currEntityAnim->currFrame = currEntityAnim->currFrame % anim->numFrames;
|
||||||
frameIndex = entityAnim->anim->frameIndex[entityAnim->currFrame];
|
currEntityAnim->currDuration = anim->frameDuration;
|
||||||
texRect = anim.atlas->texRect[frameIndex];
|
|
||||||
entityAnim->currDuration = anim.frameDuration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(doyle): If humanoid entity, let animation dictate render size which
|
// NOTE(doyle): If humanoid entity, let animation dictate render size which
|
||||||
@ -47,18 +50,31 @@ void entity_updateAnim(Entity *entity, f32 dt)
|
|||||||
case entitytype_hero:
|
case entitytype_hero:
|
||||||
case entitytype_mob:
|
case entitytype_mob:
|
||||||
case entitytype_npc:
|
case entitytype_npc:
|
||||||
entity->renderSize = math_getRectSize(texRect);
|
char *frameName = anim->frameList[currEntityAnim->currFrame];
|
||||||
|
Rect texRect =
|
||||||
|
asset_getAtlasSubTexRect(anim->atlas, frameName);
|
||||||
|
entity->renderSize = texRect.size;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void entity_addAnim(AssetManager *assetManager, Entity *entity, i32 animId)
|
void entity_addAnim(AssetManager *assetManager, Entity *entity, char *animName)
|
||||||
{
|
{
|
||||||
Animation *anim = asset_getAnim(assetManager, animId);
|
i32 freeAnimIndex = 0;
|
||||||
entity->anim[animId].anim = anim;
|
for (i32 i = 0; i < ARRAY_COUNT(entity->animList); i++)
|
||||||
entity->anim[animId].currFrame = 0;
|
{
|
||||||
entity->anim[animId].currDuration = anim->frameDuration;
|
EntityAnim *entityAnim = &entity->animList[i];
|
||||||
|
if (!entityAnim->anim)
|
||||||
|
{
|
||||||
|
entityAnim->anim = asset_getAnim(assetManager, animName);
|
||||||
|
entityAnim->currFrame = 0;
|
||||||
|
entityAnim->currDuration = entityAnim->anim->frameDuration;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG("No more free entity animation slots");
|
||||||
}
|
}
|
||||||
|
|
||||||
void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager,
|
void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager,
|
||||||
@ -81,12 +97,7 @@ void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager,
|
|||||||
mob->audioRenderer->sourceIndex = AUDIO_SOURCE_UNASSIGNED;
|
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, "Claude idle");
|
||||||
entity_addAnim(assetManager, mob, animlist_hero_walk);
|
|
||||||
entity_addAnim(assetManager, mob, animlist_hero_wave);
|
|
||||||
entity_addAnim(assetManager, mob, animlist_hero_battlePose);
|
|
||||||
entity_addAnim(assetManager, mob, animlist_hero_tackle);
|
|
||||||
mob->currAnimId = animlist_hero_idle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size,
|
Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size,
|
||||||
|
@ -175,16 +175,13 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera,
|
|||||||
v2 pivotPoint, f32 rotate, v4 color)
|
v2 pivotPoint, f32 rotate, v4 color)
|
||||||
{
|
{
|
||||||
i32 strLen = common_strlen(string);
|
i32 strLen = common_strlen(string);
|
||||||
// TODO(doyle): Scale, not too important .. but rudimentary infrastructure
|
|
||||||
// laid out here
|
|
||||||
f32 scale = 1.0f;
|
|
||||||
|
|
||||||
// TODO(doyle): Slightly incorrect string length in pixels calculation,
|
// TODO(doyle): Slightly incorrect string length in pixels calculation,
|
||||||
// because we use the advance metric of each character for length not
|
// because we use the advance metric of each character for length not
|
||||||
// maximum character size in rendering
|
// maximum character size in rendering
|
||||||
v2 rightAlignedP =
|
v2 rightAlignedP =
|
||||||
v2_add(pos, V2(scale *(CAST(f32) font->maxSize.w * CAST(f32) strLen),
|
v2_add(pos, V2((CAST(f32) font->maxSize.w * CAST(f32) strLen),
|
||||||
scale * CAST(f32) font->maxSize.h));
|
CAST(f32) font->maxSize.h));
|
||||||
v2 leftAlignedP = pos;
|
v2 leftAlignedP = pos;
|
||||||
if (math_pointInRect(camera, leftAlignedP) ||
|
if (math_pointInRect(camera, leftAlignedP) ||
|
||||||
math_pointInRect(camera, rightAlignedP))
|
math_pointInRect(camera, rightAlignedP))
|
||||||
@ -197,27 +194,32 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera,
|
|||||||
pos = posInCameraSpace;
|
pos = posInCameraSpace;
|
||||||
|
|
||||||
// TODO(doyle): Find why font is 1px off, might be arial font semantics
|
// TODO(doyle): Find why font is 1px off, might be arial font semantics
|
||||||
|
Texture *tex = font->atlas->tex;
|
||||||
f32 baseline = pos.y - font->verticalSpacing + 1;
|
f32 baseline = pos.y - font->verticalSpacing + 1;
|
||||||
for (i32 i = 0; i < strLen; i++)
|
for (i32 i = 0; i < strLen; i++)
|
||||||
{
|
{
|
||||||
// NOTE(doyle): Atlas packs fonts tightly, so offset the codepoint
|
|
||||||
// to its actual atlas index, i.e. we skip the first 31 glyphs
|
|
||||||
i32 codepoint = string[i];
|
i32 codepoint = string[i];
|
||||||
i32 relativeIndex = CAST(i32)(codepoint - font->codepointRange.x);
|
i32 relativeIndex = CAST(i32)(codepoint - font->codepointRange.x);
|
||||||
CharMetrics charMetric = font->charMetrics[relativeIndex];
|
CharMetrics charMetric = font->charMetrics[relativeIndex];
|
||||||
pos.y = baseline - (scale * charMetric.offset.y);
|
pos.y = baseline - (charMetric.offset.y);
|
||||||
|
|
||||||
const v4 charRectOnScreen =
|
const v4 charRectOnScreen =
|
||||||
math_getRect(pos, V2(scale * CAST(f32) font->maxSize.w,
|
math_getRect(pos, V2(CAST(f32) font->maxSize.w,
|
||||||
scale * CAST(f32) font->maxSize.h));
|
CAST(f32) font->maxSize.h));
|
||||||
|
|
||||||
pos.x += scale * charMetric.advance;
|
pos.x += charMetric.advance;
|
||||||
|
|
||||||
/* Get texture out */
|
/* Get texture out */
|
||||||
v4 charTexRect = font->atlas->texRect[relativeIndex];
|
Rect charTexRect =
|
||||||
flipTexCoord(&charTexRect, FALSE, TRUE);
|
asset_getAtlasSubTexRect(font->atlas, &CAST(char)codepoint);
|
||||||
RenderTex renderTex = {font->tex, charTexRect};
|
|
||||||
|
|
||||||
|
v4 deprecatedTexRect = {0};
|
||||||
|
deprecatedTexRect.vec2[0] = charTexRect.pos;
|
||||||
|
deprecatedTexRect.vec2[1] = v2_add(charTexRect.pos, charTexRect.size);
|
||||||
|
|
||||||
|
flipTexCoord(&deprecatedTexRect, FALSE, TRUE);
|
||||||
|
|
||||||
|
RenderTex renderTex = {tex, deprecatedTexRect};
|
||||||
RenderQuad charQuad =
|
RenderQuad charQuad =
|
||||||
createTexQuad(renderer, charRectOnScreen, renderTex);
|
createTexQuad(renderer, charRectOnScreen, renderTex);
|
||||||
stringQuads[quadIndex++] = charQuad;
|
stringQuads[quadIndex++] = charQuad;
|
||||||
@ -228,7 +230,7 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera,
|
|||||||
// we're rendering a window sized buffer
|
// we're rendering a window sized buffer
|
||||||
updateBufferObject(renderer, stringQuads, quadIndex);
|
updateBufferObject(renderer, stringQuads, quadIndex);
|
||||||
renderObject(renderer, V2(0.0f, 0.0f), renderer->size, pivotPoint,
|
renderObject(renderer, V2(0.0f, 0.0f), renderer->size, pivotPoint,
|
||||||
rotate, color, font->tex);
|
rotate, color, tex);
|
||||||
PLATFORM_MEM_FREE(arena, stringQuads, strLen * sizeof(RenderQuad));
|
PLATFORM_MEM_FREE(arena, stringQuads, strLen * sizeof(RenderQuad));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -246,12 +248,17 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
|||||||
if (math_pointInRect(camera, leftAlignedP) ||
|
if (math_pointInRect(camera, leftAlignedP) ||
|
||||||
math_pointInRect(camera, rightAlignedP))
|
math_pointInRect(camera, rightAlignedP))
|
||||||
{
|
{
|
||||||
EntityAnim_ *entityAnim = &entity->anim[entity->currAnimId];
|
EntityAnim *entityAnim = &entity->animList[entity->currAnimId];
|
||||||
Animation *anim = entityAnim->anim;
|
Animation *anim = entityAnim->anim;
|
||||||
i32 frameIndex = anim->frameIndex[entityAnim->currFrame];
|
char *frameName = anim->frameList[entityAnim->currFrame];
|
||||||
v4 animTexRect = anim->atlas->texRect[frameIndex];
|
Rect animRect = asset_getAtlasSubTexRect(anim->atlas, frameName);
|
||||||
|
|
||||||
if (entity->direction == direction_east)
|
// TODO(doyle): Switch to rect
|
||||||
|
v4 animTexRect = {0};
|
||||||
|
animTexRect.vec2[0] = animRect.pos;
|
||||||
|
animTexRect.vec2[1] = v2_add(animRect.pos, animRect.size);
|
||||||
|
|
||||||
|
if (entity->direction == direction_east)
|
||||||
{
|
{
|
||||||
flipTexCoord(&animTexRect, TRUE, FALSE);
|
flipTexCoord(&animTexRect, TRUE, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -420,9 +420,6 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(doyle): Use a proper random seed
|
|
||||||
#define RANDOM_SEED 0xDEADBEEF
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
DEBUG_RECURSIVE_PRINT_XML_TREE(&root);
|
DEBUG_RECURSIVE_PRINT_XML_TREE(&root);
|
||||||
#endif
|
#endif
|
||||||
@ -433,31 +430,11 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
if(common_strcmp(node->name, "TextureAtlas") == 0)
|
if(common_strcmp(node->name, "TextureAtlas") == 0)
|
||||||
{
|
{
|
||||||
XmlNode *atlasXmlNode = node;
|
XmlNode *atlasXmlNode = node;
|
||||||
TexAtlasEntry *atlasEntry = NULL;
|
TexAtlas *atlasEntry = NULL;
|
||||||
if (common_strcmp(node->attribute.name, "imagePath") == 0)
|
if (common_strcmp(node->attribute.name, "imagePath") == 0)
|
||||||
{
|
{
|
||||||
char *imageName = atlasXmlNode->attribute.value;
|
char *imageName = atlasXmlNode->attribute.value;
|
||||||
u32 atlasHashIndex = common_murmurHash2(
|
atlasEntry = asset_makeTexAtlas(assetManager, arena, imageName);
|
||||||
imageName, common_strlen(imageName), RANDOM_SEED);
|
|
||||||
atlasHashIndex =
|
|
||||||
atlasHashIndex % ARRAY_COUNT(assetManager->texAtlas_);
|
|
||||||
|
|
||||||
atlasEntry = &assetManager->texAtlas_[atlasHashIndex];
|
|
||||||
if (atlasEntry->name)
|
|
||||||
{
|
|
||||||
#ifdef DENGINE_DEBUG
|
|
||||||
|
|
||||||
// NOTE(doyle): Two atlas textures have the same access name
|
|
||||||
ASSERT(common_strcmp(atlasEntry->name, imageName) != 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (atlasEntry->next)
|
|
||||||
atlasEntry = atlasEntry->next;
|
|
||||||
|
|
||||||
atlasEntry->next =
|
|
||||||
PLATFORM_MEM_ALLOC(arena, 1, TexAtlasEntry);
|
|
||||||
atlasEntry = atlasEntry->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *dataDir = "data/textures/WorldTraveller/";
|
char *dataDir = "data/textures/WorldTraveller/";
|
||||||
char imagePath[512] = {0};
|
char imagePath[512] = {0};
|
||||||
@ -466,9 +443,9 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
|
|
||||||
asset_loadTextureImage(assetManager, imagePath, texlist_claude);
|
asset_loadTextureImage(assetManager, imagePath, texlist_claude);
|
||||||
|
|
||||||
atlasEntry->name =
|
atlasEntry->key =
|
||||||
PLATFORM_MEM_ALLOC(arena, common_strlen(imageName), char);
|
PLATFORM_MEM_ALLOC(arena, common_strlen(imageName)+1, char);
|
||||||
common_strncpy(atlasEntry->name, imageName,
|
common_strncpy(atlasEntry->key, imageName,
|
||||||
common_strlen(imageName));
|
common_strlen(imageName));
|
||||||
|
|
||||||
atlasEntry->tex =
|
atlasEntry->tex =
|
||||||
@ -495,39 +472,43 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
0)
|
0)
|
||||||
{
|
{
|
||||||
char *value = subTextureAttrib->value;
|
char *value = subTextureAttrib->value;
|
||||||
newSubTexEntry.name = value;
|
newSubTexEntry.key = value;
|
||||||
}
|
}
|
||||||
else if (common_strcmp(subTextureAttrib->name,
|
else if (common_strcmp(subTextureAttrib->name,
|
||||||
"x") == 0)
|
"x") == 0)
|
||||||
{
|
{
|
||||||
char *value = subTextureAttrib->value;
|
char *value = subTextureAttrib->value;
|
||||||
i32 valueLen = common_strlen(value);
|
i32 valueLen = common_strlen(value);
|
||||||
newSubTexEntry.rect.pos.x =
|
i32 intValue = common_atoi(value, valueLen);
|
||||||
CAST(f32) common_atoi(value, valueLen);
|
|
||||||
|
newSubTexEntry.rect.pos.x = CAST(f32) intValue;
|
||||||
}
|
}
|
||||||
else if (common_strcmp(subTextureAttrib->name,
|
else if (common_strcmp(subTextureAttrib->name,
|
||||||
"y") == 0)
|
"y") == 0)
|
||||||
{
|
{
|
||||||
char *value = subTextureAttrib->value;
|
char *value = subTextureAttrib->value;
|
||||||
i32 valueLen = common_strlen(value);
|
i32 valueLen = common_strlen(value);
|
||||||
newSubTexEntry.rect.pos.y =
|
|
||||||
CAST(f32) common_atoi(value, valueLen);
|
i32 intValue = common_atoi(value, valueLen);
|
||||||
|
newSubTexEntry.rect.pos.y = CAST(f32) intValue;
|
||||||
}
|
}
|
||||||
else if (common_strcmp(subTextureAttrib->name,
|
else if (common_strcmp(subTextureAttrib->name,
|
||||||
"width") == 0)
|
"width") == 0)
|
||||||
{
|
{
|
||||||
char *value = subTextureAttrib->value;
|
char *value = subTextureAttrib->value;
|
||||||
i32 valueLen = common_strlen(value);
|
i32 valueLen = common_strlen(value);
|
||||||
newSubTexEntry.rect.size.w =
|
i32 intValue = common_atoi(value, valueLen);
|
||||||
CAST(f32) common_atoi(value, valueLen);
|
|
||||||
|
newSubTexEntry.rect.size.w = CAST(f32) intValue;
|
||||||
}
|
}
|
||||||
else if (common_strcmp(subTextureAttrib->name,
|
else if (common_strcmp(subTextureAttrib->name,
|
||||||
"height") == 0)
|
"height") == 0)
|
||||||
{
|
{
|
||||||
char *value = subTextureAttrib->value;
|
char *value = subTextureAttrib->value;
|
||||||
i32 valueLen = common_strlen(value);
|
i32 valueLen = common_strlen(value);
|
||||||
newSubTexEntry.rect.size.h =
|
i32 intValue = common_atoi(value, valueLen);
|
||||||
CAST(f32) common_atoi(value, valueLen);
|
|
||||||
|
newSubTexEntry.rect.size.h = CAST(f32) intValue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -536,32 +517,37 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
"Unsupported xml attribute in SubTexture");
|
"Unsupported xml attribute in SubTexture");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
subTextureAttrib = subTextureAttrib->next;
|
subTextureAttrib = subTextureAttrib->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(doyle): XML specifies 0,0 top left, we
|
||||||
|
// prefer 0,0 bottom right, so offset by size since 0,0
|
||||||
|
// is top left and size creates a bounding box below it
|
||||||
|
newSubTexEntry.rect.pos.y =
|
||||||
|
1024 - newSubTexEntry.rect.pos.y;
|
||||||
|
newSubTexEntry.rect.pos.y -= newSubTexEntry.rect.size.h;
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(newSubTexEntry.name)
|
ASSERT(newSubTexEntry.key)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
u32 subTexHashIndex = common_murmurHash2(
|
u32 subTexHashIndex = common_murmurHash2(
|
||||||
newSubTexEntry.name, common_strlen(newSubTexEntry.name),
|
newSubTexEntry.key,
|
||||||
RANDOM_SEED);
|
common_strlen(newSubTexEntry.key), 0xDEADBEEF);
|
||||||
subTexHashIndex =
|
subTexHashIndex =
|
||||||
subTexHashIndex % ARRAY_COUNT(atlasEntry->subTex);
|
subTexHashIndex % ARRAY_COUNT(atlasEntry->subTex);
|
||||||
|
|
||||||
// NOTE(doyle): Hash collision
|
// NOTE(doyle): Hash collision
|
||||||
AtlasSubTexture *subTexEntry =
|
AtlasSubTexture *subTexEntry =
|
||||||
&atlasEntry->subTex[subTexHashIndex];
|
&atlasEntry->subTex[subTexHashIndex];
|
||||||
if (subTexEntry->name)
|
if (subTexEntry->key)
|
||||||
{
|
{
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
|
|
||||||
// NOTE(doyle): Two textures have the same access
|
// NOTE(doyle): Two textures have the same access
|
||||||
// name
|
// name
|
||||||
ASSERT(common_strcmp(subTexEntry->name,
|
ASSERT(common_strcmp(subTexEntry->key,
|
||||||
newSubTexEntry.name) != 0);
|
newSubTexEntry.key) != 0);
|
||||||
#endif
|
#endif
|
||||||
while (subTexEntry->next)
|
while (subTexEntry->next)
|
||||||
subTexEntry = subTexEntry->next;
|
subTexEntry = subTexEntry->next;
|
||||||
@ -572,8 +558,12 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*subTexEntry = newSubTexEntry;
|
*subTexEntry = newSubTexEntry;
|
||||||
common_strncpy(subTexEntry->name, newSubTexEntry.name,
|
i32 keyLen = common_strlen(newSubTexEntry.key);
|
||||||
common_strlen(newSubTexEntry.name));
|
|
||||||
|
subTexEntry->key =
|
||||||
|
PLATFORM_MEM_ALLOC(arena, keyLen+1, char);
|
||||||
|
common_strncpy(subTexEntry->key, newSubTexEntry.key,
|
||||||
|
keyLen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -601,34 +591,6 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load textures */
|
|
||||||
asset_loadTextureImage(assetManager,
|
|
||||||
"data/textures/WorldTraveller/TerraSprite1024.png",
|
|
||||||
texlist_hero);
|
|
||||||
TexAtlas *heroAtlas = asset_getTextureAtlas(assetManager, texlist_hero);
|
|
||||||
heroAtlas->texRect[herorects_idle] = V4(746, 920, 804, 1018);
|
|
||||||
heroAtlas->texRect[herorects_walkA] = V4(641, 920, 699, 1018);
|
|
||||||
heroAtlas->texRect[herorects_walkB] = V4(849, 920, 904, 1018);
|
|
||||||
heroAtlas->texRect[herorects_head] = V4(108, 975, 159, 1024);
|
|
||||||
heroAtlas->texRect[herorects_waveA] = V4(944, 816, 1010, 918);
|
|
||||||
heroAtlas->texRect[herorects_waveB] = V4(944, 710, 1010, 812);
|
|
||||||
heroAtlas->texRect[herorects_battlePose] = V4(8, 814, 71, 910);
|
|
||||||
heroAtlas->texRect[herorects_castA] = V4(428, 814, 493, 910);
|
|
||||||
heroAtlas->texRect[herorects_castB] = V4(525, 816, 590, 919);
|
|
||||||
heroAtlas->texRect[herorects_castC] = V4(640, 816, 698, 916);
|
|
||||||
|
|
||||||
asset_loadTextureImage(assetManager,
|
|
||||||
"data/textures/WorldTraveller/Terrain.png",
|
|
||||||
texlist_terrain);
|
|
||||||
TexAtlas *terrainAtlas =
|
|
||||||
asset_getTextureAtlas(assetManager, texlist_terrain);
|
|
||||||
f32 atlasTileSize = 128.0f;
|
|
||||||
const i32 texSize = 1024;
|
|
||||||
v2 texOrigin = V2(0, 768);
|
|
||||||
terrainAtlas->texRect[terrainrects_ground] =
|
|
||||||
V4(texOrigin.x, texOrigin.y, texOrigin.x + atlasTileSize,
|
|
||||||
texOrigin.y + atlasTileSize);
|
|
||||||
|
|
||||||
/* Load shaders */
|
/* Load shaders */
|
||||||
asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl",
|
asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl",
|
||||||
"data/shaders/sprite.frag.glsl",
|
"data/shaders/sprite.frag.glsl",
|
||||||
@ -643,6 +605,7 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
DEBUG_LOG("Assets loaded");
|
DEBUG_LOG("Assets loaded");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Load animations */
|
/* Load animations */
|
||||||
f32 duration = 1.0f;
|
f32 duration = 1.0f;
|
||||||
i32 numRects = 1;
|
i32 numRects = 1;
|
||||||
@ -660,7 +623,20 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
i32 idleAnimAtlasIndexes[1] = {herorects_idle};
|
i32 idleAnimAtlasIndexes[1] = {herorects_idle};
|
||||||
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_idle,
|
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_idle,
|
||||||
idleAnimAtlasIndexes, numRects, duration);
|
idleAnimAtlasIndexes, numRects, duration);
|
||||||
|
#else
|
||||||
|
f32 duration = 1.0f;
|
||||||
|
i32 numRects = 1;
|
||||||
|
TexAtlas *claudeAtlas =
|
||||||
|
asset_getTexAtlas(assetManager, "ClaudeSpriteSheet.png");
|
||||||
|
|
||||||
|
duration = 1.0f;
|
||||||
|
numRects = 1;
|
||||||
|
char *subTextureNames = {"ClaudeSprite_001"};
|
||||||
|
asset_addAnimation(assetManager, arena, "Claude_idle", claudeAtlas,
|
||||||
|
&subTextureNames, 1, 1.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
// Walk animation
|
// Walk animation
|
||||||
duration = 0.10f;
|
duration = 0.10f;
|
||||||
numRects = 3;
|
numRects = 3;
|
||||||
@ -690,6 +666,8 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
herorects_castC};
|
herorects_castC};
|
||||||
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_tackle,
|
asset_addAnimation(assetManager, arena, texlist_hero, animlist_hero_tackle,
|
||||||
tackleAnimAtlasIndexes, numRects, duration);
|
tackleAnimAtlasIndexes, numRects, duration);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
DEBUG_LOG("Animations created");
|
DEBUG_LOG("Animations created");
|
||||||
#endif
|
#endif
|
||||||
@ -739,6 +717,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
|
|||||||
CAST(f32) state->tileSize));
|
CAST(f32) state->tileSize));
|
||||||
world->uniqueIdAccumulator = 0;
|
world->uniqueIdAccumulator = 0;
|
||||||
|
|
||||||
|
#if 0
|
||||||
TexAtlas *const atlas =
|
TexAtlas *const atlas =
|
||||||
asset_getTextureAtlas(assetManager, world->texType);
|
asset_getTextureAtlas(assetManager, world->texType);
|
||||||
|
|
||||||
@ -765,6 +744,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
|
|||||||
tile->currAnimId = animlist_terrain;
|
tile->currAnimId = animlist_terrain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
World *const world = &state->world[state->currWorldIndex];
|
World *const world = &state->world[state->currWorldIndex];
|
||||||
@ -790,7 +770,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
|
|||||||
pos = V2(size.x, CAST(f32) state->tileSize);
|
pos = V2(size.x, CAST(f32) state->tileSize);
|
||||||
type = entitytype_hero;
|
type = entitytype_hero;
|
||||||
dir = direction_east;
|
dir = direction_east;
|
||||||
tex = asset_getTexture(assetManager, texlist_hero);
|
tex = asset_getTexture(assetManager, texlist_claude);
|
||||||
collides = TRUE;
|
collides = TRUE;
|
||||||
Entity *hero =
|
Entity *hero =
|
||||||
entity_add(arena, world, pos, size, type, dir, tex, collides);
|
entity_add(arena, world, pos, size, type, dir, tex, collides);
|
||||||
@ -801,13 +781,10 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
|
|||||||
world->cameraFollowingId = hero->id;
|
world->cameraFollowingId = hero->id;
|
||||||
|
|
||||||
/* Populate hero animation references */
|
/* Populate hero animation references */
|
||||||
entity_addAnim(assetManager, hero, animlist_hero_idle);
|
entity_addAnim(assetManager, hero, "Claude_idle");
|
||||||
entity_addAnim(assetManager, hero, animlist_hero_walk);
|
entity_setActiveAnim(hero, "Claude_idle");
|
||||||
entity_addAnim(assetManager, hero, animlist_hero_wave);
|
|
||||||
entity_addAnim(assetManager, hero, animlist_hero_battlePose);
|
|
||||||
entity_addAnim(assetManager, hero, animlist_hero_tackle);
|
|
||||||
hero->currAnimId = animlist_hero_idle;
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Create a NPC */
|
/* Create a NPC */
|
||||||
pos = V2(hero->pos.x * 3, CAST(f32) state->tileSize);
|
pos = V2(hero->pos.x * 3, CAST(f32) state->tileSize);
|
||||||
size = hero->hitboxSize;
|
size = hero->hitboxSize;
|
||||||
@ -825,6 +802,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
|
|||||||
pos = V2(renderer->size.w - (renderer->size.w / 3.0f),
|
pos = V2(renderer->size.w - (renderer->size.w / 3.0f),
|
||||||
CAST(f32) state->tileSize);
|
CAST(f32) state->tileSize);
|
||||||
entity_addGenericMob(arena, assetManager, world, pos);
|
entity_addGenericMob(arena, assetManager, world, pos);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
DEBUG_LOG("World populated");
|
DEBUG_LOG("World populated");
|
||||||
@ -1152,7 +1130,7 @@ INTERNAL inline void updateWorldBattleEntities(World *world, Entity *entity,
|
|||||||
INTERNAL inline void resetEntityState(World *world, Entity *entity)
|
INTERNAL inline void resetEntityState(World *world, Entity *entity)
|
||||||
{
|
{
|
||||||
updateWorldBattleEntities(world, entity, ENTITY_NOT_IN_BATTLE);
|
updateWorldBattleEntities(world, entity, ENTITY_NOT_IN_BATTLE);
|
||||||
entity_setActiveAnim(entity, animlist_hero_idle);
|
entity_setActiveAnim(entity, "Claude_idle");
|
||||||
entity->stats->busyDuration = 0;
|
entity->stats->busyDuration = 0;
|
||||||
entity->stats->actionTimer = entity->stats->actionRate;
|
entity->stats->actionTimer = entity->stats->actionRate;
|
||||||
entity->stats->queuedAttack = entityattack_invalid;
|
entity->stats->queuedAttack = entityattack_invalid;
|
||||||
@ -1196,7 +1174,7 @@ INTERNAL void entityStateSwitch(EventQueue *eventQueue, World *world,
|
|||||||
// or not (i.e. has moved out of frame last frame).
|
// or not (i.e. has moved out of frame last frame).
|
||||||
case entitystate_dead:
|
case entitystate_dead:
|
||||||
registerEvent(eventQueue, eventtype_entity_died, CAST(void *)entity);
|
registerEvent(eventQueue, eventtype_entity_died, CAST(void *)entity);
|
||||||
entity_setActiveAnim(entity, animlist_hero_idle);
|
entity_setActiveAnim(entity, "Claude_idle");
|
||||||
entity->stats->busyDuration = 0;
|
entity->stats->busyDuration = 0;
|
||||||
entity->stats->actionTimer = entity->stats->actionRate;
|
entity->stats->actionTimer = entity->stats->actionRate;
|
||||||
entity->stats->queuedAttack = entityattack_invalid;
|
entity->stats->queuedAttack = entityattack_invalid;
|
||||||
@ -1236,7 +1214,7 @@ INTERNAL void entityStateSwitch(EventQueue *eventQueue, World *world,
|
|||||||
switch (newState)
|
switch (newState)
|
||||||
{
|
{
|
||||||
case entitystate_battle:
|
case entitystate_battle:
|
||||||
entity_setActiveAnim(entity, animlist_hero_battlePose);
|
entity_setActiveAnim(entity, "Claude_idle");
|
||||||
entity->stats->actionTimer = entity->stats->actionRate;
|
entity->stats->actionTimer = entity->stats->actionRate;
|
||||||
entity->stats->busyDuration = 0;
|
entity->stats->busyDuration = 0;
|
||||||
break;
|
break;
|
||||||
@ -1288,6 +1266,7 @@ typedef struct AttackSpec
|
|||||||
INTERNAL void beginAttack(EventQueue *eventQueue, World *world,
|
INTERNAL void beginAttack(EventQueue *eventQueue, World *world,
|
||||||
Entity *attacker)
|
Entity *attacker)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
#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);
|
||||||
@ -1313,6 +1292,7 @@ INTERNAL void beginAttack(EventQueue *eventQueue, World *world,
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(doyle): MemArena here is temporary until we incorporate AttackSpec to
|
// TODO(doyle): MemArena here is temporary until we incorporate AttackSpec to
|
||||||
@ -1320,6 +1300,7 @@ INTERNAL void beginAttack(EventQueue *eventQueue, World *world,
|
|||||||
INTERNAL void endAttack(MemoryArena *arena, EventQueue *eventQueue,
|
INTERNAL void endAttack(MemoryArena *arena, EventQueue *eventQueue,
|
||||||
World *world, Entity *attacker)
|
World *world, Entity *attacker)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
ASSERT(attacker->stats->entityIdToAttack != ENTITY_NULL_ID);
|
||||||
#endif
|
#endif
|
||||||
@ -1398,6 +1379,7 @@ INTERNAL void endAttack(MemoryArena *arena, EventQueue *eventQueue,
|
|||||||
entityStateSwitch(eventQueue, world, attacker, entitystate_idle);
|
entityStateSwitch(eventQueue, world, attacker, entitystate_idle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void sortWorldEntityList(World *world)
|
INTERNAL void sortWorldEntityList(World *world)
|
||||||
@ -1735,12 +1717,12 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
hero->dPos = V2(0.0f, 0.0f);
|
hero->dPos = V2(0.0f, 0.0f);
|
||||||
if (hero->currAnimId == animlist_hero_walk)
|
if (hero->currAnimId == animlist_hero_walk)
|
||||||
{
|
{
|
||||||
entity_setActiveAnim(hero, animlist_hero_idle);
|
entity_setActiveAnim(hero, "Claude_idle");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hero->currAnimId == animlist_hero_idle)
|
else if (hero->currAnimId == animlist_hero_idle)
|
||||||
{
|
{
|
||||||
entity_setActiveAnim(hero, animlist_hero_walk);
|
entity_setActiveAnim(hero, "Claude_idle");
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 heroSpeed = 6.2f * METERS_TO_PIXEL;
|
f32 heroSpeed = 6.2f * METERS_TO_PIXEL;
|
||||||
@ -1978,7 +1960,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
{
|
{
|
||||||
hero->state = entitystate_idle;
|
hero->state = entitystate_idle;
|
||||||
world->entityIdInBattle[hero->id] = FALSE;
|
world->entityIdInBattle[hero->id] = FALSE;
|
||||||
entity_setActiveAnim(hero, animlist_hero_idle);
|
entity_setActiveAnim(hero, "Claude_idle");
|
||||||
}
|
}
|
||||||
hero->stats->entityIdToAttack = -1;
|
hero->stats->entityIdToAttack = -1;
|
||||||
hero->stats->actionTimer = hero->stats->actionRate;
|
hero->stats->actionTimer = hero->stats->actionRate;
|
||||||
@ -2058,6 +2040,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
state->uiState.keyChar = keycode_null;
|
state->uiState.keyChar = keycode_null;
|
||||||
|
|
||||||
/* Draw hero avatar */
|
/* Draw hero avatar */
|
||||||
|
#if 0
|
||||||
TexAtlas *heroAtlas = asset_getTextureAtlas(assetManager, texlist_hero);
|
TexAtlas *heroAtlas = asset_getTextureAtlas(assetManager, texlist_hero);
|
||||||
v4 heroAvatarTexRect = heroAtlas->texRect[herorects_head];
|
v4 heroAvatarTexRect = heroAtlas->texRect[herorects_head];
|
||||||
v2 heroAvatarSize = math_getRectSize(heroAvatarTexRect);
|
v2 heroAvatarSize = math_getRectSize(heroAvatarTexRect);
|
||||||
@ -2079,6 +2062,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
|
|
||||||
renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr,
|
renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr,
|
||||||
strPos, V2(0, 0), 0, V4(0, 0, 1, 1));
|
strPos, V2(0, 0), 0, V4(0, 0, 1, 1));
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i32 i = 0; i < world->maxEntities; i++)
|
for (i32 i = 0; i < world->maxEntities; i++)
|
||||||
{
|
{
|
||||||
|
@ -11,25 +11,33 @@ typedef struct MemoryArena MemoryArena;
|
|||||||
typedef struct AssetManager
|
typedef struct AssetManager
|
||||||
{
|
{
|
||||||
Texture textures[32];
|
Texture textures[32];
|
||||||
TexAtlas texAtlas[32];
|
|
||||||
Shader shaders[32];
|
Shader shaders[32];
|
||||||
Animation anims[32];
|
Animation anims[1024];
|
||||||
AudioVorbis audio[32];
|
AudioVorbis audio[32];
|
||||||
Font font;
|
Font font;
|
||||||
|
|
||||||
TexAtlasEntry texAtlas_[8];
|
TexAtlas texAtlas[8];
|
||||||
} AssetManager;
|
} AssetManager;
|
||||||
|
|
||||||
#define MAX_TEXTURE_SIZE 1024
|
#define MAX_TEXTURE_SIZE 1024
|
||||||
|
|
||||||
|
Rect asset_getAtlasSubTexRect(TexAtlas *atlas, char *key);
|
||||||
|
|
||||||
AudioVorbis *asset_getVorbis(AssetManager *assetManager,
|
AudioVorbis *asset_getVorbis(AssetManager *assetManager,
|
||||||
const enum AudioList type);
|
const enum AudioList type);
|
||||||
|
|
||||||
Texture *asset_getTexture(AssetManager *const assetManager,
|
Texture *asset_getTexture(AssetManager *const assetManager,
|
||||||
const enum TexList type);
|
const enum TexList type);
|
||||||
|
|
||||||
|
TexAtlas *asset_makeTexAtlas(AssetManager *const assetManager,
|
||||||
|
MemoryArena *arena, const char *const key);
|
||||||
|
|
||||||
Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type);
|
Shader *asset_getShader(AssetManager *assetManager, const enum ShaderList type);
|
||||||
TexAtlas *asset_getTextureAtlas(AssetManager *assetManager,
|
|
||||||
const enum TexList type);
|
TexAtlas *asset_getTexAtlas(AssetManager *const assetManager,
|
||||||
Animation *asset_getAnim(AssetManager *assetManager, i32 type);
|
const char *const key);
|
||||||
|
|
||||||
|
Animation *asset_getAnim(AssetManager *assetManager, char *key);
|
||||||
|
|
||||||
const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
|
const i32 asset_loadVorbis(AssetManager *assetManager, MemoryArena *arena,
|
||||||
const char *const path, const enum AudioList type);
|
const char *const path, const enum AudioList type);
|
||||||
@ -46,8 +54,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
|
|||||||
const char *filePath);
|
const char *filePath);
|
||||||
|
|
||||||
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
void asset_addAnimation(AssetManager *assetManager, MemoryArena *arena,
|
||||||
i32 texId, i32 animId, i32 *atlasIndexes, i32 numFrames,
|
char *animName, TexAtlas *atlas, char **subTextureNames,
|
||||||
f32 frameDuration);
|
i32 numSubTextures, f32 frameDuration);
|
||||||
|
|
||||||
v2 asset_stringDimInPixels(const Font *const font, const char *const string);
|
v2 asset_stringDimInPixels(const Font *const font, const char *const string);
|
||||||
|
|
||||||
|
@ -83,36 +83,37 @@ typedef struct AudioVorbis
|
|||||||
|
|
||||||
typedef struct AtlasSubTexture
|
typedef struct AtlasSubTexture
|
||||||
{
|
{
|
||||||
char *name;
|
// NOTE(doyle): Key used to arrive to hash entry
|
||||||
|
char *key;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
||||||
// NOTE(doyle): For hashing collisions
|
// NOTE(doyle): For hashing collisions
|
||||||
struct AtlasSubTexture *next;
|
struct AtlasSubTexture *next;
|
||||||
} AtlasSubTexture;
|
} AtlasSubTexture;
|
||||||
|
|
||||||
typedef struct TexAtlasEntry
|
|
||||||
{
|
|
||||||
char *name;
|
|
||||||
Texture *tex;
|
|
||||||
AtlasSubTexture subTex[1024];
|
|
||||||
|
|
||||||
// NOTE(doyle): For hashing collisions
|
|
||||||
struct TexAtlasEntry *next;
|
|
||||||
} TexAtlasEntry;
|
|
||||||
|
|
||||||
typedef struct TexAtlas
|
typedef struct TexAtlas
|
||||||
{
|
{
|
||||||
// TODO(doyle): String hash based lookup
|
char *key;
|
||||||
v4 texRect[128];
|
Texture *tex;
|
||||||
|
AtlasSubTexture subTex[512];
|
||||||
|
|
||||||
|
struct TexAtlas *next;
|
||||||
} TexAtlas;
|
} TexAtlas;
|
||||||
|
|
||||||
typedef struct Animation
|
typedef struct Animation
|
||||||
{
|
{
|
||||||
|
union {
|
||||||
|
char *name;
|
||||||
|
char *key;
|
||||||
|
};
|
||||||
|
|
||||||
TexAtlas *atlas;
|
TexAtlas *atlas;
|
||||||
i32 *frameIndex;
|
char **frameList;
|
||||||
|
|
||||||
i32 numFrames;
|
i32 numFrames;
|
||||||
f32 frameDuration;
|
f32 frameDuration;
|
||||||
|
|
||||||
|
struct Animation *next;
|
||||||
} Animation;
|
} Animation;
|
||||||
|
|
||||||
// TODO(doyle): We only use the offset and advance metric at the moment, remove?
|
// TODO(doyle): We only use the offset and advance metric at the moment, remove?
|
||||||
@ -136,8 +137,6 @@ typedef struct CharMetrics
|
|||||||
typedef struct Font
|
typedef struct Font
|
||||||
{
|
{
|
||||||
TexAtlas *atlas;
|
TexAtlas *atlas;
|
||||||
Texture *tex;
|
|
||||||
|
|
||||||
FontMetrics metrics;
|
FontMetrics metrics;
|
||||||
|
|
||||||
// NOTE(doyle): Array of character's by ASCII value starting from
|
// NOTE(doyle): Array of character's by ASCII value starting from
|
||||||
|
@ -54,4 +54,14 @@ i32 common_atoi(const char *string, const i32 len);
|
|||||||
// machines.
|
// machines.
|
||||||
u32 common_murmurHash2(const void *key, i32 len, u32 seed);
|
u32 common_murmurHash2(const void *key, i32 len, u32 seed);
|
||||||
|
|
||||||
|
// TODO(doyle): Use a proper random seed
|
||||||
|
#define RANDOM_SEED 0xDEADBEEF
|
||||||
|
inline u32 common_getHashIndex(const char *const key, u32 tableSize)
|
||||||
|
{
|
||||||
|
u32 result = common_murmurHash2(key, common_strlen(key), RANDOM_SEED);
|
||||||
|
result = result % tableSize;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,12 +63,12 @@ typedef struct EntityStats
|
|||||||
enum EntityAttack queuedAttack;
|
enum EntityAttack queuedAttack;
|
||||||
} EntityStats;
|
} EntityStats;
|
||||||
|
|
||||||
typedef struct EntityAnim_
|
typedef struct EntityAnim
|
||||||
{
|
{
|
||||||
Animation *anim;
|
Animation *anim;
|
||||||
i32 currFrame;
|
i32 currFrame;
|
||||||
f32 currDuration;
|
f32 currDuration;
|
||||||
} EntityAnim_;
|
} EntityAnim;
|
||||||
|
|
||||||
typedef struct Entity
|
typedef struct Entity
|
||||||
{
|
{
|
||||||
@ -86,22 +86,17 @@ typedef struct Entity
|
|||||||
Texture *tex;
|
Texture *tex;
|
||||||
b32 collides;
|
b32 collides;
|
||||||
|
|
||||||
// TODO(doyle): String based access
|
EntityAnim animList[16];
|
||||||
// TODO(doyle): Separate animation refs from curr animation state, entity
|
i32 currAnimId;
|
||||||
// only ever has one active current animation. ATM every entity animation
|
|
||||||
// has a currframe and duration .. either that or we stop resetting
|
|
||||||
// animation on entity context switch
|
|
||||||
EntityAnim_ anim[16];
|
|
||||||
enum AnimList currAnimId;
|
|
||||||
|
|
||||||
EntityStats *stats;
|
EntityStats *stats;
|
||||||
AudioRenderer *audioRenderer;
|
AudioRenderer *audioRenderer;
|
||||||
i32 numAudioRenderers;
|
i32 numAudioRenderers;
|
||||||
} Entity;
|
} Entity;
|
||||||
|
|
||||||
void entity_setActiveAnim(Entity *entity, enum AnimList animId);
|
void entity_setActiveAnim(Entity *entity, char *animName);
|
||||||
void entity_updateAnim(Entity *entity, f32 dt);
|
void entity_updateAnim(Entity *entity, f32 dt);
|
||||||
void entity_addAnim(AssetManager *assetManager, Entity *entity, i32 animId);
|
void entity_addAnim(AssetManager *assetManager, Entity *entity, char *animName);
|
||||||
void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager,
|
void entity_addGenericMob(MemoryArena *arena, AssetManager *assetManager,
|
||||||
World *world, v2 pos);
|
World *world, v2 pos);
|
||||||
Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size,
|
Entity *entity_add(MemoryArena *arena, World *world, v2 pos, v2 size,
|
||||||
|
@ -25,6 +25,8 @@ typedef struct Renderer
|
|||||||
typedef struct RenderTex
|
typedef struct RenderTex
|
||||||
{
|
{
|
||||||
Texture *tex;
|
Texture *tex;
|
||||||
|
|
||||||
|
// TODO(doyle): Switch to rect
|
||||||
v4 texRect;
|
v4 texRect;
|
||||||
} RenderTex;
|
} RenderTex;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user