AS3: Structuring custom classes - actionscript-3

I wrote a class ANDGatter.as which has 4 child objects "AndIONode0-3". See code. I got drag-drop functionality working but the order in which I add the eventlisteners seems to be wrong. Should I add listeners before or after the addChild methods ? I tried both ways, but when instanciating 2 ANDGatter in my Application I get a Null-pointer Exception during the first drag-drop action. How can I fix this ?
package classes{
import classes.ConnectionLine;
import flash.display.DisplayObject;
import flash.events.MouseEvent;
import mx.containers.Canvas;
import mx.controls.Alert;
import mx.core.DragSource;
import mx.events.DragEvent;
import mx.managers.DragManager;
public class AndGatter extends Canvas
{
public var AndIONode0:Canvas;
public var AndIONode1:Canvas;
public var AndIONode2:Canvas;
public var AndIONode3:Canvas;
public var nodeWidth:int=10;
public var nodeHeight:int=10;
public var nodeColor:uint=0x919191;
public var gatterColor:uint=0x474747;
public var startconnector:DisplayObject;
public var endconnector:DisplayObject;
public function AndGatter()
{
super();
super.width=50;
super.height=50;
this.setStyle("backgroundColor",gatterColor);
/*EingangsNode0 für AndGatter*/
AndIONode0=new Canvas();
AndIONode0.name="And Output Node";
AndIONode0.width=nodeWidth;
AndIONode0.height=nodeHeight;
AndIONode0.x=40;
AndIONode0.y=20;
AndIONode0.setStyle("backgroundColor",nodeColor);
addChild(AndIONode0);
AndIONode1=new Canvas();
AndIONode1.name="And Input Node 1";
AndIONode1.width=nodeWidth;
AndIONode1.height=nodeHeight;
AndIONode1.x=0;
AndIONode1.y=5;
AndIONode1.setStyle("backgroundColor",nodeColor);
addChild(AndIONode1);
AndIONode2=new Canvas();
AndIONode2.name="And Input Node 2";
AndIONode2.width=nodeWidth;
AndIONode2.height=nodeHeight;
AndIONode2.x=0;
AndIONode2.y=20;
AndIONode2.setStyle("backgroundColor",nodeColor);
addChild(AndIONode2);
AndIONode3=new Canvas();
AndIONode3.name="And Input Node 3";
AndIONode3.width=nodeWidth;
AndIONode3.height=nodeHeight;
AndIONode3.x=0;
AndIONode3.y=35;
AndIONode3.setStyle("backgroundColor",nodeColor);
addChild(AndIONode3);
AndIONode0.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler);
AndIONode1.addEventListener(DragEvent.DRAG_ENTER,dragEnterHandler);
AndIONode1.addEventListener(DragEvent.DRAG_DROP,dragDropHandler);
AndIONode2.addEventListener(DragEvent.DRAG_ENTER,dragEnterHandler);
AndIONode2.addEventListener(DragEvent.DRAG_DROP,dragDropHandler);
AndIONode3.addEventListener(DragEvent.DRAG_ENTER,dragEnterHandler);
AndIONode3.addEventListener(DragEvent.DRAG_DROP,dragDropHandler);
}
private function mouseMoveHandler(event:MouseEvent):void {
var dragInitiator:Canvas=Canvas(event.currentTarget);
startconnector=dragInitiator;
var ds:DragSource = new DragSource();
ds.addData(id, 'start');
DragManager.doDrag(dragInitiator, ds, event);
}
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat('start')) {
var dropTarget:Canvas=Canvas(event.currentTarget);
endconnector=dropTarget;
DragManager.acceptDragDrop(dropTarget);
}
}
private function dragDropHandler(event:DragEvent):void {
/*var connector:ConnectionLine = new ConnectionLine(startconnector,endconnector,true);
stage.rawChildren.addChild(connector);*/
Alert.show("Verbindung hergestellt zwischen \n"+startconnector.name+" und "+endconnector.name);
}
}
}

In dragDropHandler(), you're referencing startconnector.name. startconnector isn't assigned until mouseMoveHandler() is called, which only happens when you move your mouse over AndIONode0. You may need to adjust which AndIONodes you are adding your move listeners to in order to make sure that startconnector always has a value.

The following statement is failing
if (event.dragSource.hasFormat('start')) {
causing endconnector
endconnector=dropTarget;
to never be dropTarget which will basically be a null object.
Null objects will not have attributes.
So
Alert.show("Verbindung hergestellt zwischen \n"+startconnector.name+" und "+endconnector.name);
Will error out because of the request of an attribute on a null object
endconnector.name

Related

Actionscript 3: Access movieclips from array with for-loop

I am having some trouble with accessing the movieclips I've added as childs. From what I've read, a way to solve this is to add every new movieclip to an array, and then loop through this array when I want to change something about all the movieclips.
In my case I want to scale them.
This is how I've tried to implement this function:
package
{
import flash.display.MovieClip;
import flash.utils.Dictionary;
import flash.events.MouseEvent;
import Airport;
public class Main extends Sprite
{
public var tile:MovieClip
public var bg_image:Sprite;
public var airport:Airport;
public static var airportDict:Dictionary = new Dictionary();
public static var collectedAirportArray:Array = new Array();
public function Main()
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// airportDict is being filled up here.. but that's not really relevant for my problem
bg_image = new Image();
addChild(bg_image);
bg_image.addEventListener(MouseEvent.CLICK, testfunction);
for (var k:Object in airportDict)
{
var airport:Airport = new Airport(k,airportDict[k]["x"], airportDict[k]["y"]);
collectedAirportArray.push(collectedAirportArray);
bg_image.addChild(airport);
}
}
private function testfunction(evt:MouseEvent):void
{
for each (tile in collectedAirportArray)
{
tile.scaleY = 2 * tile.scaleY;
}
}
}
}
This give me the error message TypeError: Error #1034: Type Coercion failed: cannot convert []#30977eb1 to flash.display.MovieClip.
at Main/testfunction() when clicking on the bg_image
You have an error in where you are making the array. You have there collectedAirportArray.push(collectedAirportArray); - you're basically pushing an array into itself. Nice snakey, they said. You should instead push the newly created airport in there:
collectedAirportArray.push(airport);
If your airport is any kind of DisplayObject your code should work.
What AirPort class is extending? If it extends MovieClip then try type casting like so:
private function testfunction(evt:MouseEvent):void
{
for each (tile in collectedAirportArray)
{
var myTile:MovieClip = MovieClip(tile);
myTile.scaleY = 2 * myTile.scaleY;
}
}

Adding eventlisteners in main document class for external classes

I have a small project I'm trying to help learn as3. It is a variation from the book Foundation Game Design with Actionscript 3.0. I am using an fla only to have a document class. All art is loaded within the as files. In the book, he just put all the code in the document class, I followed along and it worked as expected. I am trying to break out the code into separate classes to get a handle on OOP. One class makes a background - Background.as, one makes a character - Character.as, and one makes a button, which I instantiate 6 times for 6 different buttons - GameButton.as. And of course there is GameWorld.as which is the document class. Everything loads and shows up as expected. However when I try and add an eventListener for the buttons, I don't get any response. I have tried putting the eventListener in the GameButton.as and also tried it in the GameWorld.as neither of which has worked. Also I pass a reference to the stage when instantiating the various classes, because when I tried to addChild in the GameWorld.as, nothing would show up. I searched the site and found something similar, but it didn't seem to help. Thank you in advance for any advice you my have. Here is the code:
GameWorld.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.DisplayObject
import flash.events.MouseEvent;
import GameButton;
import Character;
import Background;
[SWR(width = "550", height = "400", backgroundColor = "#FFFFFF", frameRate = "60")]
public class GameWorld extends Sprite
{
//public variables
//Background
public var gameBackground:Background;
//Character
public var catCharacter:Character;
//Buttons
public var upButton:GameButton;
public var downButton:GameButton;
public var growButton:GameButton;
public var shrinkButton:GameButton;
public var vanishButton:GameButton;
public var spinButton:GameButton;
public function GameWorld ()
{
//Add the background to the stage
gameBackground = new Background("../images/background.png", stage);
//Add the character(s) to the stage
catCharacter = new Character("../images/character.png", stage);
//Set initial character position
catCharacter.CharacterPos(225, 150);
//Add the buttons to the stage
upButton = new GameButton("../images/up.png", stage, 25, 25);
downButton = new GameButton("../images/down.png", stage, 25, 85);
growButton = new GameButton("../images/grow.png", stage, 25, 145);
shrinkButton = new GameButton("../images/shrink.png", stage, 425, 25);
vanishButton = new GameButton("../images/vanish.png", stage, 425, 85);
spinButton = new GameButton("../images/spin.png", stage, 425, 145);
//Button event handlers
upButton.addEventListener(MouseEvent.CLICK, upButtonHandler);
}
public function upButtonHandler(event:MouseEvent)
{
trace("You clicked the up button!");
catCharacter.CharacterMove(15);
}
}
}
GameButton.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.MouseEvent;
public class GameButton extends Sprite
{
//public variables
public var stageRef:Stage;
public var urlRequest:URLRequest;
public var gameButtonLoader:Loader;
public var gameButtonSprite:Sprite;
//Constructor
public function GameButton (urlRequest:String, stageRef:Stage, xPos:Number, yPos:Number)
{
this.stageRef = stageRef
this.urlRequest = new URLRequest();
gameButtonLoader = new Loader();
gameButtonSprite = new Sprite();
this.urlRequest.url = urlRequest;
gameButtonLoader.load(this.urlRequest);
gameButtonSprite.addChild(gameButtonLoader);
this.stageRef.addChild(gameButtonSprite);
gameButtonSprite.buttonMode = true;
gameButtonSprite.x = xPos;
gameButtonSprite.y = yPos;
}
}
}
Character.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
public class Character
{
//private variables
private var stageRef:Stage;
private var urlRequest:URLRequest;
private var characterLoader:Loader;
private var characterSprite:Sprite;
//public variables
public var character_x_pos:Number;
public var character_y_pos:Number;
//Constructor
public function Character (urlRequest:String, stageRef:Stage)
{
this.stageRef = stageRef;
this.urlRequest = new URLRequest();
characterLoader = new Loader();
characterSprite = new Sprite();
this.urlRequest.url = urlRequest;
characterLoader.load (this.urlRequest);
characterSprite.addChild (characterLoader);
this.stageRef.addChild (characterSprite);
characterSprite.mouseEnabled = false;
}
//Set the position of the character
public function CharacterPos(xPos:Number, yPos:Number):void
{
characterSprite.x = xPos;
characterSprite.y = yPos;
}
//Move the position of the character
public function CharacterMove( yPos:Number):void
{
characterSprite.y -= yPos;
}
}
}
Background.as
package
{
import flash.net.URLRequest;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.Stage;
public class Background
{
//Private variables
private var stageRef:Stage;
private var urlRequest:URLRequest;
private var backgroundLoader:Loader;
private var backgroundSprite:Sprite;
//Constructor
public function Background (urlRequest:String, stageRef:Stage)
{
this.stageRef = stageRef;
this.urlRequest = new URLRequest();
backgroundLoader = new Loader();
backgroundSprite = new Sprite();
this.urlRequest.url = urlRequest;
backgroundLoader.load (this.urlRequest);
backgroundSprite.addChild (backgroundLoader);
this.stageRef.addChild (backgroundSprite);
backgroundSprite.mouseEnabled = false;
}
}
}
All art is loaded within the as files.
This is not an approach I recommend. There's a reason God gave us the Flash IDE--and it's not to write code! Any time you're spending on layout and viduals in code is just wasted, unless you have an actual requirement to change the visuals at runtime. The fact that your paths are all hard-coded suggests that you don't have that requirement.
So let's step back and imagine that you have a Symbol that contains 6 Symbols that you've created as just Flash buttons (when you select Button as the Symbol type). These will be SimpleButtons, but in the Class below we're just going to type them as DisplayObject. The Class doesn't care what they are, but using Simplebutton gives them up, over, down and hit states that require no code.
Note that the below assumes you have "automatically declare stage instances" off, which is IMO the best way to do things.
package view {
public class NavBar extends Sprite {
//because you put these on stage in the Symbol, they will be available in the constructor
public var upButton:DisplayObject;
public var downButton:DisplayObject;
public var growButton:DisplayObject;
public var shrinkButton:DisplayObject;
public var rotateButton:DisplayObject;
public var vanishButton:DisplayObject;
//makes it easier to do the same setup on all buttons
protected var allButtons:Vector.<DisplayObject> = <DisplayObject>([upButton, downButton, growButton, shrinkButton, rotateButton, vanishButton]);
public function NavBar() {
super();
for each (var btn:DisplayObject in allButtons) {
btn.buttonMode = true;
btn.mouseChildren = false;
btn.addEventListener(MouseEvent.CLICK, onButtonClick);
}
}
protected function onButtonClick(e:MouseEvent):void {
switch (e.target) {
case upButton:
dispatchEvent(new CharacterEvent(CharacterEvent.UP));
break;
case downButton:
dispatchEvent(new CharacterEvent(CharacterEvent.DOWN));
break;
case growButton:
dispatchEvent(new CharacterEvent(CharacterEvent.GROW));
break;
case shrinkButton:
dispatchEvent(new CharacterEvent(CharacterEvent.SHRINK));
break;
case rotateButton:
dispatchEvent(new CharacterEvent(CharacterEvent.ROTATE));
break;
case vanishButton:
dispatchEvent(new CharacterEvent(CharacterEvent.VANISH));
break;
default:
break;
}
}
}
}
Note that there's zero layout code. This code is dependent on a custom Event Class. I'm going to write that Event Class so that it always bubbles. That way, it can be dispatched anywhere on the display list and received at the top level:
package control {
class CharacterEvent extends Event {
public static var UP:String = 'characterUp';
public static var DOWN:String = 'characterDown';
public static var GROW:String = 'characterGrow';
public static var SHRINK:String = 'characterShrink';
public static var ROTATE:String = 'characterRotate';
public static var VANISH:String = 'characterVanish';
public function CharacterEvent(type:String) {
super(type, true, true);//always bubbles
}
public function clone():Event {
return new CharacterEvent(type);
}
}
}
Now, if you want to manually handle instantiation of the Symbol that has view.NavBar as its base class, it will look like this:
package {
public var navBar:NavBar;
class GameWorld {
public function GameWorld() {
try {
var navClass:Class = getDefinitionByName('NavBarSymbol') as Class;
} catch (e:Error) {
trace('You need to have a Library symbol called NavBarSymbol');
}
if (navClass) {
navBar = new navClass() as NavBar;
//unnecessary layout code here
//Note that this is NOT the responsibility of the child Class!
addChild(navBar);
}
//instantiate character
...
//by listening to the whole Document, you can add other things that
//dispatch Character events on the display list, like a keyboard listener
addEventListener(CharacterEvent.UP, moveCharacterUp);
//listeners for the rest of the character events...
}
public function moveCharacterUp(e:CharacterEvent):void {
//character move logic
}
//other handlers
}
}
Personally, I'd just add the navBar to the stage, and then there's no need to manage it at all (not even reference it with a variable), simply add the event listeners for the various character events.
The root of your problem doesn't seem to be the character code. However, I'm going to give you a few "best practice" pointers about it.
The convention in AS3 is for Class members (properties and methods) to be camel case starting with a lower case letter. So, characterPos() and characterMove().
Your Class already contains character in the name, so really these should just be pos() and move() (though there's no need now to shorten position()).
The only thing your child Classes are doing with their references to the parent are adding themselves. They don't need and shouldn't have a reference to the parent for this purpose. It is the parent's responsibility to add the Children (or the responsibility of the Flash Player if you use the stage).
That said, you could give your Character a reference to the parent Class typed as IEventDispatcher and allow the Character to listen to this channel. This concept is called an event bus.
Note that the reason that so many people do what you're doing is that Adobe failed to document how to properly use OOP with the timeline. Unfortunately, by the time a few of us started documenting that around late 2009/early 2010, the damage was done and everyone assumed that if you wanted to write good code you had to pretend the timeline and stage didn't exist.
I know I've covered a lot of ground, and probably most of what I said directly contradicts what you thought you knew, so please don't hesitate to ask any questions you might have.

AS3 public variable won't store values

first time poster here.
So I'm building a "multi-RSS feed reader" and I've broken this into 2 classes, a "TechFeed.as" and a "Feed.as"; The tech feed instantiates multiple feeds by passing URL's to a new Feed object.
My issue at the moment is that in the Feed.as I have a couple public variables which are used in TechFeed.as to display basic details about the feed, however, these variables refuse to retain any value I give them within Feed.as's functions, and are turning up "null".
Edit: Also maybe something to note; TechFeed.as is the main AS file the stage uses.
TechFeed.as
package {
import flash.display.MovieClip;
public class TechFeed extends MovieClip {
private var feed_one:Feed = new Feed("http://feeds.feedburner.com/crunchgear");
private var feed_two:Feed = new Feed("http://feeds.mashable.com/Mashable");
private var feed_three:Feed = new Feed("http://www.engadget.com/rss.xml");
public function TechFeed() {
trace(feed_one.feed_title);
//feed_name.text = feed_one.getFeedTitle();
}
}
}
Feed.as
package {
import flash.net.URLLoader;
import flash.events.Event;
import flash.net.URLRequest;
public class Feed {
//Public variables to display feed info
public var feed_title:XMLList;
public var feed_desc:String;
public var feed_link:String;
//Setting up variables which help load the feeds
private var feedXML:XML;
//Create a loader to load an external URL
private var loader:URLLoader = new URLLoader();
public function Feed(inURL:String = "") {
//Load the xml document
loader.load(new URLRequest(inURL));
loader.addEventListener(Event.COMPLETE,onLoaded);
}
//When the loader had loaded the xml document, pass that into a variable for use.
private function onLoaded(e:Event):void {
feedXML = new XML(e.target.data);
// break down the xml document elements into singular XML array lists
//Feed details
this.feed_title = feedXML.channel.title;
this.feed_link = feedXML.channel.link;
this.feed_desc = feedXML.channel.description;
trace(this.feed_title);
}
}
}
Any help will be greatly appreciated :)
Thanks,
Geoff
Your problem is timing you are trying to write the data from the feed before it is returned from the server.
In this example I assign a function to call back on when the data is loaded.
package {
import flash.display.MovieClip;
public class TechFeed extends MovieClip {
private var feed_one:Feed;
private var feed_two:Feed;
private var feed_three:Feed;
public function TechFeed() {
feed_one= new Feed("http://feeds.feedburner.com/crunchgear",assignResults);
feed_two= new Feed("http://feeds.mashable.com/Mashable",assignResults);
feed_three= new Feed("http://www.engadget.com/rss.xml",assignResults);
}
public function assignResults(value:value):void{
feed_name.text = value;
}
}
}
package {
import flash.net.URLLoader;
import flash.events.Event;
import flash.net.URLRequest;
public class Feed {
//Public variables to display feed info
public var feed_title:XMLList;
public var feed_desc:String;
public var feed_link:String;
//Setting up variables which help load the feeds
private var feedXML:XML;
//Create a loader to load an external URL
private var loader:URLLoader = new URLLoader();
private var _callBackFunc:Function;
public function Feed(inURL:String = "", callBackFunc:Function) {
this._callBackFunc = callBackFunc;
//Load the xml document
loader.load(new URLRequest(inURL));
loader.addEventListener(Event.COMPLETE,onLoaded);
}
//When the loader had loaded the xml document, pass that into a variable for use.
private function onLoaded(e:Event):void {
feedXML = new XML(e.target.data);
// break down the xml document elements into singular XML array lists
//Feed details
this.feed_title = feedXML.channel.title;
this.feed_link = feedXML.channel.link;
this.feed_desc = feedXML.channel.description;
this._callBackFunc(this.feed_title);
}
}
}
If the problem is that feed_one.feed_title is coming up null in the TechFeed() ctor, that is because you are not waiting for the feed to finish loading.
What you aught to do is dispatch an event from the Feed when it is done loading and processing the data, catch it in TechFeed and then use the public variables as you please (this also means that your Feed class will have to subclass EventDispatcher):
In Feed class:
private function onLoaded(e:Event):void {
feedXML = new XML(e.target.data);
// break down the xml document elements into singular XML array lists
//Feed details
this.feed_title = feedXML.channel.title;
this.feed_link = feedXML.channel.link;
this.feed_desc = feedXML.channel.description;
trace(this.feed_title);
dispatchEvent(new Event(Event.COMPLETE));////Dispatch Event
}
In TechFeed class:
public function TechFeed() {
trace(feed_one.feed_title);//This will trace "null"
feed_one.addEventListener(Event.COMPLETE, dataLoaded);//add event listener
}
private function dataLoaded(e:Event):void{
var feed = Feed(e.currentTarget);
feed.removeEventListener(Event.COMPLETE, dataLoaded);//remove event listener to prevent memory leaks
trace(feed.feed_title);// This will trace the correct title
}

Initialize Assets after Preload

Whenever I export the .swf file of my Flash game, I am receiving "TypeError: Error #1009: Cannot access a property or method of a null object reference.", along with a Runtime Shared Library Preloading Warning for my preloader. I have my timeline organized so that the first and third frames are both empty along with a stop(); command in the Actions layer. The second frame contains a single MovieClip that contains all of my exported assets, which are going to be initialized in the third frame of the timeline. None of my assets, except for the preloader, are exported in the first frame. What changes should I make to my Document Class for it to initialize the assets in the third frame?
Document Class:
package com.gameEngine.documentClass
{
import flash.events.*;
import flash.display.*;
import flash.geom.Point;
import com.gameEngine.assetHolders.*;
import com.gameEngine.assetHolders.Levels.*;
public class Document extends MovieClip
{
private static var _document:Document;
private var preloader:Preloader;
public var mcMain:Player;
public var restartButton:RestartButton;
public var spawnArea:SpawnArea;
public var level_1:Level_1;
public var level_2:Level_2;
public var level_3:Level_3;
public function Document()
{
addEventListener(Event.ADDED_TO_STAGE, init);
_document = this;
preloader = new Preloader(390, this.loaderInfo);
this.addChild(preloader);
preloader.addEventListener("loadComplete", loadAssets);
preloader.addEventListener("preloaderFinished", showLogo);
mcMain = new Player(this);
restartButton = new RestartButton(this);
spawnArea = new SpawnArea();
level_1 = new Level_1(this);
level_2 = new Level_2(this);
level_3 = new Level_3(this);
this.addChild(restartButton);
this.addChild(spawnArea);
this.preloader.x = 400;
this.preloader.y = 250;
restartButton.x = 822.95;
restartButton.y = 19;
spawnArea.x = 400;
spawnArea.y = 250;
trace ("Document Class Initialized");
// constructor code
}
public static function getInstance():Document
{
return _document;
}
private function loadAssets(event:Event):void
{
this.play();
}
private function showLogo(event:Event):void
{
this.removeChild(preloader);
}
public function init(event:Event)
{
if (stage.contains(spawnArea))
{
addChild(mcMain);
}
mcMain.x = spawnArea.x;
mcMain.y = spawnArea.y;
}
}
}
Preloader Class:
package com.gameEngine.assetHolders
{
import com.gameEngine.documentClass.*;
import flash.display.*;
import flash.events.*;
public class Preloader extends MovieClip
{
private var fullWidth:Number;
public var loaderInfo:LoaderInfo;
public function Preloader(fullWidth:Number = 0, loaderInfo:LoaderInfo = null)
{
this.fullWidth = fullWidth;
this.loaderInfo = loaderInfo;
addEventListener(Event.ENTER_FRAME, checkLoad);
}
private function checkLoad (event:Event):void
{
if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal && loaderInfo.bytesTotal != 0)
{
dispatchEvent(new Event("loadComplete"));
phaseOut();
}
updateLoader(loaderInfo.bytesLoaded / loaderInfo.bytesTotal);
}
private function updateLoader(num:Number):void
{
progressBar.width = num * fullWidth;
}
private function phaseOut():void
{
removeEventListener(Event.ENTER_FRAME, checkLoad);
progressBar.gotoAndPlay(2);
if (progressBar.currentFrame == progressBar.totalFrames)
{
phaseComplete();
}
}
private function phaseComplete() : void
{
dispatchEvent(new Event("preloaderFinished"));
}
}
}
You have a lot of race conditions going on here. Many of these events could occur at relatively random times in relation to one another . . . you have to think asynchronously. That is, there can be no assumption that any object exists. E.g., in Document.init(), you check is if the spawnArea exists, but it is almost guaranteed not to at that point, and you never check for it again.
Without making any specific changes, I can recommend a generic solution. For any object (objB) you want loaded after another object (objA) is loaded, have objB created in the objA's ADDED_TO_STAGE handler. A simple example would be:
var objA:Whatever;
var objB:WhateverElse;
[...]
objA = new Whatever();
objA.addEventListener(Event.ADDED_TO_STAGE, objAAddedHnd);
[...]
public function objAAddedHnd(event:Event)
{
// remove the event, if no longer needed:
objA.removeEventListener(Event.ADDED_TO_STAGE, objAAddedHnd);
objB = new WhateverElse();
objB.addEventListener(Event.ADDED_TO_STAGE, objBAddedHnd);
}
[...]
public function objBAddedHnd(event:Event)
{
// remove the event, if no longer needed:
objB.removeEventListener(Event.ADDED_TO_STAGE, objBAddedHnd);
// and so on . . .
}
At this point, it shows that you would need to plan the timeline of object creation.

Error #1034, with a MouseEvent

I am making a basic point n' click game and I came upon this error:
TypeError: Error #1034: Type Coercion failed: cannot convert 3 to cem.mouvement.
Here's my script:
package cem {
import flash.events.Event;
import flash.display.MovieClip;
import cem.microjeux.events.InfoJeuEvent;
import cem.mouvement;
import flash.events.MouseEvent;
public class monterJeu extends MovieClip
{
private static var pType:String = "type";
private static var pNom:String = "testNom";
private static var pCourriel:String = "test#hotmail.com";
private static var pDifficulte:int = 0;
private static var pLangue:int = 0;
private static var pTitre:String = "Veuillez sortir";
private static var pVersion:String = "1.5";
private static var pCoordonnees:Number;
private var environnementJeu:environnement = new environnement();
private var personnageJeu:personnage = new personnage();
public function monterJeu():void
{
jouer(pNom,pDifficulte,pLangue);
dispatchEvent(new InfoJeuEvent(pType,pNom,pCourriel,pTitre,pVersion));
stage.addEventListener(MouseEvent.CLICK, test);
}
public function jouer(PNom:String,PDifficulte:int,PLangue:int):void
{
addChild(environnementJeu);
addChild(personnageJeu);
}
function test(e:MouseEvent){
pCoordonnees = stage.mouseX;
trace(pCoordonnees);
mouvement(3);
}
}
}
And on mouvement();
package cem
{
public class mouvement {
public function mouvement(blabla) {
trace(blabla);
}
}
}
I searched everywhere I could, and didn't find anything. I have no instances on the stage. Everything is imported on the first frame. I am kind of a beginner (let's say i'm no good at programming), so you can notify at the same time if you something that needs to be corrected. (BTW, the strange words are in french ;D)
Thanks!
The error is due to you trying to cast 3 to mouvement.
I think what you want is something like
function test(e:MouseEvent){
pCoordonnees = stage.mouseX;
trace(pCoordonnees);
var mouve:mouvement = new mouvement(3);
}
Notice that you have to have new in order to create a new instance of a class.
On another note, you should capitilize classes so they stand out better. So I would name the class Mouvement.
You are trying to cast 3 to the class mouvement into the test function:
function test(e:MouseEvent){
pCoordonnees = stage.mouseX;
trace(pCoordonnees);
new mouvement().mouvement(3); // <-- here your error
}
If you have only a function into your class you don't need to create a class but you can put on the function alone:
package cem
{
public function mouvement(blabla):void {
trace(blabla);
}
}
and now you can call the mpuvement function normally into you test function:
function test(e:MouseEvent){
pCoordonnees = stage.mouseX;
trace(pCoordonnees);
mouvement(3);
}