Sébastien Belzile
Posted on December 26, 2021
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);
}
Compared to our previous code, we:
- Moved the content of the
spawn_floor
function to anadd_tile
function. - Modify the input of the
add_tile
function so that it receives anx
coordinate as well. - Modify the width of our tiles from 10 to 1 world unit.
- 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);
}
We will randomly determine the height to provide:
- Add the
rand
crate to yourcargo.toml
:
[dependencies]
rand = "0.8.4"
- 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
}
- 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
};
}
- Finally, modify the
spawn_floor
function to send a random height to theadd_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)
}
}
Running the game should render a prettier map:
The final code is available here.
Posted on December 26, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.