<commit_before>use rand;

use std::rc::Rc;

use sdl2_mixer::Music;

use super::player::Player;
use sprite::Sprite;
use renderer::Renderer;
use mixer::Mixer;

use unit;
use unit::{Unit, Vec2, AABB, Point, MS};

static BALL_MOVE_SPEED: Unit = Unit(0.5);

pub struct Ball {
    sprite: Sprite,

    pos: Vec2,
    v: Vec2,

    aabb: AABB,

    beeep: Rc<~Music>,
    peeeeeep: Rc<~Music>,
    plop: Rc<~Music>,
}

impl Ball {
    pub fn new(renderer: &mut Renderer, mixer: &mut Mixer) -> Ball {
        let mut sprite = Sprite::new(renderer, ~"assets/ball.png");
        let size = sprite.size();
        sprite.set_pivot(Point::new(size.w / 2, size.h / 2));

        Ball {
            sprite: sprite,
            pos: unit::vec2::ZERO,
            v: unit::vec2::ZERO,
            aabb: AABB::new(
                0.0, 0.0, size.w, size.h
            ),

            beeep: mixer.load_music(~"assets/beeep.ogg"),
            peeeeeep: mixer.load_music(~"assets/peeeeeep.ogg"),
            plop: mixer.load_music(~"assets/plop.ogg"),
        }
    }

    pub fn emit(&mut self) {
        if self.v.length() == unit::ZERO {
            let dx = if rand::random::<f32>() > 0.5 {
                0.5
            } else {
                -0.5
            };
            self.set_direction(Vec2::new(dx,
                                         rand::random::<f32>() * 2.0 - 1.0));
        }
    }

    pub fn offset(&mut self, offset: Vec2) {
        self.pos = self.pos + offset;
    }

    pub fn update(&mut self, dt: MS,
                  top_wall_aabb: &AABB, bottom_wall_aabb: &AABB,
                  left_wall_aabb: &AABB, right_wall_aabb: &AABB,
                  player1: &mut Player, player2: &mut Player) {
        let dp = self.v * dt;

        // check collision of x direction
        let aabb = self.aabb.transform(self.pos + Vec2::new(dp.x, 0.0));
        if dp.x < unit::ZERO {
            if aabb.is_collided_with(left_wall_aabb) {
                player2.win();
                println!("{} : {}", player1.score(), player2.score());
                self.reset();

                self.peeeeeep.play(1);
            } if aabb.is_collided_with(&player1.aabb()) {
                let dy = self.reflection(player1);
                self.set_direction(Vec2::new(1.0, dy));

                self.beeep.play(1);
            } else {
                self.pos.x = self.pos.x + dp.x;
            }
        } else {
            if aabb.is_collided_with(right_wall_aabb) {
                player1.win();
                println!("{} : {}", player1.score(), player2.score());
                self.reset();

                self.peeeeeep.play(1);
            } else if aabb.is_collided_with(&player2.aabb()) {
                let dy = self.reflection(player2);
                self.set_direction(Vec2::new(-1.0, dy));

                self.beeep.play(1);
            } else {
                self.pos.x = self.pos.x + dp.x;
            }
        }

        // check collision of y direction
        let aabb = self.aabb.transform(self.pos + Vec2::new(0.0, dp.y));
        if dp.y < unit::ZERO {
            if aabb.is_collided_with(top_wall_aabb) {
                self.pos.y = top_wall_aabb.bottom() + self.aabb.size().y / 2.0;
                self.v.y = -self.v.y;

                self.plop.play(1);
            } else {
                self.pos.y = self.pos.y + dp.y;
            }
        } else {
            if aabb.is_collided_with(bottom_wall_aabb) {
                self.pos.y = bottom_wall_aabb.top() - self.aabb.size().y / 2.0;
                self.v.y = -self.v.y;

                self.plop.play(1);
            } else {
                self.pos.y = self.pos.y + dp.y;
            }
        }
    }

    pub fn render(&self, renderer: &Renderer) {
        self.sprite.render(renderer, self.pos);
    }

    pub fn reset(&mut self) {
        self.v = unit::vec2::ZERO;
        self.pos = Vec2::new(240.0, 160.0);
    }

    fn set_direction(&mut self, dir: Vec2) {
        self.v = dir.norm() * BALL_MOVE_SPEED;
    }

    fn reflection(&self, player: &Player) -> Unit {
        let mut y = self.pos.y - player.position().y;
        if y > player.aabb().size.y / 2.0 {<commit_msg>Add random reflection.<commit_after>use rand;

use std::rc::Rc;

use sdl2_mixer::Music;

use super::player::Player;
use sprite::Sprite;
use renderer::Renderer;
use mixer::Mixer;

use unit;
use unit::{Unit, Vec2, AABB, Point, MS};

static BALL_MOVE_SPEED: Unit = Unit(0.5);

pub struct Ball {
    sprite: Sprite,

    pos: Vec2,
    v: Vec2,

    aabb: AABB,

    beeep: Rc<~Music>,
    peeeeeep: Rc<~Music>,
    plop: Rc<~Music>,
}

impl Ball {
    pub fn new(renderer: &mut Renderer, mixer: &mut Mixer) -> Ball {
        let mut sprite = Sprite::new(renderer, ~"assets/ball.png");
        let size = sprite.size();
        sprite.set_pivot(Point::new(size.w / 2, size.h / 2));

        Ball {
            sprite: sprite,
            pos: unit::vec2::ZERO,
            v: unit::vec2::ZERO,
            aabb: AABB::new(
                0.0, 0.0, size.w, size.h
            ),

            beeep: mixer.load_music(~"assets/beeep.ogg"),
            peeeeeep: mixer.load_music(~"assets/peeeeeep.ogg"),
            plop: mixer.load_music(~"assets/plop.ogg"),
        }
    }

    pub fn emit(&mut self) {
        if self.v.length() == unit::ZERO {
            let dx = if rand::random::<f32>() > 0.5 {
                0.5
            } else {
                -0.5
            };
            self.set_direction(Vec2::new(dx,
                                         rand::random::<f32>() * 2.0 - 1.0));
        }
    }

    pub fn update(&mut self, dt: MS,
                  top_wall_aabb: &AABB, bottom_wall_aabb: &AABB,
                  left_wall_aabb: &AABB, right_wall_aabb: &AABB,
                  player1: &mut Player, player2: &mut Player) {
        let dp = self.v * dt;

        // check collision of x direction
        let aabb = self.aabb.transform(self.pos + Vec2::new(dp.x, 0.0));
        if dp.x < unit::ZERO {
            if aabb.is_collided_with(left_wall_aabb) {
                player2.win();
                println!("{} : {}", player1.score(), player2.score());
                self.reset();

                self.peeeeeep.play(1).unwrap();
            } if aabb.is_collided_with(&player1.aabb()) {
                let dy = self.reflection(player1);
                self.set_direction(Vec2::new(1.0, dy));

                self.beeep.play(1).unwrap();
            } else {
                self.pos.x = self.pos.x + dp.x;
            }
        } else {
            if aabb.is_collided_with(right_wall_aabb) {
                player1.win();
                println!("{} : {}", player1.score(), player2.score());
                self.reset();

                self.peeeeeep.play(1).unwrap();
            } else if aabb.is_collided_with(&player2.aabb()) {
                let dy = self.reflection(player2);
                self.set_direction(Vec2::new(-1.0, dy));

                self.beeep.play(1).unwrap();
            } else {
                self.pos.x = self.pos.x + dp.x;
            }
        }

        // check collision of y direction
        let aabb = self.aabb.transform(self.pos + Vec2::new(0.0, dp.y));
        if dp.y < unit::ZERO {
            if aabb.is_collided_with(top_wall_aabb) {
                self.pos.y = top_wall_aabb.bottom() + self.aabb.size().y / 2.0;
                self.v.y = -self.v.y;

                self.plop.play(1).unwrap();
            } else {
                self.pos.y = self.pos.y + dp.y;
            }
        } else {
            if aabb.is_collided_with(bottom_wall_aabb) {
                self.pos.y = bottom_wall_aabb.top() - self.aabb.size().y / 2.0;
                self.v.y = -self.v.y;

                self.plop.play(1).unwrap();
            } else {
                self.pos.y = self.pos.y + dp.y;
            }
        }
    }

    pub fn render(&self, renderer: &Renderer) {
        self.sprite.render(renderer, self.pos);
    }

    pub fn reset(&mut self) {
        self.v = unit::vec2::ZERO;
        self.pos = Vec2::new(240.0, 160.0);
    }

    fn set_direction(&mut self, dir: Vec2) {
        self.v = dir.norm() * BALL_MOVE_SPEED;
    }

    fn reflection(&self, player: &Player) -> Unit {
        let mut y = self.pos.y - player.position().y;

        y = y * rand::random::<f32>() * 0.4 + 0.8;

        if y > player.aabb().size.y / 2.0 {
{'fraction_non_alphanumeric': 0.15212740670311387, 'fraction_numerical': 0.018897076301402426, 'mean_word_length': 1.4948117402905425, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6565099', 'n_tokens_mistral': 3007, 'n_tokens_neox': 2869, 'n_words': 538}