2016-09-06 20 views
1

私はゲームデザインの原則を学び、多くのチュートリアルの助けを借りてこのゲームループをJavaで作っています。 、それは十分に動作し、私はそれが着実60 FPSで動作して取得することができシンプルなJava Game LoopでCPU使用率が非常に高い

public class Game extends JPanel implements Runnable { 

String title; 
int height; 
int width; 

boolean ps; 

private int ticks; 
private JPanel p; 
private BufferStrategy bs; 
private Graphics g; 
private boolean running = false; 
private Thread thread; 
private Frame frame; 
private KeyHandler keyHandler; 

public Game(String title, int width, int height){ 
    this.width = width; 
    this.height = height; 
    this.title = title; 
    keyHandler = new KeyHandler(); 
} 

private void init() { 
    TileHandler.init(); 
    frame = new Frame(title, height, width); 
    frame.getFrame().addKeyListener(keyHandler); 
} 

private void tick() { 
    // KeyHandler.tick(); 

    // updates game logic  
} 

private void render() { 
    render(g);  
} 

private void render (Graphics g) { 
    bs = frame.getCanvas().getBufferStrategy(); 
    if(bs == null){ 
     frame.getCanvas().createBufferStrategy(3); 
     return; 
    } 
    g = bs.getDrawGraphics(); 
    g.clearRect(0, 0, width, height); 

    g.drawImage(TileHandler.grass, keyHandler.getPlayerX(), 
    keyHandler.getPlayerY(), null); 

    bs.show(); 
    g.dispose(); 
} 

@Override 
public void run() { 

    int x = 4; 
    init(); 
    int fps = 60; // target 
    double tickTime = 1000000000/fps; // time per 1 frame 
    double delta = 0; 
    long timer = 0; 

    long startTime = System.nanoTime(); 
    long endTime; 

    while (x == 4) { 
     endTime = System.nanoTime(); 
     delta += (endTime - startTime)/tickTime; 
     timer += endTime - startTime; 
     startTime = endTime; 

     if (delta >= 1) { 
      ticks++; 
      render(); 
      delta--; 
     } 
     if(timer >= 1000000000){ 
      ticks = 0; 
      timer = 0; 
     } 
    } 
} 

public int getTicks() { 
    return ticks; 
} 

public synchronized void startThread() { 
    // Start the thread 
    if (!running) {    // if not already 

     running, you can begin 
     running = true; 
     thread = new Thread(this); //Run THIS class on a 

     new thread 
     thread.start(); 
    } 
    else { // safety measure 
     return; 
    } 
} 

public void stopThread() { 
    if (!running) { 
     return; 
    } 
    running = false; 
    try { 
     thread.join(); //Method stops the thread 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

} 

}

唯一の問題は、それが食べるである:それは今ないすべてはJFrameのへの草のタイルをレンダリングしています非常に多くのCPU。平均して約50%のCPUを使用し、残りのコンピュータは減速します.Minecraftはノートパソコンでほぼ同じように使用します。私は、上記のコードで問題がゲームループにあるという事実を知っています。

だから私はこれが起こる原因を理解しようとしています。私はプロファイラを使用しようとしましたが、私はまだ問題を引き起こしていたものを解決できませんでした。

+2

ループは常にrender()を呼び出す必要があるかどうかを調べるために実行されます。これはポーリングと呼ばれ、通常は悪い考えです。タイマーを使用してrender()を呼び出してみてください。 – James

+0

また、JavaFXはハードウェアアクセラレーションを使用しているため、ゲーム開発に適しているため、JavaFXを調べることをお勧めします。また、[AnimationTimer](https://docs.oracle.com/javase/8/javafx/api/javafx/animation/AnimationTimer.html)や[タイムライン](https://docs.oracle.com)のようなクラスもあります。 /javase/8/javafx/api/javafx/animation/Timeline.html)、これはgameloopの管理を非常に簡単にします。 – Jhonny007

答えて

2

最も単純な答えは、[OK]をクリックすると、ループはCPUが処理できるほど速く実行されます。私はあなたが2つのコアを持つCPUを持っていると仮定しているので、メインループスレッドはできるだけ高速にループを実行することができる計算能力のすべてのビットを使用しているので、2つのコア(50%)のうちの1つをブロックしています。

1つの解決策は、次の反復が開始されるまでの時間の間、各反復がどれくらい時間がかかるかを計算することです。ここでは擬似コードです:

while(running) { 
    long startTime = getTime(); 

    update(); 
    render(); 

    long endTime = getTime(); 
    long elapsedTime = endTime - startTime; 
    Thread.sleep(TARGET_FRAME_TIME - elapsedTime); //sleep to yield unneeded CPU usage 
} 

あなたはLWJGLやJOGLのようなOpenGLライブラリを使用していない場合はまた、あなたは、スイングのうち、非常に良好な性能を得ることはありません。私はあなたのゲームが何であるかはわかりませんが、おそらく60fpsはスイングの上限です。

ゲーム用のJavaFXはレンダリングにハードウェアアクセラレーションを使用し、比較的複雑なアプリケーションの場合は120fps +を処理できるため、JavaFXを学ぶことをお勧めします。また、ゲームループ設計のためにTimelineAnimationTimerクラスを提供します。

+0

+1しかし、スイングは時には['newt'](http://jogamp.org/jogl/doc/NEWT-Overview.html)でレンダリングプロセスをブロックします。これはもう起こりません – elect

+0

アドバイスありがとうございます皆私は今何が起こっているのかが以前よりずっと良くなっていることを理解しています。 2Dゲームライブラリのように思えます。 – SlightlyConfused

+0

標準ライブラリのままにしたい場合は、JavaFXを参照してください。サードパーティに行きたくない2Dゲームに最適です。 (私はちょっとファンボイかもしれない) – Jhonny007

関連する問題