/** * A generalized Pong AI player. Takes a Rect object and a Ball, computes where the ball will be * when ball.y == rect.y, and tries to move toward that x-coordinate. If the ball is moving * straight it will try to clip the ball with the edge of the paddle. * * @param cpu */ private void aiPrediction(Paddle cpu, Paddle opponent) { Ball ball = new Ball(mBall); // Special case: move torward the center if the ball is blinking if (mBall.serving()) { cpu.destination = getWidth() / 2; cpu.move(true); return; } // Something is wrong if vy = 0.. let's wait until things fix themselves if (ball.vy == 0) return; // Y-Distance from ball to Rect 'cpu' float cpuDist = Math.abs(ball.y - cpu.centerY()); // Y-Distance to opponent. float oppDist = Math.abs(ball.y - opponent.centerY()); // Distance between two paddles. float paddleDistance = Math.abs(cpu.centerY() - opponent.centerY()); // Is the ball coming at us? boolean coming = (cpu.centerY() < ball.y && ball.vy < 0) || (cpu.centerY() > ball.y && ball.vy > 0); // Total amount of x-distance the ball covers float total = ((((coming) ? cpuDist : oppDist + paddleDistance)) / Math.abs(ball.vy)) * Math.abs(ball.vx); // Playable width of the stage float playWidth = getWidth() - 2 * Ball.RADIUS; float wallDist = (ball.goingLeft()) ? ball.x - Ball.RADIUS : playWidth - ball.x + Ball.RADIUS; // Effective x-translation left over after first bounce float remains = (total - wallDist) % playWidth; // Bounces the ball will incur int bounces = (int) ((total) / playWidth); boolean left = (bounces % 2 == 0) ? !ball.goingLeft() : ball.goingLeft(); cpu.destination = getWidth() / 2; // Now we need to compute the final x. That's all that matters. if (bounces == 0) { cpu.destination = (int) (ball.x + total * Math.signum(ball.vx)); } else if (left) { cpu.destination = (int) (Ball.RADIUS + remains); } else { // The ball is going right... cpu.destination = (int) ((Ball.RADIUS + playWidth) - remains); } // Try to give it a little kick if vx = 0 int salt = (int) (System.currentTimeMillis() / 10000); Random r = new Random((long) (cpu.centerY() + ball.vx + ball.vy + salt)); int width = cpu.getWidth(); cpu.destination = (int) bound( cpu.destination + r.nextInt(2 * width - (width / 5)) - width + (width / 10), 0, getWidth()); cpu.move(true); }