My classmates and I are making a pong game and we have run into a problem. The bug is that when the pong ball intersects with either the walls or player paddles, the ball will sometimes collide multiple times so that it looks like the ball is gliding on the paddle. If anyone has run into this same problem or has any knowledge of what causes this I would much appreciate the help.
We found a solution to the problem which is putting a cooldown on the ball after hitting an object (wall and or paddle) that way it won't get that weird gliding bug, thank you everyone for posting suggestions and helping us out ;)
import greenfoot.*;
import java.awt.*;
/**
* A Ball is a thing that bounces of walls and paddles (or at least i should).
*
* @author The teachers
* @version 1
*/
public class Ball extends Actor
{
private static final int BALL_SIZE = 50;
private static final int BOUNCE_DEVIANCE_MAX = 5;
private static final int STARTING_ANGLE_WIDTH = 90;
private static final int DELAY_TIME = 200;
private int speed;
private boolean hasBouncedHorizontally;
private boolean hasBouncedVertically;
private int delay;
private int touchCounter;
/**
* Contructs the ball and sets it in motion!
*/
public Ball()
{
// createImage();
init();
}
/**
* Creates and sets an image of a black ball to this actor.
*/
/*
private void createImage()
{
GreenfootImage ballImage = new GreenfootImage(BALL_SIZE,BALL_SIZE);
ballImage.setColor(Color.RED);
ballImage.fillOval(0, 0, BALL_SIZE, BALL_SIZE);
setImage(ballImage);
}
*/
/**
* Act - do whatever the Ball wants to do. This method is called whenever
* the 'Act' or 'Run' button gets pressed in the environment.
*/
public void act()
{
if (delay > 0)
{
delay--;
}
else
{
move(speed);
checkBounceOffWalls();
checkBounceOffCeiling();
checkRestart();
bounceOffPaddles();
}
}
/**
* Returns true if the ball is touching one of the side walls.
*/
private boolean isTouchingSides()
{
return getX() <= BALL_SIZE/2 || getX() >= getWorld().getWidth() - BALL_SIZE/2;
}
/**
* Returns true if the ball is touching the ceiling.
*/
private boolean isTouchingCeiling()
{
return (getY() <= BALL_SIZE/2);
}
/**
* Returns true if the ball is touching the floor.
*/
private boolean isTouchingFloor()
{
return (getY() >= getWorld().getHeight() - BALL_SIZE/2);
}
/**
* Check to see if the ball should bounce off one of the walls.
* If touching one of the walls, the ball is bouncing off.
*/
private void checkBounceOffWalls()
{
if (isTouchingSides())
{
if (! hasBouncedHorizontally)
{
revertHorizontally();
}
}
else
{
hasBouncedHorizontally = false;
}
}
/**
* Check to see if the ball should bounce off the ceiling.
* If touching the ceiling the ball is bouncing off.
*/
private void checkBounceOffCeiling()
{
if (isTouchingCeiling())
{
if (! hasBouncedVertically)
{
revertVertically();
}
}
// Removed for purpose of solving Task 3
/*
else
{
hasBouncedVertically = false;
}
*/
}
/**
* Check to see if the ball should be restarted.
* If touching the floor the ball is restarted in initial position and speed.
*/
private void checkRestart()
{
if (isTouchingFloor())
{
PingWorld theWorld = (PingWorld) getWorld();
theWorld.resetGameLevel();
init();
setLocation(getWorld().getWidth() / 2, getWorld().getHeight() / 2);
}
}
/**
* Bounces the ball back from a vertical surface.
*/
private void revertHorizontally()
{
int randomness = Greenfoot.getRandomNumber(BOUNCE_DEVIANCE_MAX)- BOUNCE_DEVIANCE_MAX / 2;
setRotation((180 - getRotation()+ randomness + 360) % 360);
Greenfoot.playSound("pewsoundeffect.mp3");
hasBouncedHorizontally = true;
}
/**
* Bounces the bal back from a horizontal surface.
*/
private void revertVertically()
{
int randomness = Greenfoot.getRandomNumber(BOUNCE_DEVIANCE_MAX)- BOUNCE_DEVIANCE_MAX / 2;
setRotation((360 - getRotation()+ randomness + 360) % 360);
Greenfoot.playSound("pewsoundeffect.mp3");
hasBouncedVertically = true;
}
// Checking for the paddles if they intersect with the ball, if touching, revert vertically.
public void bounceOffPaddles()
{
Actor paddle = getOneIntersectingObject(Paddle.class);
Actor enemyPaddle = getOneIntersectingObject(EnemyPaddle.class);
if (paddle != null) {
revertVertically();
hasBouncedVertically = false;
speedIncreaser();
}
if (hasBouncedVertically == false && enemyPaddle != null) {
revertVertically();
}
}
// Increases speed
public void speedIncreaser() {
touchCounter++;
if (touchCounter == 10) {
speed++;
PingWorld theWorld = (PingWorld) getWorld();
theWorld.increaseGameLevel();
touchCounter = 0;
}
}
/**
* Initialize the ball settings.
*/
private void init()
{
speed = 2;
delay = DELAY_TIME;
hasBouncedHorizontally = false;
hasBouncedVertically = false;
setRotation(Greenfoot.getRandomNumber(STARTING_ANGLE_WIDTH)+STARTING_ANGLE_WIDTH/2);
}
} else
{
hasBouncedVertically = false;
}
*/
}
/**
* Check to see if the ball should be restarted.
* If touching the floor the ball is restarted in initial position and speed.
*/
private void checkRestart()
{
if (isTouchingFloor())
{
PingWorld theWorld = (PingWorld) getWorld();
theWorld.resetGameLevel();
init();
setLocation(getWorld().getWidth() / 2, getWorld().getHeight() / 2);
}
}
/**
* Bounces the ball back from a vertical surface.
*/
private void revertHorizontally()
{
int randomness = Greenfoot.getRandomNumber(BOUNCE_DEVIANCE_MAX)- BOUNCE_DEVIANCE_MAX / 2;
setRotation((180 - getRotation()+ randomness + 360) % 360);
Greenfoot.playSound("pewsoundeffect.mp3");
hasBouncedHorizontally = true;
}
/**
* Bounces the bal back from a horizontal surface.
*/
private void revertVertically()
{
int randomness = Greenfoot.getRandomNumber(BOUNCE_DEVIANCE_MAX)- BOUNCE_DEVIANCE_MAX / 2;
setRotation((360 - getRotation()+ randomness + 360) % 360);
Greenfoot.playSound("pewsoundeffect.mp3");
hasBouncedVertically = true;
}
// Checking for the paddles if they intersect with the ball, if touching, revert vertically.
public void bounceOffPaddles()
{
Actor paddle = getOneIntersectingObject(Paddle.class);
Actor enemyPaddle = getOneIntersectingObject(EnemyPaddle.class);
if (paddle != null) {
revertVertically();
hasBouncedVertically = false;
speedIncreaser();
}
if (hasBouncedVertically == false && enemyPaddle != null) {
revertVertically();
}
}
// Increases speed
public void speedIncreaser() {
touchCounter++;
if (touchCounter == 10) {
speed++;
PingWorld theWorld = (PingWorld) getWorld();
theWorld.increaseGameLevel();
touchCounter = 0;
}
}
/**
* Initialize the ball settings.
*/
private void init()
{
speed = 2;
delay = DELAY_TIME;
hasBouncedHorizontally = false;
hasBouncedVertically = false;
setRotation(Greenfoot.getRandomNumber(STARTING_ANGLE_WIDTH)+STARTING_ANGLE_WIDTH/2);
}
}