
Introdução: o coração invisível de todo jogo
Todo jogo, por mais simples ou complexo que pareça, funciona com uma lógica fundamental: ele atualiza o estado do mundo e depois desenha esse mundo na tela. Esse processo acontece repetidamente, várias vezes por segundo, criando a sensação de movimento, controle e vida.
No MonoGame, esse mecanismo aparece de forma clara em dois métodos centrais:
Update(GameTime gameTime)
Draw(GameTime gameTime)
A própria documentação oficial do MonoGame explica que a classe Game é o ponto de entrada da maioria dos jogos e executa um game loop que chama Update(GameTime) e Draw(GameTime).
Em termos simples:
Update calcula. Draw mostra.
Ou seja:
Updatedecide o que acontece;Drawexibe o resultado na tela.
Se o jogador apertou uma tecla, isso é lido no Update.
Se o personagem mudou de posição, isso é calculado no Update.
Se houve colisão, isso é verificado no Update.
Se a pontuação aumentou, isso acontece no Update.
Depois disso, o Draw pega o estado atual e desenha:
- fundo;
- personagem;
- inimigos;
- moedas;
- tiros;
- partículas;
- HUD;
- texto;
- menus.
Esse capítulo é um dos mais importantes de todo o curso, porque entender o game loop significa entender a base de qualquer jogo.
🎮 O que é o game loop?
O game loop é o ciclo principal de execução de um jogo.
Enquanto o jogo está aberto, ele repete uma sequência parecida com esta:
1. Ler entradas do jogador
2. Atualizar lógica do jogo
3. Verificar colisões
4. Atualizar posições
5. Atualizar animações
6. Desenhar tudo na tela
7. Repetir
No MonoGame, esse ciclo é representado principalmente pelos métodos Update e Draw.
A documentação oficial do tutorial “The Game1 File” explica que, sempre que o game loop completa uma execução e o jogo é desenhado na tela, isso é chamado de frame. O mesmo material também explica que, se o MonoGame estiver rodando a 60 frames por segundo, ele realiza atualização e renderização de um frame em aproximadamente 16 milissegundos.
Isso significa que seu jogo não é uma imagem parada. Ele é uma sequência muito rápida de atualizações e desenhos.
É como um filme, mas interativo.
🧠 Por que o game loop é tão importante?
Porque tudo no jogo depende dele.
Sem game loop, não existe:
- movimento;
- colisão;
- animação;
- input;
- inimigo;
- física;
- câmera;
- pontuação;
- tempo;
- menu;
- pausa;
- tela de game over.
O jogo precisa estar constantemente perguntando:
“O que mudou desde o último frame?”
Essa pergunta é respondida no Update.
Depois ele pergunta:
“Como o jogo deve aparecer agora?”
Essa resposta acontece no Draw.
Essa separação parece simples, mas é uma das maiores diferenças entre um projeto organizado e um projeto confuso.
🧩 A estrutura básica do Game1.cs
Quando você cria um projeto MonoGame, normalmente recebe uma classe parecida com esta:
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void Update(GameTime gameTime)
{
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
}
A documentação oficial explica que a classe Game1 herda de Game, e essa classe base fornece os métodos principais do jogo, como carregamento de conteúdo, atualização e desenho.
Para este capítulo, os dois métodos mais importantes são:
Update(GameTime gameTime)
Draw(GameTime gameTime)
Eles são o centro da lógica interativa.
⚙️ O papel do Update
O método Update é onde a lógica do jogo acontece.
Ele é chamado repetidamente pelo MonoGame enquanto o jogo está rodando.
Dentro dele você coloca coisas como:
✅ leitura do teclado;
✅ leitura do mouse;
✅ leitura do controle;
✅ movimento do personagem;
✅ colisões;
✅ inteligência artificial simples;
✅ contadores de tempo;
✅ pontuação;
✅ vida;
✅ troca de fase;
✅ pause;
✅ game over;
✅ atualização de animações.
Exemplo simples:
protected override void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
base.Update(gameTime);
}
A documentação oficial de introdução ao MonoGame mostra justamente esse tipo de uso: no método Update, é comum verificar o estado do teclado ou do controle e sair do jogo se Escape ou o botão correspondente estiver pressionado.
Em outras palavras:
Update é onde o jogo pensa.
🎨 O papel do Draw
O método Draw é onde o jogo desenha o que deve aparecer na tela.
Ele também é chamado repetidamente enquanto o jogo está rodando.
Dentro dele você coloca:
✅ limpeza da tela;
✅ desenho do fundo;
✅ desenho do personagem;
✅ desenho dos inimigos;
✅ desenho dos objetos;
✅ desenho de textos;
✅ desenho do HUD;
✅ desenho de menus;
✅ efeitos visuais.
Exemplo básico:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
base.Draw(gameTime);
}
Esse código limpa a tela com a cor CornflowerBlue.
A documentação oficial reforça que a responsabilidade do Draw é renderizar o estado do jogo calculado no Update, e que ele não deve conter lógica complexa de jogo.
Essa frase é essencial.
Draw não deve decidir o jogo. Draw deve mostrar o jogo.
🧠 A regra de ouro: Update pensa, Draw mostra
Essa é a regra mais importante deste capítulo:
Update pensa. Draw mostra.
Se você gravar apenas uma ideia deste capítulo, grave essa.
O que deve ir no Update
Movimento
Input
Colisão
IA
Tempo
Regras
Pontuação
Vida
Estados do jogo
Animações
O que deve ir no Draw
Fundo
Sprites
Personagem
Inimigos
Moedas
Projéteis
Textos
HUD
Menus
Efeitos visuais
O que não deve ir no Draw
Evite colocar no Draw:
- cálculo de colisão;
- mudança de posição;
- leitura de teclado;
- alteração de vida;
- criação de inimigos;
- regras de vitória;
- regras de derrota;
- lógica de pontuação.
Por quê?
Porque o Draw existe para desenhar. Misturar lógica com renderização deixa o projeto difícil de manter.
🕒 O que é GameTime?
Tanto Update quanto Draw recebem um parâmetro chamado GameTime.
protected override void Update(GameTime gameTime)
protected override void Draw(GameTime gameTime)
O GameTime fornece informações de tempo para o jogo.
A documentação oficial explica que o parâmetro GameTime oferece um retrato dos valores de tempo do jogo, incluindo quanto tempo o frame anterior levou para executar.
Isso é muito importante porque jogos dependem de tempo.
Você precisa saber:
- quanto tempo passou desde o último frame;
- há quanto tempo o jogo está rodando;
- se o movimento deve ser ajustado;
- como manter animações suaves;
- como controlar timers.
O GameTime permite que o jogo não dependa apenas da velocidade da máquina.
🏃 Movimento sem delta time: o erro clássico
Imagine este código:
playerPosition.X += 5;
Parece simples. A cada Update, o personagem anda 5 pixels para a direita.
Mas há um problema.
Se o jogo roda mais rápido em um computador potente, o personagem pode andar mais rápido. Se roda mais lento em outro computador, pode andar mais devagar.
Isso acontece porque o movimento depende da quantidade de chamadas ao Update.
Por isso, em jogos, é comum usar o tempo decorrido entre frames.
⏱️ Movimento com delta time
O delta time é o tempo passado desde a última atualização.
No MonoGame, você pode obter isso assim:
float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
Depois usa esse valor no movimento:
playerPosition.X += playerSpeed * deltaTime;
Exemplo completo:
private Vector2 _playerPosition;
private float _playerSpeed = 200f;
protected override void Initialize()
{
_playerPosition = new Vector2(100, 100);
base.Initialize();
}
protected override void Update(GameTime gameTime)
{
float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Right))
_playerPosition.X += _playerSpeed * deltaTime;
if (keyboard.IsKeyDown(Keys.Left))
_playerPosition.X -= _playerSpeed * deltaTime;
base.Update(gameTime);
}
Aqui, playerSpeed significa pixels por segundo.
Se a velocidade for 200f, o personagem tenta andar 200 pixels por segundo, não 5 pixels por frame.
Isso deixa o movimento mais estável.
🧮 Por que 60 FPS importa?
FPS significa frames per second, ou quadros por segundo.
Se o jogo roda a 60 FPS, ele tenta desenhar 60 quadros por segundo. A documentação oficial usa esse exemplo para explicar que, a 60 frames por segundo, atualização e renderização precisam acontecer em aproximadamente 16 ms por frame.
Isso importa porque o tempo por frame é limitado.
Se sua lógica for pesada demais, o jogo pode perder desempenho.
Por isso, evite fazer operações pesadas dentro de Update e Draw.
Exemplos de coisas perigosas:
- carregar textura dentro do
Draw; - criar muitos objetos por frame;
- fazer leitura pesada de arquivo no
Update; - processar mapas inteiros sem necessidade;
- calcular colisões de forma desorganizada;
- desenhar milhares de sprites sem controle.
🎮 Exemplo prático: personagem se movendo na tela
Vamos montar um exemplo simples de movimento.
Primeiro, campos da classe:
private Texture2D _playerTexture;
private Vector2 _playerPosition;
private float _playerSpeed = 200f;
No LoadContent:
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
_playerTexture = Content.Load<Texture2D>("sprites/player");
}
No Initialize:
protected override void Initialize()
{
_playerPosition = new Vector2(100, 100);
base.Initialize();
}
No Update:
protected override void Update(GameTime gameTime)
{
float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Escape))
Exit();
if (keyboard.IsKeyDown(Keys.Right))
_playerPosition.X += _playerSpeed * deltaTime;
if (keyboard.IsKeyDown(Keys.Left))
_playerPosition.X -= _playerSpeed * deltaTime;
if (keyboard.IsKeyDown(Keys.Up))
_playerPosition.Y -= _playerSpeed * deltaTime;
if (keyboard.IsKeyDown(Keys.Down))
_playerPosition.Y += _playerSpeed * deltaTime;
base.Update(gameTime);
}
No Draw:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
_spriteBatch.Begin();
_spriteBatch.Draw(_playerTexture, _playerPosition, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
A documentação oficial sobre desenho de sprites explica o fluxo básico: adicionar textura ao projeto de conteúdo, carregar a textura em LoadContent e usar SpriteBatch para desenhar.
Esse é o primeiro momento em que você sente o jogo “nascer”: uma imagem aparece na tela e responde ao teclado.
🖼️ O que é SpriteBatch?
SpriteBatch é uma das classes mais usadas em jogos 2D com MonoGame.
Ela permite desenhar texturas, sprites e textos na tela.
O fluxo básico é:
_spriteBatch.Begin();
_spriteBatch.Draw(...);
_spriteBatch.End();
Ou seja:
- abre um lote de desenho;
- desenha sprites;
- fecha o lote.
Exemplo:
_spriteBatch.Begin();
_spriteBatch.Draw(_playerTexture, _playerPosition, Color.White);
_spriteBatch.End();
Pense no SpriteBatch como um organizador de desenhos 2D. Em vez de mandar cada sprite de forma desordenada para a placa gráfica, você agrupa os desenhos em um lote.
🧱 A ordem de desenho importa
No Draw, a ordem em que você desenha define o que aparece por cima.
Exemplo:
_spriteBatch.Begin();
_spriteBatch.Draw(_backgroundTexture, Vector2.Zero, Color.White);
_spriteBatch.Draw(_playerTexture, _playerPosition, Color.White);
_spriteBatch.Draw(_enemyTexture, _enemyPosition, Color.White);
_spriteBatch.End();
Aqui:
- o fundo é desenhado primeiro;
- o jogador vem por cima;
- o inimigo vem depois.
Se você desenhar o fundo por último, ele pode cobrir todo o resto.
Exemplo errado:
_spriteBatch.Begin();
_spriteBatch.Draw(_playerTexture, _playerPosition, Color.White);
_spriteBatch.Draw(_backgroundTexture, Vector2.Zero, Color.White);
_spriteBatch.End();
Nesse caso, o fundo pode esconder o jogador.
Regra prática:
Desenhe de trás para frente.
🧠 Separando lógica e desenho em classes
No começo, colocar tudo no Game1.cs é normal.
Mas logo o código cresce.
Uma boa evolução é criar uma classe Player.
Exemplo:
public class Player
{
private Texture2D _texture;
private Vector2 _position;
private float _speed = 200f;
public Player(Texture2D texture, Vector2 position)
{
_texture = texture;
_position = position;
}
public void Update(GameTime gameTime)
{
float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Right))
_position.X += _speed * deltaTime;
if (keyboard.IsKeyDown(Keys.Left))
_position.X -= _speed * deltaTime;
if (keyboard.IsKeyDown(Keys.Up))
_position.Y -= _speed * deltaTime;
if (keyboard.IsKeyDown(Keys.Down))
_position.Y += _speed * deltaTime;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(_texture, _position, Color.White);
}
}
No Game1.cs, ficaria assim:
private Player _player;
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
Texture2D playerTexture = Content.Load<Texture2D>("sprites/player");
_player = new Player(playerTexture, new Vector2(100, 100));
}
protected override void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
_player.Update(gameTime);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
_spriteBatch.Begin();
_player.Draw(_spriteBatch);
_spriteBatch.End();
base.Draw(gameTime);
}
Agora o Game1.cs não precisa saber todos os detalhes internos do jogador.
Ele apenas chama:
_player.Update(gameTime);
_player.Draw(_spriteBatch);
Isso deixa o código mais limpo.
🧭 O que deve acontecer primeiro: Update ou Draw?
A lógica natural é:
Update → Draw
Update → Draw
Update → Draw
Primeiro o jogo atualiza o estado. Depois desenha o estado atualizado.
Exemplo:
- jogador aperta seta direita;
Updatedetecta a tecla;- posição do jogador muda;
Drawdesenha o jogador na nova posição.
Se você tentar alterar posição no Draw, o projeto fica confuso.
O Draw deve ser como uma câmera: ele registra visualmente o estado atual do jogo.
🎯 Trabalhando com estados do jogo
Mesmo jogos simples têm estados.
Exemplos:
Menu
Jogando
Pausado
GameOver
Você pode representar isso com um enum:
public enum GameState
{
Menu,
Playing,
Paused,
GameOver
}
No Game1.cs:
private GameState _currentState = GameState.Menu;
No Update:
protected override void Update(GameTime gameTime)
{
KeyboardState keyboard = Keyboard.GetState();
switch (_currentState)
{
case GameState.Menu:
if (keyboard.IsKeyDown(Keys.Enter))
_currentState = GameState.Playing;
break;
case GameState.Playing:
_player.Update(gameTime);
if (keyboard.IsKeyDown(Keys.P))
_currentState = GameState.Paused;
break;
case GameState.Paused:
if (keyboard.IsKeyDown(Keys.R))
_currentState = GameState.Playing;
break;
case GameState.GameOver:
if (keyboard.IsKeyDown(Keys.Enter))
RestartGame();
break;
}
base.Update(gameTime);
}
No Draw:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
_spriteBatch.Begin();
switch (_currentState)
{
case GameState.Menu:
DrawMenu();
break;
case GameState.Playing:
DrawGameplay();
break;
case GameState.Paused:
DrawGameplay();
DrawPauseOverlay();
break;
case GameState.GameOver:
DrawGameOver();
break;
}
_spriteBatch.End();
base.Draw(gameTime);
}
Isso mostra como Update e Draw trabalham juntos, mas com responsabilidades diferentes.
⏸️ Pausar o jogo corretamente
Um erro comum é pausar apenas o desenho.
Mas pausar significa parar de atualizar a lógica principal.
Quando o jogo está pausado, normalmente você não quer:
- inimigos se movendo;
- tempo correndo;
- projéteis avançando;
- colisões acontecendo;
- jogador perdendo vida.
Então, no Update, você controla:
if (_currentState == GameState.Playing)
{
_player.Update(gameTime);
UpdateEnemies(gameTime);
UpdateCollisions();
}
Mas no Draw, você ainda pode desenhar o jogo congelado:
DrawGameplay();
DrawPauseOverlay();
Assim, a tela mostra a cena, mas a lógica está parada.
🧨 Erros comuns com Update e Draw
1. Colocar lógica dentro do Draw
Erro:
protected override void Draw(GameTime gameTime)
{
_playerPosition.X += 5;
}
Isso mistura renderização com lógica.
O correto é mover no Update.
2. Carregar textura dentro do Draw
Erro:
protected override void Draw(GameTime gameTime)
{
Texture2D player = Content.Load<Texture2D>("sprites/player");
}
Isso é ruim porque pode tentar carregar conteúdo repetidamente.
O correto é carregar em LoadContent.
3. Criar objetos demais por frame
Erro comum:
protected override void Update(GameTime gameTime)
{
List<Enemy> enemies = new List<Enemy>();
}
Criar objetos sem necessidade a cada frame pode prejudicar performance.
4. Depender de pixels por frame
Erro:
_position.X += 5;
Melhor:
_position.X += _speed * deltaTime;
5. Não separar responsabilidades
Se o Game1.cs vira um arquivo gigante, fica difícil evoluir.
Crie classes conforme o jogo cresce.
📊 Tabela prática: Update vs Draw
| Elemento | Update | Draw |
|---|---|---|
| Ler teclado | ✅ Sim | ❌ Não |
| Mover personagem | ✅ Sim | ❌ Não |
| Verificar colisão | ✅ Sim | ❌ Não |
| Atualizar pontuação | ✅ Sim | ❌ Não |
| Desenhar personagem | ❌ Não | ✅ Sim |
| Desenhar fundo | ❌ Não | ✅ Sim |
| Desenhar texto | ❌ Não | ✅ Sim |
| Desenhar HUD | ❌ Não | ✅ Sim |
| Criar regra de vitória | ✅ Sim | ❌ Não |
| Exibir tela de vitória | ❌ Não | ✅ Sim |
🧪 Pequeno exercício prático
Crie um personagem que se move pela tela e não sai dos limites da janela.
Campos:
private Texture2D _playerTexture;
private Vector2 _playerPosition;
private float _playerSpeed = 250f;
No Update:
protected override void Update(GameTime gameTime)
{
float deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
KeyboardState keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Escape))
Exit();
if (keyboard.IsKeyDown(Keys.Right))
_playerPosition.X += _playerSpeed * deltaTime;
if (keyboard.IsKeyDown(Keys.Left))
_playerPosition.X -= _playerSpeed * deltaTime;
if (keyboard.IsKeyDown(Keys.Up))
_playerPosition.Y -= _playerSpeed * deltaTime;
if (keyboard.IsKeyDown(Keys.Down))
_playerPosition.Y += _playerSpeed * deltaTime;
_playerPosition.X = MathHelper.Clamp(
_playerPosition.X,
0,
_graphics.PreferredBackBufferWidth - _playerTexture.Width
);
_playerPosition.Y = MathHelper.Clamp(
_playerPosition.Y,
0,
_graphics.PreferredBackBufferHeight - _playerTexture.Height
);
base.Update(gameTime);
}
No Draw:
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
_spriteBatch.Begin();
_spriteBatch.Draw(_playerTexture, _playerPosition, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
Esse exercício ensina três fundamentos:
- input;
- movimento;
- limite de tela.
🧠 O papel de base.Update e base.Draw
Você verá muito isto:
base.Update(gameTime);
e isto:
base.Draw(gameTime);
Essas chamadas executam o comportamento da classe base Game.
Em projetos simples, elas costumam ficar no final dos métodos.
No começo, mantenha essas chamadas. Conforme você avançar, entenderá melhor quando e por que reorganizá-las.
🧩 Componentes atualizáveis e desenháveis
O MonoGame também possui conceitos como GameComponent e DrawableGameComponent.
A documentação oficial explica que DrawableGameComponent é um objeto desenhável que, quando adicionado à coleção Game.Components, tem seu método Draw(GameTime) chamado quando Game.Draw(GameTime) é chamado.
Isso mostra que o próprio framework possui mecanismos para organizar componentes que atualizam e desenham.
Você não precisa usar isso no início, mas é útil saber que existe.
Em projetos maiores, você pode organizar sistemas com componentes, cenas ou entidades próprias.
🖊️ E texto na tela?
Além de sprites, você também pode desenhar texto.
A documentação oficial explica que o MonoGame oferece uma forma de desenhar texto usando fontes registradas no computador de desenvolvimento, convertendo a fonte em textura para renderização no jogo.
Em um jogo real, textos são usados para:
- pontuação;
- vida;
- tempo;
- menus;
- mensagens;
- diálogos;
- instruções;
- game over.
Mesmo o texto segue a mesma separação:
- o valor da pontuação muda no
Update; - a pontuação aparece na tela no
Draw.
Exemplo conceitual:
// Update
_score += 10;
// Draw
_spriteBatch.DrawString(_font, $"Score: {_score}", new Vector2(20, 20), Color.White);
🚀 Como pensar como desenvolvedor de jogos
Um iniciante costuma pensar assim:
“Como eu desenho meu personagem?”
Um desenvolvedor começa a pensar assim:
“Qual é o estado atual do meu jogo e como ele deve ser atualizado antes de ser desenhado?”
Essa mudança mental é poderosa.
Um jogo não é apenas imagem. Um jogo é estado.
Exemplos de estado:
posição do jogador
velocidade
vida
pontuação
fase atual
tempo restante
inimigos vivos
moedas coletadas
estado do menu
estado de pausa
O Update altera esse estado.
O Draw mostra esse estado.
Essa é a base.
📦 Organização recomendada após este capítulo
Depois de entender Update e Draw, comece a separar arquivos.
Estrutura sugerida:
MeuJogo/
├── Game1.cs
├── Program.cs
├── Entities/
│ └── Player.cs
├── Core/
│ └── InputManager.cs
├── Scenes/
│ └── GameScene.cs
└── Content/
└── sprites/
└── player.png
Você ainda não precisa criar arquitetura complexa, mas já pode começar a tirar responsabilidade do Game1.cs.
✅ Checklist do Capítulo 3
Ao final deste capítulo, você deve entender:
✅ o que é game loop;
✅ por que jogos atualizam e desenham várias vezes por segundo;
✅ o papel do Update;
✅ o papel do Draw;
✅ o que é GameTime;
✅ por que usar delta time;
✅ como mover um personagem;
✅ como desenhar uma textura;
✅ por que não colocar lógica no Draw;
✅ por que não carregar conteúdo por frame;
✅ como separar a classe Player;
✅ como pensar em estados de jogo;
✅ por que Update pensa e Draw mostra.
🏁 Conclusão: quem entende o game loop entende a alma do jogo
O game loop é a base invisível de qualquer jogo.
No MonoGame, ele aparece de forma clara e direta por meio dos métodos Update e Draw. Essa simplicidade é uma das maiores forças do framework: ele não esconde de você o funcionamento essencial do jogo.
Quando você entende que o Update atualiza o mundo e o Draw desenha o mundo, tudo começa a fazer mais sentido.
O personagem se move porque sua posição mudou no Update.
O jogador vê esse movimento porque o Draw desenhou o personagem na nova posição.
A pontuação aumenta no Update.
A pontuação aparece na tela no Draw.
O jogo pausa no Update.
A tela de pause aparece no Draw.
Esse padrão vai acompanhar você em todo o desenvolvimento com MonoGame.
Nos próximos capítulos, você vai usar essa base para carregar sprites, trabalhar com texturas, organizar assets e começar a transformar uma janela vazia em um jogo visualmente real.
Update é a mente do jogo. Draw é o rosto do jogo. O game loop é o coração que mantém tudo vivo.
❓ FAQ — Game Loop, Update e Draw no MonoGame
1. O que é game loop no MonoGame?
É o ciclo principal do jogo, responsável por atualizar a lógica e desenhar o resultado na tela. A classe Game do MonoGame executa esse loop chamando Update(GameTime) e Draw(GameTime).
2. Para que serve o Update?
O Update serve para atualizar a lógica do jogo: input, movimento, colisão, estados, pontuação, inimigos e regras.
3. Para que serve o Draw?
O Draw serve para renderizar o estado atual do jogo na tela: sprites, textos, fundo, HUD, menus e efeitos visuais.
4. Posso colocar lógica dentro do Draw?
Não é recomendado. A documentação oficial reforça que o Draw deve renderizar o estado calculado no Update, não conter lógica complexa de jogo.
5. O que é GameTime?
É um objeto que fornece informações de tempo do jogo, incluindo o tempo que o frame anterior levou para executar.
6. O que é delta time?
É o tempo decorrido desde o último frame. Ele ajuda a criar movimento mais consistente entre máquinas diferentes.
7. O que é FPS?
FPS significa frames por segundo. Se um jogo roda a 60 FPS, ele tenta atualizar e desenhar 60 quadros por segundo.
8. Onde devo carregar imagens?
Em geral, no LoadContent, não no Draw.
9. Onde devo desenhar sprites?
Dentro do Draw, usando SpriteBatch.
10. Qual frase resume este capítulo?
Update pensa. Draw mostra.
Capítulo 1 — O que é MonoGame e por que usar para criar jogos
Capítulo 2 — Preparando o Ambiente de Desenvolvimento
Capítulo 3 — Fundamentos do Game Loop: Update e Draw
Capítulo 4 — Sprites, Texturas e Content Pipeline
Capítulo 5 — Entrada do Jogador: Teclado, Mouse e Controle
Capítulo 6 — Colisão, Física Simples e Movimentação
Capítulo 7 — Cenas, Menus e Arquitetura do Jogo
Capítulo 8 — Áudio, Partículas, Animações e Polimento
Capítulo 9 — Shaders, Câmera, Mapas e Performance
Capítulo 10 — Publicação, Monetização e Projeto Final no MonoGame