【问题标题】:Movieclip not being removed from array or stage - AS3 - CS6未从阵列或舞台中删除影片剪辑 - AS3 - CS6
【发布时间】:2014-01-28 19:32:38
【问题描述】:

我的敌人影片剪辑没有在与子弹影​​片剪辑发生碰撞/hitTestObject 时从舞台上移除,但子弹正在被移除,只有没有被移除的敌人。感谢所有帮助。谢谢你们,你们是一个出色的社区,尊重你们。

我使用相同的代码为敌人删除子弹电影剪辑(尽管相应地更改了变量等)。

我的 Main.as 和 Enemy.as 代码在这里:

Main.as

package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;

public class Main extends MovieClip
{
    public var player:Player;
    public var enemy:Enemy;

    public var bulletList:Array = [];

    public var mousePressed:Boolean = false; //keeps track of whether the mouse is currently pressed down
    public var delayCounter:int = 0; //this adds delay between the shots
    public var delayMax:int = 7; //change this number to shoot more or less rapidly

    public var enemies:Array =  [];

    public function Main():void
    {
        player = new Player(stage, 320, 240);
        stage.addChild(player);

        //stage.addEventListener(MouseEvent.CLICK, shootBullet, false, 0, true); //remove this
        stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true);
        stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, false, 0, true);

        stage.addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
        for(var numBaddies=0; numBaddies<6;numBaddies++){
            var enemy:Enemy = new Enemy(null);
            enemy.x = numBaddies*50;
            enemy.y = numBaddies*50
            stage.addChild(enemy);
            enemies.push(enemy);
        }
    }

    public function loop(e:Event):void
    {
        if(mousePressed) // as long as the mouse is pressed...
        {
            delayCounter++; //increase the delayCounter by 1
            if(delayCounter == delayMax) //if it reaches the max...
            {
                shootBullet(); //shoot a bullet
                delayCounter = 0; //reset the delay counter so there is a pause between bullets

           }
        }

        if(bulletList.length > 0)
        {
            for(var i:int = bulletList.length-1; i >= 0; i--)
            {
                bulletList[i].loop();
            }
        }

        for(var h = 0; h<bulletList.length; ++h)
        {
            if(bulletList[h].hitTestObject(this)){
              trace("player hit by baddie " + h);
               }
        }

        for(var u:int=0; u<enemies.length; u++) {
        Enemy(enemies[u]).moveTowards(player.x, player.y);
        }
    }


    public function mouseDownHandler(e:MouseEvent):void //add this function
    {
        mousePressed = true; //set mousePressed to true
    }

    public function mouseUpHandler(e:MouseEvent):void //add this function
    {
        mousePressed = false; //reset this to false
    }

    public function shootBullet():void //delete the "e:MouseEvent" parameter
    {
        var bullet:Bullet = new Bullet(stage, player.x, player.y, player.rotation, enemies);
        bullet.addEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved, false, 0, true);
        bulletList.push(bullet);
        stage.addChild(bullet);
    }

    public function bulletRemoved(e:Event):void
    {
        e.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, bulletRemoved);
        bulletList.splice(bulletList.indexOf(e.currentTarget),1);
    }
}
}

Enemy.as

package  {

import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;

public class Enemy extends MovieClip {

    public var bullets:Array;

    public var stageRef:Stage;

    private var enemyPositionX, enemyPositionY,xDistance,yDistance,myRotation:int;
    public function Enemy(bulletList:Array) {
        // constructor code
        bullets = bulletList;
    }

    public function moveTowards(playerX:int, playerY:int){
        xDistance = this.x - playerX;
        yDistance = this.y - playerY;


        myRotation = Math.atan2(yDistance, xDistance);

        this.x -= 3 * Math.cos(myRotation);
        this.y -= 3 * Math.sin(myRotation);


    }

    public function loop():void{

    for(var i=0; i<bullets.length; ++i)
        {
            if(bullets[i].hitTestObject(this)){
               trace("you killed enemy " + i);
               removeSelf();
               }
        }
    }

    private function removeSelf():void
    {
        removeEventListener(Event.ENTER_FRAME, loop);
        if (stageRef.contains(this))
        stageRef.removeChild(this);
    }
}

}

作为参考,您可以看到我如何使用相同的代码删除影片剪辑,我将添加 Bullet.as:

Bullet.as

package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;

public class Bullet extends MovieClip
{
    private var stageRef:Stage; //checks if the bullet leaves the screen borders
    private var speed:Number = 10; //speed that the bullet will travel at
    private var xVel:Number = 0; //current x velocity
    private var yVel:Number = 0; //current y velocity
    private var rotationInRadians = 0; //convenient to store our rotation in radians instead of degrees

    public var allBaddies:Array;

    //our constructor requires: the stage, the position of the bullet, and the direction the bullet should be facing
    public function Bullet(stageRef:Stage, X:int, Y:int, rotationInDegrees:Number, enemies:Array):void
    {
        this.stageRef = stageRef;
        this.x = X;
        this.y = Y;
        this.rotation = rotationInDegrees;
        this.rotationInRadians = rotationInDegrees * Math.PI / 180; //convert degrees to radians, for trigonometry
        allBaddies = enemies;
    }

    public function loop():void //we don't need to include the "e:Event" because we aren't using an EventListener
    {
        for(var b=0; b<allBaddies.length; ++b)
        {
            if(allBaddies[b].hitTestObject(this)){
               trace("bullet hit baddie " + b);
               removeSelf();
               }
        }

        xVel = Math.cos(rotationInRadians) * speed; //uses the cosine to get the xVel from the speed and rotation
        yVel = Math.sin(rotationInRadians) * speed; //uses the sine to get the yVel

        x += xVel; //updates the position
        y += yVel;

        //if the bullet goes off the edge of the screen...
        if(x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
        {
            this.parent.removeChild(this); //remove the bullet
        }
    }

    private function removeSelf():void
    {
        removeEventListener(Event.ENTER_FRAME, loop);
        if (stageRef.contains(this))
        stageRef.removeChild(this);
    }
}
}

【问题讨论】:

  • 你得到敌人的踪迹了吗?
  • 如果你的意思是声明中要移除敌人的那个,不,它根本不在输出中。

标签: arrays actionscript-3 flash movieclip flash-cs6


【解决方案1】:

好吧,除了我注意到的几个问题外,我还会改变一些事情。

首先,据我所知,您的Enemy 类永远不会获得stageRef 变量集。因此,在您的EnemyremoveSelf() 中,您的stageRef 将为空。

您可以通过构造函数传入舞台并设置它(就像在子弹类中所做的那样),或者您可以在使用 enemy.stageRef = stage 在敌人循环中实例化之后设置它。或者,您可以为 Event.ADDED_TO_STAGE 添加事件侦听器到您的敌人类,当发生这种情况时,您的敌人将引用继承的阶段。

现在,问题的真正实质。你有 2 个 for 循环测试碰撞(除了你的 Main 类中的一个,但我会讲到的)。一个属于你的子弹类,一个属于你的敌人类。如果您开始添加大量子弹和敌人,这将是矫枉过正并且在性能上很困难。你真的只需要一个 for 循环(就像你的子弹类中的那个),当它检测到碰撞时,它会调用碰撞对象删除方法。在你的Bullet 类中看起来像这样:

public function loop():void //we don't need to include the "e:Event" because we aren't using an EventListener
{
    for(var b=0; b<allBaddies.length; ++b)
    {
        if(allBaddies[b].hitTestObject(this)){
            trace("bullet hit baddie " + b);
            removeSelf();
            allBaddies[b].removeSelf();
        }
    }

不过,要使其正常工作,您需要将 removeSelf() 中的 Enemy 类访问权限设置为公共:

public function removeSelf():void
{
    //this is removing a listener not even added Enemy...
    //removeEventListener(Event.ENTER_FRAME, loop);
    if (stageRef.contains(this))
    stageRef.removeChild(this);
}

然后您甚至可以从 Enemy 类中删除您的 loop(),看看它是如何检测不再需要的冲突的。

最后,为什么会发生这种情况?好吧,它可能是从您在主类中的调用中首先运行的子弹 hitTest:bulletList[i].loop(); 正在检测此 hitTest,然后移除子弹,使您的 Enemy 类没有对象可以命中测试。但!您没有在主类中的任何地方从敌人调用loop(),因此该命中测试将永远不会运行。

最好将碰撞压缩。您当前正在循环通过主类中的Bullet 实例,调用它们的loop()(用于测试碰撞),然后再执行for 循环再次进行碰撞测试。你可以改变这个:

if(bulletList.length > 0)
{
    for(var i:int = bulletList.length-1; i >= 0; i--)
        {
            bulletList[i].loop();
        }
    }
    //this is no longer needed...
        /*for(var h = 0; h<bulletList.length; ++h)
        {
            if(bulletList[h].hitTestObject(this)){
              trace("player hit by baddie " + h);
               }
        }*/

没有理由在Bullet 类和Mainloop(e:Event) 中测试冲突。

希望这些信息对您有所帮助!祝你好运:)

【讨论】:

  • 哇,您已经完成了一些广泛的阅读,非常感谢。我现在要睡觉了,因为已经很晚了,但明天肯定会实施,我会告诉你进展如何。亲切的问候。 :)
  • 我在Enemy.as Enemy.as, Line 32, 1004: Namespace was not found or is not a compile-time constant. 收到此错误 这是在进行了所有建议的更改之后。如果我将 removeSelf() 更改回私有而不是公共的错误,那么当我声明敌人 var 时,Main.as 在同一行号上会出现错误,要求 2 个参数,尽管它已被给予 null 作为当前参数。这里有什么想法吗?谢谢。 :)
  • 第32行就是这段代码var enemy:Enemy = new Enemy(null);
  • 我要求您发布您的代码,因为var enemy:Enemy = new Enemy(null); 不是问题所在。但由于缺少信息,请确保在类中实例化一个新的 Enemy(我假设您的 Main 类),在包中您的敌人类有一个 import 语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
  • 2014-01-04
  • 1970-01-01
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多