You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
learn-wgpu/code/showcase/pong/src/system.rs

283 lines
8.4 KiB
Rust

use winit::event::*;
use crate::state;
use crate::util;
pub trait System {
4 years ago
fn start(&mut self, state: &mut state::State);
fn process_input(&mut self, keycode: VirtualKeyCode, pressed: bool) -> bool;
fn update_state(&self, state: &mut state::State);
}
4 years ago
#[derive(Debug)]
pub struct MenuSystem {
enter_pressed: bool,
down_pressed: bool,
up_pressed: bool,
}
impl MenuSystem {
pub fn new() -> Self {
Self {
enter_pressed: false,
down_pressed: false,
up_pressed: false,
}
}
}
impl System for MenuSystem {
fn start(&mut self, state: &mut state::State) {
self.enter_pressed = false;
self.down_pressed = false;
self.up_pressed = false;
state.player1.score = 0;
state.player2.score = 0;
state.ball.visible = false;
state.player1.visible = false;
state.player2.visible = false;
state.title_text.visible = true;
state.play_button.visible = true;
state.play_button.focused = true;
state.quit_button.visible = true;
state.player1_score.visible = false;
state.player2_score.visible = false;
state.win_text.visible = false;
}
fn process_input(&mut self, keycode: VirtualKeyCode, pressed: bool) -> bool {
match keycode {
VirtualKeyCode::Up | VirtualKeyCode::W => {
self.up_pressed = pressed;
true
}
VirtualKeyCode::Down | VirtualKeyCode::S => {
self.down_pressed = pressed;
true
}
VirtualKeyCode::Return
| VirtualKeyCode::NumpadEnter
| VirtualKeyCode::Space => {
self.enter_pressed = pressed;
true
}
_ => false,
}
}
fn update_state(&self, state: &mut state::State) {
if state.play_button.focused && self.down_pressed {
state.play_button.focused = false;
state.quit_button.focused = true;
} else if state.quit_button.focused && self.up_pressed {
state.quit_button.focused = false;
state.play_button.focused = true;
}
if state.play_button.focused && self.enter_pressed {
state.game_state = state::GameState::Serving;
} else if state.quit_button.focused && self.enter_pressed {
state.game_state = state::GameState::Quiting;
}
}
}
pub struct PlaySystem {
player1_up_pressed: bool,
player1_down_pressed: bool,
player2_up_pressed: bool,
player2_down_pressed: bool,
}
4 years ago
impl PlaySystem {
pub fn new() -> Self {
Self {
player1_up_pressed: false,
player1_down_pressed: false,
player2_up_pressed: false,
player2_down_pressed: false,
}
}
}
4 years ago
impl System for PlaySystem {
fn start(&mut self, state: &mut state::State) {
self.player1_up_pressed = false;
self.player1_down_pressed = false;
self.player2_up_pressed = false;
self.player2_down_pressed = false;
state.ball.visible = true;
state.player1.visible = true;
state.player2.visible = true;
state.title_text.visible = false;
state.play_button.visible = false;
state.quit_button.visible = false;
state.player1_score.visible = true;
state.player2_score.visible = true;
}
fn process_input(&mut self, keycode: VirtualKeyCode, pressed: bool) -> bool {
match keycode {
VirtualKeyCode::W => {
self.player1_up_pressed = pressed;
true
}
VirtualKeyCode::S => {
self.player1_down_pressed = pressed;
true
}
VirtualKeyCode::Up => {
self.player2_up_pressed = pressed;
true
}
VirtualKeyCode::Down => {
self.player2_down_pressed = pressed;
true
}
_ => false,
}
}
fn update_state(&self, state: &mut state::State) {
4 years ago
// move the players
if self.player1_up_pressed {
state.player1.position.y += 0.025;
}
if self.player1_down_pressed {
state.player1.position.y -= 0.025;
}
if self.player2_up_pressed {
state.player2.position.y += 0.025;
}
if self.player2_down_pressed {
state.player2.position.y -= 0.025;
}
// normalize players
if state.player1.position.y > 1.0 {
state.player1.position.y = 1.0;
4 years ago
} else if state.player1.position.y < -1.0 {
state.player1.position.y = -1.0;
}
if state.player2.position.y > 1.0 {
state.player2.position.y = 1.0;
4 years ago
} else if state.player2.position.y < -1.0 {
state.player2.position.y = -1.0;
}
state.ball.position += state.ball.velocity;
if state.ball.position.y > 1.0 {
state.ball.position.y = 1.0;
state.ball.velocity.y *= -1.0;
4 years ago
} else if state.ball.position.y < -1.0 {
state.ball.position.y = -1.0;
state.ball.velocity.y *= -1.0;
}
4 years ago
if state.ball.position.x > 1.0 {
4 years ago
state.player1.score += 1;
state.game_state = state::GameState::Serving;
} else if state.ball.position.x < -1.0 {
state.player2.score += 1;
state.game_state = state::GameState::Serving;
}
4 years ago
if state.player1.score > 2 || state.player2.score > 2 {
state.game_state = state::GameState::GameOver;
}
// bounce the ball off the players
if state.player1.contains(&state.ball) {
4 years ago
state.ball.position.x -= state.ball.velocity.x - state.player1.size.x;
state.ball.velocity.x *= -1.0;
} else if state.player2.contains(&state.ball) {
state.ball.position.x -= state.ball.velocity.x + state.player2.size.x;
state.ball.velocity.x *= -1.0;
}
}
4 years ago
}
pub struct ServingSystem {
last_time: std::time::Instant,
}
impl ServingSystem {
pub fn new() -> Self {
Self {
last_time: std::time::Instant::now(),
}
}
}
impl System for ServingSystem {
fn start(&mut self, state: &mut state::State) {
self.last_time = std::time::Instant::now();
state.ball.visible = true;
state.player1.visible = true;
state.player2.visible = true;
state.title_text.visible = false;
state.play_button.visible = false;
state.quit_button.visible = false;
state.ball.position = (0.0, 0.0).into();
state.ball.velocity = util::random_vec2_scaled(0.025);
state.player1_score.visible = true;
state.player2_score.visible = true;
state.player1_score.text = format!("{}", state.player1.score);
state.player2_score.text = format!("{}", state.player2.score);
}
fn process_input(&mut self, _keycode: VirtualKeyCode, _pressed: bool) -> bool {
false
}
fn update_state(&self, state: &mut state::State) {
let current_time = std::time::Instant::now();
let delta_time = current_time - self.last_time;
if delta_time.as_secs_f32() > 1.0 {
state.game_state = state::GameState::Playing;
}
}
}
pub struct GameOverSystem {
last_time: std::time::Instant,
key_pressed: bool,
}
impl GameOverSystem {
pub fn new() -> Self {
Self {
last_time: std::time::Instant::now(),
key_pressed: false,
}
}
}
impl System for GameOverSystem {
fn start(&mut self, state: &mut state::State) {
self.last_time = std::time::Instant::now();
self.key_pressed = false;
state.ball.visible = false;
state.win_text.text = if state.player1.score > state.player2.score {
String::from("Player1 wins!")
} else {
String::from("Player2 wins!")
};
state.win_text.visible = true;
}
fn process_input(&mut self, _keycode: VirtualKeyCode, _pressed: bool) -> bool {
false
}
fn update_state(&self, state: &mut state::State) {
let current_time = std::time::Instant::now();
let delta_time = current_time - self.last_time;
if delta_time.as_secs_f32() > 1.0 {
state.game_state = state::GameState::MainMenu;
}
}
}