Giter VIP home page Giter VIP logo

Comments (13)

zicklag avatar zicklag commented on June 14, 2024 2

This is something I've done a little bit of work with in Bevy.

What kind of format do you think we want to use for prefabs and levels?

I tend to lean away from JSON for anything that we expect humans to write. It's quite annoying to hand-type with the rules such as no-trailing commas, and all of the extra quotes around keys.

RON seems popular in the Rust ecosystem, but I still seem to prefer YAML over RON when humans are typing it because it's easier to type out, more common as far as editor support and general ecosystem is concerned.

The biggest reason I switch to using RON for anything in a given scenario is when I need to store a HashMap that has keys that are non-strings. RON is the only format out of it, YAML, and JSON that supports non-string keys with Serde out-of-the-box.

So I would recommend YAML or RON, but YAML is my slightly preferred option.

Also, it's easy to switch later, and a conversion from one format to another can be fully automated with a simple Rust script, so it's not a big deal if we want to try one and see how it feels first.

from punchy.

odecay avatar odecay commented on June 14, 2024 2

I dont think we will have a scene editor at least for awhile so we will be hand typing for sure. It seems reasonable to use RON or YAML.

Currently we use a HashMap with enum variants as keys to map animation states to frames of spritesheets, which might be useful to store in a scene but I think its not super likely. We will probably have a finite number of enemies/animations which need mapped that way it will probably be better to have that defined elsewhere.

from punchy.

zicklag avatar zicklag commented on June 14, 2024 2

Yeah, this is similar to what I need to do for my own game right now, so I figure I'll help you out while getting free code review for code that's going to be put into my game in a similar way. 😄

I think enemies will look something like this in YAML:

name: Sharky
kind: enemy
stats:
  life: 3
  # etc...
spritesheet:
  image: ../sprites/sharky.png

  animation_fps: 0.12
  animations:
    idle: [0, 3]
    running: [8, 11]
    knocked_right: [40, 46]
    knocked_left: [40, 46]
    dying: [71, 76]
    attacking: [85, 90]

I've already gotten parallax backgrounds loading from an asset.

I'm going to try strategy of having:

  • A main game metadata YAML that lists the levels and the sets the player, until we have UI, a default level that will start immediately
  • Level YAML files that will have the parallax background info, and the list of enemies and where they spawn
  • Fighter YAML files such as "Sharky" above, that will define all of the stats for the fighters

It shouldn't take too long to set up and get a feel for whether it works well.

from punchy.

zicklag avatar zicklag commented on June 14, 2024 2

Yeah, I ended up doing that too because I needed a loading state. I'm fine resolving conflicts and fitting whatever I end up with into what you've got, but here's what I've got so far so you get an idea of what I'll probably need:

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
enum GameState {
    LoadingGame,
    LoadingLevel,
    PlayingLevel,
}

fn main() {
    let mut app = App::new();

    app.insert_resource(ClearColor(Color::rgb(0.494, 0.658, 0.650)))
        .insert_resource(WindowDescriptor {
            title: "Fish Fight Punchy".to_string(),
            scale_factor_override: Some(1.0),
            ..Default::default()
        })
        .add_event::<ThrowItemEvent>()
        .add_plugins(DefaultPlugins)
        .add_plugin(RapierPhysicsPlugin::<NoUserData>::pixels_per_meter(100.0))
        .add_plugin(RapierDebugRenderPlugin::default())
        .add_plugin(AttackPlugin)
        .add_plugin(AnimationPlugin)
        .add_plugin(StatePlugin)
        .add_plugin(ParallaxPlugin)
        .insert_resource(ParallaxResource::default())
        .add_loopless_state(GameState::LoadingGame)
        .add_startup_system(setup)
        .add_system(load_game.run_in_state(GameState::LoadingGame))
        .add_system(load_level.run_in_state(GameState::LoadingLevel))
        .add_system_set(
            ConditionSet::new()
                .run_in_state(GameState::PlayingLevel)
                .with_system(spawn_throwable_items)
                .with_system(player_controller)
                .with_system(player_attack)
                .with_system(helper_camera_controller)
                .with_system(y_sort)
                .with_system(player_attack_enemy_collision)
                .with_system(player_enemy_collision)
                .with_system(kill_entities)
                .with_system(knockback_system)
                .with_system(move_direction_system)
                .with_system(move_in_arc_system)
                .with_system(throw_item_system)
                .with_system(item_attacks_enemy_collision)
                .with_system(rotate_system)
                .into(),
        )
        .add_system_to_stage(
            CoreStage::PostUpdate,
            camera_follow_player.run_in_state(GameState::PlayingLevel),
        )
        .add_system_to_stage(CoreStage::Last, despawn_entities);

    assets::register(&mut app);

    // Insert the game handle
    let asset_server = app.world.get_resource::<AssetServer>().unwrap();
    let game_path = std::env::args()
        .nth(1)
        .unwrap_or("default.game.yaml".into());

    debug!(%game_path, "Starting game");

    let handle: Handle<Game> = asset_server.load(&game_path);
    app.world.insert_resource(handle);

    app.run();
}

fn load_game(
    mut commands: Commands,
    game_handle: Res<Handle<Game>>,
    mut assets: ResMut<Assets<Game>>,
) {
    if let Some(game) = assets.remove(game_handle.clone_weak()) {
        debug!("Loaded game");
        commands.insert_resource(game.start_level.clone());
        commands.insert_resource(game);
        commands.insert_resource(NextState(GameState::LoadingLevel));
    } else {
        trace!("Awaiting game load")
    }
}

fn load_level(
    level_handle: Res<Handle<Level>>,
    mut commands: Commands,
    mut assets: ResMut<Assets<Level>>,
    mut parallax: ResMut<ParallaxResource>,
    mut texture_atlases: ResMut<Assets<TextureAtlas>>,
    asset_server: Res<AssetServer>,
    windows: Res<Windows>,
) {
    if let Some(level) = assets.remove(level_handle.clone_weak()) {
        debug!("Loaded level");
        let window = windows.primary();

        *parallax = level.meta.parallax_background.get_resource();
        parallax.despawn_layers(&mut commands);
        parallax.window_size = Vec2::new(window.width(), window.height());
        parallax.create_layers(&mut commands, &asset_server, &mut texture_atlases);

        // TODO: Spawn players ( I'm in the middle of this )

        commands.insert_resource(level);
        commands.insert_resource(NextState(GameState::PlayingLevel));
    } else {
        trace!("Awaiting level load");
    }
}

Because we are nesting the asset loading, such that game -> level -> players, the cleanest way to do it so far has been to have a LoadingGame, LoadingLevel, and PlayingLevel states, but you can throw whatever you need in there for the menu and that will probably happen before loading level.

from punchy.

edgarssilva avatar edgarssilva commented on June 14, 2024 1

Btw, we should also have some sort of spacial data. Something like the size of the scene so we can limit the camera and player movement.

from punchy.

zicklag avatar zicklag commented on June 14, 2024 1

Got the PR up: #22.

I also rebased on your changes @odecay so we're merged up all nice and clean. :)

from punchy.

zicklag avatar zicklag commented on June 14, 2024

Sounds good, you want to assign this to me, then?

from punchy.

odecay avatar odecay commented on June 14, 2024

Sure if you have bandwidth to tackle this. Do you have any thoughts about how to define enemy types and their associated resources?

from punchy.

odecay avatar odecay commented on June 14, 2024

Yeah that seems like a good approach 👍

from punchy.

odecay avatar odecay commented on June 14, 2024

@zicklag I started implementing gamestates/menu which might effect this, do you think we will want a loading state?

from punchy.

zicklag avatar zicklag commented on June 14, 2024

@odecay, do we want to allow hot-reloading fighter Stats? What that means is that instead of storing a Stats component on the fighter entities, we store a Handle<Stats>, that can be updated at any time and hot-reloaded.

from punchy.

zicklag avatar zicklag commented on June 14, 2024

OK, just got all of the scene and player information spawning through YAML assets. Now I've just got to port the rest of the enemies to their YAML forms, spawn them, and open up a PR!

from punchy.

erlend-sh avatar erlend-sh commented on June 14, 2024

Closed by #22

from punchy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.