我如何添加重力/摩擦我的球对象,因此它不会停留在没有无人区? [英] How can I add gravity/friction to my ball object so it doesn't get stuck in no-man's-land?

查看:169
本文介绍了我如何添加重力/摩擦我的球对象,因此它不会停留在没有无人区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近对编码为我skee球风格的游戏的一个突破。我在和碰撞检测,该计算器的研究人员都帮助我解决的严重问题。我被编码在补我的对象,一球,以创建平滑滚动效果,因为我一直没能得到它顺利地以其他方式移动。我终于灵光一现,并设法使物体移动增量,而不是意念移物,并能消除我的补间。如果不补间,碰撞检测工作正常。但是我还是有一些问题。首先,我怎么重力/摩擦应用到球,这样它不会停下来在非冲突(或得分)区域时,否则耗尽蒸汽?二,我怎么可以把它与边界相撞正确,因此反转过程中适当的速率?三,稍不相关的但仍然是一个重大的挑战,所以我会现在提到它:如果我的冲击区域(得分目标)垂直排列的,我可以把条件下的碰撞检测,以测试速度的速度,目标是有效地碰撞?如何确定速度的速度?

I've recently had a breakthrough on the coding for my skee-ball style game. I was having serious issues with collision detection, which the boffins of stackoverflow have helped me solve. I was coding a tween for my object, a ball, to create a smooth roll effect because I hadn't been able to get it to move smoothly otherwise. I finally had a eureka moment and managed to make the object move incrementally instead of teleporting and was able to eliminate my tween. Without a tween, collision detection was working properly. But I still have some issues. First, how do I get gravity/friction to apply to the ball so that it doesn't come to a stop in a non-collision (or scoring) area when it otherwise runs out of steam? Two, how can I make it collide properly with the boundaries so it reverses course at a proper rate? And three, slightly unrelated but still a major challenge so I'll mention it now: if my collision areas (scoring targets) are aligned vertically, can I put conditions in the collision detection to test for rate of speed to effectively collide with a target? How can I determine that rate of speed?

好吧,这是我目前的不稳定code滚动我的球击中目标:

Ok, here's my current wobbly code for rolling my ball and hitting a target:

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


}

有关我的发展更多的背景,请看看我的previous问题线程: <一href="http://stackoverflow.com/questions/12560357/as3-how-can-i-get-rid-of-non-null-hittestobject-error-with-already-instantiated/12562887">AS3:我怎样才能摆脱非空hitTestObject误差已经实例化对象?

For more background on my development, please take a look at my previous question thread: AS3: How can I get rid of non-null hitTestObject error with already instantiated objects?

感谢您的帮助,

阿伦

只是想加入我的函数来确定球滚动的速度。它不使用键盘或任何其它常规的,我发现在搜索,方法控制移动。数量是动态变化的,直到鼠标按键时pressed然后就是一起工作的价值。这里面我drawGame函数来创建游戏桌。

Just want to add my function for determining the speed of the ball roll. It doesn't use a keyboard or any other conventional, that I have found in searching, method to control movement. The number changes dynamically until the mouse button is pressed and then that is the value to work with. This is inside my drawGame function to create the game table.

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

和我相关的全局变量列表:

and the list of my related global vars:

//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;


好吧,我已经八九不离十固定它,但它仍然是混乱的视觉。球现在向后移动。我的意思就摆在一个条件下的球,当它到达其重新presents桌上的排水沟阈值将被删除;但是,Flash似乎并没有运行条件语句很快接球之前就已经在视觉上超越了y值。它确实删除了球,但它看起来丑陋的球已经回滚到车道消失之前。我怎样才能获得条件检查时间加快了?


Ok, I've sorta fixed it, but it is still messy visually. The ball will now move backwards. I've meant to put in a condition where the ball will be removed when it reaches a threshold which represents the gutter on the table; however, flash doesn't seem to run the condition statement soon enough to catch the ball before it has moved visually beyond the y value. It does remove the ball, but it looks ugly as the ball has rolled back onto the lane before it disappears. How can I get condition checking times sped up?

下面是我修改code。指针是AP preciated。

Here's my modified code. Pointers are appreciated.

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


好吧,我希望把更新在这里。我基本上是解决我的rollBackwards通过调整Y坐标时序问题。我要么测错了,还是有我的方向在反对的方向我本来是移动的。这主要是现在的工作。


Ok, I wanted to put an update in here. I basically "solved" my rollBackwards timing issues by adjusting the Y coordinate. I either measured wrong, or got my orientation in opposition to the direction I was meant to be moving. It mostly works now.

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工作,但球似乎总是被删除几个像素前的实际碰撞的措施是(?) - 即使考虑到,而不是实际的形状边界框。我也试图把球进入补间它被删除之前,使其消失在pretty的庄园,但似乎从来没有工作。而且我从来没有试图解决转向每个目标下的弧形保险杠进那个球可以滚沿,如果目的是关实际碰撞的对象。这只是投入太辛苦菜篮子。下面是我的code的碰撞测量及补间,以防任何人有任何敏锐的洞察力补充。否则,我是比较满意的最终结果。

What is still a little ugly looking is when/where the ball is removed after making collision with a target. My, perhaps, awkward conditional chain of coordinate calculations largely works from an effectiveness POV, but the ball always seems to be removed several pixels(?) prior to the actual collision being measures - even accounting for bounding boxes as opposed to actual shapes. I also attempted to turn the ball into a tween just before it was removed to make it fade away in a pretty manor, but that never seemed to work. And I never even tried to tackle turning the arc-shaped "bumpers" under each target into actual collision objects that the ball could roll along if the aim was off. That was just put into the "too hard" basket. Below is my code for the collision measuring and the tweening, just in case anyone has any keen insights to add. Otherwise, I'm relatively happy with the end result.

//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

我认为,从长远的功能上述的一些效率的措施,但我不能完全得到的逻辑正确的排队与预期的目标,所以我只是写出来手写。

I considered some "efficiency" measures in the long function above, but I couldn't quite get the logic right in lining up with the intended targets so I just wrote it out "longhand".

感谢大家的帮助,

阿伦

推荐答案

为什么不尝试使用的Box2D模拟摩擦和重力? http://box2dflash.sourceforge.net/ 你可以建立与最终斜坡坡度和模拟移动球上与该引擎的斜率。它可能是不准确的,因为它并不用于三维物理,但是,它也将顺利,因为要尝试模拟什么仅具有两个机构,一个球和一个skeeball机器上运行

Why not try to use Box2D to simulate the friction and gravity? http://box2dflash.sourceforge.net/ You can build a slope with a ramp in the end and simulate the ball moving on that slope with that engine. It may be inaccurate since it isn't meant for 3d physics, however, it will also run smoothly since what you are attempting to simulate has only two bodies, a ball and a skeeball machine.

我认为当你想模拟物理,在大多数情况下,使用Box2DFlashAS3是一个好主意。这也是一个有价值的也有在你的背包对今后的工作。

I think when you want to simulate physics, in most cases, using Box2DFlashAS3 is a good idea. It is also a valuable too have in your satchel for future endeavors.

要简单地回答你的问题,我想你可以创建速度变量,常量摩擦和重力和简单地计算每个回合:

To answer your question simply, I think you could create a variable for speed, a constant for friction and gravity and simply calculate each turn:

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;

您可能需要降低对反弹和或考虑不同的方式处理它的斜率的角度。

You may need to lower the bounce and or treat it differently with consideration to the slope's angle.

这篇关于我如何添加重力/摩擦我的球对象,因此它不会停留在没有无人区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆