在這個答案中,我沒有找到你的櫃檯問題的原因。對我來說相當複雜。不過,我會給你一些代碼,以幫助入門:
這是一個FPS計數器代碼:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Timer;
public class FPSCounter implements ActionListener {
private final Timer resetTimer;
private int current, last;
public FPSCounter() {
resetTimer = new Timer(1000, this);
}
public synchronized void start() {
resetTimer.start();
current = 0;
last = -1;
}
public synchronized void stop() {
resetTimer.stop();
current = -1;
}
public synchronized void frame() {
++current;
}
@Override
public synchronized void actionPerformed(final ActionEvent e) {
last = current;
current = 0;
}
public synchronized int get() {
return last;
}
public static void main(final String[] args) {
final FPSCounter cnt = new FPSCounter();
cnt.start();
new Timer(2000, e -> { System.out.println(cnt.get()); }).start();
while (true)
cnt.frame();
// cnt.stop();
}
}
計數器作品(每2秒,其打印數量的主要方法測試每秒空循環)。
您可以使用它像這樣:
- 在你的遊戲類添加
private FPSCounter fpscnt;
。
- 構建遊戲構造函數中的對象,如下所示:
fpscnt = new FPSCounter();
。
- 通過調用
fpscnt.start();
在遊戲開始前啓動計數器。例如,你可以在遊戲的構造函數中調用它。
- 現在,每當畫一幅畫框時,您應該調用計數器的
frame()
方法。我現在正在演示...
- 現在,只要你想得到每秒幀數,你應該調用計數器的方法
get()
。我展示了未來...
所以,現在,你的遊戲paintComponent()
方法中,打印的幀數的行/秒應該是這樣的:
fpscnt.frame(); //Because this is a new frame paint operation.
g.setFont(new Font("Arial", Font.BOLD, 25));
g.drawString("" + fpscnt.get(), 5, 22); //Paint the FPS.
注:
get()
方法返回的每個值延遲1秒。我的意思是如果你看到64幀/秒,那麼在64幀的最後(過去)秒。
那麼你的遊戲Main
類應該再是這樣的:
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class Main extends JPanel implements KeyListener, ActionListener{
public static class FPSCounter implements ActionListener {
private final Timer resetTimer;
private int current, last;
public FPSCounter() {
resetTimer = new Timer(1000, this);
}
public synchronized void start() {
resetTimer.start();
current = 0;
last = -1;
}
public synchronized void stop() {
resetTimer.stop();
current = -1;
}
public synchronized void frame() {
++current;
}
@Override
public synchronized void actionPerformed(final ActionEvent e) {
last = current;
current = 0;
}
public synchronized int get() {
return last;
}
}
// Variabler
JFrame frame;
int windowWidth, windowHeight;
Point ballXY;
int screenWidth, screenHeight;
Timer timer;
Image imagePaddle;
Image imageBall;
int paddleY;
int paddle2Y;
boolean paddelUp, paddelDown;
Random rand;
int score, score2;
boolean ballUp, ballRight, changeDirection;
boolean paused;
int DistanceRand;
long time;
int fps, newfps;
private final FPSCounter fpscnt; //added line (step 1).
// Konstruktor
public Main(){
// Definera variabler
frame = new JFrame();
imagePaddle = new ImageIcon("src/images/Player.png").getImage();
imageBall = new ImageIcon("src/images/Pong.png").getImage();
ballXY = new Point(673, 352);
paddleY = 312;
paddle2Y = 312;
paddelUp = false;
rand = new Random();
score = 0;
score2 = 0;
ballUp = false;
ballRight = false;
changeDirection = false;
paused = false;
DistanceRand = 0;
time = System.currentTimeMillis();
fps = 0;
newfps = 0;
// Lyssnare
frame.addKeyListener(this);
// Bygga fönstret
frame.add(this);
// Obligatoriska egenskaper
frame.setTitle("Pong");
frame.setSize(1366, 724);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
this.setBackground(Color.BLACK);
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
ballUp = true;
ballRight = true;
changeDirection = false;
ballXY = new Point();
frame.add(this);
timer = new Timer(5, this);
timer.start();
fpscnt = new FPSCounter(); //added line (step 2).
fpscnt.start(); //added line (step 3).
}
// Metoder
public static void main(String[] args) {
new Main();
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(imageBall, ballXY.x, ballXY.y, null);
g.drawImage(imagePaddle, 50, paddleY, null);
g.drawImage(imagePaddle, 1300, paddle2Y, null);
g.setFont(new Font("Arial", Font.BOLD, 100));
g.setColor(Color.WHITE);
g.drawString(score2 + "", 1002, 100);
g.drawString(score + "", 314, 100);
if(paused){
g.setFont(new Font("Arial", Font.BOLD, 80));
g.drawString("PAUSED", 510, 370);
timer.stop();
}
if(System.currentTimeMillis() - time >= 1000){
time = System.currentTimeMillis();
fps = newfps;
newfps = 0;
}
else{
newfps++;
}
fpscnt.frame(); //added line (step 4).
g.setFont(new Font("Arial", Font.BOLD, 25));
g.drawString("" + fpscnt.get(), 5, 22); //added line (step 5).
}
public void AI(){
DistanceRand = rand.nextInt(200) + 960;
if(ballXY.x > DistanceRand && ballXY.x < 1380 && ballRight && paddle2Y > 0 && paddle2Y < 596){
if(paddle2Y + 50 < ballXY.y){
paddle2Y = paddle2Y + 3;
}
else{
paddle2Y = paddle2Y - 3;
}
if(paddle2Y <= 0){
paddle2Y = paddle2Y + 3;
}
if(paddle2Y >= 596){
paddle2Y = paddle2Y - 3;
}
}
}
public void ifUp(){
if(ballUp){
if(changeDirection){
if(ballXY.y < 0){
ballUp = false;
}
else{
ballXY.y = ballXY.y - 3;
}
}
else{
if(ballXY.y < 0){
ballUp = false;
}
else{
ballXY.y = ballXY.y - 3;
}
}
}
else{
if(changeDirection){
if(ballXY.y > 675){
ballUp = true;
}
else{
ballXY.y = ballXY.y + 3;
}
}
else{
if(ballXY.y > 675){
ballUp = true;
}
else{
ballXY.y = ballXY.y + 3;
}
}
}
}
public void update(){
if(paddelUp){
if(paddleY > 0){
paddleY = paddleY - 3;
}
}
if(paddelDown){
if(paddleY < 596){
paddleY = paddleY + 3;
}
}
if(ballRight){
if(ballXY.x > 1290 && ballXY.x < 1300 && ballXY.y < paddle2Y + 100 && ballXY.y > paddle2Y-20){
if(!ballUp && ballXY.y < paddle2Y){
changeDirection = true;
ballUp = true;
}
else if(ballUp && ballXY.y > paddle2Y + 80){
changeDirection = true;
ballUp = false;
}
ballRight = false;
}
else if(ballXY.x > 1600){
score++;
ballXY.y = rand.nextInt(690);
ballXY.x = 678;
}
else
ballXY.x = ballXY.x + 3;
ifUp();
}
else{
if(ballXY.x > 50 && ballXY.x < 60 &&ballXY.y < paddleY + 100 && ballXY.y > paddleY-20){
if(!ballUp && ballXY.y < paddleY){
changeDirection = true;
ballUp = true;
}
else if(ballUp && ballXY.y > paddleY + 80){
changeDirection = true;
ballUp = false;
}
ballRight = true;
}
else if(ballXY.x < -244){
score2++;
ballXY.x = 678;
ballXY.y = rand.nextInt(596);
}
else
ballXY.x = ballXY.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;
}
if(e.getKeyCode() == KeyEvent.VK_SPACE){
if(paused){
paused = false;
timer.start();
}
else{
paused = 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) {
}
}
非常感謝你的回覆,它幫助了很多。事情是,我在遊戲中有一個計時器,它不會讓遊戲運行速度超過5毫秒,現在遊戲忽略了那個計時器並且運行速度非常快。我怎樣才能讓遊戲運行得更慢而不影響fps? –
@ J.Doe可能會在遊戲代碼中使用[Thread.sleep](https://docs.oracle.com/javase/9/docs/api/java/lang/Thread.html#sleep-long-)? (不是繪畫代碼) – thanopi57
好吧,除了在屏幕上顯示FPS之外,現在一切正在運行。我試着用g.drawString等方法輸入你的建議,但它沒有奏效。每秒幀數應該每秒出現在屏幕上。我應該在哪5個步驟中放置你建議的代碼? –