The dispatchEvent only gets picked up by my main class (Engine.as) and not the ships class (Weapons.as)
I am currently trying to make a game, but the problem now is that when I dispatchEvent, only my main class picks it up (the engine). I want my Weapons.as to also pick it up. My main class is Engine.as (assigned to stage class), and my weapons.as is the ship. I am dispatching the event from a class called Score.as.
The main problem is that my Weapons.as doesn't pick up the "gameO", nor the "gameOver" event, the score.as dispatches. Another thing is that if I set the if(s_hp == 100) (which is what it starts at) my Weapons.as manages to pick up the event that is dispatched, but only then...
To be more specific, I want/need to bubble a event from the Score.as, through Weapons.as to my main class Engine.as. A eventListener in Weapons.as need to pick it up and remove the ship and making it unable to shoot, and then pass the event further on to the Engine.as class, which removes almost everything from stage
Appriciate any help I get! :)
EDIT : Full Classes
Score.as:
package Etys
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.text.TextField;
import flash.events.Event;
import flash.utils.Timer;
import flash.geom.ColorTransform;
public class Score extends MovieClip
{
private var stageRef:Stage;
public var s_score:Number = 0;
public var s_hits:Number;
public var s_kills:Number = 0;
public function Score(stageRef:Stage)
{
this.stageRef = stageRef;
s_hits = 100;
healthBar.width = 100;
kills.text = "Kills: \n0";
hits.text = "HP: \n100";
score.text = "Score: \n0";
kills.selectable = false;
hits.selectable = false;
score.selectable = false;
x = 10;
y = stageRef.stageHeight - height;
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function updateKills(value:Number) : void
{
s_kills += value;
kills.text = String("Kills: \n"+s_kills);
trace(s_hits+"I Kills");
}
public function updateHits(value:Number) : void
{
if(s_hits != 1 || s_hits != 0)
{
s_hits -= value;
healthBar.width -= value;
hits.text = String("HP: \n"+s_hits);
}else{
healthBar.width = 0;
s_hits = 0;
hits.text = String("HP: \n"+s_hits);
}
if(s_hits == 66 ||s_hits == 67)
{
var colorYellow:ColorTransform = healthBar.transform.colorTransform;
colorYellow.color = 0xFFFF00;
healthBar.transform.colorTransform = colorYellow;
}else if(s_hits == 33 || s_hits == 34)
{
var colorRed:ColorTransform = healthBar.transform.colorTransform;
colorRed.color = 0xFF0000;
healthBar.transform.colorTransform = colorRed;
}
s_score -= value;
score.text = String("Score: \n"+s_score);
trace(s_hits+"I Hits");
}
public function updateScore(value:Number) : void
{
s_score += value;
score.text = String("Score: \n"+s_score);
trace(s_hits+"I Score");
}
public function loop(e:Event)
{
if(s_hits == 99 || s_hits == 98)
{
this.dispatchEvent(new Event('gameOver', true));
this.dispatchEvent(new Event('gameO', true));
removeEventListener(Event.ENTER_FRAME, loop);
}
}
}
}
Weapons.as:
package Etys
{
import flash.display.MovieClip;
import flash.display.Stage;
import com.senocular.utils.KeyObject;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Weapons extends MovieClip
{
private var stageRef:Stage;
private var key:KeyObject;
private var speed:Number = 2;
private var vx:Number = 0;
private var vy:Number = 0;
private var friction:Number = 0.93;
private var maxspeed:Number = 8;
private var target:Stinger;
public var score:Score;
private var fireTimer:Timer;
private var canFire:Boolean = true;
private var stopIt:Boolean = false;
public function Weapons(stageRef:Stage)
{
this.stageRef = stageRef;
score = new Score(stageRef);
addChild(score);
score.addEventListener('gameO', lostGame, false, 0, false);
addChild(score);
key = new KeyObject(stageRef);
fireTimer = new Timer(200, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
if (key.isDown(Keyboard.A))
{
vx -= speed;
}else if (key.isDown(Keyboard.D))
{
vx += speed;
}else{
vx *= friction;
}
if (key.isDown(Keyboard.W))
{
vy -= speed;
}else if (key.isDown(Keyboard.S))
{
vy += speed;
}else{
vy *= friction;
}
if (key.isDown(Keyboard.SPACE))
{
fireBullet();
}
//update position
x += vx;
y += vy;
//speed adjustment
if (vx > maxspeed)
{
vx = maxspeed;
}else if (vx < -maxspeed)
{
vx = -maxspeed;
}
if (vy > maxspeed)
{
vy = maxspeed;
}else if (vy < -maxspeed)
{
vy = -maxspeed;
}
//ship appearance
rotation = vx;
scaleX = (maxspeed - Math.abs(vx))/(maxspeed*4) + 0.75;
//stay inside screen
if (x > 537)
{
x = 537;
vx = -vx;
}
else if (x < 13)
{
x = 13;
vx = -vx;
}
if (y > 378)
{
y = 378;
vy = -vy;
}
else if (y < 216)
{
y = 216;
vy = -vy;
}
}
public function lostGame(e:Event)
{
trace("bash");
fireTimer.stop();
fireTimer.reset();
canFire = false;
fireTimer.removeEventListener(TimerEvent.TIMER, fireTimerHandler);
removeEventListener(Event.ENTER_FRAME, loop);
}
private function fireBullet() : void
{
//if canFire is true, fire a bullet
//set canFire to false and start our timer
//else do nothing.
if (canFire)
{
stageRef.addChild(new LaserBlue(stageRef, x + vx +15, y - 10))开发者_如何学C;
stageRef.addChild(new LaserBlue2(stageRef, x + vx -15, y - 10));
canFire = false;
fireTimer.start();
}
}
//HANDLERS
private function fireTimerHandler(e:TimerEvent) : void
{
//timer ran, we can fire again.
canFire = true;
}
public function hitShip() : void
{
dispatchEvent(new Event("hitShipe"));
}
public function takeHit() : void
{
dispatchEvent(new Event("hit"));
}
}
}
Engine:
package Etys
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.media.SoundChannel;
import flash.utils.Timer;
import flash.display.*;
public class Engine extends MovieClip
{
private var numStars:int = 80;
private var numAsteroids:int = 4;
public static var enemyList:Array = new Array();
public static var enemyListFatso:Array = new Array();
private var ourShip:Weapons;
private var quality:qualityButton;
private var score:Score;
public function Engine() : void
{
ourShip = new Weapons(stage);
stage.addChild(ourShip);
ourShip.x = stage.stageWidth / 2;
ourShip.y = stage.stageHeight / 2;
ourShip.addEventListener("hit", shipHit, false, 0, true);
ourShip.addEventListener("hitShip", Hit, false, 0, true);
for (var i:int = 0; i < numStars; i++)
{
stage.addChildAt(new Star(stage), stage.getChildIndex(ourShip));
}
for (var a:int = 0; a < numAsteroids; a++)
{
stage.addChildAt(new Asteroids(stage), stage.getChildIndex(ourShip));
}
quality = new qualityButton(stage);
stage.addChild(quality);
score = new Score(stage);//create our HUD
stage.addChild(score);
score.addEventListener("gameOver", lostGame, false, 0, true);
//running a loop now.... so we can keep creating enemies randomly.
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function lowQ(e:MouseEvent)
{
stage.quality = StageQuality.LOW;
trace("Low");
}
private function highQ(e:MouseEvent)
{
stage.quality = StageQuality.BEST;
trace("High");
}
//our loop function
private function loop(e:Event):void
{
if (Math.floor(Math.random() * 90) == 4)
{
var enemyFatso:Fatso = new Fatso(stage,ourShip);
enemyFatso.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemyFatso, false, 0, true);
enemyFatso.addEventListener("killed", enemyFatsoKilled, false, 0, true);
enemyFatso.addEventListener("enemyC", enemyCrash, false, 0, true);
enemyListFatso.push(enemyFatso);
stage.addChild(enemyFatso);
}
//run if condition is met.
if (Math.floor(Math.random() * 90) == 5 || Math.floor(Math.random() * 90) == 6)
{
//create our enemy
var enemy:Stinger = new Stinger(stage,ourShip);
enemy.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy, false, 0, true);
enemy.addEventListener("killed", enemyKilled, false, 0, true);
enemy.addEventListener("enemyC", enemyCrash, false, 0, true);
enemyList.push(enemy);
stage.addChild(enemy);
}
}
private function enemyFatsoKilled(e:Event)
{
score.updateKills(1);
score.updateScore(e.currentTarget.points);
}
private function enemyKilled(e:Event)
{
score.updateKills(1);
score.updateScore(e.currentTarget.points);
}
private function enemyCrash(e:Event)
{
score.updateHits(2);
}
private function removeEnemyFatso(e:Event)
{
enemyListFatso.splice(enemyListFatso.indexOf(e.currentTarget), 1);
}
private function lostGame(e:Event)
{
dispatchEvent(new Event("removeShips", true));
stage.removeChild(ourShip);
ourShip.removeEventListener("hit", shipHit);
ourShip.removeEventListener("hitShip", Hit);
removeEventListener(Event.ENTER_FRAME, loop);
}
private function removeEnemy(e:Event)
{
enemyList.splice(enemyList.indexOf(e.currentTarget), 1);
}
private function Hit(e:Event)
{
trace("lol");
}
private function shipHit(e:Event)
{
score.updateHits(1);
}
}
}
Events in ActionScript 3 are, for the most part, fairly simple. An object dispatches an Event and a Listener will handle it, here's a very simple example of that in effect showing how the two parties interact:
The Event Dispatcher Class
// By extending the EventDispatcher class, we can now dispatch events! Note that
// Sprite and MovieClip both extend EventDispatcher through inheritance.
public class Dispatcher extends EventDispatcher {
public function Dispatcher() {
// Create a simple interval which will call the "dispatchTickleEvent"
// method every 1.5 seconds.
setInterval(dispatchTickleEvent, 1500);
}
private function dispatchTickleEvent() {
// Broadcast an Event of type TICKLE which other classes and listen
// out for.
dispatchEvent(new Event("TICKLE"));
}
}
The Listener Class
// Note that event listeners don't have to extend anything in order to listen
// out for Events.
public class Listener {
public function Listener() {
// Create a new instance of the Dispatcher Class.
var dispatcher : Dispatcher = new Dispatcher();
// Here's where we add an EventListener to the Dispatcher instance.
// This simply means that each time the dispatcher instances emits
// an Event of type "TICKLE", the "onDispatcherTickled" function will
// be called.
dispatcher.addEventListener("TICKLE", onDispatcherTickled);
}
// This is the event handler method which will be called whenever our dispatcher
// instance broadcasts an Event of type "TICKLE".
private function onDispatcherTicked(event : Event) : void {
trace("The dispatcher was Tickled!");
}
}
This is a very powerful system as it provides a loosely coupled way for Classes to communicate with each other. By loosely coupled, we mean that the Listener Class doesn't know what caused the Event to be broadcast (in the above case, it was caused automatically by the interval); so that the behaviour can be modified without having to change the Listener class - for example we could make it so that the Tickle Event only gets dispatched when the user clicks the mouse.
So far, so simple, but Events have one rather interesting quirk that comes into play when DisplayObjects on the Display List start dispatching Events known as bubbling, or event propagation.
The basic concept is that if a DisplayObject (for example a Sprite) which has been added to the Active Display List dispatches an Event, that Event will pass through (bubble) through each of its 'parent' DisplayObjects until it finally reaches the Stage. A great example of Event Bubbling in action is shown on Ruben Swieringa's blog. If you scroll to the bottom of the article you will see a Flash Movie which demonstrates event bubbling in action.
Here's a very simple code example of Event bubbling in action:
The Event Dispatcher Class, this time dispatching an Event that will bubble
// Note that we have to extend Sprite in order to be added to the Display List,
// but as mentioned before, Sprite itself extends EventDispatcher further down
// its inheritance tree.
public class Dispatcher extends Sprite {
public function Dispatcher() {
// The interval will call dispatchTickleEvent every 1.5 seconds.
setInterval(dispatchTickleEvent, 1500);
}
private function dispatchTickleEvent() {
// Dispatch the Tickle Event, but this time notice how we pass true as
// the second argument when constructing the new Event() instance, this
// tells the Event that it should Bubble up the Display List. All of
// the "internal" Flash Event which are dispatched automatically, such as
// MouseEvent.CLICK, Event.ENTER_FRAME, etc are all set to bubble by default.
dispatchEvent(new Event("TICKLE", true));
}
}
The Listener Class, which also sets up the Display List
public class Listener {
public function Listener(stage : Stage) {
// Create the Dispatcher instance.
const dispatcher : Dispatcher = new Dispatcher();
// Add the Dispatcher Instance to the Display List by adding it as a
// child of the Stage.
stage.addChild(dispatcher);
// Now we add the EventListeners, but instead of listening directly to
// the Dispatcher instance, like we did last time, we will instead listen
// for the Tickle event on the Stage.
stage.addEventListener("TICKLE", onTickleEvent);
}
private function onTickleEvent(event : Event) : void {
trace("Someone was tickled! :)");
}
}
So, if all your Class instances are Display Objects which you are adding to the Display List, it should be as simple as making the dispatched Events bubble up the Display List and then adding your Event Listeners to the Stage.
Hope that helps!
精彩评论