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(RenderBundle::new(pipe, Some(config)).with_sprite_sheet_processor())?
|
||||||
.with_bundle(TransformBundle::new())?
|
.with_bundle(TransformBundle::new())?
|
||||||
.with_bundle(input_bundle)?
|
.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)?;
|
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_HEIGHT: f32 = 100.0;
|
||||||
pub const ARENA_WIDTH: f32 = 100.0;
|
pub const ARENA_WIDTH: f32 = 100.0;
|
||||||
pub const PADDLE_HEIGHT: f32 = 16.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;
|
const PADDLE_WIDTH: f32 = 4.0;
|
||||||
|
|
||||||
@ -22,6 +25,10 @@ impl SimpleState for Pong {
|
|||||||
let sprite_sheet_handle = load_sprite_sheet(world);
|
let sprite_sheet_handle = load_sprite_sheet(world);
|
||||||
|
|
||||||
//world.register::<Paddle>();
|
//world.register::<Paddle>();
|
||||||
|
world.register::<Ball>();
|
||||||
|
|
||||||
|
|
||||||
|
initialise_ball(world, sprite_sheet_handle.clone());
|
||||||
initialise_paddles(world, sprite_sheet_handle);
|
initialise_paddles(world, sprite_sheet_handle);
|
||||||
initialise_camera(world);
|
initialise_camera(world);
|
||||||
}
|
}
|
||||||
@ -53,6 +60,15 @@ impl Component for Paddle {
|
|||||||
type Storage = DenseVecStorage<Self>;
|
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) {
|
fn initialise_camera(world: &mut World) {
|
||||||
let mut transform = Transform::default();
|
let mut transform = Transform::default();
|
||||||
transform.set_z(1.0);
|
transform.set_z(1.0);
|
||||||
@ -101,6 +117,29 @@ fn initialise_paddles(world: &mut World, sprite_sheet: SpriteSheetHandle){
|
|||||||
.build();
|
.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 {
|
fn load_sprite_sheet(world: &mut World) -> SpriteSheetHandle {
|
||||||
// Load the sprite sheet necessary to render the graphics.
|
// Load the sprite sheet necessary to render the graphics.
|
||||||
// The texture is the pixel data
|
// 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 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