Sébastien Belzile
Posted on December 10, 2021
Drawing a Square
Our game will be composed of sprites. All our world will be built with squares of equal width and height.
This means that the first thing we want to do is draw a square on the screen.
Let's create a new system called spawn_player
:
// Player component
struct Player;
// spawn player system
fn spawn_player(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
commands
.spawn_bundle(SpriteBundle {
material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()),
sprite: Sprite::new(Vec2::new(10.0, 10.0)),
..Default::default()
})
.insert(Player);
}
and register this system with our Bevy application:
App::build()
.insert_resource(WindowDescriptor {
title: "Platformer!".to_string(),
width: 640.0,
height: 400.0,
vsync: true,
..Default::default()
})
.insert_resource(ClearColor(Color::rgb(0.04, 0.04, 0.04)))
.add_startup_stage("player_setup", SystemStage::single(spawn_player.system())) // line to add
.add_plugins(DefaultPlugins)
.run();
Now let's run cargo run
. The window will open and we should see: well, nothing.
We drew a square in our Bevy scene, but it is not yet visible since we did not add a camera to the scene...
Adding a Camera
To add a camera, we will create a new setup
system.
fn setup(mut commands: Commands) {
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
}
and register it with our application:
// ...
+ .add_startup_system(setup.system())
.add_startup_stage("player_setup", SystemStage::single(spawn_player.system()))
// ...
This new system adds an orthographic camera to the scene. There are 2 main types of camera that you need to know about when making computer games: orthographic and perspective.
Perspective camera are mostly used in 3D games, when we need to simulate a real world view. This type of camera is more representative of the way we see things in real life.
Orthographic cameras are used when we don't need a concept of depth. An orthographic camera does not modify the size of our objects as they are moved further from our point of view (camera). In our case, we are building a 2D platformer, so this is what we are going to use.
Let's run cargo run
:
Camera Adjustments
If the window is resized, the visible area gets bigger... In a usual platformer, the width of the visible area rarely changes. The camera will follow our player, but the visible width of our screen should remain constant.
Looking at the code of OrthographicCameraBundle::new_2d()
(the source, not our code), we can see that it adds a resource called OrthographicProjection
which has a parameter called scaling_mode
. This parameter is an enum
that can take 4 different values. The one we are interested in is the FixedHorizontal
option.
Let's try it:
// src/camera.rs
use bevy::{prelude::OrthographicCameraBundle, render::camera::{OrthographicProjection, DepthCalculation, ScalingMode}, math::Vec3};
pub fn new_camera_2d() -> OrthographicCameraBundle {
let far = 1000.0;
let mut camera = OrthographicCameraBundle::new_2d();
camera.orthographic_projection = OrthographicProjection {
far,
depth_calculation: DepthCalculation::ZDifference,
scaling_mode: ScalingMode::FixedHorizontal,
..Default::default()
};
camera.transform.scale = Vec3::new(10., 10., 1.);
return camera;
}
The line camera.transform.scale = Vec3::new(10., 10., 1.);
is to scale up our camera, otherwise, the visible area goes from -1 to +1 on the y and x axis in our world's units.
// src/main.rs
mod camera;
pub use camera::*;
// ...
+ commands.spawn_bundle(new_camera_2d());
- commands.spawn_bundle(OrthographicCameraBundle::new_2d());
It works, but our player is way too huge. Let's scale it down:
// src/main.rs spawn_player method
.spawn_bundle(SpriteBundle {
material: materials.add(Color::rgb(0.7, 0.7, 0.7).into()),
sprite: Sprite::new(Vec2::new(1.0, 1.0)),
..Default::default()
})
It's all for today, in the next part, we will discuss physics.
All code available here.
Part 1:
Posted on December 10, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.