ユーザ用ツール

サイト用ツール


youtube:sfml-pong

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

両方とも前のリビジョン前のリビジョン
次のリビジョン
前のリビジョン
youtube:sfml-pong [2024/02/28 18:26] – 削除 - 外部編集 (不明な日付) 127.0.0.1youtube:sfml-pong [2024/02/29 11:49] (現在) freemikan
行 1: 行 1:
 +====== Pong ======
 +
 +作成日: 2022-12-07 (水)
 +
 +{{:youtube:sfml-pong.png?400|}}
 +
 +src/main.rs
 +
 +<file rust pong.rs>
 +use sfml::{system::*, window::*, graphics::*};
 +
 +struct MoveFlags {
 +    up: bool,
 +    down: bool,
 +}
 +
 +struct Game<'a> {
 +    window: RenderWindow,
 +    paddle: RectangleShape<'a>,
 +    paddle_speed: f32,
 +    ball: CircleShape<'a>,
 +    ball_velocity: Vector2f,
 +    move_flags: MoveFlags
 +}
 +
 +impl<'a> Game<'a> {
 +    const FPS: f32 = 60.0; // Time::seconds(1.0 / 60.0) is not allowed for const
 +    const WIDTH: u32 = 1000;
 +    const HEIGHT: u32 = 800;
 +    const PADDLE_SPEED: f32 = 200.0;
 +    const PADDLE_SIZE_X: f32 = 30.0;
 +    const PADDLE_SIZE_Y: f32 = 100.0;
 +    const BALL_SPEED: f32 = 400.0;
 +    const BALL_RADIUS: f32 = 20.0;
 +
 +    pub fn new() -> Game<'a> {
 +        let window = RenderWindow::new(
 +            (Self::WIDTH, Self::HEIGHT),
 +            "Pong with Rust and SFML",
 +            Style::CLOSE,
 +            &Default::default());
 +            
 +        let mut paddle = RectangleShape::with_size(Vector2f::new(Self::PADDLE_SIZE_X, Self::PADDLE_SIZE_Y));
 +        paddle.set_position((Self::PADDLE_SIZE_X, (Self::HEIGHT as f32 / 2.0) - Self::PADDLE_SIZE_Y));
 +        
 +        let paddle_speed = Self::PADDLE_SPEED;
 +        
 +        let mut ball = CircleShape::new(Self::BALL_RADIUS, 30);
 +        ball.set_position((Self::WIDTH as f32 / 2.0, Self::HEIGHT as f32 / 2.0));
 +        ball.set_origin((Self::BALL_RADIUS, Self::BALL_RADIUS));
 +        
 +        let ball_velocity = Vector2f::new(Self::BALL_SPEED, Self::BALL_SPEED);
 +            
 +        Game {
 +            window,
 +            paddle,
 +            paddle_speed,
 +            ball,
 +            ball_velocity,
 +            move_flags: MoveFlags {
 +                up: false,
 +                down: false,
 +            }
 +        }
 +    }
 +    
 +    pub fn run(&mut self) {
 +        let mut clock = Clock::start();
 +        let mut time_since_last_update = Time::ZERO;
 +        let time_per_frame = Time::seconds(1.0 / Self::FPS);
 +        
 +        while self.window.is_open() {
 +            self.process_events();
 +
 +            time_since_last_update += clock.restart();
 +            while time_since_last_update > time_per_frame {
 +                time_since_last_update -= time_per_frame;
 +                self.process_events();
 +                self.update(&time_per_frame);
 +            }
 +            self.render();
 +        }
 +    }
 +    
 +    fn process_events(&mut self) {
 +        while let Some(event) = self.window.poll_event() {
 +            match event {
 +                Event::Closed => self.window.close(),
 +                Event::KeyPressed { code, .. } =>
 +                    if code == Key::Enter || code == Key::Escape {
 +                        self.window.close();
 +                    } else {
 +                        self.handle_player_input(code, true);
 +                    },
 +                Event::KeyReleased { code, .. } =>
 +                    self.handle_player_input(code, false),
 +                _ => {}
 +            }
 +        }
 +    }
 +    
 +    fn update(&mut self, delta_time: &Time) {
 +        // short names for readability
 +        let paddle = &mut self.paddle;
 +        let ball = &mut self.ball;
 +        let ball_velocity = &mut self.ball_velocity;
 +
 +        // update paddle
 +        let mut movement = Vector2f::new(0.0, 0.0);
 +        
 +        if self.move_flags.up {
 +            if paddle.position().y > 0.0 {
 +                movement.y -= self.paddle_speed;
 +            }
 +        }
 +        if self.move_flags.down {
 +            if paddle.position().y + paddle.size().y < Self::HEIGHT as f32 {
 +                movement.y += self.paddle_speed;
 +            }
 +        }
 +        paddle.move_(movement * delta_time.as_seconds());
 +        
 +        // update ball
 +        
 +        // update ball x
 +        ball.move_((ball_velocity.x * delta_time.as_seconds(), 0.0));
 +
 +        if ball.position().x + ball.radius() > Self::WIDTH as f32 {
 +            ball_velocity.x *= -1.0;
 +            // align to left of paddle
 +            ball.set_position((Self::WIDTH as f32 - ball.radius(), ball.position().y));
 +        }
 +        
 +        let paddle_rect = paddle.global_bounds();
 +        let mut ball_rect = ball.global_bounds(); // mut for reusing later
 +        if ball_rect.intersection(&paddle_rect) != None {
 +            ball.set_position((paddle_rect.left + paddle_rect.width + ball.radius(), ball.position().y));
 +            ball_velocity.x *= -1.0;
 +        }
 +        
 +        // update ball y
 +        ball.move_((0.0, ball_velocity.y * delta_time.as_seconds()));
 +        
 +        if ball.position().y - ball.radius() < 0.0 {
 +            ball_velocity.y *= -1.0;
 +            ball.set_position((ball.position().x, ball.radius()));
 +        }
 +        if ball.position().y + ball.radius() > Self::HEIGHT as f32 {
 +            ball_velocity.y *= -1.0;
 +            ball.set_position((ball.position().x, Self::HEIGHT as f32 - ball.radius()));
 +        }
 +        
 +        ball_rect = ball.global_bounds(); // get new rect which has been updated for x
 +        if ball_rect.intersection(&paddle_rect) != None {
 +            if ball_velocity.y > 0.0 {
 +                // align to top of paddle
 +               ball.set_position((ball.position().x, paddle_rect.top - ball.radius()));
 +            } else {
 +                // align to bottom of paddle
 +                ball.set_position((ball.position().x, paddle_rect.top + paddle_rect.height));
 +            }
 +            
 +            ball_velocity.y *= -1.0;
 +        }
 +        
 +        assert!(ball.position().x + ball.radius() <= Self::WIDTH as f32);
 +    }
 +    
 +    fn render(&mut self) {
 +        self.window.clear(Color::BLUE);
 +        self.window.draw(&self.paddle);
 +        self.window.draw(&self.ball);
 +        self.window.display();
 +    }
 +    
 +    fn handle_player_input(&mut self, code: Key, pressed: bool) {
 +        match code {
 +            Key::W => self.move_flags.up = pressed,
 +            Key::S => self.move_flags.down = pressed,
 +            _ => {}
 +        }
 +    }
 +}
 +
 +fn main() {
 +    let mut game = Game::new();
 +    game.run();
 +}
 +</file>
 +
 +Cargo.toml
 +
 +<file>
 +[package]
 +name = "pong"
 +version = "0.1.0"
 +edition = "2021"
 +
 +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 +
 +[dependencies]
 +sfml = "0.19.0"
 +</file>
  

特に明示されていない限り、本Wikiの内容は次のライセンスに従います: CC0 1.0 Universal
CC0 1.0 Universal Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki