O que a câmera faz em um jogo 2D
Em jogos 2D, a “câmera” é a forma como o jogador enxerga o mundo: ela define qual parte do layout aparece na tela a cada momento. Em vez de mover o personagem “dentro da tela”, normalmente você move a câmera para acompanhar o personagem dentro de um layout maior que a área visível (viewport). Isso permite mapas extensos, exploração e sensação de espaço.
Neste capítulo você vai montar uma câmera funcional com: seguir o jogador, respeitar limites do mapa, suavização (lerp) e travamento em áreas específicas. Depois, vai aplicar parallax por camadas para criar profundidade, mantendo a UI fixa.
Preparação do layout para scroll
1) Crie um layout maior que a tela
Para existir scroll, o layout precisa ser maior do que a janela do jogo. Ajuste o tamanho do layout para algo como 3 a 5 vezes a largura/altura da janela (por exemplo: janela 1280x720 e layout 3840x2160).
- Garanta que o “chão” e paredes do cenário cubram a área jogável.
- Crie um objeto “Player” (se já existir do capítulo anterior, reutilize).
- Crie um objeto “LevelBounds” (opcional) como referência visual: um retângulo/Tilemap que marque a área jogável.
2) Organize camadas: Mundo x UI
Para a UI não se mover com a câmera, ela deve ficar em uma camada separada com parallax 0,0 (ou com “Fixar na tela”, dependendo do recurso disponível).
- Layer: World (padrão): onde ficam cenário, inimigos, player.
- Layer: BackgroundFar e BackgroundNear: para parallax (veremos adiante).
- Layer: UI: HUD, botões, textos. Essa camada deve permanecer fixa.
Câmera seguindo o personagem (scroll to)
Conceito
“Seguir o personagem” significa definir a posição do scroll (centro da câmera) com base na posição do Player. Em Construct, isso pode ser feito com uma ação de “Scroll to object” (seguir diretamente) ou controlando manualmente o scroll X/Y para obter suavização e regras mais avançadas.
- Ouça o áudio com a tela desligada
- Ganhe Certificado após a conclusão
- + de 5000 cursos para você explorar!
Baixar o aplicativo
Opção A: seguir direto (rápido e simples)
Use esta opção se você quer um comportamento imediato (sem suavização).
- No Event Sheet, crie um evento:
Every tick→ ação:Scroll to Player.
Isso centraliza a câmera no Player a cada frame. Em mapas grandes funciona bem, mas pode ficar “duro” e não permite facilmente travas e suavização refinada.
Opção B: câmera com alvo e suavização (recomendado)
Uma abordagem flexível é criar um objeto “CameraTarget” (um Sprite invisível) que representa para onde a câmera deve ir. Você move o CameraTarget com regras (limites, travas, offsets) e faz o scroll seguir esse alvo com suavização.
Passo a passo
- Crie um Sprite chamado CameraTarget (pode ser 1x1, invisível).
- Crie variáveis globais (ou do layout):
CamX,CamY,LerpSpeed(ex.: 8 a 15).
Eventos sugeridos:
On start of layout: set CamX = Player.X; set CamY = Player.Y; set LerpSpeed = 10A cada tick, defina o alvo da câmera (por enquanto, o Player):
Every tick: set CameraTarget position to (Player.X, Player.Y)Agora aplique suavização (lerp) ao scroll. A ideia do lerp é aproximar o scroll atual do alvo aos poucos, criando um movimento “macio”. Uma forma prática é usar uma interpolação exponencial baseada em delta-time:
Every tick: set CamX = lerp(CamX, CameraTarget.X, dt * LerpSpeed)Every tick: set CamY = lerp(CamY, CameraTarget.Y, dt * LerpSpeed)Every tick: Scroll to position (CamX, CamY)Observação: o nome das expressões pode variar conforme o Construct/versão. Se não houver lerp(), você pode simular com: CamX + (TargetX - CamX) * (dt * LerpSpeed).
Limites do mapa (clamp) para a câmera não mostrar “fora do cenário”
Conceito
Quando a câmera segue o Player perto das bordas do layout, ela pode revelar áreas vazias fora do mapa. Para evitar isso, você “trava” o scroll dentro de um intervalo: mínimo e máximo, baseado no tamanho do layout e no tamanho da janela.
Passo a passo prático
Calcule os limites do centro da câmera:
- MinX = metade da largura da janela
- MaxX = largura do layout − metade da largura da janela
- MinY = metade da altura da janela
- MaxY = altura do layout − metade da altura da janela
Depois, aplique clamp no alvo (ou no CamX/CamY). É mais comum clamp no alvo antes do lerp, para suavizar sem “vazar”.
Every tick: TargetX = clamp(Player.X, ViewportWidth/2, LayoutWidth - ViewportWidth/2)Every tick: TargetY = clamp(Player.Y, ViewportHeight/2, LayoutHeight - ViewportHeight/2)Every tick: set CameraTarget position to (TargetX, TargetY)Se você estiver usando o CameraTarget, basta posicioná-lo com os valores clampados. Se estiver usando “Scroll to Player” direto, você perde esse controle fino.
Tabela de referência (o que usar em cada caso)
| Objetivo | Melhor abordagem | Por quê |
|---|---|---|
| Implementar rápido | Scroll to Player | Menos eventos e sem variáveis |
| Suavização (lerp) | CameraTarget + CamX/CamY | Controle frame a frame do scroll |
| Limites do mapa (clamp) | Clamp no Target | Evita mostrar fora do layout |
| Travas por área | CameraTarget com regras | Fácil de sobrescrever o alvo |
Travamento da câmera em áreas específicas (camera zones)
Conceito
Em alguns trechos (salas, arenas, puzzles), você pode querer que a câmera pare de seguir o Player livremente e fique limitada a uma região, ou até fixa em um ponto. Isso é feito com “zonas de câmera”: áreas invisíveis que, quando o Player entra, alteram as regras do CameraTarget.
Modelos comuns de trava
- Trava total (câmera fixa): a câmera fica em um ponto específico (ex.: centro de uma arena).
- Trava por retângulo: a câmera pode se mover, mas apenas dentro de um retângulo menor que o layout (ex.: uma sala).
- Trava por eixo: trava só X ou só Y (ex.: corredor horizontal).
Passo a passo: trava por retângulo com objeto Zone
Crie um Sprite invisível chamado CameraZone (pode haver várias instâncias). Configure cada zona com o tamanho da área onde a câmera pode circular.
Estratégia: quando o Player estiver dentro de uma zona, os limites de clamp passam a ser os limites da zona (em vez do layout inteiro).
- Crie variáveis globais:
ZoneActive(boolean),ZoneLeft,ZoneRight,ZoneTop,ZoneBottom.
Eventos sugeridos:
Player is overlapping CameraZone: set ZoneActive = truePlayer is overlapping CameraZone: set ZoneLeft = CameraZone.BBoxLeftPlayer is overlapping CameraZone: set ZoneRight = CameraZone.BBoxRightPlayer is overlapping CameraZone: set ZoneTop = CameraZone.BBoxTopPlayer is overlapping CameraZone: set ZoneBottom = CameraZone.BBoxBottomPlayer is NOT overlapping any CameraZone: set ZoneActive = falseAo calcular o TargetX/TargetY, escolha os limites conforme ZoneActive:
Every tick: if ZoneActive then MinX = ZoneLeft + ViewportWidth/2 else MinX = ViewportWidth/2Every tick: if ZoneActive then MaxX = ZoneRight - ViewportWidth/2 else MaxX = LayoutWidth - ViewportWidth/2Every tick: if ZoneActive then MinY = ZoneTop + ViewportHeight/2 else MinY = ViewportHeight/2Every tick: if ZoneActive then MaxY = ZoneBottom - ViewportHeight/2 else MaxY = LayoutHeight - ViewportHeight/2Every tick: TargetX = clamp(Player.X, MinX, MaxX)Every tick: TargetY = clamp(Player.Y, MinY, MaxY)Every tick: set CameraTarget position to (TargetX, TargetY)Dica prática: se a zona for menor que a viewport, Min pode ficar maior que Max. Para evitar “quebrar”, garanta que a zona tenha pelo menos o tamanho da viewport ou trate o caso fixando a câmera no centro da zona.
Parallax: profundidade com camadas
Conceito
Parallax é o efeito em que elementos mais distantes se movem mais devagar do que os elementos próximos quando a câmera se desloca. Em 2D, isso é feito ajustando o “fator de parallax” das camadas: uma camada com parallax menor que 100% se move menos que o mundo, parecendo estar ao fundo.
Como pensar em camadas de profundidade
- Fundo distante (BackgroundFar): montanhas, céu, nuvens grandes. Parallax baixo (ex.: 10% a 30%).
- Fundo próximo (BackgroundNear): árvores, prédios distantes, neblina. Parallax médio (ex.: 40% a 70%).
- Mundo jogável (World): cenário principal e colisões. Parallax 100%.
- UI: parallax 0% (fixa).
Passo a passo: configurar parallax por camada
Crie duas camadas: BackgroundFar e BackgroundNear, abaixo da camada World.
Em BackgroundFar, defina Parallax X/Y para algo como
20, 20.Em BackgroundNear, defina Parallax X/Y para algo como
50, 50.Deixe a camada World em
100, 100.Defina a camada UI com Parallax
0, 0(ou equivalente para ficar fixa).
Compondo o fundo sem “buracos”
Como o fundo se move em velocidades diferentes, é comum aparecerem bordas vazias se o background não for grande o suficiente. Três soluções práticas:
- Background maior que o layout: use imagens largas/altas que cubram toda a área visível mesmo com deslocamento.
- Tile/Repeat: use sprites repetíveis (tileable) e repita horizontal/verticalmente.
- Anchoring por viewport: para elementos como céu, você pode manter fixo em Y (parallax Y = 0) e só aplicar parallax em X.
Exemplo de ajuste: céu que não sobe/desce com a câmera → em BackgroundFar use Parallax X=20 e Y=0.
Exercício guiado: mapa maior, câmera seguindo e parallax em duas camadas (UI fixa)
Objetivo
- Criar um layout maior que a tela.
- Implementar câmera suave seguindo o jogador com limites do mapa.
- Aplicar parallax em duas camadas de background.
- Garantir que a UI permaneça fixa na tela.
Checklist de configuração
- Layout com tamanho maior que a janela.
- Camadas: BackgroundFar, BackgroundNear, World, UI.
- Player na camada World.
- CameraTarget (invisível) na camada World (ou em uma camada separada, não importa visualmente).
- Elementos de UI (vida, moedas, texto) na camada UI.
Passo 1: montar o fundo com duas camadas
- Coloque uma imagem/sprite de céu/montanhas em BackgroundFar.
- Coloque uma imagem/sprite de árvores/prédios distantes em BackgroundNear.
- Configure Parallax: Far =
20,20(ou20,0), Near =50,50.
Passo 2: implementar a câmera suave com clamp
Crie variáveis: CamX, CamY, LerpSpeed. No início do layout, inicialize com a posição do Player.
On start of layout: CamX = Player.X; CamY = Player.Y; LerpSpeed = 10No tick, calcule alvo clampado e aplique lerp:
Every tick: MinX = ViewportWidth/2Every tick: MaxX = LayoutWidth - ViewportWidth/2Every tick: MinY = ViewportHeight/2Every tick: MaxY = LayoutHeight - ViewportHeight/2Every tick: TargetX = clamp(Player.X, MinX, MaxX)Every tick: TargetY = clamp(Player.Y, MinY, MaxY)Every tick: CamX = lerp(CamX, TargetX, dt * LerpSpeed)Every tick: CamY = lerp(CamY, TargetY, dt * LerpSpeed)Every tick: Scroll to position (CamX, CamY)Teste andando até as bordas do mapa: a câmera deve parar antes de mostrar fora do layout.
Passo 3: UI fixa na tela
Coloque um texto de teste (ex.: “HP: 3”) e um ícone na camada UI, no canto superior esquerdo. Configure a camada UI para não acompanhar o scroll (Parallax 0,0). Ao mover o Player, o mundo e os backgrounds devem se mover, mas a UI deve permanecer no mesmo lugar da tela.
Passo 4 (extra): travar câmera em uma “sala”
Adicione um CameraZone invisível em uma área do mapa (por exemplo, uma arena). Ao entrar, aplique os limites da zona conforme descrito na seção de travamento. Teste: dentro da zona, a câmera não deve sair do retângulo definido, mesmo que o Player tente ir além.