2
這裏是我的類,做渲染:爲什麼不調用paintComponent()方法?
Game.java
package poke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import poke.GamePanel;
import poke.graphics.GraphicsHandler;
import poke.player.Player;
import poke.player.PlayerHandler;
import poke.world.WorldHandler;
public class Game extends JFrame implements MouseListener, MouseMotionListener, KeyListener {
private GamePanel gamePanel = new GamePanel();
public static Toolkit toolkit = Toolkit.getDefaultToolkit();
public static final int gameWidth = 1280;
public static final int gameHeight = 720;
public static String version = "Indev v0.1";
private boolean running = false;
private int fps = 60;
private int frameCount = 0;
// GAME INITIALIZATION
public Game() {
super("PokéRealms Client " + version);
JFrame f = new JFrame();
setVisible(true);
running = true;
setSize(new Dimension(gameWidth, gameHeight));
setResizable(false);
setBackground(Color.BLACK);
Image icon = toolkit.getImage("./data/graphics/misc/icon.png");
setIconImage(icon);
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
runGameLoop();
}
// RUN THREAD
public void runGameLoop() {
Thread loop = new Thread() {
public void run() {
gameLoop();
}
};
loop.start();
}
// GAME LOOP
private void gameLoop() {
final double GAME_HERTZ = 30.0;
final double TIME_BETWEEN_UPDATES = 1000000000/GAME_HERTZ;
final int MAX_UPDATES_BEFORE_RENDER = 5;
double lastUpdateTime = System.nanoTime();
double lastRenderTime = System.nanoTime();
final double TARGET_FPS = 60;
final double TARGET_TIME_BETWEEN_RENDERS = 1000000000/TARGET_FPS;
int lastSecondTime = (int) (lastUpdateTime/1000000000);
while (running) {
double now = System.nanoTime();
int updateCount = 0;
while(now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER) {
updateGame();
lastUpdateTime += TIME_BETWEEN_UPDATES;
updateCount++;
}
if (lastUpdateTime - now > TIME_BETWEEN_UPDATES) {
lastUpdateTime = now - TIME_BETWEEN_UPDATES;
}
float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime)/TIME_BETWEEN_UPDATES));
drawGame(interpolation);
lastRenderTime = now;
int thisSecond = (int) (lastUpdateTime/1000000000);
if(thisSecond > lastSecondTime) {
System.out.println("NEW SECOND " + thisSecond + " " + frameCount);
fps = frameCount;
frameCount = 0;
lastSecondTime = thisSecond;
}
while(now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES) {
Thread.yield();
try {
Thread.sleep(1);
} catch(Exception e) {
System.err.println(e);
}
now = System.nanoTime();
}
}
}
// UPDATES AND DRAWS
private void updateGame() {
gamePanel.update();
}
private void drawGame(float interpolation) {
gamePanel.setInterpolation(interpolation);
gamePanel.repaint();
}
// MAIN METHOD
public static void main(String[] args) {
Game game = new Game();
System.out.println("Game initialized.");
}
}
GamePanel.java
package poke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JPanel;
import poke.graphics.GraphicsHandler;
import poke.player.PlayerHandler;
import poke.util.ClockTime;
import poke.world.WorldHandler;
public class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
Image image;
Graphics graphics;
float interpolation;
private int fps = 60;
private int frameCount = 0;
public boolean time = false;
public int lastSecond = 0;
public GamePanel() {
PlayerHandler.addPlayer(0);
WorldHandler.loadTiles();
WorldHandler.loadObjects();
}
public void setInterpolation(float interp) {
interpolation = interp;
}
public void update() {
PlayerHandler.processWalking();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(lastSecond != ClockTime.getSecond()) {
lastSecond = ClockTime.getSecond();
time = !time;
}
GraphicsHandler.drawWorld(g, time);
PlayerHandler.process(g);
image = createImage(getWidth(), getHeight());
graphics = image.getGraphics();
g.drawImage(image, 0, 0, this);
g.setColor(Color.yellow);
g.drawString("FPS: " + fps, 5, 10);
frameCount++;
}
}
我的比賽一直工作正常,但我需要添加報時功能因爲遊戲邏輯會以與圖形相同的速率進行打勾,並且我最終打算添加多人遊戲支持,所以我顯然需要邏輯的固定時間跳動率。我試圖在這裏實現一個循環,但我無法弄清楚爲什麼我的paintComponent()方法沒有被調用。任何幫助表示讚賞。
尚未進入tick函數,您確認'drawGame'正在被調用嗎? – 2012-04-12 01:38:38
是的,我剛纔查了一下,確實是打電話來的。 – taylorthurlow 2012-04-12 02:17:49
你怎麼知道'paintComponent()'沒有被調用 - 可能像'paint()'這樣的更高級方法中的某個東西會覆蓋你在'paintComponent()'中所做的更改?另外,在'drawGame()'中,你可以嘗試通過調用'gamePanel.paintImmediately(0,0,width,height);'來強制重繪,看它是否沒有被正確重繪。 – wattostudios 2012-04-12 03:02:02