|
| 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 | +} |
0 commit comments