Colisões e estado do jogo
Adicione regras e condições de vitória.
Colisões e estado do jogo é uma aula grátis de Learn Rust Coding no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Learn Rust Coding, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Learn Rust Coding inclui 4 aulas no total.
Noções básicas de colisão AABB
O teste de colisão mais simples é a sobreposição de caixas delimitadoras alinhadas aos eixos (AABB). Dois retângulos colidem quando se sobrepõem nos eixos x e y.
Para sprites, isso é rápido e suficiente para muitos jogos 2D antes de recorrer a um mecanismo de física completo.
fn overlaps(a_pos: Vec2, a_size: Vec2, b_pos: Vec2, b_size: Vec2) -> bool {
(a_pos.x - b_pos.x).abs() < (a_size.x + b_size.x) * 0.5
&& (a_pos.y - b_pos.y).abs() < (a_size.y + b_size.y) * 0.5
}Um componente Collider
Anexe um componente Collider que contenha as semidimensões ou o tamanho total de cada entidade. Os sistemas então leem o transform e o collider para testar sobreposições.
Manter o tamanho em seu próprio componente permite que entidades diferentes compartilhem o mesmo sistema de colisão.
#[derive(Component)]
struct Collider {
size: Vec2,
}Detectando colisões em um sistema
Para comparar um jogador com muitos obstáculos, consulte o jogador uma vez e itere pelos obstáculos. Duas consultas separadas evitam pegar os mesmos dados duas vezes.
Quando houver sobreposição, reaja — cause dano, faça ricochetear ou remova a entidade — por meio de Commands ou alterando componentes.
fn detect(
player: Query<(&Transform, &Collider), With<Player>>,
walls: Query<(&Transform, &Collider), With<Wall>>,
) {
let (pt, pc) = player.single().unwrap();
for (wt, wc) in &walls {
if overlaps(pt.translation.truncate(), pc.size, wt.translation.truncate(), wc.size) {
info!("hit a wall");
}
}
}Reagindo com eventos
Em vez de lidar com as consequências diretamente, envie um Event personalizado. Um sistema detecta colisões e emite eventos; outro os lê e aplica os efeitos.
Isso desacopla a detecção da reação e mantém cada sistema pequeno.
#[derive(Event)]
struct CollisionEvent { entity: Entity }
fn emit(mut writer: EventWriter<CollisionEvent>, e: Entity) {
writer.send(CollisionEvent { entity: e });
}Lendo eventos
Um sistema leitor obtém os eventos enfileirados com um EventReader e age sobre cada um. Os eventos permanecem por dois quadros, então qualquer leitor pode vê-los.
Esse fluxo de publicação e assinatura escala bem: muitos produtores e muitos consumidores sem acoplamento rígido.
fn on_hit(mut reader: EventReader<CollisionEvent>, mut commands: Commands) {
for ev in reader.read() {
commands.entity(ev.entity).despawn();
}
}Atualizando a pontuação
Quando o jogador coleta um item, altere o recurso global Score com ResMut.
Como os recursos são únicos, qualquer sistema pode ler ou atualizar a pontuação sem precisar passá-la manualmente.
fn collect(mut score: ResMut<Score>, mut reader: EventReader<PickupEvent>) {
for _ in reader.read() {
score.0 += 10;
}
}Estados: a visão geral
Os jogos alternam entre modos — menu, jogando, pausado e fim de jogo. O Bevy modela esses modos com um enum States registrado por meio de init_state.
Apenas um estado fica ativo por vez, e os sistemas podem ser condicionados para serem executados em estados específicos.
#[derive(States, Default, Debug, Clone, PartialEq, Eq, Hash)]
enum GameState {
#[default]
Menu,
Playing,
GameOver,
}Registrando um estado
Adicione o estado ao aplicativo com init_state. O Bevy passa a acompanhar o valor atual e disponibiliza os recursos State e NextState.
Leia o estado atual com Res<State<GameState>> quando um sistema precisar saber o modo.
App::new()
.add_plugins(DefaultPlugins)
.init_state::<GameState>()
.run();Executando sistemas em um estado
Restrinja os sistemas a um estado com a condição run_if in_state. O movimento e as colisões só são executados enquanto Playing estiver ativo.
É assim que a pausa funciona: interrompa os sistemas de jogabilidade saindo do estado Playing, e eles simplesmente não serão executados.
app.add_systems(
Update,
(drive, detect).run_if(in_state(GameState::Playing)),
);Fazendo transições entre estados
Para alterar o estado, defina NextState em qualquer sistema. O Bevy aplica a transição no próximo limite de quadro.
Use os agendamentos OnEnter e OnExit para criar a interface ao entrar em um estado ou fazer a limpeza ao sair dele.
fn lose(mut next: ResMut<NextState<GameState>>, health: Res<Health>) {
if health.0 == 0 {
next.set(GameState::GameOver);
}
}Limpeza ao sair
Ao sair de Playing, remova as entidades do jogo para que a próxima rodada comece de forma organizada. Marque-as com um marcador e remova tudo que o tiver.
Registre a limpeza em OnExit(GameState::Playing) para que ela seja executada exatamente uma vez por transição.
fn cleanup(mut commands: Commands, q: Query<Entity, With<GameEntity>>) {
for e in &q {
commands.entity(e).despawn();
}
}
// app.add_systems(OnExit(GameState::Playing), cleanup);Verificação rápida
Considere como pausar o jogo de forma adequada.
Recapitulação: colisões e estado do jogo
Os testes de AABB junto com um componente Collider detectam sobreposições; os eventos dissociam a detecção da reação, e um recurso Score acompanha o progresso. O sistema States, com run_if, NextState e OnEnter/OnExit, estrutura os menus, o jogo e o fim de jogo.
Agora o ciclo está completo: criar, controlar, colidir e fazer a transição. Construa um jogo completo no Bevy com essas peças.
Perguntas Frequentes
A aula “Colisões e estado do jogo” é grátis?
Sim — o texto completo de “Colisões e estado do jogo” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Learn Rust Coding, atualize para CoddyKit PRO. O curso de Learn Rust Coding inclui 4 aulas no total.
O que vou aprender em “Colisões e estado do jogo”?
Adicione regras e condições de vitória. Você pratica Learn Rust Coding com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Learn Rust Coding?
Nenhuma experiência prévia é necessária. Learn Rust Coding no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Colisões e estado do jogo”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Learn Rust Coding?
Sim. Cada aula de Learn Rust Coding inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- A mentalidade ECS
- Criando e movendo entidades
- Lidando com entrada e tempo
- Colisões e estado do jogo