π₯ Camera System
Fase: 3 β O Olho da Engine
Namespace: Caffeine::Render
Arquivo: src/render/Camera2D.hpp
Status: π
Planejado
RF: RF3.7
VisΓ£o Geral
O Camera System fornece a projeΓ§Γ£o matemΓ‘tica entre o espaΓ§o do mundo (coordenadas do jogo) e o espaΓ§o da tela (pixels). A Camera2D usa projeΓ§Γ£o ortogrΓ‘fica para jogos 2D. Na Fase 5, Camera3D adicionarΓ‘ perspectiva.
API Planejada
namespace Caffeine::Render {
// ============================================================================
// @brief CΓ’mera 2D com projeΓ§Γ£o ortogrΓ‘fica.
//
// Funcionalidades:
// - View matrix (posiΓ§Γ£o + rotaΓ§Γ£o da cΓ’mera)
// - Projection matrix (ortogrΓ‘fica β sem perspectiva)
// - worldToScreen / screenToWorld
// - Follow entity com smoothing
// - Camera shake
// - World bounds clamp
// ============================================================================
class Camera2D {
public:
Camera2D();
// ββ Matrizes βββββββββββββββββββββββββββββββββββββββββββββββ
Mat4 viewMatrix() const;
Mat4 projectionMatrix() const;
Mat4 viewProjectionMatrix() const; // cached, recalculated se dirty
// ββ ConversΓ£o de espaΓ§o ββββββββββββββββββββββββββββββββββββ
Vec2 worldToScreen(Vec2 worldPos) const;
Vec2 screenToWorld(Vec2 screenPos) const;
bool isVisible(Rect2D worldRect) const; // frustum culling bΓ‘sico
// ββ ConfiguraΓ§Γ£o βββββββββββββββββββββββββββββββββββββββββββ
void setPosition(Vec2 pos);
void setZoom(f32 zoom); // 1.0 = normal, 2.0 = 2x zoom in
void setRotation(f32 degrees);
void setViewport(Rect2D viewport); // pixels (x, y, width, height)
void setAspectRatio(f32 aspect);
// ββ Follow βββββββββββββββββββββββββββββββββββββββββββββββββ
void follow(ECS::Entity target, f32 smoothing = 0.1f); // lerp per frame
void stopFollowing();
void update(f64 dt, const ECS::World& world); // processa follow + shake
// ββ Shake ββββββββββββββββββββββββββββββββββββββββββββββββββ
void shake(Vec2 intensity, f32 duration); // em pixels
// ββ Bounds βββββββββββββββββββββββββββββββββββββββββββββββββ
void setBounds(Rect2D worldBounds);
void clearBounds();
// ββ Getters ββββββββββββββββββββββββββββββββββββββββββββββββ
Vec2 position() const { return m_position; }
f32 zoom() const { return m_zoom; }
f32 rotation() const { return m_rotation; }
Rect2D viewport() const { return m_viewport; }
Vec2 size() const { return {m_viewport.size.x / m_zoom,
m_viewport.size.y / m_zoom}; }
private:
Mat4 calculateViewMatrix() const;
Mat4 calculateProjectionMatrix() const;
Vec2 applyBounds(Vec2 pos) const;
Vec2 m_position = {0, 0};
f32 m_zoom = 1.0f;
f32 m_rotation = 0.0f;
Rect2D m_viewport = {{0, 0}, {1280, 720}};
f32 m_aspect = 1280.0f / 720.0f;
// Follow
ECS::Entity m_followTarget = ECS::Entity::INVALID;
f32 m_followSmoothing = 0.1f;
// Shake
Vec2 m_shakeIntensity = {0, 0};
f32 m_shakeTime = 0.0f;
f32 m_shakeDuration = 0.0f;
Vec2 m_shakeOffset = {0, 0};
// Bounds
bool m_hasBounds = false;
Rect2D m_worldBounds = {};
mutable Mat4 m_cachedViewProj;
mutable bool m_dirty = true;
};
} // namespace Caffeine::Render
MatemΓ‘tica da ProjeΓ§Γ£o OrtogrΓ‘fica
Projection Matrix (ortho):
left = -viewport.width / 2 / zoom
right = +viewport.width / 2 / zoom
bottom = -viewport.height / 2 / zoom
top = +viewport.height / 2 / zoom
near = -1000
far = +1000
Mat4::ortho(left, right, bottom, top, near, far)
View Matrix:
Mat4::translate(-position) * Mat4::rotateZ(-rotation)
Nota: A projeΓ§Γ£o ortogrΓ‘fica nΓ£o possui perspectiva β objetos distantes tΓͺm o mesmo tamanho que objetos prΓ³ximos. Correto para jogos 2D.
Camera Follow
// Smooth follow usando lerp:
void Camera2D::update(f64 dt, const ECS::World& world) {
if (m_followTarget.isValid()) {
if (auto* pos = world.get<Position2D>(m_followTarget)) {
Vec2 target = {pos->x, pos->y};
m_position = Vec2::lerp(m_position, target, m_followSmoothing);
m_position = applyBounds(m_position);
m_dirty = true;
}
}
// Shake decay
if (m_shakeTime > 0) {
m_shakeTime -= dt;
f32 t = m_shakeTime / m_shakeDuration;
m_shakeOffset = m_shakeIntensity * t * randomDir();
m_dirty = true;
}
}
Exemplos de Uso
// ββ Setup bΓ‘sico βββββββββββββββββββββββββββββββββββββββββββββ
Caffeine::Render::Camera2D camera;
camera.setViewport({ {0, 0}, {1280, 720} });
camera.setZoom(1.0f);
// ββ Follow jogador ββββββββββββββββββββββββββββββββββββββββββββ
camera.follow(playerEntity, 0.08f); // 8% do caminho por frame
camera.setBounds({ {0, 0}, {5000, 3000} }); // limites do mapa
// ββ Por frame ββββββββββββββββββββββββββββββββββββββββββββββββ
camera.update(dt, world);
batchRenderer.setCamera(camera);
// ββ Shake ao levar dano βββββββββββββββββββββββββββββββββββββββ
eventBus.subscribe<OnPlayerHit>([&](const OnPlayerHit& e) {
camera.shake({5, 5}, 0.3f); // 5px, 300ms
});
// ββ ConversΓ£o de espaΓ§o para UI βββββββββββββββββββββββββββββββ
Vec2 screenPos = camera.worldToScreen(enemyWorldPos);
// Usa screenPos para renderizar health bar sobre o inimigo
// ββ Culling manual ββββββββββββββββββββββββββββββββββββββββββββ
if (!camera.isVisible(entityBounds)) return; // skip render
Camera 3D (Fase 5)
Na Fase 5, Camera3D serΓ‘ adicionada com a mesma interface mas projeΓ§Γ£o perspectiva:
// Fase 5:
class Camera3D {
Mat4 viewMatrix() const; // lookAt(eye, target, up)
Mat4 projectionMatrix() const; // perspective(fovY, aspect, near, far)
// ... mesma interface de setPosition/setZoom β serΓ‘ setFOV
};
O Batch Renderer aceita Camera2D e Camera3D via polimorfismo.
DecisΓ΅es de Design
| DecisΓ£o |
Justificativa |
| Ortho para 2D |
Sem distorΓ§Γ£o perspectiva β correto para jogos 2D |
Cache m_dirty |
Evita recalcular VP matrix quando cΓ’mera nΓ£o moveu |
| Follow com lerp |
Suave, sem "snap" para posiΓ§Γ£o do jogador |
isVisible(Rect2D) |
Frustum culling bΓ‘sico para 2D |
setBounds |
CΓ’mera nunca mostra Γ‘rea fora do mapa |
CritΓ©rio de AceitaΓ§Γ£o
DependΓͺncias
ReferΓͺncias
π₯ Camera System
VisΓ£o Geral
O Camera System fornece a projeΓ§Γ£o matemΓ‘tica entre o espaΓ§o do mundo (coordenadas do jogo) e o espaΓ§o da tela (pixels). A
Camera2Dusa projeΓ§Γ£o ortogrΓ‘fica para jogos 2D. Na Fase 5,Camera3DadicionarΓ‘ perspectiva.API Planejada
MatemΓ‘tica da ProjeΓ§Γ£o OrtogrΓ‘fica
Nota: A projeΓ§Γ£o ortogrΓ‘fica nΓ£o possui perspectiva β objetos distantes tΓͺm o mesmo tamanho que objetos prΓ³ximos. Correto para jogos 2D.
Camera Follow
Exemplos de Uso
Camera 3D (Fase 5)
Na Fase 5,
Camera3DserΓ‘ adicionada com a mesma interface mas projeΓ§Γ£o perspectiva:O Batch Renderer aceita
Camera2DeCamera3Dvia polimorfismo.DecisΓ΅es de Design
m_dirtyisVisible(Rect2D)setBoundsCritΓ©rio de AceitaΓ§Γ£o
smoothing = 0.1fsem jitter a 60fpsworldToScreenescreenToWorldsΓ£o operaΓ§Γ΅es inversas corretassetBoundsimpede cΓ’mera de mostrar Γ‘rea fora do mapaDependΓͺncias
ReferΓͺncias
docs/architecture_specs.mdβ Β§10 Camera Systemdocs/fase3/batch-renderer.mdβ usa viewProjectionMatrix()docs/fase5/camera3d.mdβ extensΓ£o para 3D