-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial LunarLander_pt
Select your language / Choisissez votre langue / Wählen Sie Ihre Sprache:
English | Français | Deutsch | Italiano | Español | Português | Slovenščina | Українська | Русский
Neste tutorial, você vai criar um Jogo de Pouso Lunar - um jogo de arcade clássico onde você controla uma nave espacial descendo até uma plataforma de pouso. Você precisa gerir seu empuxo para contrariar a gravidade e pousar suavemente sem se espatifar. Este jogo é perfeito para aprender conceitos de física como gravidade, empuxo, velocidade e gestão de combustível.
O que você vai aprender:
- Física de gravidade e empuxo
- Detecção de pouso baseada na velocidade
- Sistema de gestão de combustível
- Controlo de rotação ou direcional
- Zonas de pouso seguras
Dificuldade: Iniciante Preset: Preset Intermediário (a física de empuxo/combustível apoia-se em Execute Code o tempo todo, que não está no preset Iniciante)
- O módulo é puxado para baixo pela gravidade
- Pressionar CIMA aplica empuxo para cima (usa combustível)
- ESQUERDA/DIREITA controlam a rotação ou o movimento do módulo
- Pouse suavemente na plataforma para vencer
- Espatifa-se se pousar rápido demais ou errar a plataforma
- Se ficar sem combustível, não consegue mais frear!
| Elemento | Finalidade |
|---|---|
| Módulo | A nave espacial que você controla |
| Plataforma de Pouso | Zona segura para pousar |
| Solo | Terreno que causa um acidente |
| Indicador de Combustível | Mostra o combustível restante |
| Indicador de Velocidade | Mostra a velocidade atual |
- Na Árvore de Recursos, clique com o botão direito em Sprites e selecione Create Sprite
- Nomeie-o
spr_lander - Clique em Edit Sprite para abrir o editor de sprites
- Desenhe uma nave espacial simples (triângulo ou forma de módulo clássica)
- Tamanho: 32x32 pixels
- Importante: defina a origem como centro-baixo para um pouso correto
- Crie um novo sprite chamado
spr_pad - Desenhe uma plataforma plana com marcações (como um "H")
- Use cores vivas (amarelo/verde)
- Tamanho: 64x16 pixels
- Crie um novo sprite chamado
spr_ground - Desenhe um terreno rochoso/acidentado
- Use cores cinza/marrom
- Tamanho: 32x32 pixels
- Crie um novo sprite chamado
spr_flame - Desenhe uma pequena chama/jato de escape
- Use cores laranja/amarelo
- Tamanho: 16x16 pixels
![]()
O solo é um terreno perigoso que causa um acidente.
- Clique com o botão direito em Objects e selecione Create Object
- Nomeie-o
obj_ground - Defina o sprite como
spr_ground - Marque a caixa "Solid"
- Nenhum evento necessário

A plataforma de pouso é onde o jogador deve pousar em segurança.
- Crie um novo objeto chamado
obj_pad - Defina o sprite como
spr_pad - Marque a caixa "Solid"
- Nenhum evento necessário (a colisão é tratada pelo módulo)

O módulo é o principal objeto controlado pelo jogador, com física. Ao
contrário dos outros tutoriais de movimento deste wiki, seus controles
precisam acumular velocidade gradualmente e acompanhar um recurso de
combustível, então este objeto apoia-se mais em Control → Execute
Code (Python real — self é a instância atual, game é o game runner,
keyboard.check(nome) informa uma tecla mantida pressionada) do que
apenas em ações estruturadas. Onde uma ação estruturada resolve, este
tutorial ainda usa uma.
- Crie um novo objeto chamado
obj_lander - Defina o sprite como
spr_lander
Evento: Create
- Adicione a ação Move → Set Gravity (Direction:
270, Gravity:0.05) — uma puxada suave para baixo; o motor a adiciona automaticamente à velocidade vertical do módulo a cada passo, igual à gravidade do tutorial de Plataforma, só que mais fraca. - Adicione a ação Control → Execute Code:
self.thrust_force = 0.1
self.max_speed = 5
self.fuel = 100
self.fuel_use = 0.5
self.landed = False
self.crashed = False
self.safe_speed = 2O sistema de movimento deste projeto já acompanha a velocidade via
self.hspeed/self.vspeed e move a instância nessa quantidade a cada
frame (com a colisão sólida integrada) — não é preciso criar variáveis
hsp/vsp separadas como faria uma simulação física crua.
Evento: Step — Adicione a ação Control → Execute Code:
if not self.landed and not self.crashed:
if keyboard.check('up') and self.fuel > 0:
self.vspeed -= self.thrust_force
self.fuel -= self.fuel_use
if self.fuel < 0:
self.fuel = 0
if keyboard.check('left'):
self.hspeed -= 0.05
if keyboard.check('right'):
self.hspeed += 0.05
# Limita a velocidade máxima
self.hspeed = max(-self.max_speed, min(self.max_speed, self.hspeed))
self.vspeed = max(-self.max_speed, min(self.max_speed, self.vspeed))
# Impede o módulo de sair pelas laterais ou acima da room
room = game.current_room
if self.x < 16:
self.x = 16
self.hspeed = 0
if self.x > room.width - 16:
self.x = room.width - 16
self.hspeed = 0
if self.y < 16:
self.y = 16
self.vspeed = 0O bloco inteiro está envolto em if not self.landed and not self.crashed:
para que empuxo e direção parem no instante em que a partida termina — o
objeto self não tem como abandonar um evento no meio (não há exit no
estilo GML), então um if em torno do resto do código é o equivalente.
Evento: Collision with obj_pad
- Adicione a ação Control → Test Expression
- Expression:
(self.hspeed**2 + self.vspeed**2)**0.5 <= self.safe_speed— a velocidade de pouso é o comprimento do vetor velocidade; Pitágoras, não uma variávelspeed(neste motor,speedé a velocidade de animação do sprite, não a magnitude do movimento — uma armadilha real para quem vem do GameMaker). - Then Actions:
-
Control → Set Variable (Variable:
landed, Value:true, Scope:self) - Move → Stop Movement
-
Move → Set Gravity (Direction:
270, Gravity:0) — impede a gravidade de voltar a acumular silenciosamente velocidade vertical num módulo que já pousou -
Output → Show Message (Message:
Perfect Landing! You Win!)
-
Control → Set Variable (Variable:
- Else Actions:
-
Control → Set Variable (Variable:
crashed, Value:true, Scope:self) -
Output → Show Message (Message:
Crashed! Too fast!) - Room → Restart Room
-
Control → Set Variable (Variable:
- Expression:
O texto de Show Message é uma string fixa — ele não pode embutir a velocidade real de pouso. O HUD (Passo 7) já exibe a velocidade ao vivo até o momento do contato, então o jogador já viu o número.
Evento: Collision with obj_ground
- Adicione a ação Control → Set Variable (Variable:
crashed, Value:true, Scope:self) - Adicione a ação Output → Show Message (Message:
Crashed into terrain!) - Adicione a ação Room → Restart Room

Retorno visual ao aplicar empuxo.
- Crie um novo objeto chamado
obj_flame - Defina o sprite como
spr_flame
Ele será criado pelo módulo ao aplicar empuxo (recurso avançado). Para uma abordagem mais simples, você pode desenhar a chama no evento Draw do módulo.

O controlador de jogo exibe combustível, velocidade e instruções lendo-os da instância do módulo a cada frame.
- Crie um novo objeto chamado
obj_game_controller - Nenhum sprite necessário
Evento: Draw
- Adicione a ação Control → Execute Code — encontra o módulo e calcula os valores que as ações Draw abaixo vão exibir:
lander = None
for inst in game.current_room.instances:
if inst.object_name == 'obj_lander':
lander = inst
break
if lander is not None:
self.fuel_display = round(lander.fuel)
self.speed_display = round((lander.hspeed ** 2 + lander.vspeed ** 2) ** 0.5, 2)
self.too_fast = self.speed_display > lander.safe_speed
self.no_fuel = lander.fuel <= 0
else:
self.fuel_display = 0
self.speed_display = 0.0
self.too_fast = False
self.no_fuel = False- Adicione a ação Game → Set Draw Color (Color:
#FFFFFF) - Adicione a ação Game → Draw Text (Text:
LUNAR LANDER, X:10, Y:10) - Adicione a ação Game → Draw Text (Text:
Fuel:, X:10, Y:30) - Adicione a ação Game → Draw Variable (Variable:
self.fuel_display, X:70, Y:30) - Adicione a ação Game → Draw Text (Text:
Speed:, X:10, Y:50) - Adicione a ação Game → Draw Variable (Variable:
self.speed_display, X:70, Y:50) - Adicione a ação Game → Draw Text (Text:
Safe Speed: < 2, X:10, Y:70)
Depois as duas linhas de aviso, cada uma condicionada por Control → Test Expression (nenhum Else necessário — nada é desenhado quando a condição é falsa):
-
Control → Test Expression (Expression:
self.too_fast)- Then Actions: Game → Set Draw Color (
#FF0000), Game → Draw Text (TOO FAST!, X10, Y90) - Else Actions: Game → Set Draw Color (
#00FF00), Game → Draw Text (Speed OK, X10, Y90)
- Then Actions: Game → Set Draw Color (
-
Control → Test Expression (Expression:
self.no_fuel)- Then Actions: Game → Set Draw Color (
#FF0000), Game → Draw Text (NO FUEL!, X10, Y110)
- Then Actions: Game → Set Draw Color (
-
Adicione a ação Game → Set Draw Color (Color:
#808080) -
Adicione a ação Game → Draw Text (Text:
UP: Thrust | LEFT/RIGHT: Move, X:10, Y:440) — escolha um Y perto da parte inferior do tamanho de room que você usar no Passo 8.

- Clique com o botão direito em Rooms e selecione Create Room
- Nomeie-a
room_game - Defina o tamanho da room (ex.: 640x480)
- Defina a cor de fundo como preto (o espaço)
Construa o seu nível seguindo estas orientações:
-
Solo - Coloque
obj_groundao longo da parte inferior para criar o terreno -
Plataforma de pouso - Coloque
obj_padnuma lacuna do terreno -
Módulo - Coloque
obj_landerno topo da room -
Controlador de jogo - Coloque
obj_game_controllerem qualquer lugar
L <- O módulo começa aqui
GGG GGG PPPP GGG GGG
GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
G = Solo L = Módulo P = Plataforma de pouso

- Clique em Executar ou pressione F5 para testar
- Use a seta CIMA para o empuxo (fique de olho no combustível!)
- Use as setas ESQUERDA/DIREITA para dirigir
- Pouse suavemente na plataforma (a velocidade deve ser inferior a 2)
- Evite o terreno rochoso!
Em vez do movimento esquerda/direita, gire o módulo e aplique empuxo na
direção para a qual ele aponta. As instâncias deste motor têm um atributo
rotation real (graus, 0 = direita, crescente no sentido anti-horário)
usado para girar o sprite — não é preciso
image_angle/lengthdir_x/lengthdir_y, já que math já está
disponível em Execute Code:
Substitua o código do evento Create do 5.1 por:
self.thrust_force = 0.1
self.max_speed = 5
self.fuel = 100
self.fuel_use = 0.5
self.landed = False
self.crashed = False
self.safe_speed = 2
self.rotation = 90 # apontando para cima
self.rotation_speed = 3Substitua as linhas de direção do 5.2 (o bloco left/right → hspeed)
por:
if keyboard.check('left'):
self.rotation -= self.rotation_speed
if keyboard.check('right'):
self.rotation += self.rotation_speedE substitua as linhas de empuxo por:
if keyboard.check('up') and self.fuel > 0:
rad = math.radians(self.rotation)
self.hspeed += self.thrust_force * math.cos(rad)
self.vspeed -= self.thrust_force * math.sin(rad)
self.fuel -= self.fuel_use
if self.fuel < 0:
self.fuel = 0(o -= em vspeed corresponde ao código de gravidade do próprio motor —
o eixo Y da tela aumenta para baixo, então "cima" é velocidade vertical
negativa).
Crie plataformas de tamanhos diferentes com valores de pontos diferentes:
- Plataforma pequena = 100 pontos (mais difícil)
- Plataforma grande = 50 pontos (mais fácil)
- Crie
obj_fuelque flutua no ar - Ao colidir com o módulo, adicione combustível e destrua
Crie várias rooms com terreno cada vez mais difícil e plataformas de pouso menores.
Adicione um pequeno empurrão horizontal constante. No código do evento
Create de obj_lander, adicione self.wind_force = 0.02; depois, no
início do bloco if not self.landed and not self.crashed: do evento Step,
adicione:
self.hspeed += self.wind_force| Problema | Solução |
|---|---|
| O módulo cai rápido demais | Diminua o valor Gravity de Set Gravity, ou aumente thrust_force no código do evento Create |
| Não consigo frear o suficiente | Aumente thrust_force, ou aumente safe_speed
|
| O combustível acaba rápido demais | Diminua fuel_use, ou aumente o fuel inicial |
| O módulo sai da tela | Verifique o bloco de limites no fim do código do evento Step |
| O pouso não é registrado | Certifique-se de que obj_pad tem "Solid" marcado |
Parabéns! Você criou um jogo de pouso lunar! Você aprendeu:
-
Física de empuxo - Ajustar
self.vspeedcontra uma puxada contínua de Set Gravity -
Gestão de velocidade - Calcular a velocidade a partir de
hspeed/vspeedcom o teorema de Pitágoras - Sistema de combustível - Jogabilidade de gestão de recursos com uma simples variável de instância
- Detecção de colisão - Resultados diferentes para plataforma vs solo, escolhidos com Test Expression
- Exibição de HUD - Calcular os valores a exibir em Execute Code e depois mostrá-los com Draw Text/Draw Variable
- Rotação Realista - Girar e aplicar empuxo na direção para a qual se aponta
- Vários Níveis - Terreno cada vez mais difícil
- Sistema de Pontuação - Pontos com base no combustível restante e na precisão do pouso
- Asteroides - Adicionar perigos móveis a evitar
- Modo de Dois Jogadores - Corrida para pousar primeiro
- Tutoriais - Mais tutoriais de jogos
- Preset Intermediário - Visão geral do preset de que este tutorial precisa
- Tutorial: Plataforma - Criar um jogo de saltos de plataforma
- Tutorial: Labirinto - Criar um jogo de navegação em labirinto
- Referência de Eventos - Documentação completa de eventos