Add rudimentary camera and side scrolling support
This commit is contained in:
parent
ad48dd5062
commit
f6ada44b41
@ -80,12 +80,18 @@ void renderer_debugString(Renderer *const renderer, Font *const font,
|
|||||||
debugRenderer.stringPos.y -= (0.9f * asset_getVFontSpacing(font->metrics));
|
debugRenderer.stringPos.y -= (0.9f * asset_getVFontSpacing(font->metrics));
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_entity(Renderer *renderer, Entity *entity, f32 dt, f32 rotate,
|
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity, f32 dt, f32 rotate,
|
||||||
v3 color)
|
v3 color)
|
||||||
{
|
{
|
||||||
// TODO(doyle): Batch into render groups
|
// TODO(doyle): Batch into render groups
|
||||||
if ((entity->pos.x < renderer->size.w && entity->pos.x >= 0) &&
|
|
||||||
(entity->pos.y < renderer->size.h && entity->pos.y >= 0))
|
// 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
|
||||||
|
// side of the entity
|
||||||
|
v2 rightAlignedP = v2_add(entity->pos, entity->size);
|
||||||
|
v2 leftAlignedP = entity->pos;
|
||||||
|
if ((leftAlignedP.x < cameraBounds.z && rightAlignedP.x >= cameraBounds.x) &&
|
||||||
|
(leftAlignedP.y < cameraBounds.y && rightAlignedP.y >= cameraBounds.w))
|
||||||
{
|
{
|
||||||
EntityAnim *anim = &entity->anim[entity->currAnimIndex];
|
EntityAnim *anim = &entity->anim[entity->currAnimIndex];
|
||||||
v4 texRect = anim->rect[anim->currRectIndex];
|
v4 texRect = anim->rect[anim->currRectIndex];
|
||||||
@ -107,8 +113,13 @@ void renderer_entity(Renderer *renderer, Entity *entity, f32 dt, f32 rotate,
|
|||||||
RenderQuad entityQuad =
|
RenderQuad entityQuad =
|
||||||
renderer_createDefaultQuad(renderer, texRect, entity->tex);
|
renderer_createDefaultQuad(renderer, texRect, entity->tex);
|
||||||
updateBufferObject(renderer, &entityQuad, 1);
|
updateBufferObject(renderer, &entityQuad, 1);
|
||||||
renderer_object(renderer, entity->pos, entity->size, rotate, color,
|
|
||||||
entity->tex);
|
// NOTE(doyle): The camera origin is 0,0 in world positions
|
||||||
|
v2 offsetFromCamOrigin = V2(cameraBounds.x, cameraBounds.w);
|
||||||
|
v2 entityRelativeToCamera = v2_sub(entity->pos, offsetFromCamOrigin);
|
||||||
|
|
||||||
|
renderer_object(renderer, entityRelativeToCamera, entity->size, rotate,
|
||||||
|
color, entity->tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
//choose to load assets outside of WorldTraveller!
|
//choose to load assets outside of WorldTraveller!
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
INTERNAL Entity *addEntity(World *world, v2 pos, v2 size, enum EntityType type,
|
INTERNAL Entity *addEntity(World *world, v2 pos, v2 size,
|
||||||
enum Direction direction, Texture *tex, b32 collides)
|
enum EntityType type, enum Direction direction,
|
||||||
|
Texture *tex, b32 collides)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef WT_DEBUG
|
#ifdef WT_DEBUG
|
||||||
@ -74,6 +75,42 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
|||||||
state->currWorldIndex = 0;
|
state->currWorldIndex = 0;
|
||||||
state->tileSize = 64;
|
state->tileSize = 64;
|
||||||
|
|
||||||
|
/* Init renderer */
|
||||||
|
Renderer *renderer = &state->renderer;
|
||||||
|
renderer->size = V2(CAST(f32) windowSize.x, CAST(f32) windowSize.y);
|
||||||
|
// NOTE(doyle): Value to map a screen coordinate to NDC coordinate
|
||||||
|
renderer->vertexNdcFactor =
|
||||||
|
V2(1.0f / renderer->size.w, 1.0f / renderer->size.h);
|
||||||
|
renderer->shader = asset_getShader(assetManager, shaderlist_sprite);
|
||||||
|
shader_use(renderer->shader);
|
||||||
|
|
||||||
|
const mat4 projection =
|
||||||
|
mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f);
|
||||||
|
shader_uniformSetMat4fv(renderer->shader, "projection", projection);
|
||||||
|
glCheckError();
|
||||||
|
|
||||||
|
/* Create buffers */
|
||||||
|
glGenVertexArrays(1, &renderer->vao);
|
||||||
|
glGenBuffers(1, &renderer->vbo);
|
||||||
|
glCheckError();
|
||||||
|
|
||||||
|
/* Bind buffers */
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo);
|
||||||
|
glBindVertexArray(renderer->vao);
|
||||||
|
|
||||||
|
/* Configure VAO */
|
||||||
|
const GLuint numVertexElements = 4;
|
||||||
|
const GLuint vertexSize = sizeof(v4);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, numVertexElements, GL_FLOAT, GL_FALSE, vertexSize,
|
||||||
|
(GLvoid *)0);
|
||||||
|
glCheckError();
|
||||||
|
|
||||||
|
/* Unbind */
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glCheckError();
|
||||||
|
|
||||||
/* Init world */
|
/* Init world */
|
||||||
const i32 targetWorldWidth = 500 * METERS_TO_PIXEL;
|
const i32 targetWorldWidth = 500 * METERS_TO_PIXEL;
|
||||||
const i32 targetWorldHeight = 15 * METERS_TO_PIXEL;
|
const i32 targetWorldHeight = 15 * METERS_TO_PIXEL;
|
||||||
@ -120,12 +157,14 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
World *const world = &state->world[state->currWorldIndex];
|
World *const world = &state->world[state->currWorldIndex];
|
||||||
|
world->cameraPos = V2(0.0f, 0.0f);
|
||||||
|
|
||||||
/* Init hero entity */
|
/* Init hero entity */
|
||||||
world->heroIndex = world->freeEntityIndex;
|
world->heroIndex = world->freeEntityIndex;
|
||||||
|
|
||||||
v2 pos = V2(0.0f, 0.0f);
|
|
||||||
v2 size = V2(58.0f, 98.0f);
|
v2 size = V2(58.0f, 98.0f);
|
||||||
|
v2 pos = V2(((renderer->size.w * 0.5f) - (size.w * 0.5f)),
|
||||||
|
CAST(f32) state->tileSize);
|
||||||
enum EntityType type = entitytype_hero;
|
enum EntityType type = entitytype_hero;
|
||||||
enum Direction dir = direction_east;
|
enum Direction dir = direction_east;
|
||||||
Texture *tex = asset_getTexture(assetManager, texlist_hero);
|
Texture *tex = asset_getTexture(assetManager, texlist_hero);
|
||||||
@ -133,15 +172,15 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
|||||||
Entity *hero = addEntity(world, pos, size, type, dir, tex, collides);
|
Entity *hero = addEntity(world, pos, size, type, dir, tex, collides);
|
||||||
|
|
||||||
/* Add idle animation */
|
/* Add idle animation */
|
||||||
f32 duration = 1.0f;
|
f32 duration = 1.0f;
|
||||||
i32 numRects = 1;
|
i32 numRects = 1;
|
||||||
v4 *heroIdleRects = CAST(v4 *) calloc(numRects, sizeof(v4));
|
v4 *heroIdleRects = CAST(v4 *) calloc(numRects, sizeof(v4));
|
||||||
heroIdleRects[0] = V4(746.0f, 1018.0f, 804.0f, 920.0f);
|
heroIdleRects[0] = V4(746.0f, 1018.0f, 804.0f, 920.0f);
|
||||||
addAnim(hero, heroIdleRects, numRects, duration);
|
addAnim(hero, heroIdleRects, numRects, duration);
|
||||||
|
|
||||||
/* Add walking animation */
|
/* Add walking animation */
|
||||||
duration = 0.10f;
|
duration = 0.10f;
|
||||||
numRects = 3;
|
numRects = 3;
|
||||||
v4 *heroWalkRects = CAST(v4 *) calloc(numRects, sizeof(v4));
|
v4 *heroWalkRects = CAST(v4 *) calloc(numRects, sizeof(v4));
|
||||||
heroWalkRects[0] = V4(641.0f, 1018.0f, 699.0f, 920.0f);
|
heroWalkRects[0] = V4(641.0f, 1018.0f, 699.0f, 920.0f);
|
||||||
heroWalkRects[1] = V4(746.0f, 1018.0f, 804.0f, 920.0f);
|
heroWalkRects[1] = V4(746.0f, 1018.0f, 804.0f, 920.0f);
|
||||||
@ -175,42 +214,6 @@ void worldTraveller_gameInit(GameState *state, v2i windowSize)
|
|||||||
npcWavingRects[1] = V4(944.0f, 812.0f, 1010.0f, 710.0f);
|
npcWavingRects[1] = V4(944.0f, 812.0f, 1010.0f, 710.0f);
|
||||||
addAnim(npc, npcWavingRects, numRects, duration);
|
addAnim(npc, npcWavingRects, numRects, duration);
|
||||||
|
|
||||||
/* Init renderer */
|
|
||||||
Renderer *renderer = &state->renderer;
|
|
||||||
renderer->size = V2(CAST(f32)windowSize.x, CAST(f32)windowSize.y);
|
|
||||||
// NOTE(doyle): Value to map a screen coordinate to NDC coordinate
|
|
||||||
renderer->vertexNdcFactor =
|
|
||||||
V2(1.0f / renderer->size.w, 1.0f / renderer->size.h);
|
|
||||||
renderer->shader = asset_getShader(assetManager, shaderlist_sprite);
|
|
||||||
shader_use(renderer->shader);
|
|
||||||
|
|
||||||
const mat4 projection =
|
|
||||||
mat4_ortho(0.0f, renderer->size.w, 0.0f, renderer->size.h, 0.0f, 1.0f);
|
|
||||||
shader_uniformSetMat4fv(renderer->shader, "projection", projection);
|
|
||||||
glCheckError();
|
|
||||||
|
|
||||||
/* Create buffers */
|
|
||||||
glGenVertexArrays(1, &renderer->vao);
|
|
||||||
glGenBuffers(1, &renderer->vbo);
|
|
||||||
glCheckError();
|
|
||||||
|
|
||||||
/* Bind buffers */
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, renderer->vbo);
|
|
||||||
glBindVertexArray(renderer->vao);
|
|
||||||
|
|
||||||
/* Configure VAO */
|
|
||||||
const GLuint numVertexElements = 4;
|
|
||||||
const GLuint vertexSize = sizeof(v4);
|
|
||||||
glEnableVertexAttribArray(0);
|
|
||||||
glVertexAttribPointer(0, numVertexElements, GL_FLOAT, GL_FALSE, vertexSize,
|
|
||||||
(GLvoid *)0);
|
|
||||||
glCheckError();
|
|
||||||
|
|
||||||
/* Unbind */
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
glCheckError();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void parseInput(GameState *state, const f32 dt)
|
INTERNAL void parseInput(GameState *state, const f32 dt)
|
||||||
@ -346,6 +349,13 @@ INTERNAL void parseInput(GameState *state, const f32 dt)
|
|||||||
// f'(t) = curr velocity = a*t + v, where v is old velocity
|
// f'(t) = curr velocity = a*t + v, where v is old velocity
|
||||||
hero->dPos = v2_add(hero->dPos, v2_scale(ddPos, dt));
|
hero->dPos = v2_add(hero->dPos, v2_scale(ddPos, dt));
|
||||||
hero->pos = newHeroP;
|
hero->pos = newHeroP;
|
||||||
|
|
||||||
|
v2 offsetFromHeroToOrigin =
|
||||||
|
V2((hero->pos.x - (0.5f * state->renderer.size.w)), (0.0f));
|
||||||
|
|
||||||
|
// NOTE(doyle): Hero position is offset to the center so -recenter it
|
||||||
|
offsetFromHeroToOrigin.x += (hero->size.x * 0.5f);
|
||||||
|
world->cameraPos = offsetFromHeroToOrigin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,10 +372,12 @@ void worldTraveller_gameUpdateAndRender(GameState *state, const f32 dt)
|
|||||||
|
|
||||||
/* Render entities */
|
/* Render entities */
|
||||||
ASSERT(world->freeEntityIndex < world->maxEntities);
|
ASSERT(world->freeEntityIndex < world->maxEntities);
|
||||||
|
v4 cameraBounds = getRect(world->cameraPos, renderer->size);
|
||||||
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];
|
||||||
renderer_entity(&state->renderer, entity, dt, 0.0f, V3(0, 0, 0));
|
renderer_entity(&state->renderer, cameraBounds, entity, dt, 0.0f,
|
||||||
|
V3(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(doyle): Clean up lines
|
// TODO(doyle): Clean up lines
|
||||||
|
@ -18,7 +18,6 @@ enum EntityType
|
|||||||
{
|
{
|
||||||
entitytype_null,
|
entitytype_null,
|
||||||
entitytype_hero,
|
entitytype_hero,
|
||||||
entitytype_camera,
|
|
||||||
entitytype_npc,
|
entitytype_npc,
|
||||||
entitytype_tile,
|
entitytype_tile,
|
||||||
entitytype_count,
|
entitytype_count,
|
||||||
|
@ -40,8 +40,8 @@ void renderer_string(Renderer *const renderer, Font *const font,
|
|||||||
void renderer_debugString(Renderer *const renderer, Font *const font,
|
void renderer_debugString(Renderer *const renderer, Font *const font,
|
||||||
const char *const string);
|
const char *const string);
|
||||||
|
|
||||||
void renderer_entity(Renderer *renderer, Entity *entity, f32 dt, f32 rotate,
|
void renderer_entity(Renderer *renderer, v4 cameraBounds, Entity *entity,
|
||||||
v3 color);
|
f32 dt, f32 rotate, v3 color);
|
||||||
|
|
||||||
void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v3 color,
|
void renderer_object(Renderer *renderer, v2 pos, v2 size, f32 rotate, v3 color,
|
||||||
Texture *tex);
|
Texture *tex);
|
||||||
|
@ -22,6 +22,8 @@ typedef struct World
|
|||||||
|
|
||||||
enum TexList texType;
|
enum TexList texType;
|
||||||
|
|
||||||
|
v2 cameraPos;
|
||||||
|
|
||||||
i32 heroIndex;
|
i32 heroIndex;
|
||||||
i32 freeEntityIndex;
|
i32 freeEntityIndex;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user