1

私は ActionScript 3 をいじっており、ビデオ ゲーム (トップダウン アクション/シューティング) の非常に単純なプロトタイプを構築しようとしていますが、弾丸の処理は当初想像していたよりも少し難しいことに気付きました。

キャラクターとターゲットの間の弾丸のかなり適切な「飛行」を得るために、最終的にはブレゼンハムのライン アルゴリズムの高度に修正されたバージョンを使用して弾丸の飛行経路を決定し、小さな flash.geom を描画するだけになりました。アプリケーションの描画フレーム段階で、その「飛行経路」上の適切な場所に Rectangle オブジェクト。

私は実際の問題に気づいていませんが、これが Flash ゲームで弾丸を処理する最良の方法であるとは想像できません。画面に複数の敵プレイヤーがいて、たくさんの弾丸が飛び交うと(特に自動武器をコーディングすると)、物事が停止する可能性があると思います。

ここで何が欠けていますか?私は実際にはゲーム開発者ではないので、ほとんどのことはその場で「でっち上げ」でしたが、Flash で弾丸を効果的に処理する方法がわかりません。

編集: 要求されたとおり、ここに「私の」ブレゼンハム コードがあります。基本的にインターネット上のどこかからこれをリッピングしたため、引用符で「私の」と言います。アルゴリズムに対する私の変更には、基本的に下部の行が含まれます。元の実装では、プレイヤー キャラクターからターゲットまでのパスを見つけることができましたが、ときどき (これを理解しようとして少し時間を無駄にしましたが、どこにも到達しませんでした)、ターゲットからターゲットへのパスを生成します。プレーヤー。これを「修正」するために、パス配列から最初の X/Y 値をチェックし、それらの値がプレイヤー キャラクターの X/Y 値と一致しない場合は配列を逆にしました。

public function bresenham(fromX:int, fromY:int, toX:int, toY:int, value:int):Array
{
    // store the character's location
    var orig_x:int = fromX;
    var orig_y:int = fromY;

    var error:int;
    var bullet_path:Array = new Array;

    var dx:int = toX - fromX;
    var dy:int = toY - fromY;
    var yi:int = 1;
    if ( dx < dy ) {
        // swap end points
        fromX ^= toX; toX ^= fromX; fromX ^= toX;
        fromY ^= toY; toY ^= fromY; fromY ^= toY;
    }

    if ( dx < 0 ) {
        dx = -dx;
        yi = -yi;
    }
    if ( dy < 0 ) {
        dy = -dy;
        yi = -yi;
    }
    if ( dy > dx ) {
        error = -( dy >> 1 );
        for ( ; toY < fromY; toY++ ) {
            bullet_path.push( { 'x' : toX, 'y': toY } );
            error += dx;
            if ( error > 0 ) {
                toX   += yi;
                error -= dy;
            }
        }
    } else {
        error = -(dx >> 1);
        for ( ; fromX < toX; fromX++ ) {
            bullet_path.push( { 'x' : fromX, 'y': fromY } );
            error += dy;
            if ( error > 0 ) {
                fromY += yi;
                error -= dx;
            }
        }
    }
    // reverse the bullet path if it was generated from target to player.
    if ( bullet_path[0].x != orig_x && bullet_path[0].y != orig_y ) {
        return bullet_path.reverse();
    }
    return bullet_path;
}
4

4 に答える 4

1

(ブレゼンハムの)コードの実装をここに投稿できますか?私の実装がより速いかどうかベンチマークテストを行いたいです:D .. ..

奇妙なことに、実装をAS3.0のネイティブGraphics.drawLine()と比較してベンチマークを実行しました...文字通り5〜10倍高速でした。アンチエイリアス処理もされていますが、ここでのキリスト降誕がその役割を果たしていると思います。

しかし、とにかく-弾丸がある限り...ここでのミサイル(弾丸、ロケット、レーザー...)はゆっくりと動くものではなく、大きくて見栄えも良いはずです(線だけでなく)、MovieClipを使用する、またはアニメーションが不要な場合は、さらに優れたスプライト。それ以外の場所では、Graphics.drawLine()を使用します。

また、線を使用したヒットテスト、および線を描画するポイント(スプライトではない)を見つけるには、その弾丸の範囲を指定します(無限の場合は、Stage.width、Stage.heightなどを使用します)、それでもヒットできる場所。次に、その角度もあります。X軸またはY軸に沿っている場合は、線のポイントを取得するのはかなり簡単です。異なるものについては、Point.polar(range、angle) [liveDocs]を使用して、その弾丸の元の位置を追加します。

ヒットテストは、Point.interpolate() [liveDocs]を使用して実行されます。ポイント1は元の位置/開始ポイントになり、2番目はPoint.polar()から取得したポイントになります。最後に、最後のパラメータは、開始点からの距離(ここではMath.atan2()は必要ありません-この値を弾丸の速度でフレームごとにインクリメントするだけです)を開始点と終了点の間の距離で割ったものでなければなりません(ここでも、Math.atan2(はありません) ) -「範囲」だけ。このPoint.interpolate()は、弾丸の可能な各ターゲットで最終的に使用するポイントを提供します(すべてをループするか、パフォーマンスのために、XとYの距離を確認します)幅と高さ以下)-target.hitTestPoint(interX、interY、true) [liveDocs]

于 2010-11-08T18:39:25.447 に答える
1

より高速な方法を探す前に、まずコードがボトルネックになっていないかどうかを確認してください。

許容できないフレーム/秒が表示されるまで、フレームごとに起動されるオブジェクトの数を増やし続けます。

GameDev.Stackexchange.com もチェックしてください。多くの人がゲーム開発に関する質問に答える資格を持っています。

于 2010-11-08T22:33:53.093 に答える
0

弾丸が各フレームで 1 回移動する距離を決定し、放します。各弾丸がフレームごとに x および y プロパティで移動する距離を知っている場合、再度計算する必要はなく、弾丸はまっすぐに飛びます。弾丸が動くたびに Bresenham の Line Algorithm を使用している場合、多くの作業を行っています。x と y の動きが数値として保存されていることを確認してください。そうしないと、弾丸が本来あるべき場所に到達しません。

于 2010-11-08T20:13:40.510 に答える
0

何をしても、舞台に俳優が多すぎると、パフォーマンスが低下します。個人的には、シンボル インスタンスをムービークリップとして作成し、それらをパスに沿って移動して、ターゲットと接触すると削除することを試みます。(このようにすると、衝突検出も行われます。これは、ターゲットが邪魔にならないように移動できる場合に重要です。衝突が検出された場合、弾丸はその「爆発」シーンなどを再生できます。)

于 2010-11-08T17:13:57.703 に答える