maciekglowka / hike_deck

Bevy Engine rougelike with a tutorial
MIT License
39 stars 1 forks source link

add_system deprecations and OnUpdate has been removed in Bevy 0.11 #5

Open D0ubleD0uble opened 11 months ago

D0ubleD0uble commented 11 months ago

I am attempting to follow along on the tutorial using bevy 0.11 and in part 1 of the series we are utilizing add_system which has been deprecated and specifically in assets.rs we call .add_system(check_asset_loading.in_set(OnUpdate(MainState::LoadAssets))); - which comes up with an error because OnUpdate has been removed. (see https://github.com/bevyengine/bevy/issues/8239).

I'm afraid I'm still trying to figure out the intended alternative but I'm following along as someone new to bevy. Of course I can downgrade my bevy version but I imagine you will want to fix this at some point to take advantage of newer bevy features and to keep the tutorial relevant.

maciekglowka commented 11 months ago

Hi, yeah the API changed a bit again. I think it should be now smth like that:

.add_systems(
       Update,
       check_asset_loading
       .run_if(in_state(MainState::LoadAssets))
)

Unfortunately #1: because the tutorial is already quite lengthy I might not be able to update it :/ Unfortunately #2: I was playing a bit with Bevy 0.11 recently (trying to update an older game) and I am not sure if the scheduling behaviour is exactly the same in this version. But probably it won't make a difference for the tutorial.

I might do in the future some shorter turn-based approach blog post or tutorial for the recent Bevy version, but I'll probably wait a bit till those issues stabilize.

Good thing is that Bevy typically has well done migrations guides: https://bevyengine.org/learn/migration-guides/0.10-0.11/

If you have any further questions (or the above won't work) do not hesitate to keep asking :) (I am also on Mastodon and Twitter: https://maciejglowka.com/contact/)

NFodrea commented 5 months ago

@D0ubleD0uble I know I'm pretty delayed on a reply here, but I've just started this tutorial as well. If you are still interested I got part 1 working with Bevy 0.13 using bevy asset loader and a texture atlas. I switched a couple small things around in thee project:

@maciekglowka Thank you for this tutorial its been really helpful.

If a repo would be easier let me know and I will make one. Here are the relevant file changes

Asset loader

// asset_loader.rs
use bevy::prelude::*;
use bevy_asset_loader::asset_collection::AssetCollection;

#[derive(AssetCollection, Resource)]
pub struct ImageAssets {
    #[asset(key = "sprites.layout")]
    pub layout: Handle<TextureAtlasLayout>,
    #[asset(key = "sprites.image")]
    pub sprites: Handle<Image>,
}

.ron file

// assets/sprites.assets.ron
({
    "sprites.image": File (
        path: "sprites.png",
    ),
    "sprites.layout": TextureAtlasLayout (
        tile_size_x: 16.,
        tile_size_y: 16.,
        columns: 10,
        rows: 40,
    ),
})

Main

use asset_loader::ImageAssets;
use bevy::{input::common_conditions::input_toggle_active, prelude::*};
use bevy_asset_loader::prelude::*;
use bevy_inspector_egui::quick::WorldInspectorPlugin;
use globals::{ASSET_SCALE, TILE_SIZE, WINDOW_HEIGHT, WINDOW_WIDTH};
mod asset_loader;
mod globals;
mod graphics;
mod map;
mod player;
mod shared;
mod states;
mod utils;

fn main() {
    App::new()
        .init_state::<MainState>()
        .add_plugins(
            DefaultPlugins
                .set(WindowPlugin {
                    primary_window: Some(Window {
                        title: "Bevy Rogue".into(),
                        resolution: (WINDOW_WIDTH, WINDOW_HEIGHT).into(),
                        resizable: false,
                        focused: true,
                        ..default()
                    }),
                    ..default()
                })
                .set(ImagePlugin::default_nearest())
                .build(),
        )
        .add_plugins(WorldInspectorPlugin::default().run_if(input_toggle_active(true, KeyCode::F1)))
        .add_loading_state(
            LoadingState::new(MainState::LoadAssets)
                .continue_to_state(MainState::LoadMap)
                .with_dynamic_assets_file::<StandardDynamicAssetCollection>("sprites.assets.ron")
                .load_collection::<ImageAssets>(),
        )
        .add_plugins(map::MapPlugin)
        .add_systems(Startup, setup)
        .add_loading_state(
            LoadingState::new(MainState::LoadMap).continue_to_state(MainState::LoadTile),
        )
        .add_systems(OnEnter(MainState::Game), spawn_player)
        .add_loading_state(
            LoadingState::new(MainState::LoadTile).continue_to_state(MainState::Game),
        )
        .add_plugins(graphics::GraphicsPlugin)
        .add_loading_state(
            LoadingState::new(MainState::LoadTile).continue_to_state(MainState::Game),
        )
        .add_systems(OnEnter(MainState::Game), spawn_player)
        .add_systems(Update, bevy::window::close_on_esc)
        .run();
}

fn spawn_player(mut commands: Commands, assets: Res<ImageAssets>) {
    commands
        .spawn(SpriteSheetBundle {
            texture: assets.sprites.clone(),
            atlas: TextureAtlas {
                layout: assets.layout.clone(),
                index: 297,
            },
            transform: Transform {
                translation: { Vec3::new(0., 0., 1.) },
                scale: Vec3::splat(ASSET_SCALE),
                ..Default::default()
            },
            ..Default::default()
        })
        .insert(Name::new("Player"));
}

fn setup(mut commands: Commands) {
    // commands.spawn(Camera2dBundle::default());
    let mut camera = Camera2dBundle::default();
    camera.transform.translation = Vec3::new(
        4. * TILE_SIZE * ASSET_SCALE,
        4. * TILE_SIZE * ASSET_SCALE,
        camera.transform.translation.z,
    );
    commands.spawn(camera);
}

Map

//map.mod.rs
use bevy::prelude::*;
use std::collections::HashMap;

use crate::states::MainState;
use crate::utils::Vector2Int;

pub mod systems;

pub struct MapPlugin;

impl Plugin for MapPlugin {
    fn build(&self, app: &mut App) {
        // making a plugin to init the map resource
        app.init_resource::<CurrentMap>()
            .add_systems(OnEnter(MainState::LoadMap), systems::spawn_map);
    }
}

#[derive(Default, Resource)]
pub struct CurrentMap {
    pub tiles: HashMap<Vector2Int, Entity>,
}
// map/systems.rs
use bevy::prelude::*;
use std::collections::HashMap;

use crate::{
    shared::shared_components::{Position, Tile},
    utils::Vector2Int,
};

use super::CurrentMap;

pub fn spawn_map(mut commands: Commands, mut current: ResMut<CurrentMap>) {
    current.tiles = HashMap::new();
    // hard coded size for now for testing
    for x in 0..8 {
        for y in 0..8 {
            let v = Vector2Int::new(x, y);
            let tile = commands.spawn((Position { v }, Tile)).id();
            current.tiles.insert(v, tile);
            // println!("v: {:?}, tile: {:?}", v, tile);
        }
    }
}

Graphics

// graphics/mod.rs
use bevy::prelude::*;

use crate::states::MainState;
pub mod tiles;

pub struct GraphicsPlugin;

impl Plugin for GraphicsPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(OnEnter(MainState::LoadTile), tiles::spawn_tile_renderer);
    }
}
// tiles.rs
use bevy::prelude::*;

use crate::asset_loader::ImageAssets;
use crate::globals::{ASSET_SCALE, TILE_SIZE};
use crate::shared::shared_components::{Position, Tile};

pub fn spawn_tile_renderer(
    mut commands: Commands,
    query: Query<(Entity, &Position), Added<Tile>>,
    assets: Res<ImageAssets>,
) {
    for (entity, position) in query.iter() {
        // print!("entity: {:?}, position: {:?}\n", entity, position);
        let v = Vec3::new(
            (TILE_SIZE * ASSET_SCALE) * position.v.x as f32,
            (TILE_SIZE * ASSET_SCALE) * position.v.y as f32,
            0.,
        );
        commands.entity(entity).insert(SpriteSheetBundle {
            texture: assets.sprites.clone(),
            atlas: TextureAtlas {
                layout: assets.layout.clone(),
                index: 60,
            },
            transform: Transform {
                translation: { v },
                scale: Vec3::splat(ASSET_SCALE),
                ..Default::default()
            },
            ..Default::default()
        });
    }
}

on to part 2 😄

maciekglowka commented 5 months ago

@NFodrea wow, thanks for such a detailed code update ! It surely will be helpful for future releases. Glad that the tutorial is still helpful despite being outdated and not exactly finished :D

I am thinking now though if it wouldn't be easier to start the tutorial from scratch with the latest Bevy version - instead of updating the existing parts. It could be more minimalist and easier to handle. I think I've made a typical too-large-scope mistake (like card mechanics, complex dungeon generation) - that is not needed for the learning process so much.

Perhaps it'd be more beneficial to keep a shorted bare-bones tutorial with only basic mechanic - esp. how to deal with turns in Bevy. And than if resources permit add more stuff on top :) I will see how it goes.

NFodrea commented 5 months ago

A new tutorial would be awesome! I sent you an invite to a repo with everything through part 5 of the old tutorial finished. Since I'm not 100% sure on the license for the assets I'm using and if it allows public redistribution I have the repo set to private for now. If other people end up wanting it I'm more than happy to create a public version with dummy assets

maciekglowka commented 5 months ago

@NFodrea thanks! I have joined it, will take a look. If you are not sure about those specific assets I am pretty confident that you could use ones from Kenney (kenney.nl). He has rather awesome roguelike packs as well. I hope time permits to attempt a simple tutorial again. I'd really like to do it with the new Bevy functionalities.