7

Making Games in Rust - Part 6 - Generating a Map

 3 years ago
source link: https://dev.to/sbelzile/making-games-in-rust-part-6-generating-a-map-4aic
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

If you did not read the previous articles, you may start here.

For future features, we will need a bigger world to move our player in. We need a bigger map.

This article builds on top of our previous code (the code I started with can be found here) and adds an automatically generated map to our world.

Flat Floor

In map.rs, let's replace our spawn_floor method with the following code:

pub fn spawn_floor(mut commands: Commands, materials: Res<Materials>) {
    for x in 0..50 {
        add_tile(&mut commands, &materials, x as f32)
    }
}

fn add_tile(commands: &mut Commands, materials: &Res<Materials>, x: f32) {
    let rigid_body = RigidBodyBundle {
        position: Vec2::new(x, -2.).into(),
        body_type: RigidBodyType::Static,
        ..Default::default()
    };
    let collider = ColliderBundle {
        shape: ColliderShape::cuboid(0.5, 0.5),
        ..Default::default()
    };
    commands
        .spawn_bundle(SpriteBundle {
            material: materials.floor_material.clone(),
            sprite: Sprite::new(Vec2::new(1., 1.)),
            ..Default::default()
        })
        .insert_bundle(rigid_body)
        .insert_bundle(collider)
        .insert(RigidBodyPositionSync::Discrete);
}

Enter fullscreen mode

Exit fullscreen mode

Compared to our previous code, we:

  1. Moved the content of the spawn_floor function to an add_tile function.
  2. Modify the input of the add_tile function so that it receives an x coordinate as well.
  3. Modify the width of our tiles from 10 to 1 world unit.
  4. Set the x component of our rigid body to the x coordinate provided as input.

The new spawn_floor function now contains a loop which calls our add_tile function with a coordinate going from 0 to 50.

Running the game will display a flat floor of length 50.

(Ha! Yeah! our player is also pink now)

Going Up or Down

To make this more interesting, our map should go up or down. Let's modify our add_tile function so that it takes a height as input:

fn add_tile(commands: &mut Commands, materials: &Res<Materials>, x: f32, height: u8) {
    let half_height = height as f32 / 2.;
    let rigid_body = RigidBodyBundle {
        position: Vec2::new(x, -2. + half_height).into(),
        body_type: RigidBodyType::Static,
        ..Default::default()
    };
    let collider = ColliderBundle {
        shape: ColliderShape::cuboid(0.5, half_height),
        ..Default::default()
    };
    commands
        .spawn_bundle(SpriteBundle {
            material: materials.floor_material.clone(),
            sprite: Sprite::new(Vec2::new(1., height as f32)),
            ..Default::default()
        })
        .insert_bundle(rigid_body)
        .insert_bundle(collider)
        .insert(RigidBodyPositionSync::Discrete);
}

Enter fullscreen mode

Exit fullscreen mode

We will randomly determine the height to provide:

  1. Add the rand crate to your cargo.toml:
[dependencies]
rand = "0.8.4"

Enter fullscreen mode

Exit fullscreen mode

  1. Add a function to randomly pick an height variation:
use rand::prelude::*;
// ...
fn get_random_height_delta() -> i8 {
    let mut rng = thread_rng();
    let random_number: u32 = rng.gen_range(0..100);
    let delta = match random_number {
        0..=70 => 0,
        71..=80 => -1,
        81..=90 => 1,
        _ => 2,
    };
    delta
}

Enter fullscreen mode

Exit fullscreen mode

  1. Add a function to calculate the next height from the current height:
fn get_next_height(current_height: u8) -> u8 {
    let next_height = current_height as i8 + get_random_height_delta();
    return if next_height > 0 {
        next_height as u8
    } else {
        1
    };
}

Enter fullscreen mode

Exit fullscreen mode

  1. Finally, modify the spawn_floor function to send a random height to the add_tile function:
pub fn spawn_floor(mut commands: Commands, materials: Res<Materials>) {
    let mut height = 1;
    for x in 0..150 {
        add_tile(&mut commands, &materials, x as f32, height);
        height = get_next_height(height)
    }
}

Enter fullscreen mode

Exit fullscreen mode

Running the game should render a prettier map:

The final code is available here.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK