0

最近、スキーボール スタイルのゲームのコーディングにブレークスルーがありました。私は衝突検出に深刻な問題を抱えていましたが、stackoverflow のボフィンが解決に役立ちました。オブジェクトであるボールのトゥイーンをコーディングして、滑らかなロール効果を作成していました。そうしないとボールをスムーズに動かすことができなかったからです。私はついにひらめいた瞬間に遭遇し、オブジェクトをテレポートする代わりに段階的に動かすことに成功し、トゥイーンを排除することができました。トゥイーンがなければ、衝突検出は適切に機能していました。しかし、私にはまだいくつかの問題があります。まず、重力/摩擦をボールに適用して、そうでなければ蒸気がなくなったときに非衝突 (または得点) 領域で停止しないようにするにはどうすればよいですか? 2 つ目は、境界と適切に衝突させて、コースを適切な速度で反転させるにはどうすればよいですか? そして3つ、少し関係はありませんが、それでも大きな課題なので、ここで言及します: 衝突領域 (スコアリング ターゲット) が垂直に配置されている場合、衝突検出に条件を設定して、ターゲットと効果的に衝突する速度をテストできますか? その速度をどのように判断できますか?

わかりました、ボールを転がしてターゲットに当てるための私の現在のぐらついたコードは次のとおりです。

function moveBall(event:MouseEvent):void
{
    if (this.mouseX <= 172 + gameTable.tableLane.width)
    {
        ball.x = this.mouseX;
    }
    else
    {
        ball.x = 172 + gameTable.tableLane.width;
    }
    if (this.mouseX < 200)
    {
        ball.x = 200;
    }
    //trace(this.mouseX)
}

function releaseBall(event:MouseEvent):void
{
    //rollBall();
    ballSpeed = rollPower * 10;
    //set minimum roll distance
    if (ballSpeed < 313)
    {
        ballSpeed = 313;
    }
    ballStop = ball.y - ballSpeed;
    gameElements.addEventListener(Event.ENTER_FRAME, rollBall);
    gameElements.addEventListener(Event.ENTER_FRAME, ballTargetScore);
    gameElements.removeEventListener(MouseEvent.MOUSE_MOVE, moveBall);
}



function rollBall(event:Event):void
{
    trace("ballSpeed is " + ballSpeed);
    trace("ballStop is " + ballStop);
    if (ball.y > ballStop)
    {
        ball.y -= 6;
        ball.y += friction;
    }

}



//match targets to scoring values which should be tied to determineScore()
function ballTargetScore(event:Event):void
{
    var targetValue:String;
    var targetArray:Array = new Array(gameTable.upperScoringArea.upperScoringAreaCTarget,
      gameTable.upperScoringArea.upperScoringAreaLtTarget,
      gameTable.upperScoringArea.upperScoringAreaRtTarget,
      gameTable.middleScoringArea.middleScoringAreaTargetTop,
      gameTable.middleScoringArea.middleScoringAreaTargetMiddle,
      gameTable.middleScoringArea.middleScoringAreaTargetLower,
      gameTable.lowerScoringArea.lowerScoringAreaTarget);
    var targetTextArray:Array =  new Array(gameTable.upperScoringArea.upperScoringAreaC_text.text,
        gameTable.upperScoringArea.upperScoringAreaLt_text.text,
        gameTable.upperScoringArea.upperScoringAreaRt_text.text,
        gameTable.middleScoringArea.middleScoringAreaU_text.text,
        gameTable.middleScoringArea.middleScoringAreaM_text.text,
        gameTable.middleScoringArea.middleScoringAreaL_text.text,
        gameTable.lowerScoringArea.lowerSA_text.text);

    for (var i:uint; i < targetArray.length; i++)
    {
        if (targetArray[i] != null)
        {
            trace("targetArray value is " + targetArray[i]);
            if (ball.hitTestObject(targetArray[i]))
            {
                targetValue = targetTextArray[i];
                trace('targetValue becomes',targetValue);
                determineScore(targetValue);
                gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
                gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);
            }
        }
    }


}

私の開発の背景については、私の以前の質問スレッドをご覧ください

助けてくれてありがとう、

アラン


ボールの転がる速度を決定する関数を追加したいだけです。動きを制御するために、検索で見つけたキーボードやその他の従来の方法は使用しません。数値は、マウス ボタンが押されるまで動的に変化し、それが操作する値になります。これは、ゲーム テーブルを作成するための drawGame 関数内にあります。

gameElements.addEventListener(Event.ENTER_FRAME, powerMeter);

function powerMeter(event:Event):void
{
    rollPower +=  speed;
    gameTable.powerMeter.height = rollPower;
    //trace(rollPower);

    if (rollPower == 60 || rollPower == 0)
    {
        speed *=  -1;
        //trace("switch speed to " + speed);
    }
}

および関連するグローバル変数のリスト:

//physics vars
var rollPower:Number = 0;
var speed:Number = 1;//speed of ball on roll
var ballSpeed:Number;
var ballStop:Number;
var friction:Number = 0.15;
var gravity:Number = 0.70;

わかりました、私はそれを修正しましたが、それでも視覚的に乱雑です。ボールは後方に移動します。テーブルのガターを表すしきい値にボールが到達すると、ボールが削除される状態にするつもりでした。ただし、ボールが視覚的に y 値を超えて移動する前に、ボールをキャッチするのに十分な速さでフラッシュが条件ステートメントを実行していないようです。ボールは削除されますが、ボールが消える前にレーンに転がり込んでいるため、見栄えが悪くなります。状態チェックの時間を短縮するにはどうすればよいですか?

これが私の変更されたコードです。ポインタをいただければ幸いです。

function rollBall(event:Event):void
{
    trace("ballSpeed is " + ballSpeed);
    trace("ballStop is " + ballStop);
    if (ball.y > ballStop)
    {
        ball.y -=  6;
        ball.y +=  friction;
    }
    else
    {
        gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
        gameElements.addEventListener(Event.ENTER_FRAME, rollBackwards);
    }

}//end rollBall

function rollBackwards(event:Event):void
{
    trace("rollBackwards is in effect");
    trace("ball.y is " + ball.y);
    if (ball.y < 313)
    {
        ball.y +=  6 + gravity;
        if (ball.y >= 313)
        {
            gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);
            determineScore(null);
        }
    }
}//end rollBackwards

わかりました、ここに更新を入れたかったのです。Y座標を調整することで、基本的にrollBackwardsのタイミングの問題を「解決」しました。測定が間違っていたか、意図した方向とは反対の方向を向いていました。現在はほとんど機能しています。

function rollBackwards(event:Event):void
{
    //trace("rollBackwards is in effect");
    //trace("ball.y is " + ball.y);
    if (ball.y < 240)
    {
        ball.y +=  6 + gravity;
        if (ball.y >= 235)
        {
            gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);
            determineScore(null);
        }
    }
}//end rollBackwards

まだ少し見苦しいのは、ターゲットとの衝突後にボールがいつ/どこで取り除かれるかです。私の、おそらく厄介な座標計算の条件付きチェーンは、主に効果的な POV から機能しますが、実際の衝突が測定される前に、ボールは常に数ピクセル (?) 削除されているように見えます-実際の形状ではなく境界ボックスを考慮しても. また、削除する直前にボールをトゥイーンに変換して、きれいなマナーでフェードアウトさせようとしましたが、うまくいかなかったようです。そして、各ターゲットの下にある円弧状の「バンパー」を実際の衝突オブジェクトに変えて、照準が外れている場合にボールが転がることができるようにしようとさえしませんでした。それは「難しすぎる」バスケットに入れられただけです。以下は、衝突測定とトゥイーンのための私のコードです。誰かが追加する鋭い洞察を持っている場合に備えて。それ以外の場合は、最終結果に比較的満足しています。

//called during determineScore event
function disappearBall():void
{
    myBallTween = new Tween(ball,"alpha",Strong.easeOut,ball.y + 5,ball.y,8,false);
    myBallTween.obj.alpha = 0;
    myBallTween.start();
}//end disappearBall

function ballTargetScore(event:Event):void
{
    var targetValue:String;
    var targetArray:Array = new Array(gameTable.upperScoringArea.upperScoringAreaCTarget,
      gameTable.upperScoringArea.upperScoringAreaLtTarget,
      gameTable.upperScoringArea.upperScoringAreaRtTarget,
      gameTable.middleScoringArea.middleScoringAreaTargetTop,
      gameTable.middleScoringArea.middleScoringAreaTargetMiddle,
      gameTable.middleScoringArea.middleScoringAreaTargetLower,
      gameTable.lowerScoringArea.lowerScoringAreaTarget);
    var targetTextArray:Array =  new Array(gameTable.upperScoringArea.upperScoringAreaC_text.text,
        gameTable.upperScoringArea.upperScoringAreaLt_text.text,
        gameTable.upperScoringArea.upperScoringAreaRt_text.text,
        gameTable.middleScoringArea.middleScoringAreaU_text.text,
        gameTable.middleScoringArea.middleScoringAreaM_text.text,
        gameTable.middleScoringArea.middleScoringAreaL_text.text,
        gameTable.lowerScoringArea.lowerSA_text.text);

    for (var i:uint; i < targetArray.length; i++)
    {
        if (targetArray[i] != null)
        {
            //trace("targetArray value is " + targetArray[i]);
            if (ball.hitTestObject(targetArray[i]))
            {
                //handle vertically aligned targets
                if (centerTargetArray.indexOf(targetArray[i]) >= 0)
                {
                    var centerIndex:uint = centerTargetArray.indexOf(targetArray[i]);
                    //trace("centerTargetArray check works " + centerTargetArray[centerIndex]);
                    if (ballStop <= 60 && ball.hitTestObject(gameTable.upperScoringArea.upperScoringAreaCTarget))
                    {
                        targetValue = targetTextArray[i];
                        //trace('targetValue becomes ' + targetValue);
                        determineScore(targetValue);
                        gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
                        gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);

                    }
                    if (ballStop > 60 && ball.hitTestObject(gameTable.middleScoringArea.middleScoringAreaTargetTop))
                    {
                        targetValue = targetTextArray[i];
                        //trace('targetValue becomes ' + targetValue);
                        determineScore(targetValue);
                        gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
                        gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);

                    }
                    if (ballStop > 100 && ball.hitTestObject(gameTable.middleScoringArea.middleScoringAreaTargetMiddle))
                    {
                        targetValue = targetTextArray[i];
                        //trace('targetValue becomes ' + targetValue);
                        determineScore(targetValue);
                        gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
                        gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);

                    }
                    if (ballStop > 135 && ball.hitTestObject(gameTable.middleScoringArea.middleScoringAreaTargetLower))
                    {
                        targetValue = targetTextArray[i];
                        //trace('targetValue becomes ' + targetValue);
                        determineScore(targetValue);
                        gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
                        gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);

                    }
                    if (ballStop > 161 && ball.hitTestObject(gameTable.lowerScoringArea.lowerScoringAreaTarget))
                    {
                        targetValue = targetTextArray[i];
                        //trace('targetValue becomes ' + targetValue);
                        determineScore(targetValue);
                        gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
                        gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);

                    }
                }
                else
                {
                    targetValue = targetTextArray[i];
                    //trace('targetValue becomes',targetValue);
                    determineScore(targetValue);
                    gameElements.removeEventListener(Event.ENTER_FRAME, rollBall);
                    gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);
                }
            }
        }
    }
}//end ballTargetScore

上記の長い関数でいくつかの「効率」対策を検討しましたが、意図したターゲットに合わせてロジックを正しく理解できなかったため、「手書き」で書きました。

みんな助けてくれてありがとう

アラン

4

1 に答える 1

0

Box2D を使用して、摩擦と重力をシミュレートしてみませんか? http://box2dflash.sourceforge.net/ 最後にスロープのあるスロープを作成し、そのスロープをそのエンジンで移動するボールをシミュレートできます。これは 3D 物理を対象としていないため不正確かもしれませんが、シミュレートしようとしているのはボールとスキーボール マシンの 2 つのボディしかないため、スムーズに実行されます。

物理をシミュレートしたい場合、ほとんどの場合、Box2DFlashAS3 を使用することをお勧めします。また、将来の努力のためにバッグに入れておく価値もあります。

あなたの質問に簡単に答えるために、速度の変数、摩擦と重力の定数を作成し、各ターンを単純に計算できると思います。

ballX += ballSpeedX;
ballY += ballSpeedY;
if(onGround())
{
if(ballSpeedX > friction)
    ballSpeedX -= friction;
else if(ballSpeedX < - friction)
    ballSpeedX += friction;
else ballSpeedX = 0;
}

if(!onGround()) ballSpeedY -= gravity;
else ballSpeedX -= gravity * Math.cos(slopeAngle);

//do something about ballSpeedY when it hits the ground..
if(ballSpeedY < 0 && onGround()) ballSpeedY *= -0.5;

バウンスを下げるか、スロープの角度を考慮して別の方法で処理する必要がある場合があります。

于 2012-09-25T14:40:36.857 に答える