Вопрос

I'm creating a 2d side scrolling shooter with 4 different types of Enemies and 3 different types of bullets. I'm using a factory class to create the enemies and a for loop inside a for loop to do hit testing. When I run my code for some reason when one enemy get's hit some of my other enemies die. Could someone please help me locate and fix my problem.

Here's one of the Enemy classes. The other 3 are identical except with different var values.

package char {

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

public class Enemy1 extends MovieClip {

    private var _type:String;
    private var _health:Number;
    private var _vx:Number;
    private var _vy:Number;
    private var _stage:Stage;

    private static var _instance:Enemy1;

    public function Enemy1() {
        init();
    }

    private function init():void {
        //Vars
        _vx = -5;
        _vy = Math.random()*5;
        _health = 1;
        _stage = Main.getStage();
        _instance = this;

        //Listeners
        addEventListener(Event.ADDED_TO_STAGE, onAdded);
        addEventListener(Event.ENTER_FRAME, enemyLoop);
        addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
    }

    //When Added
    private function onAdded(event:Event):void{
        //Set position
        this.x = _stage.stageWidth;
        this.y = Math.random() * _stage.stageHeight;
        //trace("Enemy created");

        dispatchEvent(new Event("enemyCreated", true));
    }

    //Loop
    private function enemyLoop(event:Event):void {
        //Move
        x += _vx;
        y += _vy;

        //Boundaries
        if ( this.y <= 0 + this.height/2){
            this.y = this.height/2;
            _vy *= -1;
        }
        if ( this.y >= _stage.stageHeight - this.width/2){
            this.y = _stage.stageHeight - this.width/2;
            _vy *= -1;
        }

        //Health cheack
        if ( _health <= 0){
            if (this.parent) {
                this.parent.removeChild(this);
                Main.setScore(10);
            }
        }
        //Leaves screen
        if (this.x <= -this.width){
            if (this.parent) {
                this.parent.removeChild(this);
            }
        }
    }

    public function isHit(type:String):void{
        //trace(this + " is hit by " + type);
        if(type == "power"){
            _health -= 1;
            trace(_health);
        }
        else if(type == "quick"){
            _health -= 1;
            trace(_health);
        }
        else if(type == "strong"){
            _health -= 1;
            trace(_health);
        }
    }

    public function getHealth():Number{
        return _health;
    }

    public function getEnemy1():Enemy1{
        return _instance;
    }

    //When Removed
    private function onRemoved(event:Event):void {
        removeEventListener(Event.ADDED_TO_STAGE, onAdded);
        removeEventListener(Event.ENTER_FRAME, enemyLoop);
        removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
        //trace("enemy removed");
    }
}

}

And here's my main class that checks for all the hitTests

package screen {

import flash.display.MovieClip;
import flash.events.Event;
import com.greensock.TweenLite;
import com.greensock.easing.*;
import char.Player;
import char.EnemyFactory;


public class Level1 extends MovieClip {
    //Consts
    private const ENEMY_CHANCE:Number = 0.025;

    //Vars
    private var _player:Player;
    private var _enemyBudget:Number = 20;
    private static var _bullets:Array = [];
    private static var _enemies:Array = [];

    public function Level1() {
        init();
    }

    private function init():void {
        //Vars
        this.alpha = 0;
        _enemyBudget = 20;

        //Event listeners
        addEventListener(Event.ENTER_FRAME, levelLoop);
        addEventListener(Event.ADDED_TO_STAGE, onAdded);
        addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);

        //Add This
        Main.getInstance().addChild(this);
    }

    private function onAdded(event:Event):void {
        TweenLite.to(this, 0.5, {alpha:1});
        _player = new Player();
        trace("Level 1 reaady");
    }

    private function levelLoop(event:Event):void{
        //Health bar
        _healthBar.scaleX = Main.getPlayerHealth() / 100;

        //enemy creation
        if(_enemyBudget <= 20 && _enemyBudget > 10){
            if (ENEMY_CHANCE > Math.random()){
                var randomEnemy:Number = Math.random()* 1.2;
                //trace(randomEnemy);
                if(randomEnemy <= 0.5){
                    //trace("Enemy 1");
                    var enemy1:MovieClip = char.EnemyFactory.makeEnemy("weak");
                    Main.getInstance().addChild(enemy1);
                    _enemyBudget -= 1;
                }
                else if(randomEnemy > 0.5 && randomEnemy <= 0.8){
                    //trace("Enemy 2");
                    var enemy2:MovieClip = char.EnemyFactory.makeEnemy("quick");
                    Main.getInstance().addChild(enemy2);
                    _enemyBudget -= 3;
                }
                else if(randomEnemy > 0.8 && randomEnemy <= 1){
                    //trace("Enemy 3");
                    var enemy3:MovieClip = char.EnemyFactory.makeEnemy("strong");
                    Main.getInstance().addChild(enemy3);
                    _enemyBudget -= 3;
                }
                else if(randomEnemy > 1 && randomEnemy <= 1.2){
                    //trace("Enemy 4");
                    var enemy4:MovieClip = char.EnemyFactory.makeEnemy("power");
                    Main.getInstance().addChild(enemy4);
                    _enemyBudget -= 4;
                }
            }
        }

        else if(_enemyBudget <= 10 && _enemyBudget > 0){
            if (ENEMY_CHANCE > Math.random()){
                var randomEnemy:Number = Math.random();
                if(randomEnemy <= 0.5){
                    //trace("Enemy 1");
                    var enemy1:MovieClip = char.EnemyFactory.makeEnemy("weak");
                    Main.getInstance().addChild(enemy1);
                    _enemyBudget -= 1;
                }
                else if(randomEnemy > 0.5 && randomEnemy <= 0.8){
                    //trace("Enemy 2");
                    var enemy2:MovieClip = char.EnemyFactory.makeEnemy("quick");
                    Main.getInstance().addChild(enemy2);
                    _enemyBudget -= 3;
                }
                else if(randomEnemy > 0.8 && randomEnemy <= 1){
                    //trace("Enemy 3");
                    var enemy3:MovieClip = char.EnemyFactory.makeEnemy("strong");
                    Main.getInstance().addChild(enemy3);
                    _enemyBudget -= 3;
                }
            }
        }

        else if(_enemyBudget <= 0){
            if(_enemies == []){
                trace("Game End");
            }
        }

        if( Main.getPlayerHealth() <= 0){
            trace("Player Dead. End Game");
        }

        for (var i:int = 0; i < _enemies.length; i++){
            for(var j:int = 0; j < _bullets.length; j++){
                if(_bullets[j] != null && _enemies[i] != null){
                    //Check if bullet hits enemy
                    if(_bullets[j].hitTestObject(_enemies[i])){
                        //removes bullet
                        if (_bullets[j].parent) {
                            _bullets[j].parent.removeChild(_bullets[j]);
                        }

                        //Tells enemy he's hit
                        if(_enemies[i] != null){ 
                            _enemies[i].isHit(_bullets[j].getType());
                        }

                        //Checks enemy health
                        if(_enemies[i].getHealth() <= 0){
                            if(_enemies[i] == null){
                                _enemies.splice(i, 1);
                                i--;
                            }
                        }   

                        //Removes bullet from array
                        if(_bullets[j] == null){
                            _bullets.splice(j, 1);
                            j--;
                         }
                    }

                    //Check if player hit
                    if(_enemies[i] != null && _player != null){
                        if(_enemies[i].hitTestObject(_player)){
                            if (_enemies[i].parent) {
                                _enemies[i].parent.removeChild(_enemies[i]);
                                Main.setPlayerHealth(-10);
                            }
                        }

                        if(_enemies[i] == null){
                            _enemies.splice(i, 1);
                            i--;
                        }
                    }
                }
            }
        }
    }

    private function onRemoved(event:Event):void{
        removeEventListener(Event.ENTER_FRAME, levelLoop);
        removeEventListener(Event.ADDED_TO_STAGE, onAdded);
        removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
    }

    //Get instance
    public static function addBullet(bullet:MovieClip):void {
        _bullets.push(MovieClip(bullet));
    }

    public static function addEnemy(enemy:MovieClip):void{
        _enemies.push(MovieClip(enemy));
        //trace(enemy + " was added to enemy array.");
    }
}

}

And here's the function inside the Bullet class that return's it's type.

public function getType():String{
        return TYPE;
    }
Это было полезно?

Решение

It's hard to say with certainty, this would be easy to confirm by stepping through the code in a debugger.

But what looks suspicious to me is that you're iterating over arrays of enemies/bullets, and in the middle of doing that, you delete elements from the array and decrement the counter variables. Generally, when you need to iterate over something and potentially remove elements from the thing you're iterating over, you should do that iteration in a backwards fashion. That way changing the length and contents of the array in the middle of the loop is harmless.

for (var i:int = enemeies.length -1; i >= 0; i--)
{
    // do your stuff and remove elements from the
    // enemies array at will ... just splice the current
    // element at index i out here, don't decrement i as
    // you've done in your code above it will get decremented
    // by the for loop
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top