Adding a Winning Zone
Add a Winning Zone to the Level
By adding a new emoji to our level, we can add something new. Let's add a winning zone with a 🏁 emoji.
First we'll add a new variant to the Tile
enum: Flag
:
#![allow(unused)] fn main() { pub enum Tile { // ... Flag, } }
Then parse it in our LevelLoader
:
#![allow(unused)] fn main() { extern crate bevy; use bevy::{asset::{io::Reader, AssetLoader, AsyncReadExt, LoadContext}, prelude::*}; #[derive(Asset, TypePath)] struct Level {pub tiles: Vec<Vec<Tile>>} enum LevelLoaderError {UnknownTile(char)} enum Tile {Flag} struct LevelLoader; trait ShortLoader { type Error; type Asset; async fn load() -> Result<Self::Asset, Self::Error>; } impl ShortLoader for LevelLoader { type Error = LevelLoaderError; type Asset = Level; async fn load(/* ... */) -> Result<Self::Asset, Self::Error> { let buf = String::new(); let mut tiles = vec![]; let mut line = vec![]; // ... for char in buf.chars() { match char { // ... '🏁' => line.push(Tile::Flag), char => Err(LevelLoaderError::UnknownTile(char))?, } } Ok(Level { tiles }) } } }
Displaying the Zone
We'll use a new spritesheet, spritesheet_items.png
, to have items to display.
First we'll add new fields to the GameAssets
resource to hold the new handles:
#![allow(unused)] fn main() { extern crate bevy; use bevy::prelude::*; #[derive(Resource)] struct GameAssets { // ... items_image: Handle<Image>, items_layout: Handle<TextureAtlasLayout>, } }
Then load the new spritesheet during the splash screen:
#![allow(unused)] fn main() { extern crate bevy; use bevy::prelude::*; let commands: Commands = unimplemented!(); let texture_atlas_layouts: Assets<TextureAtlasLayout> = unimplemented!(); let asset_server: AssetServer = unimplemented!(); #[derive(Resource)] struct GameAssets { items_image: Handle<Image>, items_layout: Handle<TextureAtlasLayout>, } commands.insert_resource(GameAssets { // ... items_image: asset_server.load("spritesheet_items.png"), items_layout: texture_atlas_layouts.add(TextureAtlasLayout::from_grid( UVec2::new(128, 128), 6, 4, None, None, )), }); }
And finally we'll display the flag in display_tile
:
#![allow(unused)] fn main() { extern crate bevy; use bevy::prelude::*; struct GameAssets { items_image: Handle<Image>, items_layout: Handle<TextureAtlasLayout>, } #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, States, Default)] enum GameState { #[default] Game } enum Tile { Flag } #[derive(Component)] struct Flag; fn display_tile(/* ... */) { let assets: GameAssets = unimplemented!(); let commands: Commands = unimplemented!(); let (x, y) = (0.0, 0.0); let tile = Tile::Flag; match tile { // ... Tile::Flag => { commands.spawn(( Sprite::from_atlas_image( assets.items_image.clone(), TextureAtlas { layout: assets.items_layout.clone(), index: 6, }, ), Transform::from_xyz(x, y, 0.0).with_scale(Vec3::splat(0.5)), StateScoped(GameState::Game), Flag, )); } } } }
Z-Index
If you play a few times, you may notice that the order of sprites varies: sometimes the alien is in front of the flag, sometimes behind. This can be controlled with the Z
index.
Everything we've displayed up till now, we've used O.O
for the z
value when calling Transform::from_xyz
. By using the same value for every sprite, we're not telling the engine the order they should be displayed. In Bevy, higher values are displayed in front.