2016-03-24 2 views
-1

Я очень новичок в AS3 и программировании вообще, и я разрабатывал космическую шутерскую игру в AS3 и столкнулся с проблемами в отношении вражеских выстрелов. Враги летают вертикально вниз от верхней части экрана и должны стрелять двумя выстрелами (один идет влево и один идет вправо), как только их координаты y равны тому, что у игрока. Это работает отлично, за исключением случаев, когда что-либо составляет от 30 секунд до 2 минут, возникают следующие ошибки.AS3 - Space Shooter Enemy Shots

TypeError: Error #1009: Cannot access a property or method of a null object reference. at EnemyShip2/fireWeapon()[G:\Games Related\1942\src\EnemyShip2.as:78] at EnemyShip2/loop2()[G:\Games Related\1942\src\EnemyShip2.as:65]

TypeError: Error #1009: Cannot access a property or method of a null object reference. at EnemyShot/removeSelf()[G:\Games Related\1942\src\EnemyShot.as:43] at EnemyShot/loop()[G:\Games Related\1942\src\EnemyShot.as:36]

Ниже приведен соответствующий код для класса корабля противника, а также класс вражеского выстрела.

Enemy Ship

package 
{ 
    import flash.display.Sprite; 
    import flash.display.Bitmap; 
    import flash.display.Stage; 
    import flash.events.Event; 
    import flash.events.TimerEvent; 
    import flash.utils.Timer; 

    /** 
    * ... 
    * @author D Nelson 
    */ 

    [Embed(source = "../assets/enemyship2.png")] 
    //This enemy moves relatively slowly and fires horizontal shots 
    public class EnemyShip2 extends Bitmap 
    { 
     private var vy:Number = 3; 
     //private var ay:Number = .2; 
     private var target:HeroShip; 
     private var enemyShip2:EnemyShip2; 
     private var enemyfireTimer:Timer; 
     private var enemycanFire:Boolean = true; 

     public function EnemyShip2(target:HeroShip):void 
     { 
      this.target = target; 
      scaleX = 0.3; 
      scaleY = 0.3; 
      x = Math.floor(Math.random() * 550); 
      y = -105; 
      addEventListener(Event.ENTER_FRAME, loop2, false, 0, true); 
      enemyfireTimer = new Timer(1000, 1); 
      enemyfireTimer.addEventListener(TimerEvent.TIMER, handleenemyfireTimer, false, 0, true); 
     } 

     private function handleenemyfireTimer(e:TimerEvent) : void 
     { 
      //the timer runs, so a shot can be fired again 
      enemycanFire = true; 
     } 


     private function removeSelf2():void 
     { 
      removeEventListener(Event.ENTER_FRAME, loop2); 
      if (stage.contains(this)) 
      { 
       stage.removeChild(this); 
      } 
     } 

     private function loop2 (e:Event):void 
     { 
      //vy += ay; 
      y += vy; 
      if (y > stage.stageHeight) 
      { 
       removeSelf2(); 
      } 

      if (y >= target.y && (enemycanFire)) 
      { 
       fireWeapon(); 
       enemycanFire = false; 
       enemyfireTimer.start(); 
      } 

      if (this.x > 540 || this.x < 10) 
      { 
       removeSelf2(); 
      } 
     } 

     private function fireWeapon():void 
     { 
      stage.addChild(new EnemyShot(target, x, y, -4)); 
      stage.addChild(new EnemyShot(target, x, y, +4)); 
     } 
    } 
} 

Enemy Выстрел

package 
{ 
    import flash.display.Sprite; 
    import flash.display.Bitmap; 
    import flash.events.Event; 
    import flash.display.Stage; 

    /** 
    * ... 
    * @author D Nelson 
    */ 

    [Embed(source="../assets/enemyshot.png")] 
    public class EnemyShot extends Bitmap 
    { 
     private var speed:Number; 
     private var target:HeroShip; 
     private var vx:Number; 

     public function EnemyShot(target:HeroShip, x:Number, y:Number, vx:Number) 
     { 
      this.target = target; 
      this.x = x; 
      this.y = y; 
      this.vx = vx; 
      scaleX = 0.3; 
      scaleY = 0.3; 
      addEventListener(Event.ENTER_FRAME, loop, false, 0, true); 
     } 

     private function loop(e:Event) : void 
     { 
      x += vx; 
      if (x >= 600 || x <= -50) 
      {    
       removeSelf(); 
      } 
     } 

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

Также предоставляется основной класс, в случае, если есть какой-либо помощи.

package 
{ 
    import flash.display.Sprite; 
    import flash.display.MovieClip; 
    import flash.display.DisplayObject; 
    import flash.display.Stage; 
    import flash.events.*; 
    import flash.events.Event; 
    import flash.events.EventDispatcher; 
    import flash.events.KeyboardEvent; 
    import flash.events.TimerEvent; 
    import flash.ui.Mouse; 
    import flash.utils.*; 
    import flash.utils.ByteArray; 
    import flash.utils.Timer; 
    import flash.text.*; 
    import flash.media.Sound; 
    import flash.media.SoundChannel; 

    /** 
    * ... 
    * @author D Nelson 
    */ 

    public class Main extends MovieClip 
    { 
     [Embed(source = "snd/gamemusic2.mp3")] 
     private var MySound : Class;   
     private var mainsound : Sound; 
     private var shootsound: Sound = new ShootSound; 
     private var sndChannel:SoundChannel = new SoundChannel; 
     public var heroShip:HeroShip; 
     public var enemyShip1:EnemyShip1 
     public var enemyShip2:EnemyShip2 
     public var enemyShip3:EnemyShip3 
     public var enemyShip4:EnemyShip4 
     public var bossShip: BossShip 
     public var enemyShot: EnemyShot; 
     public var playerShot: PlayerShot; 
     private var background1:Background1; 
     private var background2:Background2; 
     public static const scrollspeed:Number = 2; 
     public var playerShotArray:Array = new Array() 
     public var enemyShotArray:Array = new Array() 
     public var enemies1Array:Array = new Array() 
     public var enemies2Array:Array = new Array() 
     private var fireTimer:Timer; //this creates a delay between each shot 
     private var canFire:Boolean = true; //this checks if a shot can be fired     

     public function Main():void 
     { 
      if (stage) init(); 
      else addEventListener(Event.ADDED_TO_STAGE, init); 
      mainsound = (new MySound) as Sound; 
      shootsound = (new ShootSound) as Sound; 
      mainsound.play(); 
      background1 = new Background1(); 
      background2 = new Background2(); 
      //setting the backgrounds one below another 
      background1.y = 0; 
      background2.y = background1.height; 
      //add background at the lowest depth level 
      stage.addChildAt(background1,0); 
      stage.addChildAt(background2, 0);   
      //sets up the timer and its listener 
      fireTimer = new Timer(250, 1); 
      fireTimer.addEventListener(TimerEvent.TIMER, handlefireTimer, false, 0, true); 
      stage.addEventListener(KeyboardEvent.KEY_DOWN, handleCharacterShoot); 
      //background scrolling effect 
      stage.addEventListener(Event.ENTER_FRAME, backgroundScroll); 
      //loop for enemy1 variety 
      stage.addEventListener(Event.ENTER_FRAME, loop1, false, 0, true); 
      //loop for enemy2 variety 
      stage.addEventListener(Event.ENTER_FRAME, loop2, false, 0, true); 
      //speed of player shots 
      setInterval(playerShootMovement, 10);   
     } 

     private function init(e:Event = null):void 
     { 
      removeEventListener(Event.ADDED_TO_STAGE, init); 
      //entry point   
      heroShip = new HeroShip(); 
      stage.addChild(heroShip); 

      //test values for enemies 
      /*enemyShip1 = new EnemyShip1(); 
      stage.addChildAt(enemyShip1, 2); 
      enemyShip1.y = stage.stageWidth * 0.3; 
      enemyShip1.x = 300; 

      enemyShip2 = new EnemyShip2(); 
      stage.addChildAt(enemyShip2, 2); 
      enemyShip2.y = stage.stageWidth * 0.3; 
      enemyShip2.x = 200; 

      enemyShip3 = new EnemyShip3(); 
      stage.addChildAt(enemyShip3, 2); 
      enemyShip3.y = stage.stageWidth * 0.3; 
      enemyShip3.x = 100; 

      enemyShip4 = new EnemyShip4(); 
      stage.addChildAt(enemyShip4, 2); 
      enemyShip4.y = stage.stageWidth * 0.3; 
      enemyShip4.x = 400; 

      bossShip = new BossShip(); 
      stage.addChildAt(bossShip, 1); 
      bossShip.y = 10; 
      bossShip.x = 130;*/   

      Mouse.hide();   
     } 

     private function handlefireTimer(e:TimerEvent) : void 
     { 
      //the timer runs, so a shot can be fired again 
      canFire = true; 
     } 

     public function playerShoot():void 
     { 
      //if canFire is true, allow a shot to be fired, then set canFire to false and start the timer again 
      //else, do nothing   
      if (canFire) 
      { 
       //Add new line to the array 
       playerShotArray.push(playerShot = new PlayerShot); 
       //Spawn missile in ship 
       playerShot.y = heroShip.y; 
       playerShot.x = heroShip.x+11; 
       addChild(playerShot); 
       canFire = false; 
       fireTimer.start();    
       sndChannel = shootsound.play(); 
      } 
     } 

     public function playerShootMovement():void 
     { 
      //code adapted from the Pie Throw tutorial 
      for (var i:int = 0; i < playerShotArray.length; i++) 
      { 
       playerShotArray[i].y -= 10; 

       if (playerShotArray[i].y == 850) 
       { 
        playerShotArray.shift(); 
       } 
      }   
     } 

     public function handleCharacterShoot(e:KeyboardEvent):void 
     { 
      /** 
      * SpaceBar = 32 
      */         
      if (e.keyCode == 32) 
      { 
       playerShoot(); 
      }   
     }  

     public function backgroundScroll (evt:Event):void 
     { 
      background1.y += scrollspeed; 
      background2.y += scrollspeed; 
      if (background1.y >= stage.stageHeight) 
      { 
       //the background is below the visible stage area, put it above the other background  
       background1.y = background2.y - background2.height; 
      } 
      else if (background2.y >= stage.stageHeight) 
      { 

       background2.y = background1.y - background2.height; 
      }   
     } 

     //EnemyShip 1 spawning 
     private function loop1(e:Event):void 
     { 
      //generates probability for the ship to spawn (lower number to increase odds, decrease it to decrease odds) 
      if (Math.floor(Math.random() * 55) == 5) 
      { 
       var enemyShip1:EnemyShip1 = new EnemyShip1(heroShip); 
       enemyShip1.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy1, false, 0, true); 
       enemies1Array.push(enemyShip1); 
       stage.addChild(enemyShip1); 
      } 
     } 

     private function removeEnemy1(e:Event):void 
     { 
      //removes the enemy that most recently left the screen from the array 
      enemies1Array.splice(enemies1Array.indexOf(e.currentTarget), 1); 
     } 

     //EnemyShip2 spawning 
     private function loop2(e:Event):void 
     { 
      if (Math.floor(Math.random() * 40) == 5) 
      { 
       var enemyShip2:EnemyShip2 = new EnemyShip2(heroShip); 
       enemyShip2.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy2, false, 0, true); 
       enemies2Array.push(enemyShip2); 
       stage.addChild(enemyShip2); 
      } 
     } 

     private function removeEnemy2(e:Event):void 
     { 
      enemies2Array.splice(enemies2Array.indexOf(e.currentTarget), 1); 
     } 
    } 
} 

Первоначально я думал, что это делать с врагами выстрелами в то же время слишком далеко, чтобы обе стороны от экрана, но это, кажется, не так. Любая помощь будет принята с благодарностью.

+0

Я предполагаю, что ваш элемент не добавляется в сцену или сцену, это не вещь внутри вашего класса. Прошло некоторое время, так как я использовал AS3, поэтому не уверен. – putvande

+0

Да, единственное, что может быть пустым в fireWeapon(), - это этап. Похоже, что ваш корабль не добавлен на сцену? – Philarmon

+0

Возможный дубликат [Ошибка в действии # 1009] (http://stackoverflow.com/questions/1287770/actionscript-error-1009) – Brian

ответ

1

Вам необходимо убедиться, что вы удаляете прослушивателей ENTER_FRAME всякий раз, когда вы удаляете объект.

На самом деле, мой совет: не добавить ENTER_FRAME обработчиков по всей вашей игровой объектов. Это становится трудно управлять и приводит к ошибкам, как вы столкнулись. Вместо этого добавьте один ENTER_FRAME в качестве основного игрового цикла и обновите объекты, вызвав функцию update() в список игровых объектов, которые вы поддерживаете в своем основном игровом классе. Когда вы удаляете объект, вы просто не будете звонить update(). Также легко приостановить игру, просто удалив обработчик ENTER_FRAME.

Например, вот образец, который я хотел бы использовать для простых игр:

interface IGameObject { 
    update():void; 
} 

class Enemy extends Sprite implements IGameObject { 
    public update():void { 
     // move, fire, etc 
    } 
} 

class Player extends Sprite implements IGameObject { 
    public update():void { 
     // move, fire, etc 
    } 
} 

class Bullet extends Bitmap implements IGameObject { 
    public update():void { 
     // move, collide, etc 
    } 
} 

class Main extends Sprite { 
    private objects:Vector.<IGameObject> = new <IGameObject>[]; 

    public start():void { 
     addEventListener(Event.ENTER_FRAME, update); 
    } 

    public stopGame():void { 
     removeEventListener(Event.ENTER_FRAME, update); 
    } 

    private function update(e:Event):void { 
     for each (var object:IGameObject in objects) { 
      object.update(); 
     } 
    } 

    public addObject(object:IGameObject):void { 
     objects.push(object); 
     addChild(object as DisplayObject); 
    } 

    public removeObject(object:IGameObject):void { 
     objects.splice(objects.indexOf(object), 1); 
     removeChild(object as DisplayObject); 
    } 
} 

Добавить и удалить объекты с помощью addObject и removeObject. Вы можете вызвать их через ссылку на Main или через обработчики событий, отправляемые с ваших объектов.

 Смежные вопросы

  • Нет связанных вопросов^_^