Introdução
O desenvolvimento de jogos com Rust é uma das áreas mais empolgantes e de mais rápido crescimento no ecossistema da linguagem. Embora a indústria de jogos tenha sido historicamente dominada por C++ (com Unreal Engine) e C# (com Unity), Rust está emergindo como uma alternativa poderosa, especialmente com a ascensão do Bevy Engine e o crescente interesse de estúdios por ferramentas de desenvolvimento mais seguras e performáticas.
A combinação de performance de nível C++, segurança de memória, concorrência sem data races e um ecossistema moderno de ferramentas torna Rust particularmente atrativo para desenvolvimento de game engines, ferramentas de pipeline de arte, servidores de jogos multiplayer e sistemas de física/simulação.
Para desenvolvedores brasileiros, o mercado de gamedev com Rust é ainda jovem mas com enorme potencial. O Brasil possui uma comunidade de desenvolvedores de jogos vibrante e crescente, e ser um especialista em Rust gamedev posiciona você de forma única tanto no mercado nacional quanto internacional.
Por Que Rust Para Game Development?
Performance Comparável a C++
Jogos exigem cada frame renderizado em milissegundos. Rust oferece:
- Zero overhead abstractions: Traits e generics são resolvidos em compilação
- Sem garbage collector: Controle preciso de alocação de memória
- Otimização LLVM: Mesmo backend de otimização do Clang/C++
- SIMD: Suporte a instruções SIMD para cálculos vetoriais
Segurança de Memória
Bugs de memória são uma das principais causas de crashes em jogos:
- Sem segfaults: O compilador previne acessos inválidos de memória
- Thread safety: Paralelismo seguro para sistemas ECS
- Sem leaks: Recursos são liberados deterministicamente via Drop trait
Entity Component System (ECS) Nativo
O padrão ECS, que revolucionou o gamedev moderno, é naturalmente expressivo em Rust graças a traits e generics:
// O padrão ECS é idiomático em Rust
// Componentes são structs simples
struct Posicao { x: f32, y: f32 }
struct Velocidade { dx: f32, dy: f32 }
struct Vida { atual: i32, maxima: i32 }
// Sistemas são funções que operam sobre conjuntos de componentes
// O type system garante acesso seguro a dados entre sistemas paralelos
Bevy Engine: O Framework Líder
Bevy é o game engine/framework mais popular do ecossistema Rust, com uma comunidade enorme e ativa:
Exemplo: Jogo Simples com Bevy
use bevy::prelude::*;
// === Componentes ===
#[derive(Component)]
struct Jogador {
velocidade: f32,
vida: i32,
}
#[derive(Component)]
struct Inimigo {
velocidade: f32,
direcao: Vec2,
}
#[derive(Component)]
struct Projetil {
velocidade: f32,
direcao: Vec2,
dano: i32,
}
#[derive(Component)]
struct Pontuacao(u32);
// === Recursos ===
#[derive(Resource)]
struct ConfigJogo {
velocidade_jogador: f32,
velocidade_projetil: f32,
intervalo_spawn: f32,
}
impl Default for ConfigJogo {
fn default() -> Self {
ConfigJogo {
velocidade_jogador: 300.0,
velocidade_projetil: 500.0,
intervalo_spawn: 2.0,
}
}
}
#[derive(Resource)]
struct TimerSpawn(Timer);
// === Sistemas ===
/// Sistema de setup: cria entidades iniciais
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
) {
// Câmera
commands.spawn(Camera2d::default());
// Jogador
commands.spawn((
Sprite {
color: Color::srgb(0.2, 0.6, 1.0),
custom_size: Some(Vec2::new(40.0, 40.0)),
..default()
},
Transform::from_xyz(0.0, -200.0, 0.0),
Jogador {
velocidade: 300.0,
vida: 100,
},
));
// Recurso de pontuação
commands.insert_resource(ConfigJogo::default());
commands.insert_resource(TimerSpawn(Timer::from_seconds(
2.0,
TimerMode::Repeating,
)));
println!("Jogo inicializado!");
}
/// Sistema de movimento do jogador
fn mover_jogador(
keyboard: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
mut query: Query<(&Jogador, &mut Transform)>,
) {
for (jogador, mut transform) in query.iter_mut() {
let mut direcao = Vec3::ZERO;
if keyboard.pressed(KeyCode::ArrowLeft) || keyboard.pressed(KeyCode::KeyA) {
direcao.x -= 1.0;
}
if keyboard.pressed(KeyCode::ArrowRight) || keyboard.pressed(KeyCode::KeyD) {
direcao.x += 1.0;
}
if keyboard.pressed(KeyCode::ArrowUp) || keyboard.pressed(KeyCode::KeyW) {
direcao.y += 1.0;
}
if keyboard.pressed(KeyCode::ArrowDown) || keyboard.pressed(KeyCode::KeyS) {
direcao.y -= 1.0;
}
if direcao.length() > 0.0 {
direcao = direcao.normalize();
}
transform.translation +=
direcao * jogador.velocidade * time.delta_secs();
// Limitar posição à tela
transform.translation.x = transform.translation.x.clamp(-400.0, 400.0);
transform.translation.y = transform.translation.y.clamp(-300.0, 300.0);
}
}
/// Sistema de disparo de projéteis
fn disparar_projetil(
mut commands: Commands,
keyboard: Res<ButtonInput<KeyCode>>,
config: Res<ConfigJogo>,
query: Query<&Transform, With<Jogador>>,
) {
if keyboard.just_pressed(KeyCode::Space) {
for transform in query.iter() {
commands.spawn((
Sprite {
color: Color::srgb(1.0, 1.0, 0.0),
custom_size: Some(Vec2::new(8.0, 16.0)),
..default()
},
Transform::from_translation(transform.translation),
Projetil {
velocidade: config.velocidade_projetil,
direcao: Vec2::new(0.0, 1.0),
dano: 25,
},
));
}
}
}
/// Sistema de movimento dos projéteis
fn mover_projeteis(
mut commands: Commands,
time: Res<Time>,
mut query: Query<(Entity, &Projetil, &mut Transform)>,
) {
for (entity, projetil, mut transform) in query.iter_mut() {
transform.translation.x +=
projetil.direcao.x * projetil.velocidade * time.delta_secs();
transform.translation.y +=
projetil.direcao.y * projetil.velocidade * time.delta_secs();
// Remover projéteis fora da tela
if transform.translation.y > 400.0
|| transform.translation.y < -400.0
|| transform.translation.x > 500.0
|| transform.translation.x < -500.0
{
commands.entity(entity).despawn();
}
}
}
/// Sistema de spawn de inimigos
fn spawn_inimigos(
mut commands: Commands,
time: Res<Time>,
mut timer: ResMut<TimerSpawn>,
) {
timer.0.tick(time.delta());
if timer.0.just_finished() {
let x = (rand::random::<f32>() - 0.5) * 700.0;
commands.spawn((
Sprite {
color: Color::srgb(1.0, 0.2, 0.2),
custom_size: Some(Vec2::new(35.0, 35.0)),
..default()
},
Transform::from_xyz(x, 350.0, 0.0),
Inimigo {
velocidade: 100.0 + rand::random::<f32>() * 100.0,
direcao: Vec2::new(0.0, -1.0),
},
));
}
}
/// Sistema de movimento dos inimigos
fn mover_inimigos(
mut commands: Commands,
time: Res<Time>,
mut query: Query<(Entity, &Inimigo, &mut Transform)>,
) {
for (entity, inimigo, mut transform) in query.iter_mut() {
transform.translation.y +=
inimigo.direcao.y * inimigo.velocidade * time.delta_secs();
// Remover inimigos que saíram da tela
if transform.translation.y < -400.0 {
commands.entity(entity).despawn();
}
}
}
/// Sistema de colisão simples
fn detectar_colisoes(
mut commands: Commands,
projeteis: Query<(Entity, &Transform, &Projetil)>,
inimigos: Query<(Entity, &Transform), With<Inimigo>>,
) {
for (proj_entity, proj_transform, _projetil) in projeteis.iter() {
for (inimigo_entity, inimigo_transform) in inimigos.iter() {
let distancia = proj_transform
.translation
.distance(inimigo_transform.translation);
if distancia < 30.0 {
commands.entity(proj_entity).despawn();
commands.entity(inimigo_entity).despawn();
}
}
}
}
/// Ponto de entrada do jogo
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Meu Jogo Rust - Bevy".to_string(),
resolution: (800.0, 600.0).into(),
..default()
}),
..default()
}))
.add_systems(Startup, setup)
.add_systems(
Update,
(
mover_jogador,
disparar_projetil,
mover_projeteis,
spawn_inimigos,
mover_inimigos,
detectar_colisoes,
),
)
.run();
}
Outros Frameworks e Engines
macroquad
Framework simples e minimalista, ideal para game jams e protótipos:
use macroquad::prelude::*;
#[macroquad::main("Pong Simples")]
async fn main() {
let mut jogador_y: f32 = 300.0;
let mut bola_x: f32 = 400.0;
let mut bola_y: f32 = 300.0;
let mut vel_x: f32 = 200.0;
let mut vel_y: f32 = 150.0;
let mut pontos: u32 = 0;
let velocidade_paddle: f32 = 400.0;
let tamanho_paddle: f32 = 80.0;
let raio_bola: f32 = 8.0;
loop {
let dt = get_frame_time();
// Input do jogador
if is_key_down(KeyCode::Up) {
jogador_y -= velocidade_paddle * dt;
}
if is_key_down(KeyCode::Down) {
jogador_y += velocidade_paddle * dt;
}
jogador_y = jogador_y.clamp(0.0, 600.0 - tamanho_paddle);
// Mover bola
bola_x += vel_x * dt;
bola_y += vel_y * dt;
// Colisão com paredes
if bola_y <= 0.0 || bola_y >= 600.0 {
vel_y = -vel_y;
}
if bola_x >= 800.0 {
vel_x = -vel_x;
}
// Colisão com paddle do jogador
if bola_x <= 30.0
&& bola_y >= jogador_y
&& bola_y <= jogador_y + tamanho_paddle
{
vel_x = vel_x.abs();
pontos += 1;
}
// Reset se a bola sair pela esquerda
if bola_x < 0.0 {
bola_x = 400.0;
bola_y = 300.0;
pontos = 0;
}
// Renderização
clear_background(BLACK);
// Paddle do jogador
draw_rectangle(10.0, jogador_y, 15.0, tamanho_paddle, WHITE);
// Bola
draw_circle(bola_x, bola_y, raio_bola, YELLOW);
// Linha central
for i in 0..30 {
draw_rectangle(
398.0,
i as f32 * 20.0,
4.0,
10.0,
GRAY,
);
}
// Pontuação
draw_text(
&format!("Pontos: {}", pontos),
350.0,
30.0,
30.0,
WHITE,
);
// FPS
draw_text(
&format!("FPS: {}", get_fps()),
10.0,
590.0,
20.0,
GREEN,
);
next_frame().await;
}
}
wgpu: Gráficos de Baixo Nível
Para quem quer trabalhar diretamente com a GPU:
use wgpu;
/// Inicialização básica de um contexto wgpu
async fn inicializar_gpu() -> (wgpu::Device, wgpu::Queue) {
// Criar instância wgpu
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..Default::default()
});
// Solicitar adaptador (GPU)
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: None,
force_fallback_adapter: false,
})
.await
.expect("Falha ao encontrar GPU compatível");
println!("GPU encontrada: {}", adapter.get_info().name);
println!("Backend: {:?}", adapter.get_info().backend);
// Criar device e queue
let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: Some("Meu Device"),
required_features: wgpu::Features::empty(),
required_limits: wgpu::Limits::default(),
memory_hints: wgpu::MemoryHints::default(),
},
None,
)
.await
.expect("Falha ao criar device GPU");
(device, queue)
}
Áreas de Atuação no Gamedev
Desenvolvimento de Game Engines
Criar ou contribuir para game engines é uma das áreas mais valorizadas:
- Rendering engines: Pipelines de renderização 2D/3D
- Physics engines: Simulação de física com Rapier
- Audio engines: Processamento de áudio em tempo real
- Asset pipelines: Carregamento e processamento de assets
- Scripting systems: Integração com linguagens de script
- Networking: Netcode para multiplayer
Ferramentas de Pipeline
Estúdios de jogos precisam de ferramentas de produção:
- Level editors: Editores de níveis e mapas
- Asset converters: Conversão de formatos 3D, texturas, áudio
- Build systems: Automação de builds e packaging
- Profilers: Ferramentas de análise de performance
- Testing frameworks: Testes automatizados para gameplay
Servidores de Jogos
Backend para jogos multiplayer é uma área em alta demanda:
- Game servers: Servidores autoritativos para multiplayer
- Matchmaking: Sistemas de matchmaking e ranking
- Anti-cheat: Detecção de trapaças no lado do servidor
- Analytics: Coleta e processamento de telemetria
Crates Essenciais para Gamedev
Engines e Frameworks
| Crate | Descrição |
|---|---|
bevy | Game engine/framework ECS completo |
macroquad | Framework simples para jogos 2D |
ggez | Framework 2D inspirado no LOVE2D |
fyrox | Game engine 3D com editor visual |
godot-rust | Bindings Rust para Godot Engine |
Gráficos
| Crate | Descrição |
|---|---|
wgpu | API gráfica cross-platform (Vulkan/Metal/DX12) |
winit | Criação de janelas e input |
glam | Biblioteca de matemática para games |
image | Carregamento e manipulação de imagens |
lyon | Tessellation para renderização 2D |
Física e Colisão
| Crate | Descrição |
|---|---|
rapier | Engine de física 2D/3D |
parry | Detecção de colisão |
nalgebra | Álgebra linear |
nphysics | Simulação de física (predecessor do Rapier) |
Áudio
| Crate | Descrição |
|---|---|
rodio | Reprodução de áudio simples |
cpal | Acesso a dispositivos de áudio |
kira | Sistema de áudio para jogos |
oddio | Áudio 3D posicional |
Networking para Games
| Crate | Descrição |
|---|---|
naia | Networking para jogos multiplayer |
matchbox | WebRTC peer-to-peer para jogos |
quinn | Implementação QUIC (UDP confiável) |
laminar | Protocolo de rede para jogos |
Utilidades
| Crate | Descrição |
|---|---|
rand | Geração de números aleatórios |
noise | Geração procedural (Perlin, Simplex) |
serde | Serialização para save games |
specs | ECS alternativo ao Bevy |
hecs | ECS minimalista e rápido |
Empresas que Contratam
Estúdios de Jogos
- Embark Studios: Estúdio sueco usando Rust extensivamente
- Ready At Dawn: Agora parte da Meta, com componentes Rust
- Foresight Mining: Simulação e visualização com Rust
Ferramentas e Engines
- Bevy Foundation: Desenvolvimento do Bevy Engine (grants/sponsorship)
- Dimforge: Criadores do Rapier (engine de física)
- Fyrox: Game engine 3D em Rust
- Ambient: Engine multiplayer em Rust
Servidores e Infraestrutura
- Riot Games: Infraestrutura de servidores
- Epic Games: Componentes de backend
- Unity: Ferramentas internas e otimização
- Roblox: Infraestrutura de plataforma
Empresas de Tecnologia para Games
- Valve: Steam e infraestrutura de distribuição
- Discord: Real-time communication infrastructure
- Activision-Blizzard: Backend e anti-cheat
No Brasil
- Estúdios indie: Crescente comunidade de gamedev brasileiro
- Empresas de gamificação: Aplicações de gamificação empresarial
- Consultorias: Desenvolvimento de jogos por projeto
- Trabalho remoto: Estúdios internacionais contratam remotamente
Roadmap de Habilidades
Nível Júnior (0-12 meses)
- Fundamentos Rust: Ownership, traits, generics, ECS concepts
- Bevy básico: Setup, sprites, input, audio, cenas
- Matemática para games: Vetores, matrizes, trigonometria
- Game design básico: Loops, estados, game feel
- 2D primeiro: Comece com jogos 2D antes de 3D
- Game jams: Participe de jams para praticar
Nível Pleno (1-3 anos)
- Bevy avançado: Plugins, sistemas complexos, networking
- Gráficos: Shaders, rendering pipeline, wgpu
- Física: Rapier, detecção de colisão, raycasting
- Áudio: Sistemas de áudio posicional, mixing
- AI para games: Pathfinding, behavior trees, FSM
- Otimização: Profiling, batching, LOD, culling
Nível Sênior (3+ anos)
- Engine development: Arquitetura de game engines
- Gráficos avançados: PBR, GI, ray tracing
- Networking: Netcode, rollback, prediction
- Ferramentas: Editors, asset pipelines, build systems
- Liderança: Direção técnica, mentoria, arquitetura
- Contribuição core: Bevy, wgpu, ou engine própria
Expectativas Salariais
Brasil (CLT/PJ)
| Nível | Faixa Salarial (R$/mês) | Observações |
|---|---|---|
| Júnior | R$ 4.000 - R$ 8.000 | Gameplay programming |
| Pleno | R$ 8.000 - R$ 16.000 | Engine/systems programming |
| Sênior | R$ 16.000 - R$ 28.000 | Engine architecture, tech lead |
| Lead | R$ 28.000 - R$ 40.000+ | Direção técnica |
Remoto Internacional (USD)
| Nível | Faixa Salarial (USD/ano) | Observações |
|---|---|---|
| Júnior | $50.000 - $80.000 | Estúdios indie |
| Pleno | $80.000 - $130.000 | Estúdios AA/AAA |
| Sênior | $130.000 - $200.000 | Engine development |
| Lead/Principal | $200.000 - $300.000+ | Big studios, tech lead |
Observações
- Salários em gamedev tendem a ser ligeiramente menores que em outras áreas de software, mas a satisfação profissional é frequentemente mais alta
- Especialistas em engine development (gráficos, física, networking) tendem a ter os maiores salários
- O nicho de Rust gamedev ainda é pequeno, o que significa menos vagas mas também menos competição
Projetos Práticos para o Portfólio
Jogos 2D
- Clone de Pong: Introdução a input, física e rendering
- Breakout/Arkanoid: Colisão, power-ups, sistema de pontuação
- Platformer: Gravidade, tiles, animação de sprites
- Tower Defense: AI básica, pathfinding, upgrades
- Roguelike: Geração procedural, inventário, turnos
Jogos 3D
- FPS simples: Câmera 3D, raycasting, inimigos
- Jogo de corrida: Física de veículos, pistas
- Sandbox voxel: Geração de terreno, destruição de blocos
Ferramentas
- Editor de níveis: Interface gráfica para criar mapas
- Particle system: Sistema de partículas configurável
- Shader playground: Ferramenta para testar shaders em tempo real
Recursos de Aprendizado
Livros e Tutoriais
- “Hands-on Rust” (Herbert Wolverson): Gamedev com Rust passo a passo
- “Bevy Cheatbook”: Referência prática para Bevy
- Bevy Examples: Exemplos oficiais do Bevy no GitHub
- “Game Programming Patterns” (Robert Nystrom): Padrões universais de gamedev
Comunidades
- Bevy Discord: Comunidade oficial do Bevy Engine
- r/rust_gamedev: Subreddit de gamedev com Rust
- Rust GameDev Working Group: Grupo de trabalho oficial
- Rust Brasil: Comunidade brasileira
Game Jams
- Ludum Dare: Uma das maiores game jams do mundo
- Global Game Jam: Evento presencial global
- Bevy Jam: Game jam específica para Bevy
- Rust Game Jam: Jam focada em jogos com Rust
- SBGames (Brasil): Simpósio Brasileiro de Jogos
Conclusão
O desenvolvimento de jogos com Rust está em um momento especial: o ecossistema está maduro o suficiente para criar jogos reais, mas jovem o suficiente para que novos participantes possam ter impacto significativo. O Bevy Engine, em particular, é um dos projetos open source mais ativos e bem financiados do ecossistema Rust.
Próximos Passos Concretos
- Instale Bevy: Configure um projeto Bevy e rode os exemplos
- Faça o tutorial oficial: Complete o tutorial de introdução do Bevy
- Clone um jogo clássico: Pong, Snake ou Breakout para aprender os fundamentos
- Estude ECS: Entenda profundamente o padrão Entity Component System
- Participe de game jams: Ludum Dare, Bevy Jam e jams brasileiras
- Aprenda matemática de games: Vetores, matrizes, quaternions, trigonometria
- Explore gráficos: Shaders, wgpu, rendering pipeline
- Construa um jogo completo: Com menu, save/load, sons, polido
- Publique: itch.io, Steam ou web (via WebAssembly)
- Contribua para o Bevy: Issues marcadas como “good first issue”
O gamedev com Rust é uma jornada desafiadora e incrivelmente gratificante. Cada sistema que você implementa, cada bug que você resolve e cada jogo que você publica constrói habilidades transferíveis para qualquer área de programação de sistemas. Comece hoje e faça parte da revolução do gamedev com Rust.