游戏窗体:
JFrame 容器加载一个游戏画布实现【add(GamePanel)】
pack()方法表示由JComponent来决定窗体大小
import javax.swing.JFrame;
public class Game {
public static void main(String []args) {
JFrame window = new JFrame("First Game");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.add(new GamePanel());
window.pack();
window.setVisible(true);
}
}
游戏画布:
构造函数中
/*实现GUI event的处理*/
setFocusable(true); 设置GamePanel成为控件焦点
requestFocus(); 请求获取焦点
游戏线程的创建:
addNotify(); 方法在JFrame加载了GamePanel后执行 因为方便开始游戏线程 所以重写了该方法 该方法一定要先执行super.addNotify 父类方法 然后在执行游戏线程等
双缓冲:
private BufferedImage image; // 后备缓冲【back-buffer 是一个与屏幕大小一样的虚拟屏幕】 与屏幕 互相切换 平滑的实现游戏中动态效果
private Graphics2D g; // 游戏画刷 用于把图像画到image中
gameRender(); // 渲染到后备缓冲 【具体细节参照实现】
gameDraw(); // 将后备缓冲绘制到屏幕上 【具体细节参照实现】
计算fps:
一般游戏为30fps
startTime = System.nanoTime(); 获取当前时间【单位纳秒】
URDTime = (System.nanoTime - startTime) / 1000000; 求出 当前循环中的游戏逻辑使用时间【单位微秒】
waitTime = targetTime - URDTimeMillis; 求出fps【单位微秒】
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
public class GamePanel extends JPanel implements Runnable {
private static final int WIDTH = 400;
private static final int HEIGHT = 400;
private Thread thread;
private boolean running;
private BufferedImage image; // game canvas
private Graphics2D g; // game paint brush
private int FPS = 30;
private double averageFPS;
public GamePanel() {
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
}
// FUNCTIONS
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
thread.start();
}
// other game thread stuff
}
private void gameStart() {
running = true;
}
public void run() {
gameStart();
image = new BufferedImage (WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
long startTime;
long URDTimeMillis;
long waitTime;
long totalTime = 0;
int frameCount = 0;
int maxFrameCount = 30;
long targetTime = 1000 / FPS;
// GAME LOOP
while (running) {
startTime = System.nanoTime();
gameUpdate();
gameRender();
gameDraw();
URDTimeMillis = (System.nanoTime() - startTime) / 1000000;
waitTime = targetTime - URDTimeMillis;
try {
Thread.sleep(waitTime);
}
catch (Exception e) { }
totalTime += System.nanoTime() - startTime;
frameCount++;
if (frameCount == maxFrameCount) {
averageFPS = 1000.0 / ((totalTime / frameCount) / 1000000);
frameCount = 0;
totalTime = 0;
}
}
}
private void gameUpdate() {
}
private void gameRender() {
// draw to screen image first
g.setColor(Color.WHITE);
g.fillRect(0, 0, WIDTH, HEIGHT);
g.setColor(Color.BLACK);
g.drawString("FPS: " + averageFPS, WIDTH / 2, HEIGHT / 2);
}
private void gameDraw() {
// draw to game screen image second
Graphics g2 = this.getGraphics();
g2.drawImage(image, 0 , 0, null);
g2.dispose();
}
}