2016-03-24 9 views
-1

Ich bin sehr neu in AS3 und Programmierung im Allgemeinen und ich habe ein Space Shooter-Spiel in AS3 entwickelt und habe Probleme mit den feindlichen Schüssen. Die Gegner fliegen senkrecht vom oberen Bildschirmrand herunter und sollten zwei Schüsse abfeuern (einer nach links und einer nach rechts), sobald ihre y-Koordinaten der des Spielers entsprechen. Dies funktioniert einwandfrei, außer nach etwa 30 Sekunden bis 2 Minuten treten die folgenden Fehler auf.AS3 - Space Shooter Feindbilder

Unten ist der relevante Code für die feindliche Schiffsklasse sowie die feindliche Schussklasse.

feindliches Schiff

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)); 
     } 
    } 
} 

Feind Schuss

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); 
      } 
     }  
    } 
} 

Auch ist die Hauptklasse vorgesehen, in dem Fall, dass keine Hilfe ist.

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); 
     } 
    } 
} 

Anfangs dachte ich, es mit Feinden feuern Schüsse während zu sein weit zu beiden Seiten des Bildschirms zu tun war, aber das scheint nicht der Fall zu sein. Jede Hilfe würde sehr geschätzt werden.

+0

Ich vermute, dass Ihr Element nicht auf der Bühne oder Bühne hinzugefügt wird, ist keine Sache in Ihrer Klasse. Es ist schon eine Weile her, dass ich AS3 nicht so sicher benutzt habe. – putvande

+0

Ja, das einzige, was im FireWeapon() null sein kann, ist die Stufe. Klingt wie dein Schiff in der Bühne nicht hinzugefügt? – Philarmon

+0

Mögliches Duplikat von [Actionscript Fehler # 1009] (http://stackoverflow.com/questions/1287770/actionscript-error-1009) – Brian

Antwort

1

Sie müssen sicherstellen, dass Sie die ENTER_FRAME Listener entfernen, immer wenn Sie das Objekt entfernen.

Eigentlich ist mein Rat zu nicht hinzufügen ENTER_FRAME Handler in Ihrem Spiel Objekte. Dies wird schwer zu verwalten und führt zu Fehlern, wie Sie sie kennen. Füge stattdessen eine einzelne ENTER_FRAME als Hauptspielschleife hinzu und aktualisiere Objekte, indem du eine update() Funktion in einer Liste von Spielobjekten anrufst, die du in deiner Hauptspielklasse behältst. Wenn Sie ein Objekt entfernen, rufen Sie einfach nicht mehr update() auf. Es wird auch leicht, das Spiel anzuhalten, indem man einfach den ENTER_FRAME Handler entfernt.

Zum Beispiel, hier ist ein Muster, das ich für einfache Spiele nutzen möchten:

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); 
    } 
} 

Hinzufügen und addObject und removeObject mit Objekten entfernen. Sie können sie über einen Verweis auf Main oder über Ereignishandler aufrufen, die Sie von Ihren Objekten aus versenden.