0

我是一名初学者/中级 AS3“程序员”,试图为大学评估完成一个类似 skeeball 的基于 flash 的游戏,我正在给自己造成严重的精神伤害,试图让基本的物体(球)碰撞与得分目标一起工作我的舞台。我正在使用功率棒类型变量来确定球滚动的力,该力被转换为补间,以在我的“车道”上创建平滑的移动并进入得分区域(这是头顶视角)。目标是由游戏表的所有组件组成的较大影片剪辑中的影片剪辑实例。即使在我释放球时我的游戏桌和计分组件已经被实例化,我还是得到了典型的非空错误:

球速为 552

targetArray 值为 [object upperScoringAreaCTarget_mc]

TypeError:错误 #2007:参数 hitTestObject 必须为非空。

在 flash.display::DisplayObject/_hitTest()

在 flash.display::DisplayObject/hitTestObject()

在 SkeeBlast_7_fla::MainTimeline/ballTargetScore()

在 SkeeBlast_7_fla::MainTimeline/rollBall()

在 SkeeBlast_7_fla::MainTimeline/releaseBall()

这是我的球释放功能:

function releaseBall(event:MouseEvent):void
{
    rollBall();
    gameElements.removeEventListener(MouseEvent.MOUSE_MOVE, moveBall);
}

function rollBall():void
{
    ballSpeed = rollPower * 12;
    trace("ballSpeed is " + ballSpeed);
    ballFriction();
    ballGravity();
    //ball.y -= ballSpeed;
    //var myBallTween:Tween = new Tween(ball,"y",Strong.easeOut,ball.y,ball.y -     ballSpeed,3,true);
    myBallTween = new Tween(ball,"y",Strong.easeOut,ball.y,ball.y - ballSpeed,3,true);
    myBallTween.start();
    ballTargetScore();

}

和我的碰撞检测和评分功能:

 //match targets to scoring values which should be tied to determineScore()
function ballTargetScore():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);

if (ball.hitTestObject(gameTable.tableDisplay))
{
    myBallTween.stop();
}
else
{
    for (var i:uint; i < targetArray.length; i++)
    {
        if (targetArray[i] != null)
        {
            trace("targetArray value is " + targetArray[i]);

            if (ball.hitTestObject(gameTable.upperScoringArea.upperScoringAreaCTarget))
            {
                targetValue = gameTable.upperScoringArea.upperScoringAreaC_text.text;
            }
            if (ball.hitTestObject(gameTable.upperScoringArea.upperScoringAreaLtTarget))
            {
                targetValue = gameTable.upperScoringArea.upperScoringAreaLt_text.text;
            }
            if (ball.hitTestObject(gameTable.upperScoringArea.upperScoringAreaRtTarget))
            {
                targetValue = gameTable.upperScoringArea.upperScoringAreaRt_text.text;
            }
            if (ball.hitTestObject(gameTable.upperScoringArea.middleScoringAreaTargetTop))
            {
                targetValue = gameTable.middleScoringArea.middleScoringAreaU_text.text;
            }
            if (ball.hitTestObject(gameTable.upperScoringArea.middleScoringAreaTargetMiddle))
            {
                targetValue = gameTable.middleScoringArea.middleScoringAreaM_text.text;
            }
            if (ball.hitTestObject(gameTable.upperScoringArea.middleScoringAreaTargetLower))
            {
                targetValue = gameTable.middleScoringArea.middleScoringAreaL_text.text;
            }
            if (ball.hitTestObject(gameTable.upperScoringArea.lowerScoringAreaTarget))
            {
                targetValue = gameTable.lowerScoringArea.lowerSA_text.text;
            }
            else
            {
                trace("no hit");
            }
        }
    }
}

//gameElements.removeEventListener(Event.ENTER_FRAME, ballTargetScore);
determineScore(targetValue);
//return targetValue;
}

当我试图找到正确的组合时,这一切仍然有点混乱。

我需要首先让一个基本的球<->目标或边界碰撞正常工作,但最终,我想尝试弄清楚如何有条件地控制碰撞,因为许多目标像 skeeball 表一样垂直对齐。我可以在补间/滚动时测量球的速度吗?我是否能够正确应用重力以使球落下,并且如果它抓住得分目标下方的弧线之一,它将沿着弧线滚动直到它“落入洞中”?我认为我的对象的边界框会出现问题。

谢谢你的帮助,

艾伦


这是对 Vesper 的回复,其中包含已清理的功能(谢谢)和新错误。

function ballTargetScore():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);
}

和错误:

球速为 432

targetArray 值为 [object upperScoringAreaCTarget_mc]

targetArray 值为 [object upperScoringAreaLtTarget_mc]

targetArray 值为 [object upperScoringAreaRtTarget_mc]

targetArray 值为 [object middleScoringAreaTargetTop_mc]

targetArray 值为 [object middleScoringAreaTargetMiddle_mc]

targetArray 值为 [object middleScoringAreaTargetLower_mc]

targetArray 值为 [object lowerScoringAreaTarget_mc]

ArgumentError:错误 #2025:提供的 DisplayObject 必须是调用者的子对象。

在 flash.display::DisplayObjectContainer/removeChild()

在 SkeeBlast_7_fla::MainTimeline/determineScore()

在 SkeeBlast_7_fla::MainTimeline/ballTargetScore()

在 SkeeBlast_7_fla::MainTimeline/rollBall()

在 SkeeBlast_7_fla::MainTimeline/releaseBall()

感谢您的帮助。


我确信这些规则是必要的,这让我把这个问题变成了一个很长的问题。:)

无论如何,我有点弄清楚了有关 DisplayObject 的错误,但程序仍然无法正常工作。

我通过将我的 gameElements MC 添加到确定Score 函数中的 removeChild 调用来修复错误,如下所示;但是,即使错误消失了,球仍然没有被移除,并且 targetValue 和 score 永远不会更新(或显示在上面的跟踪中)。

function determineScore(scoreEvent:String):void
{
    if ( scoreEvent == "D-O" || scoreEvent == "2XB" || scoreEvent == "?")
    {
        if (scoreEvent == "D-O")
        {
            ballCount +=  1;
            gameTable.tableDisplay.BR_text.text = ballCount - 1;
            gameTable.tableDisplay.BR_text.embedFonts = false;
            gameElements.removeChild(ball);
            if (ballCount > 0 )
            {
                initBall();
            }
            else
            {
                drawEnd();
            }
        }
        else if (scoreEvent == "2XB")
        {
            ballCount +=  2;
            gameTable.tableDisplay.BR_text.text = ballCount - 1;
            gameTable.tableDisplay.BR_text.embedFonts = false;
            gameElements.removeChild(ball);
            if (ballCount > 0 )
            {
                initBall();
            }
            else
            {
                drawEnd();
            }
        }
        else
        {
            determineScore(allRandomScore(allScoresArray));
        }
    }
    else
    {
        scoreTotal +=  Number(scoreEvent);
        ballScore = Number(scoreEvent);
        gameTable.tableDisplay.Score_text.text = scoreTotal;
        gameTable.tableDisplay.Score_text.embedFonts = false;
        gameElements.removeChild(ball);
        if (ballCount > 0 )
        {
            initBall();
        }
        else
        {
            drawEnd();
        }
    }
}

谢谢你看这个。我觉得我终于取得了一点进步。


好的,继续进行另一个更新。

gameElements 是我添加所有其他 MC(如游戏桌和球)的主要空 MC,这样当我返回主菜单时,我可以立即删除所有内容。

var gameElements:MovieClip = new MovieClip();
var gameTable:MovieClip = new table_mc();
var ball:MovieClip = new blastBall();

并从我的 drawGame 功能:

...
stage.addChildAt(gameElements, 1);
gameElements.addChild(gameTable);
initBall();
...

和初始化球:

function initBall():void
{
    //resize ball
    ball.height = 18;
    ball.width = 18;
    //place ball on table in correct location
    ball.x = gameTable.x;
    ball.y = gameTable.height - 20;
    gameElements.addChild(ball);
    //reduce number of remaining balls;
    ballCount -=  1;
    //hide the mouse and connect its movement to ball
    Mouse.hide();
    gameElements.addEventListener(MouseEvent.MOUSE_MOVE, moveBall);
}

希望这个条目没有限制。:)

这是我在确定得分中添加的一点点,以从 ballTargetScore 中获取“结果”(或者实际上没有):

if (scoreEvent == null)
    {
        trace("scoreEvent is null");
        gameTable.tableDisplay.BR_text.text = ballCount - 1;
        gameTable.tableDisplay.BR_text.embedFonts = false;
        gameElements.removeChild(ball);
        if (ballCount > 0)
        {
            initBall();
        }
        else
        {
            drawEnd();
        }
    }

(还没有清理其他任何东西)仍然试图让第一次碰撞工作。当我开始捕捉空值时,initBall 和 drawEnd 开始工作(好吧,它仍然没有真正做我想要的,但至少有一个响应)。

4

1 回答 1

0

好吧,你有一个目标数组,你收到的错误意味着它的一些元素是空的。但是,当您遍历数组时,出于某种原因,您会检查整个目标集,而不是检查它们中的任何一个是否为空。我不明白为什么。看到如果检测到命中,您需要分配一个文本变量,我建议您制作另一个具有相应索引的数组,其中包含您要分配的所有文本。

var targetTextArray: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);

然后,当您遍历 targetArray 时,您不再需要检查目标是什么来检索正确的文本。你做:

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() 函数。看起来你正确地添加和移除了你的球,但你可能会这样做两次。将球移出两次而不将其放回原处将使您出现此错误。gameElements.removeChild(ball);目前,如果在该函数中被调用两次,我无法获得。

function determineScore(scoreEvent:String):void
{
    var reBall:Boolean=false; // should we make another ball roll, given the score
    var reDisplay:Boolean=false; // should we set new text
    if ((scoreEvent==null)||(scoreEvent=="")) return; // we haven't scored
    if ( scoreEvent == "D-O" || scoreEvent == "2XB" || scoreEvent == "?")
    {
        if (scoreEvent == "D-O")
        {
            ballCount +=  1;
            reBall=true;
            reDisplay=true;
        } 
        else if (scoreEvent == "2XB")
        {
            ballCount +=  2;
            reBall=true;
            reDisplay=true;
        }
        else
        {
            determineScore(allRandomScore(allScoresArray));
            // hey, what are we doing here? We seemingly receive a "?" as an input,
            // and we roll a random value out of a set given elsewhere. Okay
            return; // as good measure, because we don't have to do anything more
        }
    }
    else
    { // if we're here, we assume we have a numeric score passed inside, right?
        scoreTotal +=  Number(scoreEvent);
        ballScore = Number(scoreEvent);
        reBall=true;
        reDisplay=true;
    }
    // Now look, we always have to launch a new ball or display end, and
    // we always have to redraw score textfield. But look, you are always calling 
    // determineScore with some value, while you should do it only if you hit something!
    // So I added starting clause of "if null or empty string".
    if (reDisplay) {
        // we have to update text
        gameTable.tableDisplay.BR_text.text = ballCount - 1;
        gameTable.tableDisplay.BR_text.embedFonts = false;
    }
    if (reBall) {
        // we have to remove ball and launch another, if we have any left
        gameElements.removeChild(ball);
        if (ballCount > 0 )
        {
            initBall();
        }
        else
        {
            drawEnd();
        }
    }
}
于 2012-09-24T10:10:52.900 回答