首页 > 解决方案 > 谁能帮我解决这个项目中的错误参数 hitTestObject 必须为非空?

问题描述

我对 as3 有点陌生,我正在尝试为我的教育制作简单的射击游戏。首先,我知道还有其他类似的问题,但我不知道我的问题是什么!因此,如果有人可以提供帮助,我会很高兴:)) 提前谢谢

当我点击大按钮时,我的船左右移动并发射子弹。敌舰(dusman/dusmanlar)也下降了。所以问题是我无法弄清楚一些子弹(mermi / mermiler)击中并用那颗子弹本身摧毁了一些敌舰,但大多数时候子弹只是穿过敌舰而没有任何反应。当然 animate 给出了错误 Parameter hitTestObject must be non-null on this project!

我在这里做错了什么?

var mermiler: Array = new Array(); //mermiler means bullets
var dusmanlar: Array = new Array(); // dusmanlar means enemy ships
var game_speed: int = 20;
var game_timer: int = 0;
var oyunHiz: int = 8; //bullet speed
var skor: Number = 0;

btn.addEventListener(MouseEvent.CLICK, ates);

function ates(event: MouseEvent): void {
    //whenever the mouse is pressed add the Bullet from the library to the screen
    var mermi: Mermi = new Mermi();
    mermi.x = gemi.x;
    mermi.y = gemi.y - (gemi.height / 2);
    addChild(mermi);
    //add it to the bullet array so we can loop through to move and hit test
    mermiler.push(mermi);

}

addEventListener(Event.ENTER_FRAME, basla);

function basla(event: Event): void {

    game_timer++;
    if (game_timer >= game_speed) {
        var dusman: Dusman = new Dusman();
        dusman.x = Math.random() * 640 + 10;
        dusman.y = Math.random() * 100 - 120;
        dusman.xspeed = (Math.random() * 15) - 10;
        dusman.yspeed = (Math.random() * 5) + 10;
        addChild(dusman);
        dusmanlar.push(dusman);
        game_timer = 0;
    }

    yaz.text = String(skor);
    gemi.x = mouseX;
    gemi.y = 750;

    //move all enemy ships down the screen
    for (i = 0; i < dusmanlar.length; i++) {
        //move enemy ships
        dusmanlar[i].y += dusmanlar[i].yspeed;
        dusmanlar[i].x += dusmanlar[i].xspeed;
        //bounce off sides
        if (dusmanlar[i].x >= 640 || dusmanlar[i].x <= 0) {
            dusmanlar[i].xspeed = -dusmanlar[i].xspeed;
        }
        //if reach bottom remove ship
        if (dusmanlar[i].y >= 860) {
            removeChild(dusmanlar[i]);
            dusmanlar[i] = null;
            dusmanlar.splice(i, 1);
            break;
        }
    }

    //move all the bullets on the screen up 
    for (var i: int = 0; i < mermiler.length; i++) {
        //move bullets
        mermiler[i].y -= 20;
        //if bullets got of screen
        if (mermiler[i].y <= 0) {
            removeChild(mermiler[i]);
            mermiler[i] = null;
            mermiler.splice(i, 1);
            break;
        }
    }

    //test if any bullets have hit any ships
    for (var j: int = 0; j < dusmanlar.length; j++) {
        if (mermiler != null && dusmanlar[j].hitTestObject(mermiler[i])) {
            if (mermiler.length != 0 && dusmanlar[j] != null && mermiler[i].hitTestObject(dusmanlar[j])) {
                removeChild(dusmanlar[j]);
                dusmanlar[j] = null;
                dusmanlar.splice(j, 1);

                removeChild(mermiler[i]);
                mermiler[i] = null;
                mermiler.splice(i, 1);
                skor++
                break;
            }

        }
    }
}

标签: arraysactionscript-3hittest

解决方案


你做的很多事情都是错误的。

首先,当您打算浏览一个数组以从中删除一个或多个元素时,请使用后向循环而不是前向循环,因为当您使用 Array.splice(...)时,数组的其余部分会向左移动一个位置而您会错过一个对象。我在这个答案中解释了原理。你也不需要打破循环。

// Move all enemy ships down the screen.
for (i = dusmanlar.length - 1; i >= 0; i--)
{
    // Get a ship to work with.
    var aShip:Dusman = dusmanlar[i];

    // Move the ship.
    aShip.y += aShip.yspeed;
    aShip.x += aShip.xspeed;

    if (aShip.y > 860)
    {
        // Remove the ship if it reached the bottom.
        removeChild(aShip);
        dusmanlar.splice(i, 1);
    }
    else if (aShip.x > 640)
    {
        // Bounce the ship off right.
        aShip.xspeed = -Math.abs(aShip.xspeed);
    }
    else if (aShip.x < 0)
    {
        // Bounce the ship off left.
        aShip.xspeed = Math.abs(aShip.xspeed);
    }
}

其次,您需要对许多对象与许多对象进行适当的检查。最直接的方法是检查每一个可能的碰撞。

var aShip:Dusman;
var aBullet:Mermi;

// Prepare lists for objects to remove.
var deadShips:Array = new Array;
var deadBullets:Array = new Array;

// Iterate over all enemy ships, presently alive.
for each (aShip in dusmanlar)
{
    // Iterate over all flying bullets in an inner loop.
    for each (aBullet in mermiler)
    {
        // As both ship and bullet are listed in the respective Arrays,
        // you don't need to check if they are not "null" or whatever.
        if (aShip.hitTestObject(aBullet))
        {
            // Add them for deletion. But only once.
            if (deadShips.indexOf(aShip) < 0)
            {
                deadShips.push(aShip);
            }

            // The bullets are iterated over in an inner loop,
            // you can kill many ships with the single bullet,
            // if it hits these ships at the same time.
            // Also, a single ship can take several bullets at once,
            // again, if they all hit simultaneously.
            if (deadBullets.indexOf(aBullet) < 0)
            {
                deadBullets.push(aBullet);
            }
        }
    }
}

// Now you have a list of killed ships and dead bullets.
// It's time to remove them.

var anIndex:int;

for each (aShip in deadShips)
{
    anIndex = dusmanlar.indexOf(aShip);

    // Sanity check.
    if (anIndex > 0)
    {
        dusmanlar.splice(anIndex, 1);
    }

    // Another sanity check.
    if (aShip.parent == this)
    {
        removeChild(aShip);
    }
}

for each (aBullet in deadBullets)
{
    anIndex = mermiler.indexOf(aBullet);

    // Sanity check.
    if (anIndex > 0)
    {
        mermiler.splice(anIndex, 1);
    }

    // Another sanity check.
    if (aBullet.parent == this)
    {
        removeChild(aBullet);
    }
}

推荐阅读