1

私はJava 2Dサイドスクローラーを作成していますが、同時に複数のキーに問題があります。右+上など。上を放すたびに、右がまだ押されているにもかかわらず、ゆっくりと地面に戻ると、右の動きが止まります。これが私がセットアップしたキーボードリスナーです。dx は水平方向の移動速度、dy は垂直方向の高さです。以下は文字クラスから

public void keyPressed(KeyEvent e) {
    int key = e.getKeyCode();
    if (key == KeyEvent.VK_LEFT) {
        dx = -5;
        mainCharacterImageFacing = l.getImage();
        }

    if (key == KeyEvent.VK_RIGHT) {
        dx = 5;
        mainCharacterImageFacing = r.getImage();
    } 

    if (key == KeyEvent.VK_UP) {
        dy = 1;
        mainCharacterImageFacing = r.getImage();
    }

}

public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();
    if (key == KeyEvent.VK_LEFT);
    dx = 0;
    if (key == KeyEvent.VK_RIGHT)
        dx = 0;
    if (key == KeyEvent.VK_UP)
        {dy = 0;
        mainCharacterImageFacing = r.getImage();
        }

これは、キーのプレス/リリース メソッドの呼び出しとジャンプの処理を処理するメイン ゲーム ウィンドウのコードです。

private class AL extends KeyAdapter{
    public void keyReleased(KeyEvent e) {
        p.keyReleased(e);
    }

    public void keyPressed(KeyEvent e) {
        p.keyPressed(e);
    }
}

@Override
public void run() 
{
    long beforeTime;
    long timeDiff;
    long sleep;

    beforeTime = System.currentTimeMillis();
    while(done == false)
    {
        cycle();
        timeDiff = System.currentTimeMillis() - beforeTime;
        sleep = 10 - timeDiff;
        if (sleep < 0 )
            sleep = 2;
        try {
            Thread.sleep(sleep);
        } catch (Exception e)
        {}
        beforeTime = System.currentTimeMillis();
    }
    done = false;
    h = false;
    k = false;
}

boolean h = false;
boolean done = false;   
public void cycle() {
    if (h == false)
        v = v - 2; //jump speed falling
    if (v == 350) //max y value of jump.  Lower numbers = higher jumps
        h = true;
    if (h == true && v <= 470) //starting y value
        {
        v = v + 2; //jump speed rising
        if (v == 470)
            done = true;
    }

}
4

2 に答える 2

2

AL クラスで自分の動きを直接処理しないでください。代わりに、ブール値を使用して、それに応じて true/false に設定します。

private class AL extends KeyAdapter{
    public void keyPressed(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_LEFT) {
            left = true;
        }

        if (key == KeyEvent.VK_RIGHT) {
            right = true
        } 

        if (key == KeyEvent.VK_UP) {
            //...
        }

    }

    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();
        if (key == KeyEvent.VK_LEFT)
            left = false
        if (key == KeyEvent.VK_RIGHT)
            right = false
        if (key == KeyEvent.VK_UP)
            //...
        }
    }

これは、keyPressed と keyReleased がキーの操作時に呼び出されるためですが、これはメイン ループと同期しないことを意味します。

スプライトを移動するには、ループ内でメソッドを呼び出します。条件が true の場合、それに応じてスプライトを移動し、そうでない場合は何もしません。

EDIT:あなたのコードをもう少し見直した後、いくつかの提案があります。

まず、サブピクセル レンダリングを調べます。サブピクセル レンダリングは、スプライトの動きをより滑らかに見せるために使用されます。

調べるべきもう 1 つのことは、可変タイムステップです (デルタ タイムステップと呼ばれることもあります)。デルタ時間は、アクションがプレーヤーの fps と同期して実行されるようにするために使用できます。あるプレーヤーが 60fps で、別のプレーヤーが 30fps の場合、30fps のプレーヤーではアクションが半分の速度で実行されます。ただし、デルタ タイムステップでは、アクションは常に同じ速度で実行されます。ここに良い記事があります。

3つ目はタイミングです。現在System.getCurrentTimeMillsを使用しています。これは悪いことであり、正確ではありません。代わりに、System.nanoTimeを使用してください。

私が見つけた 4 番目のことは、ジャンプ アルゴリズムです。より良い方法は、加速を含めることです。最初に、加速度の定数 (0.1 または 0.2 が適切) を宣言し、垂直速度を集計する必要があります。垂直速度が特定の値に達すると、落下することができます。ここに小さなスニペットがありますが、重力がある場合は編集することをお勧めします。まず、vSpeed をデフォルトで -8 に設定します。

public void jump() {
    vSpeed += ACCELERATION;
    if(vSpeed < 8)
        dy += vSpeed;
    else
        vSpeed = -8;
        falling = false;
}

勝手に書いたのですが、基本的には上に移動すると数字が奪われるので、マイナスの数字を足すとジャンプして、0になると落ちて、また8になると着地するように見えます.

于 2013-10-15T15:29:23.703 に答える
0

問題は、OS が重要なイベントを処理してアプリケーションに渡す方法です。キーを押すと、ダウンのイベントが発生します。次に、繰り返しの設定に基づいて、一定の時間が経過すると、一定の頻度でキーを再度押し始めます。(これは入力時に表示されます。キーを押したままにします)。

別のキーを押すと、他のキーの繰り返しトリガーが停止します。これは、入力中にも確認できます。キーを押したままにしてから、別のキーを押し始めます。ご想像のとおり、元のキーが停止します。

これはすべての OS で一貫しているわけではなく、キーボードのリピート タイマーを高速化することで、そのままゲームをごまかす可能性があります。

これらの理由から、主要なリスナー内でアニメーションを行うことは非常に悪い考えです。フラグを true/false に設定し、ゲーム ループでそれらを読み取る必要があります。(@Troubleshootの回答で示されているように)。

于 2013-10-15T15:40:35.310 に答える