我最近在我的skee-ball风格游戏的编码方面取得了突破。我遇到了严重的碰撞检测问题,stackoverflow的boffins帮助我解决了这个问题。我正在编写一个补间作为我的物体,一个球,以创建一个平滑的滚动效果,因为我无法让它顺利移动否则。我终于有了一个尤里卡时刻,并设法让对象逐步移动而不是传送,并且能够消除我的补间。没有补间,碰撞检测工作正常。但我还是有一些问题。首先,我如何将重力/摩擦力施加到球上,这样当它没有蒸汽时,它不会在非碰撞(或划线)区域停止?二,如何使其与边界正确碰撞,以便以适当的速率反转航向?三,略有不相关,但仍然是一个重大挑战所以我现在要提到它:如果我的碰撞区域(得分目标)垂直对齐,我可以在碰撞检测中设置条件来测试速度以有效地与目标碰撞?我怎样才能确定速度?
好的,这是我目前用来滚动球并击中目标的摇摆不定的代码:
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);
}
}
}
}
有关我开发的更多背景信息,请查看我之前的问题主题: How can I get rid of non-null hitTestObject error with already instantiated objects?
感谢您的帮助,
艾伦
只想添加我的功能来确定球滚动的速度。它不使用键盘或任何其他常规,我在搜索中找到,控制运动的方法。数字会动态变化,直到按下鼠标按钮,然后这就是要使用的值。这是在我的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
我在上面的长函数中考虑了一些“效率”度量,但是我无法在排列预期目标时得到正确的逻辑,因此我只是将其写成“longhand”。
感谢大家的帮助,
艾伦
答案 0 :(得分:0)
为什么不尝试使用Box2D来模拟摩擦力和重力? http://box2dflash.sourceforge.net/ 您可以在最后建造一个带斜坡的斜坡,并模拟在该斜坡上使用该发动机移动的球。它可能不准确,因为它不适用于3d物理,但它也会顺利运行,因为你试图模拟的只有两个物体,一个球和一个双球机。
我认为当你想要模拟物理时,在大多数情况下,使用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;
您可能需要降低弹跳,或者在考虑坡度角度的情况下对其进行不同的处理。