## DEV Community is a community of 866,220 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Sébastien Belzile

Posted on • Updated on

# Making Games in Rust - Part 7 - Fixing the Player Randomly Stuck Issue

If you played with the code from part 6 of this tutorial, you probably noticed that our player often gets randomly stuck on the ground. You may also have gotten stuck in that way:

## Solution 1

We could make our player smaller:

``````// player.rs
shape: ColliderShape::cuboid(0.45, 0.45),
// ...
sprite: Sprite::new(Vec2::new(0.9, 0.9)),
``````

This fixes the hole issue:

But our player still randomly gets stuck on a flat surface.

## Solution 2

What about a round corners on our character?

``````shape: ColliderShape::round_cuboid(0.35, 0.35, 0.1),
``````

This way, our character is no longer stuck, but it looks like it bumps on the corner of the colliders...

## Solution 3

We could modify our drawing strategy to only have flat colliders. Instead of one collider per square, we could layer colliders one on top of the other:

The code to do this adds some complexity though:

We will split world creation in 3 steps.

``````pub fn spawn_floor(mut commands: Commands, materials: Res<Materials>) {
let world = create_world(150);
}
``````

First step is to generate our height map, second step is to add our sprites, and finally we add our colliders.

1. World creation:
``````fn create_world(width: usize) -> Vec<usize> {
let mut heights: Vec<usize> = Vec::with_capacity(width);
let mut height = 1;
(0..width).for_each(|_| {
heights.push(height);
height = get_next_height(height)
});
heights
}
``````

Code is similar to what we previously had, we fill a vector with our heights.

``````fn add_sprites(commands: &mut Commands, materials: Res<Materials>, world: &Vec<usize>) {
world.iter().enumerate().for_each(|(x, height)| {
add_tile(commands, &materials, x as f32, *height);
});
}

fn add_tile(commands: &mut Commands, materials: &Res<Materials>, x: f32, height: usize) {
commands
.spawn_bundle(SpriteBundle {
material: materials.floor_material.clone(),
sprite: Sprite::new(Vec2::new(1., height as f32)),
transform: Transform::from_translation(Vec3::new(x, height as f32 / 2., 0.)),
..Default::default()
});
}
``````

Also similar to what we previously had. Our entity no longer includes the rigid bodies and colliders components. The code iterates on our vector, and prints our world.

``````fn add_colliders(world: &Vec<usize>, commands: &mut Commands) {
let max = match world.iter().max() {
Some(m) => m,
_ => panic!("add_colliders: World is empty")
};
(1..=*max).for_each(|floor_height| {
let mut start: Option<usize> = None;
world.iter().enumerate().for_each(|(index, height_at_index)| {
if  *height_at_index >= floor_height && start.is_none() {
start = Some(index);
} else if *height_at_index < floor_height && start.is_some() {
start = None
}
});

if start.is_some() {
}
})
}

fn add_collider(commands: &mut Commands, height: usize, from: usize, to: usize) {
let width = to - from;
let half_width = width as f32 / 2.;
let rigid_body = RigidBodyBundle {
position: Vec2::new(from as f32 + half_width - 0.5, height as f32 - 0.5).into(),
body_type: RigidBodyType::Static,
..Default::default()
};
let collider = ColliderBundle {
shape: ColliderShape::cuboid(half_width, 0.5),
..Default::default()
};
commands
.spawn_bundle(rigid_body)
.insert_bundle(collider)
.insert(RigidBodyPositionSync::Discrete);
}
``````

This code renders our world layer by layer. It adds a rigid body and a collider for every continuous length of floor on the layer.

The final code is available here.