Reputation: 1
Ok, so for some reason, when player 1's paddle is going down at the very bottom of the screen, the game starts spazzing out. Both players paddles freeze up and stop responding to keyboard input, and the pause button stops working as well. However, the ball keeps moving and bounces off the walls and paddles as if nothing has happened. I first thought it was a problem with the panel losing focus, and added a focusListener so that if the panel loses focus it will immediately grab the focus again. However that did not fix this strange bug. Then I thought something was wrong with my KeyListener so after doing research online, changed to using keybindings because they were apparently better. However, even that didn't work, and now I'm stumped and need your help. Also, before I added two player functionality my pong game was a single player game, and did not have this bug. However, the single racket was controlled with the up and down keys. I know it's a lot of code, but any help is greatly appreciated. Thank you
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TableTennis
{
private final static int WIDTH = 700, HEIGHT = 500;
private JFrame window = new JFrame();
//Constructor
public TableTennis()
{
window.setTitle("Table Tennis");
window.setSize(WIDTH,HEIGHT);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
//Centers the window on the screen
window.setLocationRelativeTo(null);
PongPanel panel = new PongPanel();
Container pane = window.getContentPane();
pane.add(panel);
/*panel.addFocusListener(new FocusAdapter()
{
public void focusLost(FocusEvent ev)
{
panel.requestFocus();
}
});*/
panel.setFocusable(true);
panel.requestFocusInWindow();
window.setVisible(true);
}//end of constructor
public static void main(String [] args)
{
new TableTennis();
}//end of main
}//end of class
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.sound.sampled.*;
import java.net.*;
//public class PongPanel extends JPanel implements KeyListener, ActionListener, FocusListener
public class PongPanel extends JPanel implements ActionListener, FocusListener
{
//Instance variables
private int playerScore, player2Score, numberOfTimesResumed, numberOfTimesPaused;
private HumanRacket r1;
private Ball b1;
private ComputerRacket r2;
private HumanRacket r3;
private boolean gameRunning, playerWin, player2Win, gamePaused, onePlayerGame, twoPlayerGame;
private Timer timer;
private Font font;
private int ballBounces;
private JButton playerVsPlayerButton, playerVsComputerButton;
//Constructor;
public PongPanel()
{
playerScore = 0;
ballBounces = 0;
player2Score = 0;
gameRunning = false;
playerWin = false;
player2Win = false;
gamePaused = false;
font = new Font("Courier", Font.BOLD, 16);
setBackground(Color.black);
r1 = new HumanRacket(20, 210);
b1 = new Ball();
r2 = new ComputerRacket(b1);
r3 = new HumanRacket(660,210);
playerVsPlayerButton = new JButton("Two Player");
playerVsPlayerButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
twoPlayerGame = true;
gameRunning = true;
}
});
playerVsComputerButton = new JButton("One Player");
playerVsComputerButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
onePlayerGame = true;
gameRunning = true;
}
});
playerVsPlayerButton.setBackground(Color.WHITE);
playerVsComputerButton.setBackground(Color.WHITE);
playerVsPlayerButton.setFocusable(false);
playerVsComputerButton.setFocusable(false);
timer = new Timer(33, this);
timer.start();
//this.addKeyListener(this);
this.addFocusListener(this);
this.add(playerVsPlayerButton);
this.add(playerVsComputerButton);
//Key Bindings for keys that are pressed
this.addKeyBindingPressed(KeyEvent.VK_W, "Player 1 paddle move up", (evt) ->{
r1.setUpAccel(true);
});
this.addKeyBindingPressed(KeyEvent.VK_S, "Player 1 paddle move down", (evt) -> {
r1.setDownAccel(true);
});
this.addKeyBindingPressed(KeyEvent.VK_P, "Pause Game", (evt) ->{
if(!gamePaused && gameRunning) {
gamePaused = true;
this.pause();
numberOfTimesPaused++;
repaint();
}//end of if
});
this.addKeyBindingPressed(KeyEvent.VK_R, "Resume Game", (evt) -> {
if(numberOfTimesResumed < numberOfTimesPaused)
{
this.resume();
gamePaused = false;
numberOfTimesResumed++;
}//end of if
});
this.addKeyBindingPressed(KeyEvent.VK_UP, "Player 2 paddle move up", (evt) ->{
r3.setUpAccel(true);
});
this.addKeyBindingPressed(KeyEvent.VK_DOWN, "Player 2 paddle move down", (evt) ->{
r3.setDownAccel(true);
});
//Key bindings for keys that are released
this.addKeyBindingReleased(KeyEvent.VK_W, "Player 1 paddle stop moving up", (evt) ->{
r1.setUpAccel(false);
});
this.addKeyBindingReleased(KeyEvent.VK_S, "Player 1 paddle stop moving down", (evt) ->{
r1.setDownAccel(false);
});
this.addKeyBindingReleased(KeyEvent.VK_UP, "Player 2 paddle stop moving up", (evt) ->{
r3.setUpAccel(false);
});
this.addKeyBindingReleased(KeyEvent.VK_DOWN, "Player 2 paddle stop moving down", (evt) ->{
r3.setDownAccel(false);
});
}//end of constructor
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if(gameRunning)
{
this.remove(playerVsPlayerButton);
this.remove(playerVsComputerButton);
}//end of if
if(gameRunning == false && playerWin == false && player2Win == false)
{
g.setColor(Color.white);
g.setFont(font);
g.drawString("Table Tennis ", 300, 100);
g.drawString("Score 5 to win", 290, 130);
g.drawString("Player 1 uses W and S keys to move", 190, 160);
g.drawString("Player 2 uses up and down keys to move", 200, 190);
g.drawString("Press P to Pause and R to Resume", 210, 220);
g.drawString("Created by: Tae-young Kim ", 0, 465);
}//end of if
else if(playerWin == true)
{
if(onePlayerGame)
{
g.setColor(Color.white);
g.setFont(font);
g.drawString("You Win!", 315, 100);
}
else if(twoPlayerGame)
{
g.setColor(Color.white);
g.setFont(font);
g.drawString("Player 1 Wins!", 310, 100);
}
}//end of if
else if(player2Win == true)
{
if(onePlayerGame)
{
g.setColor(Color.white);
g.setFont(font);
g.drawString("Game Over", 315, 100);
}
else if(twoPlayerGame)
{
g.setColor(Color.white);
g.setFont(font);
g.drawString("Player 2 Wins", 310, 100);
}
}//end of if
else if(gamePaused)
{
g.setColor(Color.white);
g.setFont(font);
g.drawString("Game Paused", 310, 100);
g.drawString("Press R to resume", 300, 130);
}//end of else if
//Prints out player score
g.setColor(Color.white);
g.setFont(font);
g.drawString(String.valueOf(playerScore), 50 , 40);
g.drawString(String.valueOf(player2Score), 640, 40);
r1.paint(g);
b1.paint(g);
if(onePlayerGame)
{
r2.paint(g);
}
else if(twoPlayerGame)
{
r3.paint(g);
}
}//end of paintComponent method
/*public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_UP)
{
r3.setUpAccel(true);
}//end of if
if(e.getKeyCode() == KeyEvent.VK_DOWN)
{
r3.setDownAccel(true);
}//end of else if
if(e.getKeyCode() == KeyEvent.VK_P)
{
if(!gamePaused && gameRunning) {
gamePaused = true;
this.pause();
numberOfTimesPaused++;
repaint();
}//end of if
}//end of else if
if(e.getKeyCode() == KeyEvent.VK_R)
{
if(numberOfTimesResumed < numberOfTimesPaused)
{
this.resume();
gamePaused = false;
numberOfTimesResumed++;
}//end of if
}//end of else if
if(e.getKeyCode() == KeyEvent.VK_W)
{
r1.setUpAccel(true);
}
if(e.getKeyCode() == KeyEvent.VK_S)
{
r1.setDownAccel(true);
}
}//end of keyPressed method
@Override
public void keyReleased(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_UP)
{
r3.setUpAccel(false);
}//end of if
if(e.getKeyCode() == KeyEvent.VK_DOWN)
{
r3.setDownAccel(false);
}//end of else if
if(e.getKeyCode() == KeyEvent.VK_W)
{
r1.setUpAccel(false);
}
if(e.getKeyCode() == KeyEvent.VK_S)
{
r1.setDownAccel(false);
}
}//end of keyReleased method
public void keyTyped(KeyEvent e)
{
//Method not useful for this program
}//end of keyTyped method*/
public void actionPerformed(ActionEvent e)
{
if(gameRunning)
{
r1.move();
b1.move();
if(onePlayerGame)
{
r2.move();
}
else if(twoPlayerGame)
{
r3.move();
}
b1.increaseSpeed(ballBounces);
this.checkBallRacketCollision();
this.addScore();
this.checkForWin();
repaint();
this.endGameIfOver();
}//end of if
}//end of actionPerformed method
public void checkBallRacketCollision()
{
if(b1.getXPos() <= r1.getX() + 1)
{
if( b1.getYPos() >= r1.getY() && b1.getYPos() <= r1.getY() + 80)
{
b1.setXVel(b1.getXVel() * -1);
ballBounces++;
playBounceSound();
}//end of if
}//end of if
if(onePlayerGame)
{
if(b1.getXPos() +15 >= r2.getX())
{
if((b1.getYPos() + 7) >= r2.getY() && b1.getYPos() <= r2.getY() + 80)
{
b1.setXVel(b1.getXVel() * -1);
ballBounces++;
playBounceSound();
}//end of if
}//end of if
}
else if(twoPlayerGame)
{
if(b1.getXPos() + 15 >= r3.getX())
{
if((b1.getYPos() + 7) >= r3.getY() && b1.getYPos() <= r3.getY() + 80)
{
b1.setXVel(b1.getXVel() * -1);
ballBounces++;
playBounceSound();
}
}
}
}//end of checkBallRacketCollsion method
public void addScore()
{
if(b1.getXPos() < 1)
{
player2Score++;
playScoreSound();
b1.setXPos(350);
b1.setYPos(250);
b1.generateRandomXVelocity();
b1.generateRandomYVelocity();
this.pause();
this.resumeDelay();
b1.setSpeedIncreaseBoolean(true);
ballBounces = 0;
}//end of if
//If ball is behind racket end the round
else if(b1.getXPos() > 0 && b1.getXPos() < r1.getX() -10)
{
if(b1.getYPos() > r1.getY() && b1.getYPos() < (r1.getY() + 80))
{
player2Score++;
playScoreSound();
b1.setXPos(350);
b1.setYPos(250);
b1.generateRandomXVelocity();
b1.generateRandomYVelocity();
this.pause();
this.resumeDelay();
b1.setSpeedIncreaseBoolean(true);
ballBounces = 0;
}//end of if
}//end of else if
if(b1.getXPos() > 699)
{
playerScore++;
playScoreSound();
b1.setXPos(350);
b1.setYPos(250);
b1.generateRandomXVelocity();
b1.generateRandomYVelocity();
this.pause();
this.resumeDelay();
b1.setSpeedIncreaseBoolean(true);
ballBounces = 0;
}//end of if
//If ball is behind computer racket end the round
if(onePlayerGame)
{
if(b1.getXPos() > (r2.getX() + 10) && b1.getXPos() < 700)
{
if(b1.getYPos() > r2.getY() && b1.getYPos() < (r2.getY() + 80))
{
playerScore++;
playScoreSound();
b1.setXPos(350);
b1.setYPos(250);
b1.generateRandomXVelocity();
b1.generateRandomYVelocity();
this.pause();
this.resumeDelay();
b1.setSpeedIncreaseBoolean(true);
ballBounces = 0;
}//end of if
}//end of else if
}
if(twoPlayerGame)
{
if(b1.getXPos() > (r3.getX() + 10) && b1.getXPos() < 700)
{
if(b1.getYPos() > r3.getY() && b1.getYPos() < (r3.getY() + 80))
{
playerScore++;
playScoreSound();
b1.setXPos(350);
b1.setYPos(250);
b1.generateRandomXVelocity();
b1.generateRandomYVelocity();
this.pause();
this.resumeDelay();
b1.setSpeedIncreaseBoolean(true);
ballBounces = 0;
}
}
}
}//end of addScore method
public void pause()
{
this.timer.stop();
}//end of pause method
public void resumeDelay()
{
this.timer = new Timer(33,this);
timer.setInitialDelay(1500);
timer.start();
}//end of resume method
public void resume()
{
this.timer = new Timer(33,this);
timer.start();
}//end of resume
public void checkForWin()
{
if(playerScore == 5)
{
playerWin = true;
gameRunning = false;
}//end of if
else if(player2Score == 5)
{
player2Win = true;
gameRunning = false;
}//end of if
}//end of checkForWin method
public void endGameIfOver()
{
if(playerWin || player2Win)
{
this.timer.stop();
}//end of if
}//end of endGameIfOver method
public void playBounceSound()
{
try {
URL soundURL1 = getClass().getClassLoader().getResource("audio/pong sound effect 2.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(soundURL1);
Clip clip = AudioSystem.getClip();
clip.open(ais);
clip.start();
} catch(Exception ex) {
System.out.println("Error with playing bounce sound.");
ex.printStackTrace();
}
}//end of playBounceSound method
public void playScoreSound()
{
try
{
URL soundURL2 = getClass().getClassLoader().getResource("audio/Pong Sound effect 1.wav");
AudioInputStream ais2 = AudioSystem.getAudioInputStream(soundURL2);
Clip clip1 = AudioSystem.getClip();
clip1.open(ais2);
clip1.start();
}//end of try
catch(Exception e)
{
System.out.println("Error with playing score sound.");
e.printStackTrace();
}//end of catch
}//end of playScoreSound method
public void focusGained(FocusEvent e)
{
}
@Override
public void focusLost(FocusEvent e) {
this.requestFocusInWindow();
}
public void addKeyBindingPressed(int keyCode, String description, ActionListener action)
{
InputMap im = this.getInputMap(this.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = this.getActionMap();
im.put(KeyStroke.getKeyStroke(keyCode, 0, false), description);
am.put(description, new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
action.actionPerformed(e);
}
});
}
public void addKeyBindingReleased(int keyCode1, String description1, ActionListener action1)
{
InputMap im1 = this.getInputMap(this.WHEN_IN_FOCUSED_WINDOW);
ActionMap am1 = this.getActionMap();
im1.put(KeyStroke.getKeyStroke(keyCode1,0,true), description1);
am1.put(description1, new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
action1.actionPerformed(e);
}
});
}
}//end of PongPanel class
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class Ball
{
private int x, y, xVel, yVel;
private boolean speedIncrease;
public Ball()
{
speedIncrease = true;
x = 350;
y = 250;
xVel = generateRandomXVelocity();
yVel = generateRandomYVelocity();
}//end of Ball constructor
public void paint(Graphics g)
{
g.setColor(Color.white);
g.fillOval(x,y,15,15);
}//end of paint method
public void move()
{
x += xVel;
y += yVel;
if(y < 10)
{
yVel *= -1;
}//end of if
else if(y > 460)
{
yVel *= -1;
}//end of if
}//end of move method
public int getXPos()
{
return x;
}//end of getXPos method
public int getYPos()
{
return y;
}//end of getYPos method
public void setXVel(int xVelocity)
{
xVel = xVelocity;
}//end of setXVel method
public int getXVel()
{
return xVel;
}//end of getXVel method
public int getYVel()
{
return yVel;
}//end of getYVel method
public int generateRandomXVelocity()
{
Random generator = new Random();
xVel = (generator.nextInt(2) + 6) * getRandomDirection();
return xVel;
}//end of generateRandomXVelocity method
public int generateRandomYVelocity()
{
Random generator = new Random();
yVel = generator.nextInt(2) + 6;
return yVel;
}//end of generateRandomYVelocity method
public int getRandomDirection()
{
Random generator = new Random();
int rand = generator.nextInt(2);
if(rand == 0)
{
return 1;
}//end of if
else
{
return -1;
}//end of else
}//end of getRandomDirection method
public void setXPos(int xPosition)
{
x = xPosition;
}//end of setXPos method
public void setYPos(int yPosition)
{
y = yPosition;
}//end of setYPos method
public void increaseSpeed(int ballBounces)
{
if(ballBounces == 3 && speedIncrease)
{
if(xVel > 0 && yVel > 0)
{
xVel+=3;
yVel+=3;
speedIncrease = false;
}//end of if
else if(xVel >0 && yVel < 0)
{
xVel+=3;
yVel-=3;
speedIncrease = false;
}//end of else if
else if(xVel <0 && yVel > 0)
{
xVel-=3;
yVel+=3;
speedIncrease = false;
}//end of else if
else
{
xVel-=3;
yVel-=3;
speedIncrease = false;
}//end of else
}//end of if
}//end of increaseSpeed
public void setSpeedIncreaseBoolean(boolean incomingInput)
{
speedIncrease = incomingInput;
}//end of setSpeedIncreaseBoolean method
}//end of class
import java.awt.*;
public interface Racket
{
public void paint(Graphics g);
public void move();
public int getY();
}//end of interface
import java.awt.*;
public class HumanRacket implements Racket
{
//Instance variables
private final double GRAVITY = 0.95;
private int x,y;
private double yVel;
private boolean upAccel, downAccel;
//Constructor
public HumanRacket(int xLoc, int yLoc)
{
x = xLoc;
y = yLoc;
yVel = 0;
upAccel = false;
downAccel = false;
}//end of constructor
//Methods
public void paint(Graphics g)
{
g.setColor(Color.white);
g.fillRect(x,y,1,80);
}//end of draw method
public void move()
{
if(upAccel)
{
yVel -= 4;
//Caps the speed at a certain point
if(yVel < -12)
{
yVel = -12;
}//end of if
}//end of if
else if(downAccel)
{
yVel += 4;
//Caps the speed at a certain point
if(yVel > 12)
{
yVel = 12;
}//end of if
}//end of else if
else if(!upAccel && !downAccel)
{
yVel *= GRAVITY;
}//end of else if
y += yVel;
//Prevents racket from leaving screen
if(y > 390)
{
y = 390;
}//end of if
else if(y < 0)
{
y = 0;
}//end of else if
}//end of move method
public void setUpAccel(boolean input)
{
upAccel = input;
}//end of setUpAccel method
public void setDownAccel(boolean input)
{
downAccel = input;
}//end of setDownAccel method
public int getY()
{
return y;
}//end of getY accessor method
public int getX()
{
return x;
}//end of getX accessor method
}//end of class
import java.awt.*;
import javax.swing.*;
import java.util.*;
public class ComputerRacket implements Racket
{
private int x, y;
private double yVel;
private int HALFWAY_POINT = 350;
Random generator;
Ball b1;
public ComputerRacket(Ball whiteBall)
{
x = 660;
y = 210;
b1 = whiteBall;
generator = new Random();
yVel = 0;
}//end of constructor
public void paint(Graphics g)
{
g.setColor(Color.white);
//g.fillRect(x,y,20,80);
g.fillRect(x,y,1,80);
}//end of paint method
public void move()
{
this.setYVel(Math.abs(b1.getYVel()));
int randomelyGeneratedNum = generateRandomNumber();
if(b1.getXPos() >= HALFWAY_POINT)
{
if(randomelyGeneratedNum == 0 || randomelyGeneratedNum == 1 || randomelyGeneratedNum == 2)
{
if( b1.getYPos() > y + 40)
{
y += yVel;
}//end of if
else
{
y -= yVel;
}//end of else
}//end of if
else if(randomelyGeneratedNum == 3)//Overcorrect
{
if(b1.getYPos() > y + 40)
{
y += yVel + 2;
}//end of if
else
{
y -= yVel + 2;
}//end of else if
}//end of else if
else//Undercorrect
{
if(b1.getYPos() > y + 40)
{
y += yVel - 2;
}//end of if
else
{
y -= yVel - 2;
}//end of else
}//end of else
}//end of if
//Move around with ball but slightly slower
else
{
if(b1.getYPos() > y )
{
y += 3;
}//end of if
else
{
y -= 3;
}//end of else
}//end of else
//Prevents racket from leaving screen
if(y > 390)
{
y = 390;
}//end of if
else if(y < 0)
{
y = 0;
}//end of else if
}//end of move method
public int getY()
{
return y;
}//end of getY method
public int getX()
{
return x;
}//end of getX method
public int generateRandomNumber()
{
int randomNumber = 0;
randomNumber = generator.nextInt(5);
return randomNumber;
}//end of generateError
public void setYVel(int ballSpeed)
{
//yVel = ballSpeed - 0.9;
yVel = ballSpeed * 0.85;
}//end of setYVel method
}//end of class
Upvotes: 0
Views: 338
Reputation: 1
Okay, the reason why it worked on my windows laptop but not on my Mac is because of mac's secondary keys. When I would hold down s, instead of repeatedly typing s it would instead pop up a menu that would contain s with accent and etc. It was messing with my keybindings so I fixed it by disabling it in the terminal This was what I entered: Defaults write -g ApplePressAndHoldEnabled -bool false
Upvotes: 0
Reputation: 174
Don't know what you mean. I tried your code in eclipse and it works fine for me for 1 Player and 2 Player. The only problem is that the ball goes under the screen. To fix this, you have to change the bottom coordinate check pixel position from 460 to 440.
public void move()
{
x += xVel;
y += yVel;
if(y < 10)
{
yVel *= -1;
}//end of if
else if(y > 460)//here make this 440 from 460
{
yVel *= -1;
}//end of if
}//end of move method
Upvotes: 0