3

私はEclipseを使用してJavaでパックマンのクローンを作成していますが、パックマン/ゴーストの動きが遅く、場合によってはうまくいくことがあります。実行中に発生したため、コードを追加した後ではなく、ゲーム内の特定のイベントの後ではないようです。トリガーが見つからないか、意図的にラグを生成できません

リソースマネージャーは、同じCPU使用率(約50%のみ)/メモリ使用率を示します。また、FPSは、ラグを介して、またそれがうまく機能している期間中、一貫して約200であるように見えます。

誰かがこれが何であるか知っていますか?

省略した情報で役立つ情報はありますか?

編集-私はタイマーに基づいて動きますそれは悪いですか?以下にムーブメント関連のコードを投稿します。ここにコード全体を投稿する良い方法はありますか?

Timer movement = new Timer(20, new ActionListener()//500 is time in milliseconds between
      //calls to actionPerformed as far as I know.
    {
        public void actionPerformed(ActionEvent arg0) 
        {
            if(movingUp == true)
            {
                moveUp();
            }
            else if(movingDown == true)
            {
                moveDown();
            }
            else if(movingRight == true)
            {
                moveRight();
            }
            else if(movingLeft == true)
            {
                moveLeft();
            }

        }

    });


public void moveUp()
    {
        yPos -= 1;
        this.rect.y -= 1;
    }

public void setDirUp()
    {
        movingUp = true;
        movingDown = false;
        movingRight = false;
        movingLeft = false;
    }

public void keyPressedのメインクラスで:

if(keyCode == KeyEvent.VK_W)
        {
            if(pacMan.isUpHittingWall == false)
            {
                pacMan.setDirUp();

                pacMan.isDownHittingWall = false;
                pacMan.isRightHittingWall = false;
                pacMan.isLeftHittingWall = false;
            }

        }

編集2-助けてくれてありがとう。現在、システムタイムを使用したムーブメントがありますが、最初はpacmanにのみ実装し、ゴーストはまだ遅いため、問題は修正されたようです。今、右と下への移動が左または上への移動よりもはるかに遅いという問題があります。私が見る唯一の違いは、右と下の両方が加算であり、左と上が減算であるということです。これについて私は何ができますか?

更新されたコードは以下のとおりです。

//updated movement code
public void moveUp(long timePassed)
    {
        yPos -= vy * timePassed;
        this.rect.y -= vy * timePassed;
    }

    public void moveDown(long timePassed)
    {
        yPos += vy * timePassed;
        this.rect.y += vy * timePassed;
    }

    public void moveRight(long timePassed)
    {
        xPos += vx * timePassed;
        this.rect.x += vx * timePassed;
    }

    public void moveLeft(long timePassed)
    {
        xPos -= vx * timePassed;
        this.rect.x -= vx * timePassed;
    }


//I passed timePassed through a globalInputObject because my input is handled in public //void keyPressed(KeyEvent e) and I didnt know how else to get timePassed in to the //movement method

//Here is the code in gameLoop()
                 globalInputObject.isPacManMovingUp(timePassed);
             globalInputObject.isPacManMovingDown(timePassed);
             globalInputObject.isPacManMovingRight(timePassed);
         globalInputObject.isPacManMovingLeft(timePassed);




//This is inside the GlobalInputObject
public void isPacManMovingUp(long timePassed)
    {
        if(pacMan.movingUp == true)
        {
            pacMan.moveUp(timePassed);
        }
    }

    public void isPacManMovingDown(long timePassed)
    {
        if(pacMan.movingDown == true)
        {
            pacMan.moveDown(timePassed);
        }
    }

    public void isPacManMovingRight(long timePassed)
    {
        if(pacMan.movingRight == true)
        {
            pacMan.moveRight(timePassed);
        }
    }

    public void isPacManMovingLeft(long timePassed)
    {
        if(pacMan.movingLeft == true)
        {
            pacMan.moveLeft(timePassed);
        }
    }
4

3 に答える 3

2

私が恐れていたように、タイマーからの時間チャンクに基づいて移動距離を計算しています。特に小さな時間チャンクでは、すべてのタイマーが可変で信頼できない可能性があるため、これを行うべきではありません。システム時間の違いに基づいて移動することをお勧めします。はい、タイマーなどを使用して「ゲームループ」を実行しますが、スプライトの位置と速度を double を使用して把握し、速度ベクトル (Java ベクトルではなく数学ベクトル) * システム時間の差に基づいて移動距離を計算します。そうすれば、たとえばガベージ コレクションによってタイマーが遅延し、時間のチャンクが大きくなると、移動距離がそれに応じて大きくなり、より滑らかに見えます。

于 2011-09-30T12:08:31.967 に答える
2

タイマーが実行されるたびに常にパックマンを一定の距離 (1 ピクセル、表示されます) だけ移動するのではなく、次のことを行う必要があります。

  1. タイマーをできるだけ速く実行するように設定します (たとえば、ミリ秒ごとに 1 回以下)。編集:設定が速すぎると、ゲームの実行が実際には遅くなる可能性があるため、実験する必要があります。
  2. システム クロックを使用して各フレーム間の経過時間を計算し、それに比例して pacman を移動します。

上記を実行すると、システムが「遅延」している場合、実際にすべてが遅くなるのではなく、1 秒あたりのフレーム数が少なくなるだけです。

于 2011-09-29T20:07:29.763 に答える
1

適切な「メイン ループ」または「ゲーム ループ」と呼ばれるものを作成することを検討する必要があります。このウィキペディアの記事のゲーム構造の部分を見てください。. 基本的に、これらの入力イベントは、メイン スレッドとは別のスレッドから発生\呼び出しされ、ゲーム オブジェクト内のジオメトリを直接変更しています。代わりに、メイン ループに対して次のようなものを検討してください。

loop:
    process collision detection
    process animation (alters geometry of game objects)
    process input (more on this later)
    any other game specific logic
    render screen

プロセス入力は次のようになります

if (globalInputObject.movingUp==true) {
   hero.y -= 10;
}
if (globalInputObject.movingDown==true) {
   hero.y += 10;
}
if (globalInputObject.movingLeft==true) {
   hero.x -= 10;
}
if (globalInputObject.movingRight==true) {
   hero.x += 10;
}

入力ハンドラは次のようになります。

public void actionPerformed(ActionEvent evt) {
    if (evt.button==UP_BUTTON) {
        globalInputObject.movingUp=true;
    }
    if (evt.button==DOWN_BUTTON) {
        globalInputObject.movingDown=true;
    }
    if (evt.button==LEFT_BUTTON) {
        globalInputObject.movingLeft=true;
    }
    if (evt.button==RIGHT_BUTTON) {
        globalInputObject.movingRight=true;
    }

}

基本的に、「余分な」スレッド (入力スレッド) で行っている処理は最小限であるため、メイン スレッドに干渉しません。また、この方法には、複数の方向を同時に簡単にサポートできるという利点があります (つまり、上 + 右 = 斜め)。

超ハイエンドのゲームだけが複数のスレッドを持っています (たとえ必要であったとしても)。ゲームで同期を処理すると、パフォーマンスが低下します。

于 2011-09-29T22:16:06.410 に答える