Smooth movement
Since Macroquad will draw frames as quickly as possible, we need to check how much time has passed between each update to determine how far the circle should move. Otherwise, our game will run at different speeds on different computers, depending on how quickly they can run the application. The specific framerate will depend on your computer; if Vsync is enabled it may be locked to 30 or 60 frames per second.
Implementation
We will expand the application and add a constant that determines how quickly
the circle should move. We call the constant MOVEMENT_SPEED
and assign the
value 200.0
. If the circle moves too fast or too slow, we can decrease or
increase this value.
const MOVEMENT_SPEED: f32 = 200.0;
Time between frames
Now we will use the function get_frame_time()
to get the time in seconds
that has passed since the last frame. We assign this value to a variable
called delta_time
that we will use later.
let delta_time = get_frame_time();
Update movement
When the variables x
and y
are updated, we will multiply the values of
the constant MOVEMENT_SPEED
by the variable delta_time
to get how far the
circle should move during this frame.
if is_key_down(KeyCode::Right) {
x += MOVEMENT_SPEED * delta_time;
}
if is_key_down(KeyCode::Left) {
x -= MOVEMENT_SPEED * delta_time;
}
if is_key_down(KeyCode::Down) {
y += MOVEMENT_SPEED * delta_time;
}
if is_key_down(KeyCode::Up) {
y -= MOVEMENT_SPEED * delta_time;
}
Limit movement
Finally, we will prevent the circle from moving outside of the window.
We use the Macroquad function clamp()
to make sure x
and y
are never
below 0
or above the width of the window.
x = clamp(x, 0.0, screen_width());
y = clamp(y, 0.0, screen_height());
The clamp()
function is used to clamp a value between a minimum and maximum
value. It is part of the Macroquad
Math API.
Change the constant MOVEMENT_SPEED
if the circle is moving too slow or too
fast.
What do you need to change to ensure that the entire circle stays within the window when the position is clamped?
Source
The code should now look like this:
use macroquad::prelude::*;
#[macroquad::main("My game")]
async fn main() {
const MOVEMENT_SPEED: f32 = 200.0;
let mut x = screen_width() / 2.0;
let mut y = screen_height() / 2.0;
loop {
clear_background(DARKPURPLE);
let delta_time = get_frame_time();
if is_key_down(KeyCode::Right) {
x += MOVEMENT_SPEED * delta_time;
}
if is_key_down(KeyCode::Left) {
x -= MOVEMENT_SPEED * delta_time;
}
if is_key_down(KeyCode::Down) {
y += MOVEMENT_SPEED * delta_time;
}
if is_key_down(KeyCode::Up) {
y -= MOVEMENT_SPEED * delta_time;
}
x = clamp(x, 0.0, screen_width());
y = clamp(y, 0.0, screen_height());
draw_circle(x, y, 16.0, YELLOW);
next_frame().await
}
}