7

独自のプリミティブ 2D グラフィック ベースのゲーム エンジンを作成しようとしています。ゲームのコア コンポーネントは、敵にさまざまな発射物を発射することです。作業を続ける前に、このコンポーネントを動作させる必要があります。

私が今持っているものは、開始点(x、y)とターゲット点(x1、x2)を通る線に沿って発射体を動かします。線形関数を利用しますy = mx + b。問題は、発射体の位置をどのように更新するかによって、線の傾きに応じて一貫性のない速度が発生することです。(傾斜が大きいほど、より速く離れていきます)。

私が実行しているゲームループのコア構造は次のとおりです。

    private void executeGameLoop() 
    {

        long nextFrameStart = System.nanoTime();
        while(panel.getRunning()) 
        {
            do 
            {
                panel.update();
                nextFrameStart += FRAME_PERIOD;
            } while(nextFrameStart < System.nanoTime());

            long remaining = nextFrameStart - System.nanoTime();
            panel.repaint();

            if (remaining > 0) 
            {
                try 
                {
                    Thread.sleep(remaining / 1000000);
                } 
                catch(Throwable e) 
                {
                System.out.println(e.getMessage()); 
                }
            }
        }
    }

これは、構造とグラフィックを更新するための単なるメカニズムです。これが呼び出されるたびpanel.updateに、特定の状況下で発射体の位置が更新されます。発射物を更新するメソッドは次のとおりです。

これは、発射物にターゲットがあることを伝え、ラインに関する情報を設定します。

public void setHasTarget(boolean hasTargetIn)
    {
        if(hasTargetIn)
        {
            deltaX = getTargetX() - getX();
            deltaY = getTargetY() - getY();
            slope = deltaY / deltaX;
            intercept = getY();
            System.out.println("y = " + slope + "x + " + intercept); //line the projectile will follow
        }
        hasTarget = hasTargetIn;
    }

この next メソッドは、ラインの次のステップに位置を設定します。(X は速度によって更新され、y は x に依存して更新されます)

public void setNext()
        {
            float temp = (slope) * (getX() + velocity) + intercept;
            System.out.println("Slope: " + (slope) * (getX() + velocity));
            System.out.println("Current: (" + getX() + ", " + getY() + ")");
            System.out.println("Next: (" + (getX() + velocity)  + ", " + (getY() + temp) + ")");
            setX(getX() + velocity);
            setY(temp);
        }

この最後のメソッドsetNext()が呼び出され、メイン ループによって呼び出されます。

public void update()
        {
            if(hasTarget)
                setNext();
        }

私が言ったように、私の現在のコードを考えると、実行すると、線の傾きに応じて一貫性のない速度で画面上を移動する発射物が得られます。発射体が画面上を一定の速度で移動するように、コードを変更できるようにしたいと考えています。よろしくお願いします。

4

1 に答える 1

11

一般に、方向の動きを処理する最良の方法は、三角法を使用することです。発射体には、方向 (ラジアン単位) と速度の 2 つが必要です。

必要な 3 つの三角関数は、sin、cos、arctan です。

X を更新する場合:setX(getX() + (speed * Math.cos(direction)));

Y: を更新する場合:setY(getY() + (speed * Math.sin(direction)));

方向を計算する場合:Math.atan(slope)

directionフィールドとをクラスに追加し、speedそれらを double として宣言する必要があります。

public void setHasTarget(boolean hasTargetIn)
{
    if (hasTargetIn)
    {
        deltaX = getTargetX() - getX();
        deltaY = getTargetY() - getY();
        direction = Math.atan(deltaY / deltaX); // Math.atan2(deltaY, deltaX) does the same thing but checks for deltaX being zero to prevent divide-by-zero exceptions
        speed = 5.0;
    }
    hasTarget = hasTargetIn;
}

public void setNext()
{
    setX(getX() + (speed * Math.cos(direction)));
    setY(getY() + (speed * Math.sin(direction)));
}
于 2013-09-11T04:36:47.367 に答える