Add additional entity struct data

Attempting to add child weapon data to an entity has revealed the need for an
entity origin to which children start transformations from. Worth exploring
scene graphs in the future.
This commit is contained in:
Doyle Thai 2016-09-15 03:20:13 +10:00
parent 5c4f493979
commit 7cb13b3cf8
8 changed files with 145 additions and 90 deletions

View File

@ -82,7 +82,7 @@ INTERNAL HashTableEntry *const getEntryFromHash(HashTable *const table,
* Texture Operations * Texture Operations
********************************* *********************************
*/ */
INTERNAL Rect *getFreeAtlasSubTexSlot(TexAtlas *const atlas, INTERNAL SubTexture *getFreeAtlasSubTexSlot(TexAtlas *const atlas,
MemoryArena *const arena, MemoryArena *const arena,
const char *const key) const char *const key)
{ {
@ -90,8 +90,8 @@ INTERNAL Rect *getFreeAtlasSubTexSlot(TexAtlas *const atlas,
if (entry) if (entry)
{ {
entry->data = PLATFORM_MEM_ALLOC(arena, 1, Rect); entry->data = PLATFORM_MEM_ALLOC(arena, 1, SubTexture);
Rect *result = CAST(Rect *)entry->data; SubTexture *result = CAST(SubTexture *)entry->data;
return result; return result;
} }
else else
@ -100,15 +100,15 @@ INTERNAL Rect *getFreeAtlasSubTexSlot(TexAtlas *const atlas,
} }
} }
const Rect asset_getAtlasSubTex(TexAtlas *const atlas, const char *const key) const SubTexture asset_getAtlasSubTex(TexAtlas *const atlas, const char *const key)
{ {
HashTableEntry *entry = getEntryFromHash(&atlas->subTex, key); HashTableEntry *entry = getEntryFromHash(&atlas->subTex, key);
Rect result = {0}; SubTexture result = {0};
if (entry) if (entry)
{ {
result = *(CAST(Rect *) entry->data); result = *(CAST(SubTexture *) entry->data);
return result; return result;
} }
@ -638,7 +638,7 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
XmlAttribute *subTexAttrib = &atlasChildNode->attribute; XmlAttribute *subTexAttrib = &atlasChildNode->attribute;
char *key = NULL; char *key = NULL;
Rect subTex = {0}; SubTexture subTex = {0};
while (subTexAttrib) while (subTexAttrib)
{ {
@ -659,7 +659,7 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
i32 valueLen = common_strlen(value); i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen); i32 intValue = common_atoi(value, valueLen);
subTex.pos.x = CAST(f32) intValue; subTex.rect.pos.x = CAST(f32) intValue;
} }
else if (common_strcmp(subTexAttrib->name, "y") == else if (common_strcmp(subTexAttrib->name, "y") ==
0) 0)
@ -668,7 +668,7 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
i32 valueLen = common_strlen(value); i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen); i32 intValue = common_atoi(value, valueLen);
subTex.pos.y = CAST(f32) intValue; subTex.rect.pos.y = CAST(f32) intValue;
} }
else if (common_strcmp(subTexAttrib->name, else if (common_strcmp(subTexAttrib->name,
"width") == 0) "width") == 0)
@ -677,7 +677,7 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
i32 valueLen = common_strlen(value); i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen); i32 intValue = common_atoi(value, valueLen);
subTex.size.w = CAST(f32) intValue; subTex.rect.size.w = CAST(f32) intValue;
} }
else if (common_strcmp(subTexAttrib->name, else if (common_strcmp(subTexAttrib->name,
"height") == 0) "height") == 0)
@ -686,7 +686,25 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
i32 valueLen = common_strlen(value); i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen); i32 intValue = common_atoi(value, valueLen);
subTex.size.h = CAST(f32) intValue; subTex.rect.size.h = CAST(f32) intValue;
}
else if (common_strcmp(subTexAttrib->name,
"hand_offset_x") == 0)
{
char *value = subTexAttrib->value;
i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen);
subTex.offset.x = CAST(f32) intValue;
}
else if (common_strcmp(subTexAttrib->name,
"hand_offset_y") == 0)
{
char *value = subTexAttrib->value;
i32 valueLen = common_strlen(value);
i32 intValue = common_atoi(value, valueLen);
subTex.offset.y = CAST(f32) intValue;
} }
else else
{ {
@ -701,13 +719,14 @@ INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
// TODO(doyle): XML specifies 0,0 top left, we // TODO(doyle): XML specifies 0,0 top left, we
// prefer 0,0 bottom right, so offset by size since 0,0 // prefer 0,0 bottom right, so offset by size since 0,0
// is top left and size creates a bounding box below it // is top left and size creates a bounding box below it
subTex.pos.y = 1024 - subTex.pos.y; subTex.rect.pos.y = 1024 - subTex.rect.pos.y;
subTex.pos.y -= subTex.size.h; subTex.rect.pos.y -= subTex.rect.size.h;
subTex.offset.y = subTex.rect.size.h - subTex.offset.y;
#ifdef DENGINE_DEBUG #ifdef DENGINE_DEBUG
ASSERT(key); ASSERT(key);
#endif #endif
Rect *subTexInHash = SubTexture *subTexInHash =
getFreeAtlasSubTexSlot(atlas, arena, key); getFreeAtlasSubTexSlot(atlas, arena, key);
*subTexInHash = subTex; *subTexInHash = subTex;
} }
@ -1126,8 +1145,8 @@ const i32 asset_loadTTFont(AssetManager *assetManager, MemoryArena *arena,
// all ascii characters, charToEncode represents the character // all ascii characters, charToEncode represents the character
// 1:1 // 1:1
const char key[2] = {charToEncode, 0}; const char key[2] = {charToEncode, 0};
Rect *subTex = getFreeAtlasSubTexSlot(fontAtlas, arena, key); SubTexture *subTex = getFreeAtlasSubTexSlot(fontAtlas, arena, key);
*subTex = CAST(Rect){origin, font->maxSize}; subTex->rect = CAST(Rect){origin, font->maxSize};
charToEncode++; charToEncode++;
} }

View File

@ -377,7 +377,7 @@ void debug_drawUi(GameState *state, f32 dt)
if (debugString) if (debugString)
{ {
v2 strPos = v2_add(entity->pos, entity->hitboxSize); v2 strPos = v2_add(entity->pos, entity->hitbox);
i32 indexOfLowerAInMetrics = 'a' - CAST(i32) font->codepointRange.x; i32 indexOfLowerAInMetrics = 'a' - CAST(i32) font->codepointRange.x;
strPos.y += font->charMetrics[indexOfLowerAInMetrics].offset.y; strPos.y += font->charMetrics[indexOfLowerAInMetrics].offset.y;

View File

@ -3,6 +3,16 @@
#include "Dengine/Platform.h" #include "Dengine/Platform.h"
#include "Dengine/WorldTraveller.h" #include "Dengine/WorldTraveller.h"
SubTexture entity_getActiveSubTexture(Entity *const entity)
{
EntityAnim *entityAnim = &entity->animList[entity->currAnimId];
Animation *anim = entityAnim->anim;
char *frameName = anim->frameList[entityAnim->currFrame];
SubTexture result = asset_getAtlasSubTex(anim->atlas, frameName);
return result;
}
void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity, void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity,
const char *const animName) const char *const animName)
{ {
@ -71,9 +81,9 @@ void entity_updateAnim(EventQueue *eventQueue, Entity *const entity,
case entitytype_weapon: case entitytype_weapon:
case entitytype_projectile: case entitytype_projectile:
char *frameName = anim->frameList[currEntityAnim->currFrame]; char *frameName = anim->frameList[currEntityAnim->currFrame];
Rect texRect = SubTexture texRect =
asset_getAtlasSubTex(anim->atlas, frameName); asset_getAtlasSubTex(anim->atlas, frameName);
entity->renderSize = texRect.size; entity->size = v2_scale(texRect.rect.size, entity->scale);
default: default:
break; break;
} }
@ -114,8 +124,8 @@ Entity *const entity_add(MemoryArena *const arena, World *const world,
Entity entity = {0}; Entity entity = {0};
entity.id = world->uniqueIdAccumulator++; entity.id = world->uniqueIdAccumulator++;
entity.pos = pos; entity.pos = pos;
entity.hitboxSize = size; entity.size = size;
entity.renderSize = size; entity.hitbox = size;
entity.scale = scale; entity.scale = scale;
entity.type = type; entity.type = type;
entity.direction = direction; entity.direction = direction;

View File

@ -210,13 +210,13 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera,
pos.x += charMetric.advance; pos.x += charMetric.advance;
/* Get texture out */ /* Get texture out */
Rect charTexRect = SubTexture charTexRect =
asset_getAtlasSubTex(font->atlas, &CAST(char)codepoint); asset_getAtlasSubTex(font->atlas, &CAST(char)codepoint);
v4 deprecatedTexRect = {0}; v4 deprecatedTexRect = {0};
deprecatedTexRect.vec2[0] = charTexRect.pos; deprecatedTexRect.vec2[0] = charTexRect.rect.pos;
deprecatedTexRect.vec2[1] = deprecatedTexRect.vec2[1] =
v2_add(charTexRect.pos, charTexRect.size); v2_add(charTexRect.rect.pos, charTexRect.rect.size);
flipTexCoord(&deprecatedTexRect, FALSE, TRUE); flipTexCoord(&deprecatedTexRect, FALSE, TRUE);
@ -244,7 +244,7 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
// NOTE(doyle): Pos + Size since the origin of an entity is it's bottom left // NOTE(doyle): Pos + Size since the origin of an entity is it's bottom left
// corner. Add the two together so that the clipping point is the far right // corner. Add the two together so that the clipping point is the far right
// side of the entity // side of the entity
v2 rightAlignedP = v2_add(entity->pos, entity->hitboxSize); v2 rightAlignedP = v2_add(entity->pos, entity->hitbox);
v2 leftAlignedP = entity->pos; v2 leftAlignedP = entity->pos;
if (math_pointInRect(camera, leftAlignedP) || if (math_pointInRect(camera, leftAlignedP) ||
math_pointInRect(camera, rightAlignedP)) math_pointInRect(camera, rightAlignedP))
@ -252,12 +252,14 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
EntityAnim *entityAnim = &entity->animList[entity->currAnimId]; EntityAnim *entityAnim = &entity->animList[entity->currAnimId];
Animation *anim = entityAnim->anim; Animation *anim = entityAnim->anim;
char *frameName = anim->frameList[entityAnim->currFrame]; char *frameName = anim->frameList[entityAnim->currFrame];
Rect animRect = asset_getAtlasSubTex(anim->atlas, frameName); SubTexture animRect = asset_getAtlasSubTex(anim->atlas, frameName);
// TODO(doyle): Switch to rect // TODO(doyle): Switch to rect
v4 animTexRect = {0}; v4 animTexRect = {0};
animTexRect.vec2[0] = animRect.pos; animTexRect.vec2[0] = animRect.rect.pos;
animTexRect.vec2[1] = v2_add(animRect.pos, animRect.size); animTexRect.vec2[1] = v2_add(animRect.rect.pos, animRect.rect.size);
flipTexCoord(&animTexRect, entity->flipX, entity->flipY);
if (entity->direction == direction_east) if (entity->direction == direction_east)
{ {
@ -270,9 +272,8 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
updateBufferObject(renderer, &entityQuad, 1); updateBufferObject(renderer, &entityQuad, 1);
v2 posInCameraSpace = v2_sub(entity->pos, camera.pos); v2 posInCameraSpace = v2_sub(entity->pos, camera.pos);
// TODO(doyle): Scale temporarily
renderObject(renderer, posInCameraSpace, renderObject(renderer, posInCameraSpace,
v2_scale(entity->renderSize, entity->scale), pivotPoint, entity->size, pivotPoint,
entity->rotation + rotate, color, entity->tex); entity->rotation + rotate, color, entity->tex);
} }
} }

View File

@ -301,7 +301,10 @@ INTERNAL void assetInit(GameState *state)
claudeAtlas, claudeRipperBlast, numRects, claudeAtlas, claudeRipperBlast, numRects,
duration); duration);
char *claudeRipperBlastVfx[9] = { char *claudeRipperBlastVfx[12] = {
"ClaudeSprite_Attack_RipperBlast_Vfx_01",
"ClaudeSprite_Attack_RipperBlast_Vfx_02",
"ClaudeSprite_Attack_RipperBlast_Vfx_03",
"ClaudeSprite_Attack_RipperBlast_Vfx_04", "ClaudeSprite_Attack_RipperBlast_Vfx_04",
"ClaudeSprite_Attack_RipperBlast_Vfx_05", "ClaudeSprite_Attack_RipperBlast_Vfx_05",
"ClaudeSprite_Attack_RipperBlast_Vfx_06", "ClaudeSprite_Attack_RipperBlast_Vfx_06",
@ -601,19 +604,17 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
dir = direction_east; dir = direction_east;
tex = asset_getTex(assetManager, "ClaudeSprite.png"); tex = asset_getTex(assetManager, "ClaudeSprite.png");
collides = TRUE; collides = TRUE;
Entity *hero = Entity *hero =
entity_add(arena, world, pos, size, scale, type, dir, tex, collides); entity_add(arena, world, pos, size, scale, type, dir, tex, collides);
#if 0
Entity *heroWeapon = Entity *heroWeapon =
entity_add(arena, world, pos, V2(0, 0), entitytype_weapon, entity_add(arena, world, pos, V2(20, 20), scale, entitytype_weapon,
hero->direction, hero->tex, FALSE); dir, tex, FALSE);
heroWeapon->rotation = -90.0f; heroWeapon->flipX = TRUE;
heroWeapon->invisible = TRUE;
entity_addAnim(assetManager, heroWeapon, "claudeSword"); entity_addAnim(assetManager, heroWeapon, "claudeSword");
hero->stats->weapon = heroWeapon; hero->stats->weapon = heroWeapon;
#endif
hero->numAudioRenderers = 4; hero->numAudioRenderers = 4;
hero->audioRenderer = hero->audioRenderer =
@ -639,11 +640,11 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
entity_addAnim(assetManager, hero, "claudeRipperBlast"); entity_addAnim(assetManager, hero, "claudeRipperBlast");
entity_addAnim(assetManager, hero, "claudeAirSlash"); entity_addAnim(assetManager, hero, "claudeAirSlash");
entity_setActiveAnim(eventQueue, hero, "claudeIdle"); entity_setActiveAnim(eventQueue, hero, "claudeBattleIdle");
/* 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->hitbox;
type = entitytype_npc; type = entitytype_npc;
dir = direction_null; dir = direction_null;
tex = hero->tex; tex = hero->tex;
@ -855,7 +856,7 @@ void worldTraveller_gameInit(GameState *state, v2 windowSize)
INTERNAL inline v4 getEntityScreenRect(Entity entity) INTERNAL inline v4 getEntityScreenRect(Entity entity)
{ {
v4 result = math_getRect(entity.pos, entity.hitboxSize); v4 result = math_getRect(entity.pos, entity.hitbox);
return result; return result;
} }
@ -1162,12 +1163,6 @@ INTERNAL void beginAttack(AssetManager *assetManager, MemoryArena *arena,
case entityattack_claudeAttack: case entityattack_claudeAttack:
{ {
entity_setActiveAnim(eventQueue, attacker, "claudeAttack"); entity_setActiveAnim(eventQueue, attacker, "claudeAttack");
if (attacker->stats->weapon)
{
attacker->stats->weapon->invisible = FALSE;
entity_setActiveAnim(eventQueue, attacker->stats->weapon,
"claudeAttackSlashLeft");
}
if (attacker->direction == direction_east) if (attacker->direction == direction_east)
attacker->dPos.x += (1.0f * METERS_TO_PIXEL); attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
else else
@ -1178,12 +1173,6 @@ INTERNAL void beginAttack(AssetManager *assetManager, MemoryArena *arena,
case entityattack_claudeAttackUp: case entityattack_claudeAttackUp:
{ {
entity_setActiveAnim(eventQueue, attacker, "claudeAttackUp"); entity_setActiveAnim(eventQueue, attacker, "claudeAttackUp");
if (attacker->stats->weapon)
{
attacker->stats->weapon->invisible = FALSE;
entity_setActiveAnim(eventQueue, attacker->stats->weapon,
"claudeAttackSlashLeft");
}
if (attacker->direction == direction_east) if (attacker->direction == direction_east)
attacker->dPos.x += (1.0f * METERS_TO_PIXEL); attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
else else
@ -1194,12 +1183,6 @@ INTERNAL void beginAttack(AssetManager *assetManager, MemoryArena *arena,
case entityattack_claudeAttackDown: case entityattack_claudeAttackDown:
{ {
entity_setActiveAnim(eventQueue, attacker, "claudeAttackDown"); entity_setActiveAnim(eventQueue, attacker, "claudeAttackDown");
if (attacker->stats->weapon)
{
attacker->stats->weapon->invisible = FALSE;
entity_setActiveAnim(eventQueue, attacker->stats->weapon,
"claudeAttackSlashLeft");
}
if (attacker->direction == direction_east) if (attacker->direction == direction_east)
attacker->dPos.x += (1.0f * METERS_TO_PIXEL); attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
else else
@ -1330,12 +1313,6 @@ INTERNAL void endAttack(MemoryArena *arena, EventQueue *eventQueue,
case entityattack_claudeAttackUp: case entityattack_claudeAttackUp:
case entityattack_claudeAttackDown: case entityattack_claudeAttackDown:
// TODO(doyle): Move animation offsets out and into animation type // TODO(doyle): Move animation offsets out and into animation type
if (attacker->stats->weapon)
{
attacker->stats->weapon->invisible = TRUE;
}
if (attacker->direction == direction_east) if (attacker->direction == direction_east)
attacker->dPos.x -= (1.0f * METERS_TO_PIXEL); attacker->dPos.x -= (1.0f * METERS_TO_PIXEL);
else else
@ -1515,7 +1492,7 @@ INTERNAL b32 checkCollision(Entity *a, Entity *b)
b32 result = FALSE; b32 result = FALSE;
if (a->collides && b->collides && a->collidesWith[b->type]) if (a->collides && b->collides && a->collidesWith[b->type])
{ {
Rect aRect = {a->pos, a->hitboxSize}; Rect aRect = {a->pos, a->hitbox};
v2 aTopLeftP = v2 aTopLeftP =
getPosRelativeToRect(aRect, V2(0, 0), rectbaseline_topLeft); getPosRelativeToRect(aRect, V2(0, 0), rectbaseline_topLeft);
@ -1526,7 +1503,7 @@ INTERNAL b32 checkCollision(Entity *a, Entity *b)
v2 aBottomRightP = v2 aBottomRightP =
getPosRelativeToRect(aRect, V2(0, 0), rectbaseline_bottomRight); getPosRelativeToRect(aRect, V2(0, 0), rectbaseline_bottomRight);
Rect bRect = {b->pos, b->hitboxSize}; Rect bRect = {b->pos, b->hitbox};
if (math_pointInRect(bRect, aTopLeftP) || if (math_pointInRect(bRect, aTopLeftP) ||
math_pointInRect(bRect, aTopRightP) || math_pointInRect(bRect, aTopRightP) ||
@ -1730,7 +1707,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
V2((entity->pos.x - (0.5f * state->renderer.size.w)), (0.0f)); V2((entity->pos.x - (0.5f * state->renderer.size.w)), (0.0f));
// NOTE(doyle): Account for the hero's origin being the bottom left // NOTE(doyle): Account for the hero's origin being the bottom left
offsetFromEntityToCameraOrigin.x += (entity->hitboxSize.x * 0.5f); offsetFromEntityToCameraOrigin.x += (entity->hitbox.w * 0.5f);
world->cameraPos = offsetFromEntityToCameraOrigin; world->cameraPos = offsetFromEntityToCameraOrigin;
} }
@ -2017,11 +1994,38 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
if (stats->weapon) if (stats->weapon)
{ {
stats->weapon->pos = entity->pos; Entity *weapon = stats->weapon;
weapon->pos = entity->pos;
// TODO(doyle): Add concept of entity origin and make all
// transform start from that origin point
if (entity->direction == direction_east)
{
weapon->pos.x += entity->size.w;
weapon->pos.x -= weapon->size.w;
}
weapon->direction = entity->direction;
SubTexture entitySubTexture =
entity_getActiveSubTexture(entity);
weapon->pos.y += entitySubTexture.offset.y;
if (weapon->direction == direction_west)
{
weapon->pos.x += entitySubTexture.offset.x;
// TODO(doyle): Typedef rotation to degrees for type safety
weapon->rotation = DEGREES_TO_RADIANS(60.0f);
}
else
{
weapon->pos.x -= entitySubTexture.offset.x;
weapon->rotation = DEGREES_TO_RADIANS(-60.0f);
}
} }
if (entity->state == entitystate_battle) if (entity->state == entitystate_battle)
{ {
if (stats->actionTimer > 0) if (stats->actionTimer > 0)
stats->actionTimer -= dt * stats->actionSpdMul; stats->actionTimer -= dt * stats->actionSpdMul;
@ -2067,11 +2071,21 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
{ {
entity_updateAnim(eventQueue, entity, dt); entity_updateAnim(eventQueue, entity, dt);
/* Calculate region to render */ /* Calculate region to render */
if (entity->type == entitytype_weapon)
{
renderer_entity(renderer, camera, entity, renderer_entity(renderer, camera, entity,
v2_scale(entity->renderSize, 0.5f), 0, v2_scale(entity->size, 0.5f), 0,
V4(1, 1, 1, 1.0f));
}
else
{
renderer_entity(renderer, camera, entity,
v2_scale(entity->size, 0.5f), 0,
V4(1, 1, 1, 1)); V4(1, 1, 1, 1));
} }
} }
}
/* /*
***************************************** *****************************************
@ -2372,18 +2386,19 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
/* Draw hero avatar */ /* Draw hero avatar */
TexAtlas *heroAtlas = TexAtlas *heroAtlas =
asset_getTexAtlas(assetManager, "ClaudeSprite.png"); asset_getTexAtlas(assetManager, "ClaudeSprite.png");
Rect heroAvatarRect = SubTexture heroAvatarRect =
asset_getAtlasSubTex(heroAtlas, "ClaudeSprite_Avatar_01"); asset_getAtlasSubTex(heroAtlas, "ClaudeSprite_Avatar_01");
v2 heroAvatarP = v2 heroAvatarP = V2(10.0f, (renderer->size.h * 0.5f) -
V2(10.0f, (renderer->size.h * 0.5f) - (0.5f * heroAvatarRect.size.h)); (0.5f * heroAvatarRect.rect.size.h));
// TODO(doyle): Use rect in rendering not V4 // TODO(doyle): Use rect in rendering not V4
v4 heroAvatarTexRect = {0}; v4 heroAvatarTexRect = {0};
heroAvatarTexRect.vec2[0] = heroAvatarRect.pos; heroAvatarTexRect.vec2[0] = heroAvatarRect.rect.pos;
heroAvatarTexRect.vec2[1] = v2_add(heroAvatarRect.pos, heroAvatarRect.size); heroAvatarTexRect.vec2[1] =
v2_add(heroAvatarRect.rect.pos, heroAvatarRect.rect.size);
RenderTex heroRenderTex = {hero->tex, heroAvatarTexRect}; RenderTex heroRenderTex = {hero->tex, heroAvatarTexRect};
renderer_staticRect(renderer, heroAvatarP, heroAvatarRect.size, V2(0, 0), 0, renderer_staticRect(renderer, heroAvatarP, heroAvatarRect.rect.size, V2(0, 0), 0,
heroRenderTex, V4(1, 1, 1, 1)); heroRenderTex, V4(1, 1, 1, 1));
char heroAvatarStr[20]; char heroAvatarStr[20];
@ -2392,7 +2407,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
f32 strLenInPixels = f32 strLenInPixels =
CAST(f32)(font->maxSize.w * common_strlen(heroAvatarStr)); CAST(f32)(font->maxSize.w * common_strlen(heroAvatarStr));
v2 strPos = v2 strPos =
V2(heroAvatarP.x, heroAvatarP.y - (0.5f * heroAvatarRect.size.h)); V2(heroAvatarP.x, heroAvatarP.y - (0.5f * heroAvatarRect.rect.size.h));
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));
@ -2410,9 +2425,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
{ {
v2 difference = v2_sub(entity->pos, hero->pos); v2 difference = v2_sub(entity->pos, hero->pos);
f32 angle = math_atan2f(difference.y, difference.x); f32 angle = math_atan2f(difference.y, difference.x);
f32 angleDegrees = RADIANS_TO_DEGREES(angle);
v2 heroCenter = v2_add(hero->pos, v2_scale(hero->hitboxSize, 0.5f)); v2 heroCenter = v2_add(hero->pos, v2_scale(hero->hitbox, 0.5f));
RenderTex renderTex = renderer_createNullRenderTex(assetManager); RenderTex renderTex = renderer_createNullRenderTex(assetManager);
f32 distance = v2_magnitude(hero->pos, entity->pos); f32 distance = v2_magnitude(hero->pos, entity->pos);
renderer_rect(&state->renderer, camera, heroCenter, renderer_rect(&state->renderer, camera, heroCenter,

View File

@ -28,7 +28,8 @@ typedef struct AssetManager
* Texture Operations * Texture Operations
********************************* *********************************
*/ */
const Rect asset_getAtlasSubTex(TexAtlas *const atlas, const char *const key); const SubTexture asset_getAtlasSubTex(TexAtlas *const atlas,
const char *const key);
Texture *asset_getTex(AssetManager *const assetManager, const char *const key); Texture *asset_getTex(AssetManager *const assetManager, const char *const key);
TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager, TexAtlas *asset_getFreeTexAtlasSlot(AssetManager *const assetManager,
MemoryArena *arena, const char *const key, MemoryArena *arena, const char *const key,

View File

@ -94,6 +94,13 @@ typedef struct AudioVorbis
* Texture Assets * Texture Assets
********************************* *********************************
*/ */
typedef struct SubTexture
{
Rect rect;
v2 offset;
} SubTexture;
typedef struct TexAtlas typedef struct TexAtlas
{ {
Texture *tex; Texture *tex;

View File

@ -3,12 +3,11 @@
#include "Dengine/Common.h" #include "Dengine/Common.h"
#include "Dengine/Math.h" #include "Dengine/Math.h"
#include "Dengine/Assets.h"
typedef struct AssetManager AssetManager; typedef struct AssetManager AssetManager;
typedef struct AudioRenderer AudioRenderer; typedef struct AudioRenderer AudioRenderer;
typedef struct MemoryArena MemoryArena; typedef struct MemoryArena MemoryArena;
typedef struct Texture Texture;
typedef struct Animation Animation;
typedef struct World World; typedef struct World World;
typedef struct EventQueue EventQueue; typedef struct EventQueue EventQueue;
@ -95,8 +94,9 @@ struct Entity
v2 pos; // Position v2 pos; // Position
v2 dPos; // Velocity v2 dPos; // Velocity
v2 hitboxSize; v2 hitbox;
v2 renderSize; v2 size;
f32 scale; f32 scale;
f32 rotation; f32 rotation;
@ -107,6 +107,8 @@ struct Entity
enum Direction direction; enum Direction direction;
Texture *tex; Texture *tex;
b32 flipX;
b32 flipY;
// TODO(doyle): Two collision flags, we want certain entities to collide // TODO(doyle): Two collision flags, we want certain entities to collide
// with certain types of entities only (i.e. projectile from hero to enemy, // with certain types of entities only (i.e. projectile from hero to enemy,
@ -126,6 +128,7 @@ struct Entity
i32 numAudioRenderers; i32 numAudioRenderers;
}; };
SubTexture entity_getActiveSubTexture(Entity *const entity);
void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity, void entity_setActiveAnim(EventQueue *eventQueue, Entity *const entity,
const char *const animName); const char *const animName);
void entity_updateAnim(EventQueue *eventQueue, Entity *const entity, void entity_updateAnim(EventQueue *eventQueue, Entity *const entity,