0

我最近在我的滑雪球风格游戏的编码方面取得了突破。我在碰撞检测方面遇到了严重的问题,stackoverflow 的专家帮助我解决了这些问题。我正在为我的对象(球)编写补间代码,以创建平滑的滚动效果,因为否则我无法让它平滑移动。我终于有一个灵光乍现的时刻,并设法使对象逐渐移动而不是传送,并且能够消除我的补间。没有补间,碰撞检测工作正常。但我还有一些问题。首先,我如何将重力/摩擦力施加到球上,以使其在失去动力时不会在非碰撞(或得分)区域停止?二,我怎样才能让它与边界正确碰撞,从而以适当的速度反转航向?三,稍微不相关但仍然是一个重大挑战,所以我现在要提一下:如果我的碰撞区域(得分目标)垂直对齐,我可以在碰撞检测中设置条件来测试速度以有效地与目标碰撞吗?我如何确定该速度?

好的,这是我当前用于滚动球并击中目标的不稳定代码:

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);
            }
        }
    }


}

有关我的开发的更多背景信息,请查看我之前的问题线程: 如何摆脱已实例化对象的非空 hitTestObject 错误?

谢谢你的帮助,

艾伦


只想添加我的函数来确定球滚动的速度。它不使用我在搜索中发现的键盘或任何其他常规方法来控制移动。数字会动态变化,直到按下鼠标按钮,这就是要使用的值。这是在我的 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 值之前,flash 似乎没有足够快地运行条件语句来接住球。它确实移除了球,但它看起来很难看,因为球在消失之前已经滚回了球道。如何加快条件检查时间?

这是我修改后的代码。指针表示赞赏。

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

我在上面的 long 函数中考虑了一些“效率”措施,但我无法完全理解与预期目标对齐的逻辑,所以我只是把它写成了“速写”。

谢谢大家的帮助,

艾伦

4

1 回答 1

0

为什么不尝试使用 Box2D 来模拟摩擦力和重力呢? http://box2dflash.sourceforge.net/ 您可以在末端建立一个带有坡道的斜坡,并使用该引擎模拟球在该斜坡上的移动。它可能不准确,因为它不适用于 3d 物理,但是,它也会顺利运行,因为您尝试模拟的只有两个物体,一个球和一个 skeeball 机器。

我认为当你想模拟物理时,在大多数情况下,使用 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 回答