Winning the Game

We'll send an event when the player gets near the flag, then react to it to win the game.

We'll need a system to trigger the event and another to react to it.

Declare an event

First we'll declare an event that we can trigger when the player is near the flag.

#![allow(unused)]
fn main() {
extern crate bevy;
use bevy::prelude::*;
#[derive(Event)]
struct ReachedFlag;
}

Triggers

They can be global with Commands::trigger and App::add_observer, or specific to an entity with EntityCommands::trigger and EntityCommands::observe.

Here is the entity specific version to trigger the event:

#![allow(unused)]
fn main() {
extern crate bevy;
use bevy::prelude::*;
#[derive(Event)]
struct ReachedFlag;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Flag;
fn near_flag(
    mut commands: Commands,
    player_transform: Query<&Transform, With<Player>>,
    flags: Query<(Entity, &Transform), With<Flag>>,
) {
    let player_transform = player_transform.single();
    for (flag, flag_transform) in &flags {
        if player_transform
            .translation
            .distance(flag_transform.translation)
            < 50.0
        {
            commands.entity(flag).trigger(ReachedFlag);
        }
    }
}
}

The near_flag system is added to the player_plugin:

#![allow(unused)]
fn main() {
extern crate bevy;
use bevy::prelude::*;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, States, Default)]
enum GameState { #[default] Game }
fn near_flag(){}
fn player_plugin(app: &mut App) {
    // ...
    app.add_systems(FixedUpdate, near_flag.run_if(in_state(GameState::Game)));
}
}

Observers

To react to the trigger, we use a system that takes a Trigger as a system parameter, plus any other parameter needed.

#![allow(unused)]
fn main() {
extern crate bevy;
use bevy::prelude::*;
#[derive(Event)]
struct ReachedFlag;
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, States, Default)]
enum GameState { #[default] Menu }
fn reached_flag(_trigger: Trigger<ReachedFlag>, mut next: ResMut<NextState<GameState>>) {
    next.set(GameState::Menu);
}
}

And the reached_flag observer is added to the Flag entity:

#![allow(unused)]
fn main() {
extern crate bevy;
use bevy::prelude::*;
enum Tile { Flag }
#[derive(Component)]
struct Flag;
#[derive(Event)]
struct ReachedFlag;
fn reached_flag(_trigger: Trigger<ReachedFlag>) {}
fn display_tile(/* ... */) {
    let commands: Commands = unimplemented!();
    let (x, y) = (0.0, 0.0);
    let tile = Tile::Flag;
    match tile {
        // ...
        Tile::Flag => {
            commands
                .spawn((
                    // ...
                    Flag,
                ))
                .observe(reached_flag);
        }
    }
}
}