pong-cli 1.0.1

Play pong from the command-line!
Documentation
use super::system_prelude::*;

#[derive(Default)]
pub struct PaddleAiSystem;

impl<'a> System<'a> for PaddleAiSystem {
    type SystemData = (
        ReadExpect<'a, Settings>,
        ReadStorage<'a, PaddleAi>,
        ReadStorage<'a, Ball>,
        ReadStorage<'a, Position>,
        ReadStorage<'a, Size>,
        ReadStorage<'a, Velocity>,
        WriteStorage<'a, Paddle>,
    );

    fn run(
        &mut self,
        (
            settings,
            paddle_ais,
            balls,
            positions,
            sizes,
            velocities,
            mut paddles,
        ): Self::SystemData,
    ) {
        for (_, paddle, paddle_position, paddle_size) in
            (&paddle_ais, &mut paddles, &positions, &sizes).join()
        {
            let follow_padding =
                paddle_size.h * settings.paddle.ai.follow_padding_percent;

            if let Some(ball_position) = (&balls, &positions, &velocities)
                .join()
                .fold(None, |nearest_opt: Option<(f32, f32)>, (_, pos, vel)| {
                    if (&paddle.side == &Side::Left && vel.x < 0.0)
                        || (&paddle.side == &Side::Right && vel.x > 0.0)
                    {
                        if let Some(nearest) = nearest_opt {
                            match &paddle.side {
                                Side::Left if pos.x < nearest.0 => {
                                    Some(pos.into())
                                }
                                Side::Right if pos.x > nearest.0 => {
                                    Some(pos.into())
                                }
                                _ => Some(nearest),
                            }
                        } else {
                            Some(pos.into())
                        }
                    } else {
                        nearest_opt
                    }
                })
            {
                if ball_position.1 < paddle_position.y - follow_padding {
                    paddle.move_up();
                } else if ball_position.1 > paddle_position.y + follow_padding {
                    paddle.move_down();
                }
            }
        }
    }
}