Java 2D游戏。怎么办而不是调用addnotify?

时间:2014-07-25 22:03:20

标签: java graphics2d game-loop

我在java中使用2D游戏。

到目前为止,我的代码是:

Game.java:

package main;

import javax.swing.JFrame;

public class Game {

public static void main(String[] args) {
    JFrame gameWindow = new JFrame("Snake! - By Casida");
    gameWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    gameWindow.add(new GamePanel());
    gameWindow.pack();
    gameWindow.setResizable(false);
    gameWindow.setVisible(true);
}
}

GamePanel.java,这是我覆盖addNotify()的地方。

package main;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

public class GamePanel extends JPanel implements Runnable, KeyListener {

//Dimensions
public static final int WIDTH = 384;
public static final int HEIGHT = 384;
public static final int SCALE = 2;

//Game loop
private Thread thread;
private boolean running = false;
private int FPS = 60;
private long targetTime = 1000 / FPS;

//Image
private BufferedImage image;
private Graphics2D g;

public GamePanel() {
    setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
    setFocusable(true);
    requestFocus();
}

@Override
public void addNotify() {
    super.addNotify();

    if(thread == null) {
        thread = new Thread(this);
        addKeyListener(this);
        thread.start();
    }
}

private void init() {
    running = true;
    image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    g = (Graphics2D) image.getGraphics();
}

@Override
public void run() {
    init();

    long start;
    long elapsed;
    long wait;

    while(running) {

        start = System.nanoTime();

        update();
        draw();
        drawToScreen();

        elapsed = System.nanoTime() - start;
        wait = targetTime - elapsed / 1000000;

        if(wait < 0)
            wait = 5;

        try {
            Thread.sleep(wait);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public void update() {

}

public void draw() {
    g.clearRect(0, 0, WIDTH, HEIGHT);
}

public void drawToScreen() {
    Graphics g2 = getGraphics();
    g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
    g2.dispose();
}

@Override
public void keyPressed(KeyEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void keyTyped(KeyEvent e) {
    // TODO Auto-generated method stub

}
}

我已经看到不鼓励覆盖addNotify方法,但我需要做些什么来获得相同的结果,而不是覆盖它?

1 个答案:

答案 0 :(得分:1)

分开你的游戏循环&#34;进入自己的类,可能实现Runnable。使用面板和游戏循环之间共享的某种模型&#34;。 &#34;游戏循环&#34;应该更新模型的状态,面板应该绘制它。

如果需要,您可以考虑使用一个允许&#34;游戏循环的界面。通知UI它应该自行更新

一旦你创建了UI,你就构建了游戏循环&#34;上课并开始

  • 请勿使用KeyListener,请使用Key bindings
  • 请勿使用getGraphics,覆盖paintComponent并在那里执行自定义绘画。有关详细信息,请参阅Performing Custom Painting。 Swing使用被动渲染引擎,这意味着可以随时进行更新,大多数情况下都不会执行任何操作。使用getGraphics进行绘画的任何内容都将被绘画,这可能会导致意外且难以复制的闪烁
  • 不要处置您没有&#34;创建&#34;的Graphics上下文,这可能会阻止将来的更新发生
  • 默认情况下,Swing组件是双缓冲的,所以除非你迫切需要这样做,否则你不需要重新发明轮子