Skip to content

Commit c9686ea

Browse files
authored
Add paddle acceleration (inertia) (#4)
* Refactor game structure: move paddle logic to game module and update viewport constants for default values * Bump version to 0.3.0 in Cargo.toml
1 parent c85b7cf commit c9686ea

File tree

6 files changed

+86
-57
lines changed

6 files changed

+86
-57
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "Breakout"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
authors = ["Vianpyro"]
55
edition = "2024"
66

File renamed without changes.

src/game/paddle.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use crate::viewport::{DEFAULT_VIRTUAL_HEIGHT, DEFAULT_VIRTUAL_WIDTH};
2+
use bevy::prelude::*;
3+
4+
const PADDLE_START_Y: f32 = -DEFAULT_VIRTUAL_HEIGHT / 2.0 + PADDLE_SIZE.y * 2.0;
5+
const PADDLE_SIZE: Vec2 = Vec2::new(DEFAULT_VIRTUAL_WIDTH / 15.0, DEFAULT_VIRTUAL_HEIGHT / 40.0);
6+
const PADDLE_COLOR: Color = Color::srgb(1.0, 1.0, 1.0);
7+
const PADDLE_SPEED: f32 = 650.0;
8+
const PADDLE_ACCELERATION: f32 = 2000.0;
9+
10+
#[derive(Component)]
11+
pub struct Paddle {
12+
pub velocity: f32,
13+
}
14+
15+
pub fn create_paddle(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<ColorMaterial>>) {
16+
let paddle_mesh = meshes.add(Rectangle::new(PADDLE_SIZE.x, PADDLE_SIZE.y));
17+
let paddle_material = materials.add(ColorMaterial::from(PADDLE_COLOR));
18+
commands.spawn((
19+
Mesh2d(paddle_mesh),
20+
MeshMaterial2d(paddle_material),
21+
Transform::from_translation(Vec3::new(0.0, PADDLE_START_Y, 0.0)),
22+
Paddle { velocity: 0.0 },
23+
));
24+
}
25+
26+
pub fn paddle_movement_system(
27+
keyboard_input: Res<ButtonInput<KeyCode>>,
28+
time: Res<Time>,
29+
viewport: Res<crate::viewport::WindowViewport>,
30+
mut query: Query<(&mut Transform, &mut Paddle), With<Paddle>>,
31+
) {
32+
let half_world_width = viewport.half_width;
33+
let delta_time = time.delta_secs();
34+
35+
for (mut transform, mut paddle) in query.iter_mut() {
36+
let mut direction = 0.0;
37+
if keyboard_input.pressed(KeyCode::ArrowLeft) {
38+
direction -= 1.0;
39+
}
40+
if keyboard_input.pressed(KeyCode::ArrowRight) {
41+
direction += 1.0;
42+
}
43+
44+
// Apply acceleration when input is held
45+
if direction != 0.0 {
46+
paddle.velocity += direction * PADDLE_ACCELERATION * delta_time;
47+
paddle.velocity = paddle.velocity.clamp(-PADDLE_SPEED, PADDLE_SPEED);
48+
} else {
49+
// Decelerate towards 0 when no input (simple friction)
50+
let deceleration = PADDLE_ACCELERATION * delta_time;
51+
if paddle.velocity.abs() <= deceleration {
52+
paddle.velocity = 0.0;
53+
} else {
54+
paddle.velocity -= paddle.velocity.signum() * deceleration;
55+
}
56+
}
57+
58+
// Move by current velocity
59+
transform.translation.x += paddle.velocity * delta_time;
60+
61+
// Clamp to world bounds
62+
let half_paddle_width = PADDLE_SIZE.x / 2.0;
63+
transform.translation.x = transform
64+
.translation
65+
.x
66+
.clamp(-half_world_width + half_paddle_width, half_world_width - half_paddle_width);
67+
}
68+
}

src/main.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#![windows_subsystem = "windows"]
22

3-
mod player;
3+
mod game;
44
mod viewport;
55
use bevy::app::AppExit;
66
use bevy::prelude::*;
@@ -9,7 +9,7 @@ use viewport::{VirtualResolution, WindowViewport};
99

1010
fn main() {
1111
App::new()
12-
.insert_resource(VirtualResolution { width: 1280.0, height: 720.0 })
12+
.insert_resource(VirtualResolution::default())
1313
.insert_resource(viewport::ScalingStrategy::AutoMin)
1414
.insert_resource(WindowViewport::default())
1515
.add_plugins(DefaultPlugins.set(WindowPlugin {
@@ -30,7 +30,7 @@ fn main() {
3030
)
3131
.add_systems(PreUpdate, exit_on_esc_system)
3232
.add_systems(Update, (viewport::maybe_update_window_viewport, viewport::update_camera_on_resize))
33-
.add_systems(Update, player::paddle::paddle_movement_system)
33+
.add_systems(Update, game::paddle::paddle_movement_system)
3434
.run();
3535
}
3636

@@ -46,5 +46,5 @@ fn spawn_camera(mut commands: Commands) {
4646
}
4747

4848
fn spawn_map(mut _commands: Commands, mut _meshes: ResMut<Assets<Mesh>>, mut _materials: ResMut<Assets<ColorMaterial>>) {
49-
player::paddle::create_paddle(_commands, _meshes, _materials);
49+
game::paddle::create_paddle(_commands, _meshes, _materials);
5050
}

src/player/paddle.rs

Lines changed: 0 additions & 47 deletions
This file was deleted.

src/viewport.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
use bevy::prelude::*;
22

3+
const DEFAULT_VIEWPORT_WIDTH: f32 = 1920.0;
4+
const DEFAULT_VIEWPORT_HEIGHT: f32 = 1080.0;
5+
pub const DEFAULT_VIRTUAL_WIDTH: f32 = 1280.0;
6+
pub const DEFAULT_VIRTUAL_HEIGHT: f32 = 720.0;
7+
38
// Virtual resolution (in world units) that should be visible on screen regardless
49
// of the physical pixel resolution. For example, a height of 720 means the camera
510
// will display 720 world units vertically; the projection scale is adjusted so
@@ -12,7 +17,10 @@ pub struct VirtualResolution {
1217

1318
impl Default for VirtualResolution {
1419
fn default() -> Self {
15-
Self { width: 1280.0, height: 720.0 }
20+
Self {
21+
width: DEFAULT_VIRTUAL_WIDTH,
22+
height: DEFAULT_VIRTUAL_HEIGHT,
23+
}
1624
}
1725
}
1826

@@ -46,10 +54,10 @@ pub struct WindowViewport {
4654
impl Default for WindowViewport {
4755
fn default() -> Self {
4856
Self {
49-
half_width: 1920.0 / 2.0,
50-
half_height: 1080.0 / 2.0,
51-
pixel_width: 1920.0,
52-
pixel_height: 1080.0,
57+
half_width: DEFAULT_VIEWPORT_WIDTH / 2.0,
58+
half_height: DEFAULT_VIEWPORT_HEIGHT / 2.0,
59+
pixel_width: DEFAULT_VIEWPORT_WIDTH,
60+
pixel_height: DEFAULT_VIEWPORT_HEIGHT,
5361
scale: 1.0,
5462
}
5563
}

0 commit comments

Comments
 (0)