📋 O Que Você Vai Construir
Neste tutorial, você criará um jogo de empilhamento de torre onde os jogadores devem cronometrar seus cliques para empilhar blocos precisamente um em cima do outro. Os blocos se movem horizontalmente, e os jogadores devem pará-los no momento exato para criar a torre mais alta possível!
🚀 Começando
1Instalar Ruby2D
Primeiro, você precisa instalar a gem Ruby2D:
gem install ruby2d
2Criar Seu Arquivo de Jogo
Crie um novo arquivo chamado tower_stack.rb ou baixe aqui:tower_stack.rb e adicione a configuração básica:
require 'ruby2d'
set title: "Tower Stacking Game"
set width: 400
set height: 600
set background: '#1a1a2e'
show
Isso cria uma janela com um fundo azul escuro.
🎯 Conceitos Principais
Variáveis de Estado do Jogo
Precisamos rastrear várias informações ao longo do jogo:
@blocks = [] # Array para armazenar todos os blocos empilhados
@current_block = nil # O bloco atualmente em movimento
@direction = 1 # Direção do movimento (1 = direita, -1 = esquerda)
@speed = 2 # Quão rápido os blocos se movem
@score = 0 # Pontuação do jogador
@game_over = false # Flag de estado do jogo
@base_width = 100 # Largura do bloco inicial
@block_height = 30 # Altura de cada bloco
Criando Elementos de Interface
Adicione elementos de texto para exibir informações do jogo:
@score_text = Text.new(
'Score: 0',
x: 10, y: 10,
size: 20,
color: 'white'
)
@instruction_text = Text.new(
'Press SPACE to stack',
x: 10, y: 40,
size: 16,
color: 'gray'
)
@game_over_text = Text.new(
'GAME OVER! Press R to restart',
x: 50, y: 250,
size: 16,
color: 'red',
opacity: 0 # Inicialmente oculto
)
🏗️ Construindo a Lógica do Jogo
3Criar o Bloco Base
Toda torre precisa de uma fundação. Este método cria o primeiro bloco na parte inferior:
def create_base
base = Rectangle.new(
x: (Window.width - @base_width) / 2, # Centralizar horizontalmente
y: Window.height - @block_height - 10, # Perto da parte inferior
width: @base_width,
height: @block_height,
color: '#16a085'
)
@blocks << {
rect: base,
x: base.x,
width: @base_width
}
end
Armazenamos tanto o objeto Rectangle quanto suas propriedades para cálculos posteriores.
4Criar Blocos em Movimento
Este método cria um novo bloco que se move horizontalmente:
def create_block
return if @game_over
last_block = @blocks.last
y_pos = last_block[:rect].y - @block_height # Empilhar em cima
@current_block = {
rect: Rectangle.new(
x: 0,
y: y_pos,
width: last_block[:width], # Mesma largura do anterior
height: @block_height,
color: ['#e74c3c', '#3498db', '#f39c12',
'#9b59b6', '#e67e22'].sample # Cor aleatória
),
width: last_block[:width],
moving: true
}
end
Cada novo bloco começa com a mesma largura do anterior e recebe uma cor aleatória!
5O Mecanismo de Empilhamento
Este é o coração do jogo - calcular a sobreposição e aparar os blocos:
def stack_block
return if !@current_block || @game_over
last_block = @blocks.last
current_x = @current_block[:rect].x
last_x = last_block[:x]
# Calcular região de sobreposição
overlap_start = [current_x, last_x].max
overlap_end = [current_x + @current_block[:width],
last_x + last_block[:width]].min
overlap = overlap_end - overlap_start
if overlap <= 0
# Sem sobreposição - fim de jogo!
@game_over = true
@game_over_text.opacity = 1
@current_block[:rect].color = '#c0392b'
return
end
# Aparar bloco para área de sobreposição
@current_block[:rect].x = overlap_start
@current_block[:rect].width = overlap
@current_block[:width] = overlap
@current_block[:x] = overlap_start
@current_block[:moving] = false
@blocks << @current_block
@current_block = nil
@score += 1
@score_text.text = "Score: #{@score}"
@speed += 0.1 # Aumentar dificuldade
create_block
end
🎮 Loop de Jogo e Controles
Lógica de Movimento
O bloco update é executado a cada frame e gerencia o movimento do bloco:
update do
if @current_block && @current_block[:moving] && !@game_over
# Mover bloco horizontalmente
@current_block[:rect].x += @speed * @direction
# Rebater nas paredes
if @current_block[:rect].x <= 0
@direction = 1 # Mover para direita
elsif @current_block[:rect].x + @current_block[:width] >= Window.width
@direction = -1 # Mover para esquerda
end
end
end
Manipulação de Entrada
Responder à entrada do teclado do jogador:
on :key_down do |event|
if event.key == 'space'
stack_block unless @game_over
elsif event.key == 'r'
reset_game if @game_over
end
end
6Função de Reinicialização
Permitir que os jogadores reiniciem após o fim do jogo:
def reset_game
@blocks.each { |b| b[:rect].remove } # Remover todos os blocos
@blocks.clear
@current_block[:rect].remove if @current_block
@current_block = nil
@score = 0
@speed = 2
@game_over = false
@score_text.text = "Score: 0"
@game_over_text.opacity = 0
create_base
create_block
end
