レンダリングを行う私のクラスは次のとおりです。
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()メソッドが呼び出されない理由がわかりません。どんな助けでも大歓迎です。