Skip to content

Instantly share code, notes, and snippets.

@jsimmons
Created December 30, 2020 12:06
Show Gist options
  • Save jsimmons/bcf1eaf7aa58d702ccea44965a5ea017 to your computer and use it in GitHub Desktop.
Save jsimmons/bcf1eaf7aa58d702ccea44965a5ea017 to your computer and use it in GitHub Desktop.
use sdl2::{event::Event, keyboard::Keycode};
use slappy::{Colour, Draw, Input, Loop, TickState, Vec2};
#[derive(Default)]
struct PongInput {
player_1_up: bool,
player_1_down: bool,
player_2_up: bool,
player_2_down: bool,
}
impl Input for PongInput {
fn process(&mut self, event: &Event) {
match event {
Event::KeyDown { keycode, .. } | Event::KeyUp { keycode, .. } => {
let is_key_down = match event {
Event::KeyDown { .. } => true,
_ => false,
};
if keycode == &Some(Keycode::W) {
self.player_1_up = is_key_down;
}
if keycode == &Some(Keycode::S) {
self.player_1_down = is_key_down;
}
if keycode == &Some(Keycode::Up) {
self.player_2_up = is_key_down;
}
if keycode == &Some(Keycode::Down) {
self.player_2_down = is_key_down;
}
}
_ => {}
}
}
}
const BALL_INITIAL_POSITION: Vec2 = Vec2::new(400, 300);
const BALL_INITIAL_VELOCITY: Vec2 = Vec2::new(-2, 2);
struct Pong {
ball_position: Vec2,
ball_velocity: Vec2,
paddle_1: i32,
paddle_2: i32,
score_1: u32,
score_2: u32,
}
impl Default for Pong {
fn default() -> Self {
Self {
ball_position: BALL_INITIAL_POSITION,
ball_velocity: BALL_INITIAL_VELOCITY,
paddle_1: 400,
paddle_2: 100,
score_1: 0,
score_2: 0,
}
}
}
impl Loop<PongInput> for Pong {
const NAME: &'static str = "Pong";
fn tick(&mut self, _frame: u64, input: &PongInput) -> TickState {
if input.player_1_up {
self.paddle_1 -= 4;
} else if input.player_1_down {
self.paddle_1 += 4;
}
if input.player_2_up {
self.paddle_2 -= 4;
} else if input.player_2_down {
self.paddle_2 += 4;
}
self.paddle_1 = self.paddle_1.clamp(100, 400);
self.paddle_2 = self.paddle_2.clamp(100, 400);
let mut velocity = self.ball_velocity;
'substep: while velocity != Vec2::zero() {
if velocity.x.abs() > velocity.y.abs() {
let sign = velocity.x.signum();
self.ball_position.x += sign;
velocity.x -= sign;
} else {
let sign = velocity.y.signum();
self.ball_position.y += sign;
velocity.y -= sign;
}
if self.ball_position.y > 500 - 8 {
self.ball_position.y = 500 - 8;
velocity.y = -velocity.y;
self.ball_velocity.y = -self.ball_velocity.y;
}
if self.ball_position.y < 100 + 8 {
self.ball_position.y = 100 + 8;
velocity.y = -velocity.y;
self.ball_velocity.y = -self.ball_velocity.y;
}
if self.ball_position.x < 120
&& (self.ball_position.y - (self.paddle_1 + 50)).abs() < 50
{
self.ball_position.x = 120;
velocity.x = -velocity.x;
self.ball_velocity.x = -(self.ball_velocity.x + self.ball_velocity.x.signum());
}
if self.ball_position.x > 680
&& (self.ball_position.y - (self.paddle_2 + 50)).abs() < 50
{
self.ball_position.x = 680;
velocity.x = -velocity.x;
self.ball_velocity.x = -(self.ball_velocity.x + self.ball_velocity.x.signum());
}
if self.ball_position.x == 700 {
self.score_1 += 1;
self.ball_position = BALL_INITIAL_POSITION;
self.ball_velocity = BALL_INITIAL_VELOCITY;
break 'substep;
}
if self.ball_position.x == 100 {
self.score_2 += 1;
self.ball_position = BALL_INITIAL_POSITION;
self.ball_velocity = BALL_INITIAL_VELOCITY;
break 'substep;
}
}
TickState::Continue
}
fn draw(&self, draw: &mut Draw) {
let bg = Colour::new(220, 220, 220, 255);
let board_color = Colour::new(240, 240, 240, 255);
let fg = Colour::new(20, 20, 20, 255);
draw.clear(bg);
draw.rectangle_fill(Vec2::new(100, 100), Vec2::new(600, 400), board_color);
draw.rectangle_fill(Vec2::new(100, self.paddle_1), Vec2::new(20, 100), fg);
draw.rectangle_fill(Vec2::new(680, self.paddle_2), Vec2::new(20, 100), fg);
draw.rectangle_fill(
Vec2::new(self.ball_position.x - 8, self.ball_position.y - 8),
Vec2::new(16, 16),
fg,
);
}
}
fn main() {
Pong::default().run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment