Actionscript 碰撞不起作用

发布于 2024-11-05 23:34:43 字数 3166 浏览 4 评论 0原文

我正在制作一款游戏,遇到了一个我一直无法解决的问题。玩家是一艘船,船可以投雷(通过空格键)。我在 init() 中创建了一个 Mine() 数组:

function initGame():void
{
    level = 1;
    player = new Player();
    //Create an enemies array
    enemies = new Array();
    //Create a plane array
    planes = new Array();
    crates = new Array();
    explosions = new Array();
    mines = new Array();
    var tempMine:MovieClip;
    for(var i:Number = 1; i < 4; i++){
        tempMine = new Mine();
        mines.push(tempMine);
        minesTxt.text = String(mines.length);
    }
    gameState = STATE_START_PLAYER;
    rightKeyIsDown = false;
    leftKeyIsDown = false;
    upKeyIsDown = false;
    downKeyIsDown = false;
    trace(gameState);

}

我有一个名为 releaseKey() 的函数来处理键盘事件,并将地雷添加到屏幕上:

function releaseKey(event:KeyboardEvent):void
{
    var thisKey:uint = event.keyCode;
    if (thisKey == Keyboard.RIGHT)
    {
        rightKeyIsDown = false;
    }
    if (thisKey == Keyboard.LEFT)
    {
        leftKeyIsDown = false;
    }
    if (thisKey == Keyboard.UP)
    {
        upKeyIsDown = false;
    }
    if(thisKey == Keyboard.SPACE){
        var tempMine:MovieClip;
        if(mines.length > 0){
        tempMine = new Mine();
        tempMine.y = player.y;
        tempMine.x = player.x;
        addChild(tempMine);
        mines.length--;
        minesTxt.text = String(mines.length);
        }else if(mines.length == 0){
            minesTxt.text = String(0);

        }
    }
}

问题出在我的碰撞检查函数中。我收到 TypeError: Error #2007: Parameter hitTestObject must be non-null。我猜我创建地雷并将其添加到数组的方式有问题,但我看不出问题出在哪里。

function testCollisions():void
{
    var tempEnemy:MovieClip;
    var tempCrate:MovieClip;
    var tempMine:MovieClip;

    enemy:for (var i:int=enemies.length-1; i>=0; i--)
    {
        tempEnemy = enemies[i]; 
        for (var j:int=crates.length-1; j>=0; j--)
        {
            tempCrate = crates[j];
            if (tempEnemy.hitTestObject(tempCrate))
            {
                if (crates[j].parent)
                {
                    crates[j].parent.removeChild(crates[j]);
                }
                break enemy;
            }
            if (tempEnemy.hitTestObject(player))
            {
                if (player.parent)
                {
                    trace("Hit!!!!!!!!!!!!!!!!!!!!");
                    makeExplosion(player.x, player.y);
                    player.parent.removeChild(player);
                }
                break enemy;
            }
            tempMine=mines[i];
            if (tempEnemy.hitTestObject(tempMine))
            {
                if (tempEnemy.parent)
                {
                    trace("BOOM!!!!!!!!!!!!!!!!!!!!");
                    makeExplosion(tempEnemy.x, tempEnemy.y);
                    player.parent.removeChild(tempEnemy);
                }
                break enemy;
            }
            if (player.hitTestObject(tempCrate))
            {
                if (crates[j].parent)
                {
                    crates[j].parent.removeChild(crates[j]);
                }
            }

        }

    }
}

I'm making a game and ran into a problem I've been unable to figure out. The player is a boat, the boat can drop mines (via space key). I've created a Mine() Array in the init():

function initGame():void
{
    level = 1;
    player = new Player();
    //Create an enemies array
    enemies = new Array();
    //Create a plane array
    planes = new Array();
    crates = new Array();
    explosions = new Array();
    mines = new Array();
    var tempMine:MovieClip;
    for(var i:Number = 1; i < 4; i++){
        tempMine = new Mine();
        mines.push(tempMine);
        minesTxt.text = String(mines.length);
    }
    gameState = STATE_START_PLAYER;
    rightKeyIsDown = false;
    leftKeyIsDown = false;
    upKeyIsDown = false;
    downKeyIsDown = false;
    trace(gameState);

}

I have a function called releaseKey() to handle keyboard events and the mines are added to the screen here:

function releaseKey(event:KeyboardEvent):void
{
    var thisKey:uint = event.keyCode;
    if (thisKey == Keyboard.RIGHT)
    {
        rightKeyIsDown = false;
    }
    if (thisKey == Keyboard.LEFT)
    {
        leftKeyIsDown = false;
    }
    if (thisKey == Keyboard.UP)
    {
        upKeyIsDown = false;
    }
    if(thisKey == Keyboard.SPACE){
        var tempMine:MovieClip;
        if(mines.length > 0){
        tempMine = new Mine();
        tempMine.y = player.y;
        tempMine.x = player.x;
        addChild(tempMine);
        mines.length--;
        minesTxt.text = String(mines.length);
        }else if(mines.length == 0){
            minesTxt.text = String(0);

        }
    }
}

The problem comes in my collision checking function. I'm getting a TypeError: Error #2007: Parameter hitTestObject must be non-null. I guess there's a problem in the way I'm creating the mines and adding them to the array but I can't see where the problem is.

function testCollisions():void
{
    var tempEnemy:MovieClip;
    var tempCrate:MovieClip;
    var tempMine:MovieClip;

    enemy:for (var i:int=enemies.length-1; i>=0; i--)
    {
        tempEnemy = enemies[i]; 
        for (var j:int=crates.length-1; j>=0; j--)
        {
            tempCrate = crates[j];
            if (tempEnemy.hitTestObject(tempCrate))
            {
                if (crates[j].parent)
                {
                    crates[j].parent.removeChild(crates[j]);
                }
                break enemy;
            }
            if (tempEnemy.hitTestObject(player))
            {
                if (player.parent)
                {
                    trace("Hit!!!!!!!!!!!!!!!!!!!!");
                    makeExplosion(player.x, player.y);
                    player.parent.removeChild(player);
                }
                break enemy;
            }
            tempMine=mines[i];
            if (tempEnemy.hitTestObject(tempMine))
            {
                if (tempEnemy.parent)
                {
                    trace("BOOM!!!!!!!!!!!!!!!!!!!!");
                    makeExplosion(tempEnemy.x, tempEnemy.y);
                    player.parent.removeChild(tempEnemy);
                }
                break enemy;
            }
            if (player.hitTestObject(tempCrate))
            {
                if (crates[j].parent)
                {
                    crates[j].parent.removeChild(crates[j]);
                }
            }

        }

    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

明媚殇 2024-11-12 23:34:43

只是想在处理也在单独数组中维护的显示对象时提供一些建议。

我可以看到:
- 您正在使用您创建的数组解析对象(板条箱或敌人)。
- 您将它们从各自的显示列表中删除,但不要从数组中删除它们。

您应该制定一种机制,将它们从数组中删除,除非有目的将它们保留在那里。例如,像这样的函数:

function RemoveCrate(index) : void
{
   crates[index].parent.removeChild(crates[index]); /// remove from display list
   crates.splice(index, 1); /// remove reference from the array;
}

我没有像你那样故意检查父级,因为我认为它应该有一个父级,如果没有,我想抛出一个错误,因为这意味着其余部分有问题我的代码。

此外,如果您正在解析数组并删除元素而不破坏删除时的迭代,您还应该像这样递减迭代器:

for(var i:int = 0; i < crates.length; i++)
{
   [....]
   RemoveCrate(i);
   i --;  // not doing this after deletion will skip one element in the next iteration
   [....]
}

拼接数组可能不是最优化的解决方案(链表应该更好),但对于小型数组(十个或多个)甚至数百个)这应该不重要。

最后一件事......不从数组中删除对象将保留它们的引用,这将使垃圾收集器跳过它们

希望它有帮助。

--
米赫内亚

Just want to give a piece of advice for when handling display objects that you also maintain in separate arrays.

I can see that:
- You're parsing the objects (crates or enemies) using the arrays made by you.
- You remove them from their respective display lists, but don't remove them from the arrays.

You should make a mechanism that also remove them from the arrays unless there is a purpose for keeping them there. For example a function like:

function RemoveCrate(index) : void
{
   crates[index].parent.removeChild(crates[index]); /// remove from display list
   crates.splice(index, 1); /// remove reference from the array;
}

And I didn't check for the parent like you did intentionally because I assume it should have a parent and if it doesn't I want to throw an error because it means there is something wrong with the rest of my code.

Also if you are parsing the array and removing elements without breaking the iteration on remove you should also decrement the iterator like this:

for(var i:int = 0; i < crates.length; i++)
{
   [....]
   RemoveCrate(i);
   i --;  // not doing this after deletion will skip one element in the next iteration
   [....]
}

Splicing arrays might not be the most optimized solution (linked list should be the better) but for small arrays (tens, or even hundreds) it shouldn't matter.

One last thing ... not removing the objects from the arrays will keep reference of them, which will make the garbage collector skip them

Hope it helps.

--
Mihnea

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文