Rotate targetting reticule to mob. Add pivot point

Notion of pivot point now for rotating, i.e. the anchor point at which
rotations are applied. Rotating the reticule is done by using inverse
trigonometry, namely atan2f.
This commit is contained in:
Doyle Thai 2016-07-23 21:26:15 +10:00
parent 358f850a2c
commit a43102ee26
6 changed files with 95 additions and 63 deletions

Binary file not shown.

View File

@ -147,7 +147,7 @@ INTERNAL void updateAndRenderDebugStack(Renderer *renderer, MemoryArena *arena,
v4 color = V4(0, 0, 0, 1);
renderer_staticString(renderer, arena, &GLOBAL_debug.font,
GLOBAL_debug.debugStrings[i],
GLOBAL_debug.currStringP, rotate, color);
GLOBAL_debug.currStringP, V2(0, 0), rotate, color);
GLOBAL_debug.currStringP.y -= (0.9f * GLOBAL_debug.stringLineGap);
}
@ -179,7 +179,7 @@ INTERNAL void renderConsole(Renderer *renderer, MemoryArena *arena)
v4 color = V4(0, 0, 0, 1);
renderer_staticString(renderer, arena, &GLOBAL_debug.font,
GLOBAL_debug.console[i], consoleStrP,
rotate, color);
V2(0, 0), rotate, color);
consoleStrP.y -= (0.9f * GLOBAL_debug.stringLineGap);
}
}
@ -218,7 +218,7 @@ void debug_drawUi(GameState *state, f32 dt)
v2 strPos = V2((renderer->size.w * 0.5f) - (strLenInPixels * 0.5f),
renderer->size.h - 300.0f);
renderer_staticString(&state->renderer, &state->arena, font, battleStr,
strPos, 0, color);
strPos, V2(0, 0), 0, color);
}
for (i32 i = 0; i < world->freeEntityIndex; i++)
@ -257,7 +257,7 @@ void debug_drawUi(GameState *state, f32 dt)
strPos.y += font->charMetrics[indexOfLowerAInMetrics].offset.y;
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
debugString, strPos, 0, color);
debugString, strPos, V2(0, 0), 0, color);
f32 stringLineGap = 1.1f * asset_getVFontSpacing(font->metrics);
strPos.y -= GLOBAL_debug.stringLineGap;
@ -266,14 +266,14 @@ void debug_drawUi(GameState *state, f32 dt)
snprintf(entityPosStr, ARRAY_COUNT(entityPosStr), "%06.2f, %06.2f",
entity->pos.x, entity->pos.y);
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
entityPosStr, strPos, 0, color);
entityPosStr, strPos, V2(0, 0), 0, color);
strPos.y -= GLOBAL_debug.stringLineGap;
char entityIDStr[32];
snprintf(entityIDStr, ARRAY_COUNT(entityIDStr), "ID: %4d/%d", entity->id,
world->uniqueIdAccumulator-1);
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
entityIDStr, strPos, 0, color);
entityIDStr, strPos, V2(0, 0), 0, color);
if (entity->stats)
{
@ -282,27 +282,27 @@ void debug_drawUi(GameState *state, f32 dt)
snprintf(entityHealth, ARRAY_COUNT(entityHealth), "HP: %3.0f/%3.0f",
entity->stats->health, entity->stats->maxHealth);
renderer_string(&state->renderer, &state->arena, cameraBounds,
font, entityHealth, strPos, 0, color);
font, entityHealth, strPos, V2(0, 0), 0, color);
strPos.y -= GLOBAL_debug.stringLineGap;
char entityTimer[32];
snprintf(entityTimer, ARRAY_COUNT(entityTimer), "ATB: %3.0f/%3.0f",
entity->stats->actionTimer, entity->stats->actionRate);
renderer_string(&state->renderer, &state->arena, cameraBounds,
font, entityTimer, strPos, 0, color);
font, entityTimer, strPos, V2(0, 0), 0, color);
strPos.y -= GLOBAL_debug.stringLineGap;
char entityIdTarget[32];
snprintf(entityIdTarget, ARRAY_COUNT(entityIdTarget),
"Targetting ID: %d", entity->stats->entityIdToAttack);
renderer_string(&state->renderer, &state->arena, cameraBounds,
font, entityIdTarget, strPos, 0, color);
font, entityIdTarget, strPos, V2(0, 0), 0, color);
}
strPos.y -= GLOBAL_debug.stringLineGap;
char *entityStateStr = debug_entitystate_string(entity->state);
renderer_string(&state->renderer, &state->arena, cameraBounds, font,
entityStateStr, strPos, 0, color);
entityStateStr, strPos, V2(0, 0), 0, color);
}
}

View File

@ -87,20 +87,16 @@ createDefaultTexQuad(Renderer *renderer, RenderTex renderTex)
return result;
}
INTERNAL void renderObject(Renderer *renderer, v2 pos, v2 size, f32 rotate,
v4 color, Texture *tex)
INTERNAL void renderObject(Renderer *renderer, v2 pos, v2 size, v2 pivotPoint,
f32 rotate, v4 color, Texture *tex)
{
mat4 transMatrix = mat4_translate(pos.x, pos.y, 0.0f);
// NOTE(doyle): Rotate from the center of the object, not its' origin (i.e.
// top left)
mat4 rotateMatrix = mat4_translate((size.x * 0.5f), (size.y * 0.5f), 0.0f);
// NOTE(doyle): Rotate from pivot point of the object, (0, 0) is top left
mat4 rotateMatrix = mat4_translate(pivotPoint.x, pivotPoint.y, 0.0f);
rotateMatrix = mat4_mul(rotateMatrix, mat4_rotate(rotate, 0.0f, 0.0f, 1.0f));
rotateMatrix = mat4_mul(rotateMatrix, mat4_translate((size.x * -0.5f), (size.y * -0.5f), 0.0f));
rotateMatrix = mat4_mul(rotateMatrix, mat4_translate(-pivotPoint.x, -pivotPoint.y, 0.0f));
// NOTE(doyle): We draw everything as a unit square in OGL. Scale it to size
// TODO(doyle): We should have a notion of hitbox size and texture size
// we're going to render so we can draw textures that may be bigger than the
// entity, (slightly) but keep a consistent bounding box
mat4 scaleMatrix = mat4_scale(size.x, size.y, 1.0f);
mat4 model = mat4_mul(transMatrix, mat4_mul(rotateMatrix, scaleMatrix));
@ -140,7 +136,7 @@ INTERNAL void renderObject(Renderer *renderer, v2 pos, v2 size, f32 rotate,
}
void renderer_rect(Renderer *const renderer, v4 cameraBounds, v2 pos, v2 size,
f32 rotate, RenderTex renderTex, v4 color)
v2 pivotPoint, f32 rotate, RenderTex renderTex, v4 color)
{
RenderQuad quad = createDefaultTexQuad(renderer, renderTex);
updateBufferObject(renderer, &quad, 1);
@ -148,13 +144,14 @@ void renderer_rect(Renderer *const renderer, v4 cameraBounds, v2 pos, v2 size,
// NOTE(doyle): Get the origin of cameraBounds in world space, bottom left
v2 offsetFromCamOrigin = V2(cameraBounds.x, cameraBounds.w);
v2 rectRelativeToCamera = v2_sub(pos, offsetFromCamOrigin);
renderObject(renderer, rectRelativeToCamera, size, rotate, color,
renderTex.tex);
renderObject(renderer, rectRelativeToCamera, size, pivotPoint, rotate,
color, renderTex.tex);
}
void renderer_string(Renderer *const renderer, MemoryArena *arena,
v4 cameraBounds, Font *const font,
const char *const string, v2 pos, f32 rotate, v4 color)
const char *const string, v2 pos, v2 pivotPoint,
f32 rotate, v4 color)
{
i32 strLen = common_strlen(string);
// TODO(doyle): Scale, not too important .. but rudimentary infrastructure
@ -208,14 +205,14 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena,
// relative to the window size, hence we also render at the origin since
// we're rendering a window sized buffer
updateBufferObject(renderer, stringQuads, quadIndex);
renderObject(renderer, V2(0.0f, 0.0f), renderer->size, rotate, color,
font->tex);
renderObject(renderer, V2(0.0f, 0.0f), renderer->size, pivotPoint,
rotate, color, font->tex);
PLATFORM_MEM_FREE(arena, stringQuads, strLen * sizeof(RenderQuad));
}
}
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
f32 rotate, v4 color)
v2 pivotPoint, f32 rotate, v4 color)
{
// TODO(doyle): Batch into render groups
@ -247,6 +244,6 @@ void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
v2 entityRelativeToCamera = v2_sub(entity->pos, offsetFromCamOrigin);
renderObject(renderer, entityRelativeToCamera, entity->renderSize,
rotate, color, entity->tex);
pivotPoint, rotate, color, entity->tex);
}
}

View File

@ -1022,7 +1022,7 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
*/
updateEntityAnim(entity, dt);
/* Calculate region to render */
renderer_entity(renderer, cameraBounds, entity, 0, V4(1, 1, 1, 1));
renderer_entity(renderer, cameraBounds, entity, V2(0, 0), 0, V4(1, 1, 1, 1));
}
// TODO(doyle): Dead hero not accounted for here
@ -1060,8 +1060,8 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
V2(10.0f, (renderer->size.h * 0.5f) - (0.5f * heroAvatarSize.h));
RenderTex heroRenderTex = {hero->tex, heroAvatarTexRect};
renderer_staticRect(renderer, heroAvatarP, heroAvatarSize, 0, heroRenderTex,
V4(1, 1, 1, 1));
renderer_staticRect(renderer, heroAvatarP, heroAvatarSize, V2(0, 0), 0,
heroRenderTex, V4(1, 1, 1, 1));
char heroAvatarStr[20];
snprintf(heroAvatarStr, ARRAY_COUNT(heroAvatarStr), "HP: %3.0f/%3.0f",
@ -1070,36 +1070,42 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
CAST(f32)(font->maxSize.w * common_strlen(heroAvatarStr));
v2 strPos = V2(heroAvatarP.x, heroAvatarP.y - (0.5f * heroAvatarSize.h));
renderer_staticString(&state->renderer, &state->arena, font, heroAvatarStr,
strPos, 0, V4(0, 0, 1, 1));
strPos, V2(0, 0), 0, V4(0, 0, 1, 1));
#ifdef DENGINE_DEBUG
ASSERT(world->numEntitiesInBattle != 1);
#endif
if (world->numEntitiesInBattle > 1)
for (i32 i = 0; i < world->maxEntities; i++)
{
for (i32 i = 0; i < world->maxEntities; i++)
Entity *entity = &world->entities[i];
if (entity->id == hero->id)
continue;
if (entity->state == entitystate_attack ||
entity->state == entitystate_battle)
{
Entity entity = world->entities[i];
if (entity.id == hero->id) continue;
v2 difference = v2_sub(entity->pos, hero->pos);
f32 angle = math_atan2f(difference.y, difference.x);
f32 angleDegrees = RADIANS_TO_DEGREES(angle);
Texture *emptyTex = asset_getTexture(assetManager, texlist_empty);
v2 heroCenter = v2_add(hero->pos, v2_scale(hero->hitboxSize, 0.5f));
RenderTex renderTex = {emptyTex, V4(0, 1, 1, 0)};
f32 distance = v2_magnitude(hero->pos, entity->pos);
renderer_rect(&state->renderer, cameraBounds, heroCenter,
V2(distance, 2.0f), V2(0, 0), angle, renderTex,
V4(1, 0, 0, 1.0f));
f32 distance = v2_magnitude(hero->pos, entity.pos);
if (entity.state == entitystate_battle)
{
Texture *emptyTex =
asset_getTexture(assetManager, texlist_empty);
v2 heroCenter =
v2_add(hero->pos, v2_scale(hero->hitboxSize, 0.5f));
RenderTex renderTex = {emptyTex, V4(0, 1, 1, 0)};
renderer_rect(&state->renderer, cameraBounds, heroCenter,
V2(distance, 5.0f), 0, renderTex,
V4(1, 0, 0, 0.5f));
}
}
}
#ifdef DENGINE_DEBUG
renderer_rect(&state->renderer, cameraBounds, V2(500, 500), V2(100, 2.0f),
V2(0, 0), DEGREES_TO_RADIANS(0.0f), renderTex,
V4(0, 0, 1, 1.0f));
renderer_rect(&state->renderer, cameraBounds, V2(500, 500), V2(100, 2.0f),
V2(0, 0), DEGREES_TO_RADIANS(5.0f), renderTex,
V4(0, 0, 1, 1.0f));
renderer_rect(&state->renderer, cameraBounds, V2(500, 500), V2(100, 2.0f),
V2(0, 0), DEGREES_TO_RADIANS(90.0f), renderTex,
V4(0, 0, 1, 1.0f));
debug_drawUi(state, dt);
#endif
}

View File

@ -8,8 +8,21 @@
#define SQUARED(x) (x * x)
#define ABS(x) ((x) > 0 ? (x) : -(x))
#define DEGREES_TO_RADIANS(x) (x * (MATH_PI / 180.0f))
#define RADIANS_TO_DEGREES(x) (x * (180.0f / MATH_PI))
#define SQRT(x) (sqrtf(x))
INTERNAL inline f32 math_acosf(f32 a)
{
f32 result = acosf(a);
return result;
}
INTERNAL inline f32 math_atan2f(f32 y, f32 x)
{
f32 result = atan2f(y, x);
return result;
}
/* VECTORS */
typedef union v2
{
@ -120,12 +133,26 @@ DEFINE_VECTOR_FLOAT_MATH(2);
DEFINE_VECTOR_FLOAT_MATH(3);
DEFINE_VECTOR_FLOAT_MATH(4);
INTERNAL inline f32 v2_lengthSq(const v2 a, const v2 b)
{
f32 x = b.x - a.x;
f32 y = b.y - a.y;
f32 result = (SQUARED(x) + SQUARED(y));
return result;
}
INTERNAL inline f32 v2_magnitude(const v2 a, const v2 b)
{
f32 x = b.x - a.x;
f32 y = b.y - a.y;
f32 inner = (SQUARED(x) + SQUARED(y));
f32 result = SQRT(inner);
f32 lengthSq = v2_lengthSq(a, b);
f32 result = SQRT(lengthSq);
return result;
}
INTERNAL inline v2 v2_normalise(const v2 a)
{
f32 magnitude = v2_magnitude(V2(0, 0), a);
v2 result = V2(a.x, a.y);
result = v2_scale(a, 1 / magnitude);
return result;
}

View File

@ -27,30 +27,32 @@ typedef struct RenderTex
// TODO(doyle): Clean up lines
// Renderer::~Renderer() { glDeleteVertexArrays(1, &this->quadVAO); }
void renderer_rect(Renderer *const renderer, v4 cameraBounds, v2 pos, v2 size,
f32 rotate, RenderTex renderTex, v4 color);
v2 pivotPoint, f32 rotate, RenderTex renderTex, v4 color);
inline void renderer_staticRect(Renderer *const renderer, v2 pos, v2 size,
f32 rotate, RenderTex renderTex, v4 color)
v2 pivotPoint, f32 rotate, RenderTex renderTex,
v4 color)
{
v4 staticCameraBounds = math_getRect(V2(0, 0), renderer->size);
renderer_rect(renderer, staticCameraBounds, pos, size, rotate, renderTex,
color);
renderer_rect(renderer, staticCameraBounds, pos, size, pivotPoint, rotate,
renderTex, color);
}
void renderer_string(Renderer *const renderer, MemoryArena *arena,
v4 cameraBounds, Font *const font,
const char *const string, v2 pos, f32 rotate, v4 color);
const char *const string, v2 pos, v2 pivotPoint,
f32 rotate, v4 color);
inline void renderer_staticString(Renderer *const renderer, MemoryArena *arena,
Font *const font, const char *const string,
v2 pos, f32 rotate, v4 color)
v2 pos, v2 pivotPoint, f32 rotate, v4 color)
{
v4 staticCameraBounds = math_getRect(V2(0, 0), renderer->size);
renderer_string(renderer, arena, staticCameraBounds, font, string, pos,
rotate, color);
pivotPoint, rotate, color);
}
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
f32 rotate, v4 color);
v2 pivotPoint, f32 rotate, v4 color);
#endif