mirror of
https://github.com/neogeek23/rust_pong.git
synced 2026-02-04 10:58:20 +00:00
ball movement and reaction to paddle added
This commit is contained in:
parent
87c8fe2b1b
commit
8d74a3ca40
@ -35,7 +35,9 @@ fn main() -> amethyst::Result<()> {
|
||||
.with_bundle(RenderBundle::new(pipe, Some(config)).with_sprite_sheet_processor())?
|
||||
.with_bundle(TransformBundle::new())?
|
||||
.with_bundle(input_bundle)?
|
||||
.with(systems::PaddleSystem, "paddle_system", &["input_system"]);
|
||||
.with(systems::PaddleSystem, "paddle_system", &["input_system"])
|
||||
.with(systems::MoveBallsSystem, "ball_system", &[])
|
||||
.with(systems::BounceSystem, "collision_system", &["paddle_system", "ball_system"],);
|
||||
|
||||
let mut game = Application::new("./", Pong, game_data)?;
|
||||
|
||||
|
||||
39
src/pong.rs
39
src/pong.rs
@ -11,6 +11,9 @@ use amethyst::renderer::{
|
||||
pub const ARENA_HEIGHT: f32 = 100.0;
|
||||
pub const ARENA_WIDTH: f32 = 100.0;
|
||||
pub const PADDLE_HEIGHT: f32 = 16.0;
|
||||
pub const BALL_VELOCITY_X: f32 = 65.0;
|
||||
pub const BALL_VELOCITY_Y: f32 = 40.0;
|
||||
pub const BALL_RADIUS: f32 = 2.0;
|
||||
|
||||
const PADDLE_WIDTH: f32 = 4.0;
|
||||
|
||||
@ -22,6 +25,10 @@ impl SimpleState for Pong {
|
||||
let sprite_sheet_handle = load_sprite_sheet(world);
|
||||
|
||||
//world.register::<Paddle>();
|
||||
world.register::<Ball>();
|
||||
|
||||
|
||||
initialise_ball(world, sprite_sheet_handle.clone());
|
||||
initialise_paddles(world, sprite_sheet_handle);
|
||||
initialise_camera(world);
|
||||
}
|
||||
@ -53,6 +60,15 @@ impl Component for Paddle {
|
||||
type Storage = DenseVecStorage<Self>;
|
||||
}
|
||||
|
||||
pub struct Ball {
|
||||
pub velocity: [f32; 2],
|
||||
pub radius: f32,
|
||||
}
|
||||
|
||||
impl Component for Ball {
|
||||
type Storage = DenseVecStorage<Self>;
|
||||
}
|
||||
|
||||
fn initialise_camera(world: &mut World) {
|
||||
let mut transform = Transform::default();
|
||||
transform.set_z(1.0);
|
||||
@ -101,6 +117,29 @@ fn initialise_paddles(world: &mut World, sprite_sheet: SpriteSheetHandle){
|
||||
.build();
|
||||
}
|
||||
|
||||
/// Initialises one ball in the middle-ish of the arena.
|
||||
fn initialise_ball(world: &mut World, sprite_sheet_handle: SpriteSheetHandle) {
|
||||
// Create the translation.
|
||||
let mut local_transform = Transform::default();
|
||||
local_transform.set_xyz(ARENA_WIDTH / 2.0, ARENA_HEIGHT / 2.0, 0.0);
|
||||
|
||||
// Assign the sprite for the ball
|
||||
let sprite_render = SpriteRender {
|
||||
sprite_sheet: sprite_sheet_handle,
|
||||
sprite_number: 1, // ball is the second sprite on the sprite sheet
|
||||
};
|
||||
|
||||
world
|
||||
.create_entity()
|
||||
.with(sprite_render)
|
||||
.with(Ball {
|
||||
radius: BALL_RADIUS,
|
||||
velocity: [BALL_VELOCITY_X, BALL_VELOCITY_Y],
|
||||
})
|
||||
.with(local_transform)
|
||||
.build();
|
||||
}
|
||||
|
||||
fn load_sprite_sheet(world: &mut World) -> SpriteSheetHandle {
|
||||
// Load the sprite sheet necessary to render the graphics.
|
||||
// The texture is the pixel data
|
||||
|
||||
66
src/systems/bounce.rs
Normal file
66
src/systems/bounce.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use amethyst::{
|
||||
core::transform::Transform,
|
||||
ecs::prelude::{Join, ReadStorage, System, WriteStorage},
|
||||
};
|
||||
|
||||
use crate::pong::{Ball, Side, Paddle, ARENA_HEIGHT};
|
||||
|
||||
pub struct BounceSystem;
|
||||
|
||||
impl<'s> System<'s> for BounceSystem {
|
||||
type SystemData = (
|
||||
WriteStorage<'s, Ball>,
|
||||
ReadStorage<'s, Paddle>,
|
||||
ReadStorage<'s, Transform>,
|
||||
);
|
||||
|
||||
fn run(&mut self, (mut balls, paddles, transforms): Self::SystemData) {
|
||||
// Check whether a ball collided, and bounce off accordingly.
|
||||
//
|
||||
// We also check for the velocity of the ball every time, to prevent multiple collisions
|
||||
// from occurring.
|
||||
for (ball, transform) in (&mut balls, &transforms).join() {
|
||||
let ball_x = transform.translation().x;
|
||||
let ball_y = transform.translation().y;
|
||||
|
||||
// Bounce at the top or the bottom of the arena.
|
||||
if ball_y >= ARENA_HEIGHT - ball.radius && ball.velocity[1] > 0.0 {
|
||||
ball.velocity[1] = -ball.velocity[1];
|
||||
} else if ball_y <= ball.radius && ball.velocity[1] < 0.0 {
|
||||
ball.velocity[1] = -ball.velocity[1];
|
||||
}
|
||||
|
||||
// Bounce at the paddles.
|
||||
for (paddle, paddle_transform) in (&paddles, &transforms).join() {
|
||||
let paddle_x = paddle_transform.translation().x - paddle.width * 0.5;
|
||||
let paddle_y = paddle_transform.translation().y - paddle.height * 0.5;
|
||||
|
||||
// To determine whether the ball has collided with a paddle, we create a larger
|
||||
// rectangle around the current one, by subtracting the ball radius from the
|
||||
// lowest coordinates, and adding the ball radius to the highest ones. The ball
|
||||
// is then within the paddle if its centre is within the larger wrapper
|
||||
// rectangle.
|
||||
if point_in_rect(
|
||||
ball_x,
|
||||
ball_y,
|
||||
paddle_x - ball.radius,
|
||||
paddle_y - ball.radius,
|
||||
paddle_x + paddle.width + ball.radius,
|
||||
paddle_y + paddle.height + ball.radius,
|
||||
) {
|
||||
if paddle.side == Side::Left && ball.velocity[0] < 0.0 {
|
||||
ball.velocity[0] = -ball.velocity[0];
|
||||
} else if paddle.side == Side::Right && ball.velocity[0] > 0.0 {
|
||||
ball.velocity[0] = -ball.velocity[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A point is in a box when its coordinates are smaller or equal than the top
|
||||
// right and larger or equal than the bottom left.
|
||||
fn point_in_rect(x: f32, y: f32, left: f32, bottom: f32, right: f32, top: f32) -> bool {
|
||||
x >= left && x <= right && y >= bottom && y <= top
|
||||
}
|
||||
@ -1,3 +1,7 @@
|
||||
mod paddle;
|
||||
mod move_balls;
|
||||
mod bounce;
|
||||
|
||||
pub use self::paddle::PaddleSystem;
|
||||
pub use self::paddle::PaddleSystem;
|
||||
pub use self::bounce::BounceSystem;
|
||||
pub use self::move_balls::MoveBallsSystem;
|
||||
25
src/systems/move_balls.rs
Normal file
25
src/systems/move_balls.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use amethyst::{
|
||||
core::timing::Time,
|
||||
core::transform::Transform,
|
||||
ecs::prelude::{Join, Read, ReadStorage, System, WriteStorage},
|
||||
};
|
||||
|
||||
use crate::pong::Ball;
|
||||
|
||||
pub struct MoveBallsSystem;
|
||||
|
||||
impl<'s> System<'s> for MoveBallsSystem {
|
||||
type SystemData = (
|
||||
ReadStorage<'s, Ball>,
|
||||
WriteStorage<'s, Transform>,
|
||||
Read<'s, Time>,
|
||||
);
|
||||
|
||||
fn run(&mut self, (balls, mut locals, time): Self::SystemData) {
|
||||
// Move every ball according to its speed, and the time passed.
|
||||
for (ball, local) in (&balls, &mut locals).join() {
|
||||
local.translate_x(ball.velocity[0] * time.delta_seconds());
|
||||
local.translate_y(ball.velocity[1] * time.delta_seconds());
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user