使用多线程创建游戏,但在Java Swing中有背景运动的平滑度有问题
我正在研究一个关于创建游戏的项目。我正在实施线程以移动背景,但是背景运动的平滑性遇到了一些问题。我也有一个鸟类成分,但应该与钥匙夹一起使用。这两个组件都是通过使用paintcomponent()
方法来绘制的。
问题是当我启动游戏时,背景开始移动,但是1-2秒后,它开始滞后,但是当我使用钥匙向右和向左移动鸟的组件时,背景运动再次变得顺利'按任何键,它再次开始落后。我还观察到,当我将鼠标悬停在窗口上时,它也开始顺利移动。我无法意识到这个问题。尝试使用替代品而不是原始词,例如使用标签代替paintcomponent()
和使用计时器
。而不是线程
,但没有任何改变。
我还经常搜索这个问题,并找到了一些选项,例如PC性能等。但是我认为我对此没有问题。有没有办法解决这个问题?事先谢谢!这是代码:
flyingchicken.java
这是调用其他类
import java.io.*;
import java.time.*;
import java.lang.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class FlyingChicken extends JFrame implements ActionListener{
JButton startButton, firstLoginButton, firstRegisterButton, firstQuitButton;
boolean gameStarted = false, gameOver = false, gamePaused = false;
RegisterPage registerPage;
LoginPage loginPage;
GamePage gamePage;
public FlyingChicken(){
//FirstRegisterButton
firstRegisterButton = new JButton("Register Account");
firstRegisterButton.setBounds(360,445,200,50);
firstRegisterButton.setFocusable(false);
firstRegisterButton.addActionListener(this);
firstRegisterButton.setBackground(Color.green);
firstRegisterButton.setForeground(Color.white);
//FirstLoginButton
firstLoginButton = new JButton("Login Account");
firstLoginButton.setBounds(360,520,200,50);
firstLoginButton.setFocusable(false);
firstLoginButton.addActionListener(this);
firstLoginButton.setBackground(Color.green);
firstLoginButton.setForeground(Color.white);
//FirstQuitButton
firstQuitButton = new JButton("Quit the Game");
firstQuitButton.setBounds(385,595,150,50);
firstQuitButton.setFocusable(false);
firstQuitButton.addActionListener(this);
firstQuitButton.setBackground(Color.green);
firstQuitButton.setForeground(Color.white);
//StartButton
startButton = new JButton("Start Game");
startButton.setBounds(360,495,200,50);
startButton.setFocusable(false);
startButton.addActionListener(this);
startButton.setVisible(false);
startButton.setFont(new Font("Arial",Font.BOLD, 20));
loginPage = new LoginPage();
registerPage = new RegisterPage();
gamePage = new GamePage();
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(false);
gamePage.gamePageVisibility(false);
loginPage.backButton.addActionListener(this);
loginPage.loginButton.addActionListener(this);
registerPage.registerButton.addActionListener(this);
registerPage.backButton.addActionListener(this);
gamePage.quitButton.addActionListener(this);
//Frame Settings
Image img = new ImageIcon("Flying_Chicken_Icon.png").getImage();
this.setIconImage(img);
this.setSize(920,1080);
this.setTitle("Flying Chicken");
this.getContentPane().setBackground(new Color(14, 194, 176));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setFocusable(true);
this.setLayout(null);
this.setVisible(true);
this.add(loginPage);this.add(registerPage);
this.add(gamePage);this.add(startButton);
this.add(firstQuitButton);this.add(firstRegisterButton);
this.add(firstLoginButton);
}
public void mainPanel(){
this.getContentPane().setBackground(new Color(14, 194, 176));
firstRegisterButton.setVisible(true);
firstQuitButton.setVisible(true);
firstLoginButton.setVisible(true);
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(false);
loginPage.loginLabel.setVisible(false);
registerPage.label1.setVisible(false);
registerPage.label2.setVisible(false);
registerPage.label3.setVisible(false);
registerPage.label4.setVisible(false);
registerPage.label5.setVisible(false);
}
public void loginPanel(){
loginPage.tpassword.setText("");
loginPage.tusername.setText("");
firstRegisterButton.setVisible(false);
firstQuitButton.setVisible(false);
firstLoginButton.setVisible(false);
loginPage.loginPageVisibility(true);
registerPage.registerPageVisibility(false);
}
public void registerPanel(){
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(true);
registerPage.tpassword.setText("");
registerPage.tusername.setText("");
firstRegisterButton.setVisible(false);
firstQuitButton.setVisible(false);
firstLoginButton.setVisible(false);
}
public void startPage(){
this.getContentPane().setBackground(new Color(128,198,209));
startButton.setVisible(true);
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(false);
}
public void startGame(){
startButton.setVisible(false);
gamePage.gamePageVisibility(true);
// gamePage.timer.start();
gameStarted = true;
}
public void quitFunction(){
String[] resp = {"Resume", "Quit"};
int k = JOptionPane.showOptionDialog(this, "Are you sure you want to quit?","Quit Panel",JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE, null, resp, 0);
if (k==1){
this.setVisible(false);
this.dispose();
}
}
@Override
public void actionPerformed(ActionEvent e){
if(e.getSource() == startButton){
startGame();
}
if(e.getSource() == gamePage.quitButton){
// gamePage.timer.stop();
quitFunction();
}
if(e.getSource() == firstQuitButton){
quitFunction();
}
if(e.getSource() == firstRegisterButton){
registerPanel();
}
if(e.getSource() == firstLoginButton){
loginPanel();
}
if(e.getSource() == registerPage.registerButton){
if(registerPage.registerValidate() == false){
registerPage.registerData();
loginPanel();
}
}
if(e.getSource() == loginPage.loginButton){
if(loginPage.loginValidate() == false)
startPage();
}
if(e.getSource() == loginPage.backButton || e.getSource() == registerPage.backButton){
mainPanel();
}
}
public static void main(String[] args){
FlyingChicken game = new FlyingChicken();
}
}
gamepage.java 的
主要类别,这是我应该创建动画和游戏的
import java.io.*;
import java.time.*;
import java.lang.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class GamePage extends JPanel implements ActionListener, Runnable{
JLabel scoreBoard;
Image backgroundImage, birdImage, catImage;
JButton quitButton;
int birdX, birdY, xpos=0, ypos=0, score = 0;
Timer timer;
Thread animator;
Action leftAction, rightAction;
public GamePage(){
//GamePage Panel Settings
this.setSize(920,1080);
this.setLocation(xpos,ypos);
this.setLayout(null);
this.setFocusable(true);
this.setVisible(true);
backgroundImage = new ImageIcon("background.jpg").getImage();
birdImage = new ImageIcon("bird.png").getImage();
birdX = 264;birdY = 230;
//Scoreboard
scoreBoard = new JLabel("Score: "+ score);
scoreBoard.setOpaque(false);
scoreBoard.setForeground(new Color(33,30,31));
scoreBoard.setFont(new Font("Arial", Font.BOLD, 25));
scoreBoard.setBounds(0,0,200,30);
scoreBoard.setVisible(true);
//QuitButton
quitButton = new JButton("Quit");
quitButton.setBounds(820,0,100,50);
quitButton.setFocusable(false);
quitButton.setVisible(true);
// timer = new Timer(10,this);
createKeyBindings(this);
this.add(quitButton);
this.add(scoreBoard);
}
public void addNotify(){
super.addNotify();
animator = new Thread(this);
animator.start();
}
@Override
public void run(){
while(true){
try{
ypos = ypos-1;
repaint();
Thread.sleep(25);
} catch(InterruptedException e){System.out.println("hey");}
}
}
//The function to draw background
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(backgroundImage, xpos, ypos, null);
g.drawImage(birdImage,birdX,birdY,null);
}
@Override
public void actionPerformed(ActionEvent e){
// scoreBoard.setText("Score: "+score);
repaint();
}
//The function to create keybindings
public void createKeyBindings(JPanel p) {
InputMap im = p.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = p.getActionMap();
leftAction = new LeftAction();
rightAction = new RightAction();
im.put(KeyStroke.getKeyStroke("LEFT"), "left");
im.put(KeyStroke.getKeyStroke("RIGHT"), "right");
am.put("left", leftAction);
am.put("right", rightAction);
}
public class LeftAction extends AbstractAction{
@Override
public void actionPerformed(ActionEvent e){
if(birdX>0)
birdX = birdX-10;
repaint();
}
}
public class RightAction extends AbstractAction{
@Override
public void actionPerformed(ActionEvent e){
if(birdX+530<1080)
birdX = birdX+10;
repaint();
}
}
public void gamePageVisibility(boolean x){
this.setVisible(x);
}
}
类>编辑:我发现我的应用程序滞后的实际原因。该问题主要与Linux OS图形有关,并通过添加toolkit.getDefaultToolkit()。sync()
来解决它。。
I'm working on a project which is about creating a game. I was implementing threads to move my background but had some problems with the smoothness of background movement. I also have a bird component, but it is supposed to be used with keybindings. Both of these components are drawn by using the paintComponent()
method.
The problem is when I start the game, the background starts moving, but after 1-2 seconds, it starts lagging, but when I use keys to move my bird component right and left, the background movement becomes smooth again, and when I don't press any key, it starts lagging again. I also observed that when I hover the mouse over the window, it also starts moving smoothly. I couldn't realize the problem. Tried to use alternatives instead of original ones, like using labels instead of paintComponent()
and using timer
. instead of thread
, but nothing changes.
I also searched about this problem a lot, and found some options like PC performance and so on. But I don't think that I have a problem with that. Is there a way to solve this problem? Thanks beforehand! Here is the code:
FlyingChicken.java
This is the main class to call other classes
import java.io.*;
import java.time.*;
import java.lang.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class FlyingChicken extends JFrame implements ActionListener{
JButton startButton, firstLoginButton, firstRegisterButton, firstQuitButton;
boolean gameStarted = false, gameOver = false, gamePaused = false;
RegisterPage registerPage;
LoginPage loginPage;
GamePage gamePage;
public FlyingChicken(){
//FirstRegisterButton
firstRegisterButton = new JButton("Register Account");
firstRegisterButton.setBounds(360,445,200,50);
firstRegisterButton.setFocusable(false);
firstRegisterButton.addActionListener(this);
firstRegisterButton.setBackground(Color.green);
firstRegisterButton.setForeground(Color.white);
//FirstLoginButton
firstLoginButton = new JButton("Login Account");
firstLoginButton.setBounds(360,520,200,50);
firstLoginButton.setFocusable(false);
firstLoginButton.addActionListener(this);
firstLoginButton.setBackground(Color.green);
firstLoginButton.setForeground(Color.white);
//FirstQuitButton
firstQuitButton = new JButton("Quit the Game");
firstQuitButton.setBounds(385,595,150,50);
firstQuitButton.setFocusable(false);
firstQuitButton.addActionListener(this);
firstQuitButton.setBackground(Color.green);
firstQuitButton.setForeground(Color.white);
//StartButton
startButton = new JButton("Start Game");
startButton.setBounds(360,495,200,50);
startButton.setFocusable(false);
startButton.addActionListener(this);
startButton.setVisible(false);
startButton.setFont(new Font("Arial",Font.BOLD, 20));
loginPage = new LoginPage();
registerPage = new RegisterPage();
gamePage = new GamePage();
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(false);
gamePage.gamePageVisibility(false);
loginPage.backButton.addActionListener(this);
loginPage.loginButton.addActionListener(this);
registerPage.registerButton.addActionListener(this);
registerPage.backButton.addActionListener(this);
gamePage.quitButton.addActionListener(this);
//Frame Settings
Image img = new ImageIcon("Flying_Chicken_Icon.png").getImage();
this.setIconImage(img);
this.setSize(920,1080);
this.setTitle("Flying Chicken");
this.getContentPane().setBackground(new Color(14, 194, 176));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setFocusable(true);
this.setLayout(null);
this.setVisible(true);
this.add(loginPage);this.add(registerPage);
this.add(gamePage);this.add(startButton);
this.add(firstQuitButton);this.add(firstRegisterButton);
this.add(firstLoginButton);
}
public void mainPanel(){
this.getContentPane().setBackground(new Color(14, 194, 176));
firstRegisterButton.setVisible(true);
firstQuitButton.setVisible(true);
firstLoginButton.setVisible(true);
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(false);
loginPage.loginLabel.setVisible(false);
registerPage.label1.setVisible(false);
registerPage.label2.setVisible(false);
registerPage.label3.setVisible(false);
registerPage.label4.setVisible(false);
registerPage.label5.setVisible(false);
}
public void loginPanel(){
loginPage.tpassword.setText("");
loginPage.tusername.setText("");
firstRegisterButton.setVisible(false);
firstQuitButton.setVisible(false);
firstLoginButton.setVisible(false);
loginPage.loginPageVisibility(true);
registerPage.registerPageVisibility(false);
}
public void registerPanel(){
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(true);
registerPage.tpassword.setText("");
registerPage.tusername.setText("");
firstRegisterButton.setVisible(false);
firstQuitButton.setVisible(false);
firstLoginButton.setVisible(false);
}
public void startPage(){
this.getContentPane().setBackground(new Color(128,198,209));
startButton.setVisible(true);
loginPage.loginPageVisibility(false);
registerPage.registerPageVisibility(false);
}
public void startGame(){
startButton.setVisible(false);
gamePage.gamePageVisibility(true);
// gamePage.timer.start();
gameStarted = true;
}
public void quitFunction(){
String[] resp = {"Resume", "Quit"};
int k = JOptionPane.showOptionDialog(this, "Are you sure you want to quit?","Quit Panel",JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE, null, resp, 0);
if (k==1){
this.setVisible(false);
this.dispose();
}
}
@Override
public void actionPerformed(ActionEvent e){
if(e.getSource() == startButton){
startGame();
}
if(e.getSource() == gamePage.quitButton){
// gamePage.timer.stop();
quitFunction();
}
if(e.getSource() == firstQuitButton){
quitFunction();
}
if(e.getSource() == firstRegisterButton){
registerPanel();
}
if(e.getSource() == firstLoginButton){
loginPanel();
}
if(e.getSource() == registerPage.registerButton){
if(registerPage.registerValidate() == false){
registerPage.registerData();
loginPanel();
}
}
if(e.getSource() == loginPage.loginButton){
if(loginPage.loginValidate() == false)
startPage();
}
if(e.getSource() == loginPage.backButton || e.getSource() == registerPage.backButton){
mainPanel();
}
}
public static void main(String[] args){
FlyingChicken game = new FlyingChicken();
}
}
GamePage.java
This is the class that I'm supposed to create animations and game
import java.io.*;
import java.time.*;
import java.lang.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.Timer;
public class GamePage extends JPanel implements ActionListener, Runnable{
JLabel scoreBoard;
Image backgroundImage, birdImage, catImage;
JButton quitButton;
int birdX, birdY, xpos=0, ypos=0, score = 0;
Timer timer;
Thread animator;
Action leftAction, rightAction;
public GamePage(){
//GamePage Panel Settings
this.setSize(920,1080);
this.setLocation(xpos,ypos);
this.setLayout(null);
this.setFocusable(true);
this.setVisible(true);
backgroundImage = new ImageIcon("background.jpg").getImage();
birdImage = new ImageIcon("bird.png").getImage();
birdX = 264;birdY = 230;
//Scoreboard
scoreBoard = new JLabel("Score: "+ score);
scoreBoard.setOpaque(false);
scoreBoard.setForeground(new Color(33,30,31));
scoreBoard.setFont(new Font("Arial", Font.BOLD, 25));
scoreBoard.setBounds(0,0,200,30);
scoreBoard.setVisible(true);
//QuitButton
quitButton = new JButton("Quit");
quitButton.setBounds(820,0,100,50);
quitButton.setFocusable(false);
quitButton.setVisible(true);
// timer = new Timer(10,this);
createKeyBindings(this);
this.add(quitButton);
this.add(scoreBoard);
}
public void addNotify(){
super.addNotify();
animator = new Thread(this);
animator.start();
}
@Override
public void run(){
while(true){
try{
ypos = ypos-1;
repaint();
Thread.sleep(25);
} catch(InterruptedException e){System.out.println("hey");}
}
}
//The function to draw background
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(backgroundImage, xpos, ypos, null);
g.drawImage(birdImage,birdX,birdY,null);
}
@Override
public void actionPerformed(ActionEvent e){
// scoreBoard.setText("Score: "+score);
repaint();
}
//The function to create keybindings
public void createKeyBindings(JPanel p) {
InputMap im = p.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap am = p.getActionMap();
leftAction = new LeftAction();
rightAction = new RightAction();
im.put(KeyStroke.getKeyStroke("LEFT"), "left");
im.put(KeyStroke.getKeyStroke("RIGHT"), "right");
am.put("left", leftAction);
am.put("right", rightAction);
}
public class LeftAction extends AbstractAction{
@Override
public void actionPerformed(ActionEvent e){
if(birdX>0)
birdX = birdX-10;
repaint();
}
}
public class RightAction extends AbstractAction{
@Override
public void actionPerformed(ActionEvent e){
if(birdX+530<1080)
birdX = birdX+10;
repaint();
}
}
public void gamePageVisibility(boolean x){
this.setVisible(x);
}
}
EDIT: I found the actual reason my application was lagging. The problem was mainly related with Linux OS graphics and solved it by adding Toolkit.getDefaultToolkit().sync()
to my loop.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论