何かの理由で、プレイヤー1のパドルが画面の一番下にくると、ゲームが始まります。両方のプレーヤーがフリーズしてキーボード入力に応答しなくなり、一時停止ボタンも機能しなくなります。しかし、何も起こっていないかのように、ボールは動き続けて壁やパドルから跳ね返ります。私はまず、パネルがフォーカスを失う問題であると思って、パネルがフォーカスを失った場合にフォーカスを直ちに取得するようにfocusListenerを追加しました。しかし、それはこの奇妙なバグを修正しませんでした。オンラインでリサーチをした後、KeyListenerに何か問題があったと思ったので、キーバインドを使用するように変更しました。しかし、それでもうまくいきませんでした、そして今、私は困っており、あなたの助けが必要です。また、2つのプレーヤー機能を追加する前に、私のポンゲームはシングルプレイヤーゲームであり、このバグはありませんでした。しかし、単一のラケットは、上下のキーで制御されていました。私はそれが多くのコードだと知っていますが、どんな助けも大歓迎です。 PongPanelクラス がJava Pongゲームのヘルプ。私のキーの動きや一時停止ボタンに反応しないパドルに関する奇妙なバグは、うまくいきません。
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.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 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
HumanRacketクラス
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
ComputerRacketクラス
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
これは奇妙です。バグを再現するには、Sを押し続けて、プレイヤー1を画面の一番下まで送ってみてください。ゲームのバグやプレイヤー1とプレイヤー2が制御不能になり、一時停止ボタンが機能しなくなることがあります。しかし、チップのおかげで、私はそれが下に行かないようにボールを変更します。 –
編集:何らかの理由でこれは私のMacでのみ発生し、制限されたテスト中に私の窓のラップトップで正常に動作するようです。 –
それは私がそれをテストしていたWindowsラップトップを持っているので、それを説明するでしょう。 –