java - Pong 游戏运行速度太快,且带有 FPS 计数器

标签 java performance timer frames frame-rate

我有一个带有 FPS 计数器的 Pong 游戏,但遇到了一些问题。我希望 FPS 计数器不限于 60 FPS,我希望 FPS 计数器尽可能高。

FPS 目前可以运行,但问题是游戏运行得非常快,我希望游戏始终以可玩的速度运行。我尝试添加一个 5 毫秒的计时器,但这导致 FPS 计数器无法正常工作。

我希望 FPS 计数器不限于 60 FPS,但同时使用某种计时器。这是我的代码:

package Game;

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class Main extends JPanel implements KeyListener, ActionListener{

// Lite variabler
JFrame frame;
int windowWidth, windowHeight;
Point bollXY;
int screenWidth, screenHeight;
Image bildPaddel;
Image bildBollen;
int paddelY;
int paddel2Y;
boolean paddelUp, paddelDown;
Random rand;
int score, score2;
boolean bollUp, bollRight, changeDirection;
int fruktDistansRand;
long time;
int fps, newfps;
int fpsTimesCounter;

// Konstruktor
public Main(){
    // Definera variabler
    frame = new JFrame();
    bildPaddel = new ImageIcon("src/images/Player.png").getImage();
    bildBollen = new ImageIcon("src/images/Pong.png").getImage();
    bollXY = new Point(673, 352);
    paddelY = 312;
    paddel2Y = 312;
    paddelUp = false;
    rand = new Random();
    score = 0;
    score2 = 0;
    bollUp = false;
    bollRight = false;
    changeDirection = false;
    fruktDistansRand = 0;
    time = System.currentTimeMillis();
    fps = 0;
    newfps = 0;
    fpsTimesCounter = 0;

    // Lyssnare
    frame.addKeyListener(this);

    // Bygga fönstret

    frame.add(this);

    // Obligatoriska egenskaper
    frame.setTitle("Pong");
    frame.setSize(1366, 724); // Eftersom spelet inte ska vara helt i fullskärm sätts fönstret på 1366x724 så att aktivitetsfältet syns
    frame.setVisible(true);
    frame.setLocationRelativeTo(null); // Centrerar fönstret
    frame.setResizable(false);
    this.setBackground(Color.BLACK);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    bollUp = true;
    bollRight = true;
    changeDirection = false;
    bollXY = new Point();

    frame.add(this);
}
// Metoder
public static void main(String[] args) {
    new Main();
}

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.drawImage(bildBollen, bollXY.x, bollXY.y, null);
    g.drawImage(bildPaddel, 50, paddelY, null);
    g.drawImage(bildPaddel, 1300, paddel2Y, null);
    g.setFont(new Font("Arial", Font.BOLD, 100));
    g.setColor(Color.WHITE);
    g.drawString(score2 + "", 1002, 100);
    g.drawString(score + "", 314, 100);

    if(System.currentTimeMillis() - time >= 1000){
        time = System.currentTimeMillis();
        fps = newfps;
        newfps = 0;
    }
    else{
        newfps++;
    }
    g.setFont(new Font("Arial", Font.BOLD, 25));
    g.drawString(fps + "", 5, 22);

    update();
}

public void AI(){

    fruktDistansRand = rand.nextInt(200) + 950;
    if(bollXY.x > fruktDistansRand && bollXY.x < 1380 && bollRight && paddel2Y > 0 && paddel2Y < 596){
        if(paddel2Y + 50 < bollXY.y){
            paddel2Y = paddel2Y + 3;
        }
        else{
            paddel2Y = paddel2Y - 3;
        }
        if(paddel2Y <= 0){
            paddel2Y = paddel2Y + 3;
        }
        if(paddel2Y >= 596){
            paddel2Y = paddel2Y - 3;
        }
    }
}

public void ifUp(){
    if(bollUp){
        if(changeDirection){
            if(bollXY.y < 0){
                bollUp = false;
            }
            else{
                bollXY.y = bollXY.y - 3;
            }
        }
        else{
            if(bollXY.y < 0){
                bollUp = false;
            }
            else{
                bollXY.y = bollXY.y - 3;
            }
        }
    }

    else{
        if(changeDirection){
            if(bollXY.y > 675){
                bollUp = true;
            }
            else{
                bollXY.y = bollXY.y + 3;
            }
        }
        else{
            if(bollXY.y > 675){
                bollUp = true;
            }
            else{
                bollXY.y = bollXY.y + 3;
            }
        }
    }
}

public void update(){
    if(paddelUp){
        if(paddelY > 0){
            paddelY = paddelY - 3;
        }
    }
    if(paddelDown){
        if(paddelY < 596){
            paddelY = paddelY + 3;
        }
    }

    if(bollRight){

        if(bollXY.x > 1290 && bollXY.x < 1300 && bollXY.y < paddel2Y + 100 && bollXY.y > paddel2Y-20){

            if(!bollUp && bollXY.y < paddel2Y){
                changeDirection = true;
                bollUp = true;
            }
            else if(bollUp && bollXY.y > paddel2Y + 80){
                changeDirection = true;
                bollUp = false;
            }

            bollRight = false;
        }
        else if(bollXY.x > 1600){
            score++;
            bollXY.y = rand.nextInt(690);
            bollXY.x = 678;
        }
        else
            bollXY.x = bollXY.x + 3;

        ifUp();
    }
    else{
        if(bollXY.x > 50 && bollXY.x < 60 &&bollXY.y < paddelY + 100 && bollXY.y > paddelY-20){
            if(!bollUp && bollXY.y < paddelY){
                changeDirection = true;
                bollUp = true;
            }
            else if(bollUp && bollXY.y > paddelY + 80){
                changeDirection = true;
                bollUp = false;
            }
            bollRight = true;
        }
        else if(bollXY.x < -244){
            score2++;
            bollXY.x = 678;
            bollXY.y = rand.nextInt(596);
        }
        else
            bollXY.x = bollXY.x - 3;

        ifUp();
    }
    AI();
    repaint();
}

@Override
public void actionPerformed(ActionEvent e) {
    update();
}

@Override
public void keyPressed(KeyEvent e) {
    if(e.getKeyCode() == KeyEvent.VK_W || e.getKeyCode() == KeyEvent.VK_UP){
        paddelUp = true;
    }
    if(e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_DOWN){
        paddelDown = true;
    }
}

@Override
public void keyReleased(KeyEvent e) {
    if(e.getKeyCode() == KeyEvent.VK_W || e.getKeyCode() == KeyEvent.VK_UP){
        paddelUp = false;
    }
    if(e.getKeyCode() == KeyEvent.VK_S || e.getKeyCode() == KeyEvent.VK_DOWN){
        paddelDown = false;
    }
}

@Override
public void keyTyped(KeyEvent e) {

}
}

最佳答案

您的游戏运行得非常快,因为您在每个 CPU 周期中使用静态增量。如果您在较慢的 CPU 上运行此程序,您的游戏运行速度将会变慢。如果您使用快速 CPU 运行它,您的游戏将会运行得更快。

CPU 1:每秒 100 个周期:你的球每秒移动 300 个单位。

CPU 2:每秒 2000 个周期:你的球每秒移动 6000 个单位。

当您将游戏速度限制在 60 fps 时,您就避免了这个问题,因为每秒只会更新 60 次,而不是 100 或 2000 次。

另一种选择是涉及时间。 这意味着您测量自上一帧以来的时间并将其用作乘法器。你的CPU运行得越快,帧之间的时间就越短。你的球会根据你的时间移动。如果你的CPU速度较慢,帧之间的时间就会增加,球就会移动得更远。

float delta = // time between your frames
pulic void update(float delta){
...
bollXY.y -= delta * 3;

或者是一篇关于游戏循环的好文章:https://gafferongames.com/post/fix_your_timestep/

关于java - Pong 游戏运行速度太快,且带有 FPS 计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46777619/

相关文章:

java - 十进制转二进制代码

java - Spring-Hibernate : Insertion error, not-null 约束(一对多关系)

python - Speedwise,Pharo 与 Python3 相比如何?

不影响其他操作的MySql查询

objective-c - Objective-C : Sending arguments to a method called by a UIButton

c - 微 Controller 计数器溢出和计数

java - Spring MVC Bean 转换

java-如何设置向表插入记录时的回滚功能?

java - 推荐在 Web 应用程序中使用哪些外部 Java Api

mysql - 动态 MySql 查询每天返回 X 次结果