我正在用 java 制作一个 2D 游戏。
到目前为止我的代码是这样的:
游戏.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 方法,但是我需要做什么才能获得相同的结果而不重写它?
最佳答案
将你的“游戏循环”分离到它自己的类中,可能实现Runnable
。使用面板和“游戏循环”之间共享的某种模型。 “游戏循环”应该更新模型的状态,并且面板应该绘制它。
如果需要,您可以考虑使用一个允许“游戏循环”通知 UI 它应该自行更新的界面
创建 UI 后,您将构建“游戏循环”类并启动它
- 不要使用
KeyListener
,使用Key bindings - 不要使用
getGraphics
,重写paintComponent
并在那里执行自定义绘制。请参阅Performing Custom Painting更多细节。 Swing 使用被动渲染引擎,这意味着更新可以随时发生,大多数情况下您无需执行任何操作。使用getGraphics
绘制的任何内容都将被绘制,这可能会导致意外且难以复制的闪烁 - 不要处置不是您“创建”的
Graphics
上下文,这可能会阻止将来的更新 - Swing 组件默认是双缓冲的,因此除非您有迫切需要,否则不需要重新发明轮子
关于Java 2D 游戏。除了调用 addnotify 之外,还能做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24965168/