Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Move magic numbers into constants in Breakout example #4255

Closed
Closed
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 77 additions & 47 deletions examples/game/breakout.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,53 @@
//! A simplified implementation of the classic game "Breakout"

use bevy::{
core::FixedTimestep,
math::{const_vec2, const_vec3},
prelude::*,
sprite::collide_aabb::{collide, Collision},
};

/// An implementation of the classic game "Breakout"
// Sets the amount of time that should elapse between each physics step
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
const TIME_STEP: f32 = 1.0 / 60.0;

// These constants are in `Transform` units:
// with the default 2D camera they correspond 1:1 with screen pixels
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
// The `const_vec3!` macros are needed as functions that operate on floats cannot be constant in Rust.
const PADDLE_HEIGHT: f32 = -215.0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the meaning of this one is not very obvious, even less with the PADDLE_SIZE just under

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. I'll fix this in a follow-up PR.

const PADDLE_SIZE: Vec3 = const_vec3!([120.0, 30.0, 0.0]);
const PADDLE_SPEED: f32 = 500.0;
const PADDLE_BOUNDS: f32 = 380.0;

// We set the z-value of the ball to 1 so it renders on top in the case of overlapping sprites
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
const BALL_STARTING_POSITION: Vec3 = const_vec3!([0.0, -50.0, 1.0]);
const BALL_SIZE: Vec3 = const_vec3!([30.0, 30.0, 0.0]);
const BALL_SPEED: f32 = 400.0;
const INITIAL_BALL_DIRECTION: Vec2 = const_vec2!([0.5, -0.5]);

const PLAY_AREA_BOUNDS: Vec2 = const_vec2!([900.0, 600.0]);
const WALL_THICKNESS: f32 = 10.0;

const BRICK_ROWS: u8 = 4;
const BRICK_COLUMNS: u8 = 5;
const BRICK_SPACING: f32 = 20.0;
const BRICK_SIZE: Vec3 = const_vec3!([150.0, 30.0, 1.0]);

const SCOREBOARD_FONT_SIZE: f32 = 40.0;
const SCOREBOARD_TEXT_PADDING: Val = Val::Px(5.0);

const BACKGROUND_COLOR: Color = Color::rgb(0.95, 0.95, 0.95);
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
const PADDLE_COLOR: Color = Color::rgb(0.5, 0.5, 1.0);
const BALL_COLOR: Color = Color::rgb(1.0, 0.5, 0.5);
const BRICK_COLOR: Color = Color::rgb(0.5, 0.5, 1.0);
const WALL_COLOR: Color = Color::DARK_GRAY;
const TEXT_COLOR: Color = Color::BLUE;
const SCORE_COLOR: Color = Color::RED;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.insert_resource(Scoreboard { score: 0 })
.insert_resource(ClearColor(Color::rgb(0.9, 0.9, 0.9)))
.insert_resource(ClearColor(BACKGROUND_COLOR))
.add_startup_system(setup)
.add_system_set(
SystemSet::new()
Expand Down Expand Up @@ -55,34 +92,37 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands
.spawn_bundle(SpriteBundle {
transform: Transform {
translation: Vec3::new(0.0, -215.0, 0.0),
scale: Vec3::new(120.0, 30.0, 0.0),
translation: Vec3::new(0.0, PADDLE_HEIGHT, 0.0),
scale: PADDLE_SIZE,
..default()
},
sprite: Sprite {
color: Color::rgb(0.5, 0.5, 1.0),
color: PADDLE_COLOR,
..default()
},
..default()
})
.insert(Paddle { speed: 500.0 })
.insert(Paddle {
speed: PADDLE_SPEED,
})
.insert(Collider::Paddle);
// ball
commands
.spawn_bundle(SpriteBundle {
transform: Transform {
scale: Vec3::new(30.0, 30.0, 0.0),
translation: Vec3::new(0.0, -50.0, 1.0),
scale: BALL_SIZE,
translation: BALL_STARTING_POSITION,
..default()
},
sprite: Sprite {
color: Color::rgb(1.0, 0.5, 0.5),
color: BALL_COLOR,
..default()
},
..default()
})
.insert(Ball {
velocity: 400.0 * Vec3::new(0.5, -0.5, 0.0).normalize(),
// We can create a velocity by multiplying our speed by a normalized direction
alice-i-cecile marked this conversation as resolved.
Show resolved Hide resolved
velocity: BALL_SPEED * INITIAL_BALL_DIRECTION.extend(0.0).normalize(),
});
// scoreboard
commands.spawn_bundle(TextBundle {
Expand All @@ -92,16 +132,16 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
value: "Score: ".to_string(),
style: TextStyle {
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
font_size: 40.0,
color: Color::rgb(0.5, 0.5, 1.0),
font_size: SCOREBOARD_FONT_SIZE,
color: TEXT_COLOR,
},
},
TextSection {
value: "".to_string(),
style: TextStyle {
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
font_size: 40.0,
color: Color::rgb(1.0, 0.5, 0.5),
font_size: SCOREBOARD_FONT_SIZE,
color: SCORE_COLOR,
},
},
],
Expand All @@ -110,30 +150,25 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
style: Style {
position_type: PositionType::Absolute,
position: Rect {
top: Val::Px(5.0),
left: Val::Px(5.0),
top: SCOREBOARD_TEXT_PADDING,
left: SCOREBOARD_TEXT_PADDING,
..default()
},
..default()
},
..default()
});

// Add walls
let wall_color = Color::rgb(0.8, 0.8, 0.8);
let wall_thickness = 10.0;
let bounds = Vec2::new(900.0, 600.0);

// left
commands
.spawn_bundle(SpriteBundle {
transform: Transform {
translation: Vec3::new(-bounds.x / 2.0, 0.0, 0.0),
scale: Vec3::new(wall_thickness, bounds.y + wall_thickness, 1.0),
translation: Vec3::new(-PLAY_AREA_BOUNDS.x / 2.0, 0.0, 0.0),
scale: Vec3::new(WALL_THICKNESS, PLAY_AREA_BOUNDS.y + WALL_THICKNESS, 1.0),
..default()
},
sprite: Sprite {
color: wall_color,
color: WALL_COLOR,
..default()
},
..default()
Expand All @@ -143,12 +178,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands
.spawn_bundle(SpriteBundle {
transform: Transform {
translation: Vec3::new(bounds.x / 2.0, 0.0, 0.0),
scale: Vec3::new(wall_thickness, bounds.y + wall_thickness, 1.0),
translation: Vec3::new(PLAY_AREA_BOUNDS.x / 2.0, 0.0, 0.0),
scale: Vec3::new(WALL_THICKNESS, PLAY_AREA_BOUNDS.y + WALL_THICKNESS, 1.0),
..default()
},
sprite: Sprite {
color: wall_color,
color: WALL_COLOR,
..default()
},
..default()
Expand All @@ -158,12 +193,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands
.spawn_bundle(SpriteBundle {
transform: Transform {
translation: Vec3::new(0.0, -bounds.y / 2.0, 0.0),
scale: Vec3::new(bounds.x + wall_thickness, wall_thickness, 1.0),
translation: Vec3::new(0.0, -PLAY_AREA_BOUNDS.y / 2.0, 0.0),
scale: Vec3::new(PLAY_AREA_BOUNDS.x + WALL_THICKNESS, WALL_THICKNESS, 1.0),
..default()
},
sprite: Sprite {
color: wall_color,
color: WALL_COLOR,
..default()
},
..default()
Expand All @@ -173,45 +208,40 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands
.spawn_bundle(SpriteBundle {
transform: Transform {
translation: Vec3::new(0.0, bounds.y / 2.0, 0.0),
scale: Vec3::new(bounds.x + wall_thickness, wall_thickness, 1.0),
translation: Vec3::new(0.0, PLAY_AREA_BOUNDS.y / 2.0, 0.0),
scale: Vec3::new(PLAY_AREA_BOUNDS.x + WALL_THICKNESS, WALL_THICKNESS, 1.0),
..default()
},
sprite: Sprite {
color: wall_color,
color: WALL_COLOR,
..default()
},
..default()
})
.insert(Collider::Solid);

// Add bricks
let brick_rows = 4;
let brick_columns = 5;
let brick_spacing = 20.0;
let brick_size = Vec3::new(150.0, 30.0, 1.0);
let bricks_width = brick_columns as f32 * (brick_size.x + brick_spacing) - brick_spacing;
let bricks_width = BRICK_COLUMNS as f32 * (BRICK_SIZE.x + BRICK_SPACING) - BRICK_SPACING;
// center the bricks and move them up a bit
let bricks_offset = Vec3::new(-(bricks_width - brick_size.x) / 2.0, 100.0, 0.0);
let brick_color = Color::rgb(0.5, 0.5, 1.0);
for row in 0..brick_rows {
let y_position = row as f32 * (brick_size.y + brick_spacing);
for column in 0..brick_columns {
let bricks_offset = Vec3::new(-(bricks_width - BRICK_SIZE.x) / 2.0, 100.0, 0.0);
for row in 0..BRICK_ROWS {
let y_position = row as f32 * (BRICK_SIZE.y + BRICK_SPACING);
for column in 0..BRICK_COLUMNS {
let brick_position = Vec3::new(
column as f32 * (brick_size.x + brick_spacing),
column as f32 * (BRICK_SIZE.x + BRICK_SPACING),
y_position,
0.0,
) + bricks_offset;
// brick
commands
.spawn_bundle(SpriteBundle {
sprite: Sprite {
color: brick_color,
color: BRICK_COLOR,
..default()
},
transform: Transform {
translation: brick_position,
scale: brick_size,
scale: BRICK_SIZE,
..default()
},
..default()
Expand Down Expand Up @@ -239,7 +269,7 @@ fn paddle_movement_system(
// move the paddle horizontally
translation.x += direction * paddle.speed * TIME_STEP;
// bound the paddle within the walls
translation.x = translation.x.min(380.0).max(-380.0);
translation.x = translation.x.min(PADDLE_BOUNDS).max(-PADDLE_BOUNDS);
}

fn ball_movement_system(mut ball_query: Query<(&Ball, &mut Transform)>) {
Expand Down