-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial Sokoban_pt
Selecione seu idioma / Choisissez votre langue / Wählen Sie Ihre Sprache:
English | Français | Deutsch | Italiano | Español | Português | Slovenščina | Українська | Русский
Neste tutorial, você criará um jogo de puzzle Sokoban - um clássico puzzle de empurrar caixas onde o jogador deve empurrar todas as caixas para os locais de destino. Sokoban (que significa "guardião do armazém" em japonês) é perfeito para aprender movimento baseado em grade e lógica de jogo de puzzle.
O que você aprenderá:
- Movimento baseado em grade (movimento em passos fixos)
- Mecânica de empurrar para mover objetos
- Detecção de colisão com múltiplos tipos de objetos
- Detecção de condição de vitória
- Design de nível para jogos de puzzle
Dificuldade: Iniciante Preset: Preset Intermediário (a mecânica de empurrar e o movimento baseado em grade usados aqui não estão no preset Iniciante)
- O jogador pode se mover para cima, baixo, esquerda ou direita
- O jogador pode empurrar caixas (mas não puxá-las)
- Apenas uma caixa pode ser empurrada por vez
- As caixas não podem ser empurradas através de paredes ou outras caixas
- O nível é concluído quando todas as caixas estão nos locais de destino
| Elemento | Propósito |
|---|---|
| Jogador | O guardião do armazém que você controla |
| Caixa | Caixas que o jogador empurra |
| Parede | Obstáculos sólidos que bloqueiam o movimento |
| Destino | Locais de objetivo onde as caixas devem ser colocadas |
| Chão | Terreno caminhável (visual opcional) |
Todos os sprites devem ter o mesmo tamanho (32x32 pixels funciona bem) para criar uma grade apropriada.
- Na Árvore de Recursos, clique com o botão direito em Sprites e selecione Create Sprite
- Nomeie-o como
spr_player - Clique em Edit Sprite para abrir o editor de sprites
- Desenhe um personagem simples (uma forma de pessoa ou robô)
- Use uma cor distinta como azul ou verde
- Tamanho: 32x32 pixels
- Clique em OK para salvar
- Crie um novo sprite nomeado
spr_crate - Desenhe uma caixa de madeira ou forma de caixa
- Use cores marrom ou laranja
- Tamanho: 32x32 pixels
- Crie um novo sprite nomeado
spr_crate_ok - Desenhe a mesma caixa mas com uma cor diferente (verde) para mostrar que está corretamente colocada
- Tamanho: 32x32 pixels
- Crie um novo sprite nomeado
spr_wall - Desenhe um padrão sólido de tijolos ou pedra
- Use cores cinza ou escuras
- Tamanho: 32x32 pixels
- Crie um novo sprite nomeado
spr_target - Desenhe uma marca X ou indicador de objetivo
- Use uma cor brilhante como vermelho ou amarelo
- Tamanho: 32x32 pixels
- Crie um novo sprite nomeado
spr_floor - Desenhe um padrão simples de ladrilho de chão
- Use uma cor neutra
- Tamanho: 32x32 pixels
![]()
A parede é o objeto mais simples - ela apenas bloqueia o movimento.
- Clique com o botão direito em Objects e selecione Create Object
- Nomeie-o como
obj_wall - Defina o sprite como
spr_wall - Marque a caixa de seleção "Solid"
- Nenhum evento necessário

Os destinos marcam onde as caixas devem ser colocadas.
- Crie um novo objeto nomeado
obj_target - Defina o sprite como
spr_target - Nenhum evento necessário - é apenas um marcador
- Deixe "Solid" desmarcado (jogador e caixas podem estar em cima dele)

A caixa é empurrada pelo jogador e muda de aparência quando está em um destino.
- Crie um novo objeto nomeado
obj_crate - Defina o sprite como
spr_crate - Marque a caixa de seleção "Solid"
Evento: Step
- Add Event → Step → Step
- Add Action: Control → If Collision
- X Offset:
0 - Y Offset:
0 - Against:
obj_target
- X Offset:
- Add Action: Instance → Set Sprite
- Sprite:
spr_crate_ok
- Sprite:
- Add Action: Control → Else
- Add Action: Instance → Set Sprite
- Sprite:
spr_crate
- Sprite:
Isso faz a caixa ficar verde quando está em um local de destino —
If Collision com ambos os deslocamentos em 0 verifica se a
posição atual da caixa se sobrepõe a um obj_target.

O jogador se move exatamente uma célula da grade por vez e empurra as caixas em que esbarra.
- Crie um novo objeto nomeado
obj_player - Defina o sprite como
spr_player
Adicione um evento Key Press por direção, cada um com uma ação Move → Move Grid:
| Evento | Ação Move Grid |
|---|---|
| Key Press → Right Arrow | Direction: right, Grid Size: 32
|
| Key Press → Left Arrow | Direction: left, Grid Size: 32
|
| Key Press → Up Arrow | Direction: up, Grid Size: 32
|
| Key Press → Down Arrow | Direction: down, Grid Size: 32
|
Move Grid move a instância exatamente uma célula da grade e já
detecta colisões por conta própria — não moverá o jogador para dentro
de um obj_wall sólido, então não é necessária uma verificação de
parede adicional aqui.
Evento: Collision with obj_wall
- Add Event → Collision →
obj_wall - Add Action: Move → Stop Movement
Evento: Collision with obj_crate
- Add Event → Collision →
obj_crate - Add Action: Control → If Can Push
- Direction:
facing - Object Type:
obj_crate - Then Action:
push_and_move
- Direction:
If Can Push verifica se o espaço atrás da caixa (na direção em que o jogador está se movendo) está livre e, se estiver, empurra a caixa uma célula e move o jogador para o lugar dela, tudo em uma única ação. Se o espaço atrás da caixa estiver bloqueado por uma parede ou outra caixa, nada se move.

Precisamos de um controlador invisível que observe se cada caixa está em um destino.
- Crie um novo objeto nomeado
obj_game_controller - Nenhum sprite necessário
Evento: Create — define a contagem de destinos uma única vez,
usando Control → Execute Code (a ação Execute Code deste
projeto executa Python real, não GameMaker Language — self é a
instância atual, game é o executor do jogo):
# Conta quantos destinos existem na sala
self.total_targets = sum(
1 for inst in game.current_room.instances
if inst.object_name == 'obj_target'
)Evento: Step — verifica a cada quadro se todas as caixas estão em um destino:
# Conta as caixas que atualmente se sobrepõem a um destino
crates_on_targets = sum(
1 for inst in game.current_room.instances
if inst.object_name == 'obj_crate'
and game.check_collision_at_position(inst, inst.x, inst.y, 'obj_target')
)
if self.total_targets > 0 and crates_on_targets >= self.total_targets:
self.restart_room_flag = Trueself.restart_room_flag = True é a forma como um bloco Execute Code
bruto aciona o mesmo reinício de sala que a ação Restart Room
realiza — o loop principal verifica isso a cada quadro. Adicione uma
ação Show Message (de Output, mensagem Level Complete!)
logo após o bloco Execute Code se quiser mostrar um popup antes do
reinício.
Evento: Draw
- Add Event → Draw
- Add Action: Draw → Draw Text
- Text:
Sokoban - Push all crates to targets! - X:
10 - Y:
10
- Text:

- Clique com o botão direito em Rooms e selecione Create Room
- Nomeie-a como
room_level1 - Defina o tamanho da sala como um múltiplo de 32 (por ex., 640x480)
- Ative "Snap to Grid" e defina a grade como 32x32
Construa seu nível seguindo estas diretrizes:
- Cerque o nível com paredes - Crie uma borda
- Adicione paredes internas - Crie a estrutura do puzzle
- Coloque destinos - Onde as caixas precisam ir
- Coloque caixas - Mesmo número que destinos!
- Coloque o jogador - Posição inicial
- Coloque o game controller - Em qualquer lugar (é invisível)
W W W W W W W W W W
W . . . . . . . . W
W . P . . . C . . W
W . . W W . . . . W
W . . W T . . C . W
W . . . . . W W . W
W . T . . . . . . W
W . . . . . . . . W
W W W W W W W W W W
W = Parede
P = Jogador
C = Caixa
T = Destino
. = Chão vazio
Importante: Sempre tenha o mesmo número de caixas e destinos!

- Clique em Run ou pressione F5 para testar
- Use as setas para se mover
- Empurre as caixas para os destinos X vermelhos
- Quando todas as caixas estiverem nos destinos, você vence!
No evento Create de obj_game_controller, adicione Control →
Set Variable (Variable: global.moves, Value: 0, Scope: global).
Em cada um dos quatro eventos Key Press de obj_player, adicione uma
segunda ação logo após Move Grid: Control → Set Variable
(Variable: global.moves, Value: 1, Scope: global, Relative
marcado) — isso soma 1 ao contador a cada pressionamento de tecla,
independentemente de o movimento ter sido realmente bloqueado por uma
parede.
No evento Draw de obj_game_controller, adicione Draw →
Draw Variable (Variable: global.moves, X: 10, Y: 30).
Armazene posições anteriores e permita pressionar Z para desfazer o último movimento.
Crie mais salas (room_level2, room_level3, etc.) e use a ação
Next Room (categoria Room) em vez de Restart Room no bloco
Execute Code de verificação de vitória (self.next_room_flag = True
em vez de self.restart_room_flag = True) ao completar um nível.
Adicione sons para:
- Jogador se movendo
- Empurrando uma caixa
- Caixa caindo em um destino
- Nível completo
| Problema | Solução |
|---|---|
| Jogador se move através de paredes | Verifique se obj_wall tem "Solid" marcado |
| Caixa não muda de cor | Verifique se a ação If Collision do evento Step aponta para obj_target
|
| Pode empurrar caixa através de parede | Verifique a detecção de colisão antes de mover a caixa |
| Mensagem de vitória aparece imediatamente | Certifique-se de que os destinos foram colocados separadamente das caixas |
| Jogador se move vários quadrados | Use o evento Keyboard Press, não o evento Keyboard |
Parabéns! Você criou um jogo de puzzle Sokoban completo! Você aprendeu:
- Movimento baseado em grade - Movimento em passos fixos de 32 pixels
- Mecânica de empurrar - Detectar e mover objetos que o jogador empurra
- Lógica de colisão complexa - Verificar múltiplas condições antes de permitir movimento
- Mudanças de estado - Mudar sprite baseado na posição do objeto
- Condições de vitória - Verificar quando todos os objetivos são completados
- Design de nível - Criar layouts de puzzle solucionáveis
A diversão real do Sokoban é projetar puzzles. Tente criar níveis que:
- Comecem fáceis e fiquem progressivamente mais difíceis
- Exijam planejamento antecipado
- Tenham apenas uma solução
- Usem espaço mínimo eficientemente
Lembre-se: um bom puzzle Sokoban deve ser desafiador mas justo!
- Tutoriais - Mais tutoriais de jogos
- Intermediate Preset - Visão geral do preset necessário para este tutorial
- Tutorial: Pong - Criar um jogo para dois jogadores
- Tutorial: Breakout - Criar um jogo de quebrador de tijolos
- Referência de Eventos - Documentação completa de eventos