Add child to scene from within a class - actionscript-3

I'm new to flash in general and have been writing a program with two classes that extend MovieClip (Stems and Star).
I need to create a new Stems object as a child of the scene when the user stops dragging a Star object, but do not know how to reference the scene from within the Star class's code.
I've tried passing the scene into the constructor of the Star and doing sometihng like:
this.scene.addChild (new Stems ());
But apparently that's not how to do it... Below is the code for Stems and Stars, any advice would be appreciated greatly.
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.Timer;
public class Stems extends MovieClip {
public const centreX=1026/2;
public const centreY=600/2;
public var isFlowing:Boolean;
public var flowerType:Number;
public const outerLimit=210;
public const innerLimit=100;
public function Stems(fType:Number) {
this.isFlowing=false;
this.scaleX=this.scaleY= .0007* distanceFromCentre(this.x, this.y);
this.setXY();
trace(distanceFromCentre(this.x, this.y));
if (fType==2) {
gotoAndStop("Aplant");
}
}
public function distanceFromCentre(X:Number, Y:Number):int {
return (Math.sqrt((X-centreX)*(X-centreX)+(Y-centreY)*(Y-centreY)));
}
public function rotateAwayFromCentre():void {
var theX:int=centreX-this.x;
var theY:int = (centreY - this.y) * -1;
var angle = Math.atan(theY/theX)/(Math.PI/180);
if (theX<0) {
angle+=180;
}
if (theX>=0&&theY<0) {
angle+=360;
}
this.rotation = ((angle*-1) + 90)+180;
}
public function setXY() {
do {
var tempX=Math.random()*centreX*2;
var tempY=Math.random()*centreY*2;
} while (distanceFromCentre (tempX, tempY)>this.outerLimit ||
distanceFromCentre (tempX, tempY)<this.innerLimit);
this.x=tempX;
this.y=tempY;
rotateAwayFromCentre();
}
public function getFlowerType():Number {
return this.flowerType;
}
}
}
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.Timer;
public class Star extends MovieClip {
public const sWide=1026;
public const sTall=600;
public var startingX:Number;
public var startingY:Number;
public var starColor:Number;
public var flicker:Timer;
public var canUpdatePos:Boolean=true;
public const innerLimit=280;
public function Star(color:Number, basefl:Number, factorial:Number) {
this.setXY();
this.starColor=color;
this.flicker = new Timer (basefl + factorial * (Math.ceil(100* Math.random ())));
this.flicker.addEventListener(TimerEvent.TIMER, this.tick);
this.addEventListener(MouseEvent.MOUSE_OVER, this.hover);
this.addEventListener(MouseEvent.MOUSE_UP, this.drop);
this.addEventListener(MouseEvent.MOUSE_DOWN, this.drag);
this.addChild (new Stems (2));
this.flicker.start();
this.updateAnimation(0, false);
}
public function distanceOK(X:Number, Y:Number):Boolean {
if (Math.sqrt((X-(sWide/2))*(X-(sWide/2))+(Y-(sTall/2))*(Y-(sTall/2)))>innerLimit) {
return true;
} else {
return false;
}
}
public function setXY() {
do {
var tempX=this.x=Math.random()*sWide;
var tempY=this.y=Math.random()*sTall;
} while (distanceOK (tempX, tempY)==false);
this.startingX=tempX;
this.startingY=tempY;
}
public function tick(event:TimerEvent) {
if (this.canUpdatePos) {
this.setXY();
}
this.updateAnimation(0, false);
this.updateAnimation(this.starColor, false);
}
public function updateAnimation(color:Number, bright:Boolean) {
var brightStr:String;
if (bright) {
brightStr="bright";
} else {
brightStr="low";
}
switch (color) {
case 0 :
this.gotoAndStop("none");
break;
case 1 :
this.gotoAndStop("N" + brightStr);
break;
case 2 :
this.gotoAndStop("A" + brightStr);
break;
case 3 :
this.gotoAndStop("F" + brightStr);
break;
case 4 :
this.gotoAndStop("E" + brightStr);
break;
case 5 :
this.gotoAndStop("S" + brightStr);
break;
}
}
public function hover(event:MouseEvent):void {
this.updateAnimation(this.starColor, true);
this.canUpdatePos=false;
}
public function drop(event:MouseEvent):void {
this.stopDrag();
this.x=this.startingX;
this.y=this.startingY;
this.updateAnimation(0, false);
this.canUpdatePos=true;
}
public function drag(event:MouseEvent):void {
this.startDrag(false);
this.canUpdatePos=false;
}
}
}

The fastest way would be to use the parent variable which references the DisplayObject parent.
var stem:Stems = new Stems(2);
stem.x = x; //optional: set stem coordinates to that of Star
stem.y = y;
parent.addChild(stem);
If you want to add the Stems object to the stage every time a star-drag action stops you need to put the above code inside your drop function.

Related

ActionScript3, dropping on stage not working after using MouseEnabled

I'm trying to do do a BattleShip Flash game using ActionScript 3.
1- I draw a grid (class: com.Battleship.grid) using a gridCell:movieClip (class: com.battleship.GridCell)
2- I draw a ship (class: com.battleship.Bateau)
My objective is when I drag the ship to the grid the alpha cell under the mouse changes, and if I drop:
1- if the droptarget is a gridCell, the ship takes place (works fine)
2- if the droptarget is stage, the ship return to originPosition (not working)
My problem: after I used MouseEnabled= false, the ship can drop on the grid, but not on the stage and still dragging.
Here is my code:
var grid:Grid = new Grid(10,new Point(20,20));
var b1:Bateau = new Bateau();
b1.x = 490;
b1.y = 300;
b1.originPos = new Point(b1.x,b1.y);
addChild(b1)
addChild(grid);
package com.battleship {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
public class Bateau extends MovieClip {
private var _originPos:Point;
public function Bateau() {
originPos = new Point();
buttonMode = true;
addEventListener(MouseEvent.MOUSE_DOWN, onDrag);
}
protected function onDrag(e:MouseEvent):void
{
e.currentTarget.parent.addChild(e.currentTarget);
e.currentTarget.startDrag();
e.currentTarget.mouseEnabled = false;
//e.currentTarget.mouseChildren = false;
addEventListener(MouseEvent.MOUSE_UP, onDrop);
parent.addEventListener(MouseEvent.MOUSE_UP, onDrop);
}
protected function onDrop(e:MouseEvent):void
{
e.currentTarget.mouseEnabled = true;
e.currentTarget.mouseChildren = true;
e.currentTarget.stopDrag();
if(dropTarget == null){
x = originPos.x;
y = originPos.y;
}else{
trace(e.currentTarget.name);
if(dropTarget.parent is GridCell)
{
x = dropTarget.parent.x+20;
y = dropTarget.parent.y;
}
}
}
public function get originPos():Point
{
return _originPos;
}
public function set originPos(originPos:Point):void
{
_originPos = originPos;
}
}
}
package com.battleship {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class GridCell extends MovieClip {
private var _row:int;
private var _col:int;
private var _val:int;
public function GridCell()
{
addEventListener(MouseEvent.CLICK,onClick);
addEventListener(MouseEvent.MOUSE_OVER,onMouseOver);
addEventListener(MouseEvent.MOUSE_OUT,onMouseOut);
}
public function onClick(e:MouseEvent)
{
//trace("(" + e.currentTarget.row+ ", " + e.currentTarget.col + ")");
trace(e.currentTarget.name);
}
public function onMouseOver(e:MouseEvent)
{
alpha = 0.6;
}
public function onMouseOut(e:MouseEvent)
{
alpha = 1;
}
public function get row():int
{
return _row;
}
public function set row(row:int):void
{
_row = row;
}
public function get col():int
{
return _col;
}
public function set col(col:int):void
{
_col = col;
}
public function get val():int
{
return _val;
}
public function set val(val:int):void
{
_val = val;
}
}
}
package com.battleship {
import flash.geom.Point;
import flash.display.Sprite;
import flash.events.MouseEvent;
public class Grid extends Sprite {
private var _size:int;
private var _position:Point;
public function Grid(size:int,position:Point):void
{
_size = size;
_position = position;
var gridCells:Array = new Array(size,size);
var i,j:int;
for(i=0;i<size;i++)
{
gridCells[i] = new Array();
for(j=0;j<size;j++)
{
var cell:GridCell = new GridCell();
cell.row = j+1;
cell.col = i+1;
cell.x = this.position.x + cell.width * (i+1);
cell.y = this.position.x + cell.height * (j+1);
cell.name = "cell" + (j+1) + (i+1);
//cell.addEventListener(MouseEvent.CLICK,onClick);
gridCells[i][j] = cell;
this.addChild(gridCells[i][j]);
}
}
}
public function get size():int
{
return _size;
}
public function set size(size:int):void
{
_size = size;
}
public function get position():Point
{
return _position;
}
public function set position(position:Point):void
{
_position = position;
}
}
}

AS3 Trouble accessing a static class from inside a nested symbol

So basically this is a question about why my calling class (Door) can not identify this static variable class (Game State). it is throwing a #1009 error saying I can not access with GameState.gameState. On my stage I have a Symbol (CampaignLevel_001) that contains additional symbols like the calling symbol (Door) and above that as a separate Symbol (GameState) so essentially I am having trouble getting a nested symbol / class talking to another class.
package game.GameStates
{
import game.Assets.Player;
import game.Assets.Turret;
import game.Assets.Door;
import flash.events.Event;
import flash.display.MovieClip;
import flash.geom.Point;
import game.Levels.CampaignLevel_001;
public class GameState extends MovieClip
{
//VARIABLES
public var enemyArray : Array;
public var Bullets : Array = new Array();
public var Keys : Array = new Array();
public var HeldKeys : Array = new Array ();
public var Door : Array = new Array();
public var Terrain : Array = new Array();
public var Turrets : Array = new Array ();
public var Blood : Array = new Array ();
public var Shields : Array = new Array ();
public var Levels : Array = new Array ();
public var NumKeys : int;
public var DoorLock : Boolean = false;
public var PlayerSpawnPoint : Point;
public var CampaignSpawnPoint : Point;
public static var gameState : GameState;
public var player : Player;
public var turret : Turret;
public var PlayerLives : int = 99;
public function GameState()
{ // constructor code
gameState = this;
addEventListener(Event.ADDED_TO_STAGE, Awake);
} // constructor code
private function Awake (e : Event) : void
{
enemyArray = new Array();
trace(enemyArray.length);
}
public function OpenDoor () : void
{
if (NumKeys <= 0)
{
DoorLock = true;
}
if (NumKeys > 0)
{
DoorLock = false;
}
}
public function NextLevel () : void
{
RemoveListeners();
trace("SHOULD BE GOING TO THE NEXT LEVEL");
while (Levels.length > 0)
{
for each (var level in Levels)
{
level.NextLevel ();
}
}
}
public function RespawnPlayer () : void
{
//Spawn Player at player start point
player = new Player();
player.x = PlayerSpawnPoint.x;
player.y = PlayerSpawnPoint.y;
addChild(player);
trace("PLAYER ARRAY IS THIS LONG " + enemyArray.length);
trace("spawned Player!");
}
public function setSpellIcons (spell : String , opacity : int) : void
{
if (spell == "dodge")
{
if (opacity == 0)
{
dodgeSymbol.alpha = 0;
}
if (opacity == 1)
{
dodgeSymbol.alpha = 1;
}
}
if (spell == "shield")
{
if (opacity == 0)
{
shieldSymbol.alpha = 0;
}
if (opacity == 1)
{
shieldSymbol.alpha = 1;
}
}
} //public function setSpellIcons (spell : String , opacity : int) : void
public function RemoveListeners() : void
{
while (enemyArray.length > 0)
{
for each (var enemy : MovieClip in enemyArray)
{
enemy.RemovePlayer ();
}
}
while (Door.length > 0)
{
for each (var door : MovieClip in Door)
{
door.RemoveDoorFunctions ();
}
}
while (Bullets.length > 0)
{
for each (var bullet : MovieClip in Bullets)
{
bullet.RemoveProjectile();
}
}
while (Keys.length > 0)
{
for each (var key : MovieClip in Keys)
{
key.RemoveKey ();
}
}
while (Terrain.length > 0)
{
for each (var terrain : MovieClip in Terrain)
{
terrain.RemoveTerrainListeners();
}
}
while (Turrets.length > 0)
{
for each (var turret in Turrets)
{
turret.RemoveTurretListeners();
}
}
while (Blood.length > 0)
{
for each (var splatter in Blood)
{
splatter.RemoveBlood();
}
}
while (Shields.length > 0)
{
for each (var shield in Shields)
{
shield.RemoveShield();
}
}
} //public function RemoveListeners() : void
}
}
The Class that holds (door)
package game.Levels
{
import game.GameStates.GameState;
import flash.display.MovieClip;
import flash.events.Event;
public class CampaignLevel_001 extends MovieClip
{
var currentLevel : int = currentFrame;
public function CampaignLevel_001()
{ // constructor code
addEventListener(Event.ADDED_TO_STAGE, Awake);
}
private function Awake (e : Event) : void
{
GameState.gameState.Levels.push(this);
gotoAndStop(currentLevel);
trace ("CURRENT LEVEL IS " + currentLevel);
}
public function NextLevel () : void
{
var nextLevel : int = currentFrame + 1;
gotoAndStop(nextLevel);
trace ("NEXT LEVEL IS " + nextLevel);
}
}
}
and the calling class (door) is
package game.Assets
{
import flash.display.MovieClip;
import flash.events.Event;
import game.GameStates.GameState;
public class Door extends MovieClip
{
public function Door()
{ // constructor code
addEventListener(Event.ADDED_TO_STAGE, Awake);
}
private function Awake (e : Event) : void
{
GameState.gameState.Door.push(this);
GameState.gameState.OpenDoor ();
stage.addEventListener(Event.ENTER_FRAME, update);
open.alpha = 0;
}
private function update (e : Event) : void
{
if (GameState.gameState.DoorLock == true)
{
open.alpha = 1;
}
if (GameState.gameState.DoorLock == false)
{
open.alpha = 0;
}
}
public function RemoveDoorFunctions () : void
{
GameState.gameState.Door.splice(GameState.gameState.Door.indexOf(this),1);
stage.removeEventListener(Event.ENTER_FRAME, update);
parent.removeChild(this);
}
}
}
It looks like you're trying to make a Singleton, but haven't added the instance function.
change this:
public static var gameState:GameState;
to:
private static var _gameState:GameState;
and remove the constructor gamestate = this;
and add a function:
public static function get gameState():GameState {
if{_gameState == null) {
_gameState = new GameState();
}
return _gameState;
}
You can then call it and only get the one instance of GameState by:
GameState.gameState.DoorLock == true;
and any other function in GameState the same way

as3 addEventListner on a function in another class

I have a class calling a function in another class. I want to know
if we can add an Event Listener to know if that function has fired and is finished etc.
Here is the section of the code that is relevant.
myMC = new pictures();
addChild(myMC);
myMC.loadImages("Joyful",1)
// Add Event Listener here to let me know loadImages was called and worked.
As you can see the function is called loadImages() and it is located in a class called pictures.as
Can I add an event listener to this?
Here is a new issue. I am using a similar method and I used your example below and it did not work. Am I missing an import or something? I am only showing the functions that pertain and not my whole script.
Main.class
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.display.*;
import flash.filesystem.*;
import com.greensock.*;
import com.greensock.easing.*;
import flash.system.System;
// Ed's Scripts
import com.*;
import com.views.*;
public class iRosaryMain extends MovieClip
{
/// (Get Main Doc flow) this creates an instace of the main timeline
/// and then I send it
private static var _instance:iRosaryMain;
public static function get instance():iRosaryMain
{
return _instance;
}
/// Declaring Vars
var audio:audioPrayers;
/// Loading Images
//public var theImages:pictures = new pictures();
/// Movie Clips
public var myMary:beautifulMary;
public var myMC:MovieClip;
public var myPic:MovieClip;
public var myFlags:MovieClip;
public static var mt:MovieClip;
var vars:defaultVars = new defaultVars();
public function iRosaryMain()
{
// (Get Main Doc flow) Here I send the an instacne of iRosaryMain to defaultVars.as
_instance = this;
vars.getMainDoc(_instance);
// Sets timeline to mt :) I hope
mt = _instance;
audio = new audioPrayers();
trace("Jesus I trust in you!");// constructor code
audio.sayHailMary();
if (stage)
{
init();
}
}
public function moveLanguages()
{
/// File to languages folder
var checkLanguageFolder:File = File.applicationStorageDirectory.resolvePath("Languages");
///// CHECK LANGUAGES FOLDER - if not in App Storage move it
if (! checkLanguageFolder.exists)
{
var sourceDir:File = File.applicationDirectory.resolvePath("Languages");
var resultDir:File = File.applicationStorageDirectory.resolvePath("Languages");
sourceDir.copyTo(resultDir, true);
trace( "Moved Language!");
}
}
//// MAIN FUNCTIONS IN iRosaryMainClass
function init()
{
//loadFlags();
moveLanguages();
//addChild(theImages);
intro();
}
public function loadFlags()
{
myFlags.addEventListener("MyEvent", eventHandler);
myFlags = new viewLanguages();
addChild(myFlags);
myFlags.x = stage.stageWidth / 2 - myFlags.getBounds(this).width / 2;
function eventHandler()
{
trace("yes loaded");
TweenMax.fromTo(myMary,3, {alpha:1}, {alpha:0, ease:Quint.easeOut, onComplete: closePic} );
}
}
function intro()
{
myMary = new beautifulMary();
addChild(myMary);
loadFlags();
}
public function closePic()
{
removeChild(myMary);
}
public function languageLoaded(lang:String)
{
trace("YES... " + lang);
homeIn();
}
public function homeIn()
{
if (myFlags)
{
TweenMax.fromTo(myFlags,1, {x:myFlags.x}, {x:0-myFlags.width, ease:Quint.easeInOut, onComplete:unloadMyFlags} );
}
function unloadMyFlags()
{
trace("Called Ease out");
if (myFlags is MovieClip)
{
//trace("CURRENT DISPLAY " + currentDisplayScreen);
trace("CURRENT mc " + myFlags);
removeChild(myFlags);
System.gc();
myFlags = null;
trace("CURRENT mc " + myFlags);
}
}
if (! myMC)
{
myMC = new viewHome();
myMC.name = "Home";
myMC.x = stage.stageWidth / 2 - myMC.width / 2;
addChild(myMC);
}
theEaseIn(myMC);
//Home.B1.addEventListener(MouseEvent.CLICK, theEaseOut(Home));
}
public function loadLanguage(Language:String):Function
{
return function(e:MouseEvent):void ;
{
trace("Did it work? " +Language);
vars.loadButtonVars(Language);;
};
//TweenMax.fromTo(EnglishButton,1, {x:EnglishButton.x}, {x:0-EnglishButton.width, ease:Quint.easeOut} );
}
public function loadView(screen:String)
{
trace("Received " + screen);
if (screen=="Home")
{
myMC = new viewHome();
addChild(myMC);
theEaseIn(myMC);
//Home.B1.addEventListener(MouseEvent.CLICK, theEaseOut(Home));
}
if (screen=="PrayTheRosary")
{
myMC = new viewPrayTheRosary();
addChild(myMC);
theEaseIn(myMC);
//Home.B1.addEventListener(MouseEvent.CLICK, theEaseOut(Home));
}
if (screen=="Options")
{
myMC = new viewOptions();
addChild(myMC);
theEaseIn(myMC);
}
if (screen=="Downloads")
{
myMC = new viewDownloads();
addChild(myMC);
theEaseIn(myMC);
}
if (screen=="beautifulMary")
{
myMC = new beautifulMary();
addChild(myMC);
theEaseIn(myMC);
}
if (screen=="Flags")
{
myFlags = new viewLanguages();
addChild(myFlags);
theEaseIn(myFlags);
}
if (screen=="Joyful" || screen=="Sorrowful" || screen=="Glorious" || screen=="Luminous")
{
myPic = new pictures();
addChild(myPic);
myPic.addEventListener( "ImagesLoaded", doTheEaseIn);
myPic.loadImages(""+screen+"",1);
function doTheEaseIn()
{
theEaseIn(myPic);
}
}
}
public function theEaseIn(mc:MovieClip)
{
if (myMC)
{
TweenMax.fromTo(mc,1, {x:stage.stageWidth+mc.width}, {x:stage.stageWidth/2 - mc.width/2, ease:Quint.easeInOut} );
}
}
public function theEaseOut(mc:MovieClip,nextMC:String):Function
{
return function(e:MouseEvent):void ;
{
loadView(nextMC);
/// Tweens out view on screen
TweenMax.fromTo(mc,1, {x:mc.x}, {x:0-mc.width, ease:Quint.easeInOut, onComplete:unloadMC} );
function unloadMC();
{
trace("Called Ease out");
if(mc is MovieClip);
{
//trace("CURRENT DISPLAY " + currentDisplayScreen);
trace("CURRENT mc " + mc);
removeChild(mc);
System.gc();
myMC = null;
trace("CURRENT mc " + mc);
};
};
};/// end return
}
////////////
}/// End iRosaryMain
}// End Package
viewLanguages.as
package com.views
package com.views
{
import flash.display.MovieClip;
import flash.filesystem.File;
import com.roundFlag;
import flash.events.*;
import flash.display.*;
public class viewLanguages extends MovieClip
{
var Flag:MovieClip;
//public static const FLAGS_LOADED:String = "flagsLoaded";
public function viewLanguages()
{
getLang();
}
function numCheck(num:int):Boolean
{
return (num % 2 != 0);
}
/// Get for App Opening
public function getLang()
{
/// When Live
var folderLanguages:File = File.applicationStorageDirectory.resolvePath("Languages");
var availLang = folderLanguages.getDirectoryListing();
var Lang = new Array();
var LangPath = new Array();
var fl:int = 0;
for (var i:uint = 0; i < availLang.length; i++)
{
if (availLang[i].isDirectory)
{
//flag = new Loader();
//flag.load(new URLRequest(File.applicationStorageDirectory.url + "Languages/" + Lang[i] + "/roundFlag.png"));
Lang.push(availLang[i].name);
LangPath.push(availLang[i].nativePath);
Flag = new roundFlag(availLang[i].name);
Flag.name = availLang[i].name;
if (numCheck(i)==false)
{
Flag.y = fl;
Flag.x = 0;
}
else
{
Flag.y = fl;
Flag.x = Flag.width + 33;
fl = fl + Flag.height + 33;
}
Flag.btext.text = availLang[i].name;
addChild(Flag);
trace(availLang[i].nativePath);// gets the name
trace(availLang[i].name);
}
}
trace("Get Lang Called");
dispatchEvent(new Event("MyEvent"));
}
}
}
Yes, you can. Considering you are adding your clip to the display list I assume it extends either Movieclip or Sprite, both of which extend EventDispatcher. In your pictures class you can simply use dispatchEvent(new Event("MyEvent"); to dispatch an event. Then you could add myMC.addEventListener("MyEvent", eventHandler); to react to it.
You should also not use strings for events like I wrote above. It would be better if you declared a public static const IMAGES_LOADED:String = "imagesLoaded"; in your pictures class. Then you should use this constant by dispatching and by listening to it.
EDIT: Here how it would look with the constant:
//your class
package {
import flash.events.Event;
import flash.display.Sprite;
public class Pictures extends Sprite {
public static const IMAGES_LOADED:String = "imagesLoaded";
public function Pictures() {
}
public function onAllImagesLoaded():void {
dispatchEvent(new Event(IMAGES_LOADED));
}
//rest of your methods
}
}
//you would call it like this:
var myMc:Pictures = new Pictures();
myMc.addEventListener(Pictures.IMAGES_LOADED, onImagesLoaded);
myMc.loadImages();
function onImagesLoaded(e:Event):void {
//...etc
}
You have to create custom event class for this to work. Like:
package com.some
{
import flash.events.Event;
public class SomeEvent extends Event
{
// Loading events
public static const MAINDATA_LOADING:String = "onMainDataLoading";
// Other event
public static const SOME_LOADING:String = "onSomeLoading";
public var params:Object;
public function SomeEvent($type:String, $params:Object, $bubbles:Boolean = false, $cancelable:Boolean = false)
{
super($type, $bubbles, $cancelable);
this.params = $params;
}
public override function clone():Event
{
return new SomeEvent(type, this.params, bubbles, cancelable);
}
}
}
Add event dispatch inside wanted class (Pictures) and pass wanted params to event (this or any else)
dispatchEvent(new SomeEvent(SomeEvent.IMAGES_LOADED, this));
Handle event listening:
var myMc:Pictures = new Pictures();
myMc.addEventListener(SomeEvent.IMAGES_LOADED, onImagesLoaded);
myMc.loadImages();
function onImagesLoaded(e:SomeEvent):void {
// handle event.
var picts:Pictures = (e.params as Pictures);
}

Type 1083: Syntax error: package is unexpected

So, I got this .as file that is called, let say, class A.
class A inside has other 2 classes, class B and class C, and the only class that is inside a package is class A. And it throws that error.
I downloaded this as an example, and it should work, however Flash Builder 4.6 doesn't like it.
The structure of the as file is like this:
imports
variables
class B
class C
package
public class A
/package
Btw, I'm using Flash Builder not Flash CC.
Update, posting code:
import com.adobe.serialization.json.JSON;
import com.shephertz.appwarp.WarpClient;
import com.shephertz.appwarp.listener.ConnectionRequestListener;
import com.shephertz.appwarp.listener.NotificationListener;
import com.shephertz.appwarp.listener.RoomRequestListener;
import com.shephertz.appwarp.listener.ZoneRequestListener;
import com.shephertz.appwarp.messages.Chat;
import com.shephertz.appwarp.messages.LiveResult;
import com.shephertz.appwarp.messages.LiveRoom;
import com.shephertz.appwarp.messages.LiveUser;
import com.shephertz.appwarp.messages.Lobby;
import com.shephertz.appwarp.messages.MatchedRooms;
import com.shephertz.appwarp.messages.Move;
import com.shephertz.appwarp.messages.Room;
import com.shephertz.appwarp.types.ResultCode;
import flash.utils.ByteArray;
var APIKEY:String = "key";
var SECRETEKEY:String = "secretkey";
var Connected:Boolean = false;
var INITIALIZED:Boolean = false;
var client:WarpClient;
var roomID:String;
var State:int = 0;
var User:String;
class connectionListener implements ConnectionRequestListener
{
private var connectFunc:Function;
public function connectionListener(f:Function)
{
connectFunc = f;
}
public function onConnectDone(res:int):void
{
if(res == ResultCode.success)
{
Connected = true;
}
else
{
Connected = false;
}
connectFunc(res);
}
public function onDisConnectDone(res:int):void
{
Connected = false;
}
}
class roomListener implements RoomRequestListener
{
private var connectFunc:Function;
private var joinFunc:Function;
public function roomListener(f:Function,f1:Function)
{
connectFunc = f;
joinFunc = f1;
}
public function onSubscribeRoomDone(event:Room):void
{
if(State == 2)
joinFunc();
else
connectFunc();
}
public function onUnsubscribeRoomDone(event:Room):void
{
}
public function onJoinRoomDone(event:Room):void
{
if(event.result == ResultCode.resource_not_found)
{
if(State == 1)
{
State = 3;
}
client.createRoom("room","admin",2,null);
}
else if(event.result == ResultCode.success)
{
if(State == 1)
{
State = 2;
}
roomID = event.roomId;
client.subscribeRoom(roomID);
}
}
public function onLeaveRoomDone(event:Room):void
{
client.unsubscribeRoom(roomID);
}
public function onGetLiveRoomInfoDone(event:LiveRoom):void
{
}
public function onSetCustomRoomDataDone(event:LiveRoom):void
{
}
public function onUpdatePropertyDone(event:LiveRoom):void
{
}
public function onLockPropertiesDone(result:int):void
{
}
public function onUnlockPropertiesDone(result:int):void
{
}
public function onUpdatePropertiesDone(event:LiveRoom):void
{
}
}
class zoneListener implements ZoneRequestListener
{
public function onCreateRoomDone(event:Room):void
{
roomID = event.roomId;
client.joinRoom(roomID);
}
public function onDeleteRoomDone(event:Room):void
{
}
public function onGetLiveUserInfoDone(event:LiveUser):void
{
}
public function onGetAllRoomsDone(event:LiveResult):void
{
}
public function onGetOnlineUsersDone(event:LiveResult):void
{
}
public function onSetCustomUserInfoDone(event:LiveUser):void
{
}
public function onGetMatchedRoomsDone(event:MatchedRooms):void
{
}
}
class notifylistener implements NotificationListener
{
private var joinFunc:Function;
private var msgFunc:Function;
private var leaveFunc:Function;
public function notifylistener(f:Function)
{
joinFunc = f;
}
public function msgListener(f:Function,f1:Function):void
{
msgFunc = f;
leaveFunc = f1;
}
public function onRoomCreated(event:Room):void
{
}
public function onRoomDestroyed(event:Room):void
{
}
public function onUserLeftRoom(event:Room, user:String):void
{
if(user != User)
{
leaveFunc();
}
}
public function onUserJoinedRoom(event:Room, user:String):void
{
if(State == 3)
joinFunc();
}
public function onUserLeftLobby(event:Lobby, user:String):void
{
}
public function onUserJoinedLobby(event:Lobby, user:String):void
{
}
public function onChatReceived(event:Chat):void
{
if(event.sender != User)
{
var obj:Object = com.adobe.serialization.json.JSON.decode(event.chat);
msgFunc(obj);
}
}
public function onUpdatePeersReceived(update:ByteArray):void
{
}
public function onUserChangeRoomProperty(room:Room, user:String,properties:Object):void
{
}
public function onPrivateChatReceived(sender:String, chat:String):void
{
}
public function onUserChangeRoomProperties(room:Room, user:String,properties:Object, lockTable:Object):void
{
}
public function onMoveCompleted(move:Move):void
{
}
}
package
{
import com.adobe.serialization.json.JSON;
import com.shephertz.appwarp.WarpClient;
public class AppWarp
{
public static var _roomlistener:roomListener;
public static var _zonelistener:zoneListener;
public static var _notifylistener:notifylistener;
public static var _connectionlistener:connectionListener;
private static function generateRandomString(strlen:Number):String{
var chars:String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var num_chars:Number = chars.length - 1;
var randomChar:String = "";
for (var i:Number = 0; i < strlen; i++){
randomChar += chars.charAt(Math.floor(Math.random() * num_chars));
}
return randomChar;
}
public static function connect(f:Function):void
{
if(INITIALIZED == false)
{
WarpClient.initialize(APIKEY, SECRETEKEY);
client = WarpClient.getInstance();
INITIALIZED = true;
}
if(Connected == false)
{
_connectionlistener = new connectionListener(f);
client.setConnectionRequestListener(_connectionlistener);
User = generateRandomString(16);
client.connect(User);
}
else
f(0);
}
public static function join(f1:Function, f2:Function):void
{
_roomlistener = new roomListener(f1,f2);
_zonelistener = new zoneListener();
_notifylistener = new notifylistener(f2);
client.setRoomRequestListener(_roomlistener);
client.setZoneRequestListener(_zonelistener);
client.setNotificationListener(_notifylistener);
State = 1;
client.joinRoomInRange(1,1,true);
}
public static function leave():void
{
client.leaveRoom(roomID);
}
public static function begin(f:Function, f1:Function, dir:int, x:int, y:int):void
{
_notifylistener.msgListener(f, f1);
send(0,dir,x,y);
}
public static function move(dir:int,x:int,y:int):void
{
send(1,dir,x,y);
}
public static function eat(dir:int,x:int,y:int):void
{
send(2,dir,x,y);
}
public static function send(type:int,dir:int,x:int,y:int):void
{
if(Connected == true)
{
var obj:Object = new Object();
obj.type = type;
obj.dir = dir;
obj.x = x;
obj.y = y;
client.sendChat(com.adobe.serialization.json.JSON.encode(obj));
}
}
}
}
I needed to place the package keyword at the very beginning of the .as file, otherwise an error is thrown.
You can only define one class in a package in a file. You can define other classes outside the package, but I don't think that is a good idea as I have observed that in some versions of compiler you have to place it at the beginning and in some at the end. Sometimes, it won't work in anyway.
A better way is to define different classes for each listener in different files. You can use the same package name.
I would recommend creating a single class to listen to all listeners by implementing all base listener classes.
For e.g.
//listener.as
package
{
public class Listener implements ConnectionRequestListener, RoomRequestListener, NotificationListener
{
}
}

ActionScript - Global Custom Events?

up until now, the way i've been needing to handle my own custom events is by adding an event listener to the object that was dispatching the custom event. while this method of event handling works just fine, i've come to the point where i would like my custom events to be globally accessible, where the listening object does not need to be the same object that is dispatching the event.
in this example, my main Controller class is instantiating and adding to the display list 2 sprite classes: Square and Triangle. the 4th and final class is a custom event called ColorChangeEvent.
i'm attempting to dispatch a new ColorChangeEvent from the Square class, which uses a timer to dispatch a new random color once every second, while Triangle will listen for the dispatched event and change its fill color to the color that was dispatched by Square.
Controller.as:
package
{
import flash.display.Sprite;
public class Controller extends Sprite
{
public function Controller()
{
var sq:Square = new Square();
sq.x = sq.y = 100;
var tr:Triangle = new Triangle();
tr.x = tr.y = 250;
addChild(sq);
addChild(tr);
}
}
}
Square.as:
package
{
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
public class Square extends Sprite
{
public function Square()
{
graphics.beginFill(0x999999);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
var myTimer:Timer = new Timer(1000);
myTimer.addEventListener(TimerEvent.TIMER, dispatchNewColor);
myTimer.start();
}
private function dispatchNewColor(evt:TimerEvent):void
{
var randomColor:Number = Math.random() * 0xFFFFFF;
trace("Square Class Dispatched: " + randomColor);
dispatchEvent(new ColorChangeEvent(ColorChangeEvent.CHANGE, randomColor));
}
}
}
Triangle.as:
package
{
import flash.display.Sprite;
import flash.geom.ColorTransform;
public class Triangle extends Sprite
{
public function Triangle()
{
graphics.beginFill(0x999999);
graphics.moveTo(0, 0);
graphics.lineTo(100, 50);
graphics.lineTo(-50, 150);
graphics.endFill();
addEventListener(ColorChangeEvent.CHANGE, changeColor);
}
private function changeColor(evt:ColorChangeEvent):void
{
var ct:ColorTransform = new ColorTransform;
ct.color = evt.color;
transform.colorTransform = ct;
trace("Triangle Class Received: " + evt.color);
}
}
}
ColorChangeEvent.as:
package
{
import flash.events.Event;
public class ColorChangeEvent extends Event
{
public static const CHANGE:String = "change";
public var color:Number;
public function ColorChangeEvent(type:String, color:Number)
{
super(type);
this.color = color;
}
override public function clone():Event
{
return new ColorChangeEvent(type, color);
}
}
}
needless to say, this isn't working.
of course, i could add the event listener to the Square instance in the Controller class, who's event handler could pass that value to Triangle via a public function to change the color, but this is exactly the kind of limitation i'm trying to avoid.
it's not always easy to access and pass a value to a class from where the custom event is dispatched, which is why i'm looking for an actual global solution to handling custom events.
I have been using this class for some time now. To use it you would do this in square:
data.EventManager.instance.publish("someName", randomColor);
and then in your Triangle:
data.EventManager.instance.subscribe("someName", handleColorChange);
private function handleColorChange(color:Number):void {
// implementation here
}
You can even pass the ColorChangeEvent instead of just the color.
data.EventManager.instance.publish(ColorChangeEvent.CHANGE, new ColorChangeEvent(ColorChangeEvent.CHANGE, randomColor);
And then
data.EventManager.instance.subscribe(ColorChangeEvent.CHANGE, handleColorChange);
private function handleColorChange(colorChangeEvent:ColorChangeEvent):void {
// implement here
}
I removed a lot of code that is specific to my projects, so I am not 100% it is usable exactly as-is. But, you should be able to modify it to get it working correctly. If not, let me know and I can try to work it out with you.
This class handles additional things that I will not go into, though you are free to explore. Be aware, however, that anything that subscribes for event notification has a strong reference by the EventManager. That means that if you want to destroy something for garbage collection, you need to call EventManager.instance.cancel(ColorChangeEvent.CHANGE, handleColorChange) before the Triangle instances can be collected.
package data {
import flash.utils.*;
public class EventManager extends Object {
private var _subscribers:Dictionary;
private var _calls:Dictionary;
private var _feeds:Dictionary;
private var _requests:Dictionary;
private var _notify:Dictionary;
private var _services:Dictionary;
private static var __instance:EventManager;
public function EventManager() {
if (__instance) {
trace("EventManager is a Singleton class which should only be accessed via getInstance()");
}
_feeds = new Dictionary(true);
_subscribers = new Dictionary(true);
_requests = new Dictionary(true);
_services = new Dictionary(true);
_notify = new Dictionary(true);
}
public function getFeedData($name:String) {
if (_feeds[$name]) {
return _feeds[$name];
}
return undefined;
}
public function unpublish($name:String) {
var _post:* = _feeds[$name];
delete _feeds[$name];
return _post;
}
public function cancel($name:String, $subscriberFunc:Function, ...args): void {
var _cnt:Number;
var _subscriberArray:Array;
if (_subscribers[$name]) {
for (_cnt = 0; _cnt < _subscribers[$name].length; _cnt++) {
if (_subscribers[$name][_cnt] == $subscriberFunc) {
_subscribers[$name].splice(_cnt, 1);
}
}
}
if (_requests[$name]) {
_subscriberArray = _requests[$name];
_cnt = _subscriberArray.length;
while (_cnt > 0) {
if (_subscriberArray[_cnt] == $subscriberFunc) {
_subscriberArray.splice(_cnt, 1);
}
_cnt--;
}
}
}
public function subscribe($name:String, $subscriber:Function, ...args): void {
var _funcArray:Array;
var _func:Function;
if (_feeds[$name]) {
$subscriber(_feeds[$name]);
}
if (! _subscribers[$name]) {
_subscribers[$name] = new Array();
}
_subscribers[$name].push($subscriber);
if (_notify[$name]) {
_funcArray = _notify[$name];
for each (_func in _funcArray) {
_func();
}
delete _notify[$name];
}
}
public function request($name:String, $feedFunction:Function): void {
var _requestArray:Array;
var _request:Function;
if (! _feeds[$name]) {
if (! _requests[$name]) {
_requests[$name] = new Array();
}
_requests[$name].push($feedFunction);
} else {
$feedFunction(_feeds[$name]);
}
if (_notify[$name]) {
_requestArray = _notify[$name];
for each (_request in _requestArray) {
_request();
}
delete _notify[$name];
}
}
public function publish($name:String, $data:*, $args:Object = null): void {
var _subscriberArray:Array;
var _func:Function;
var cnt:Number = 0;
_feeds[$name] = $data;
if (_subscribers[$name] != undefined) {
_subscriberArray = _subscribers[$name].slice();
_cnt = 0;
while (_cnt < _subscriberArray.length) {
_func = _subscriberArray[_cnt] as Function;
if ($args) {
_func($data, $args);
}else {
_func($data);
}
_cnt++;
}
}
if (_requests[$name]) {
_subscriberArray = _requests[$name].slice();
delete _requests[$name];
_cnt = 0;
while (_cnt < _subscriberArray.length) {
if (_subscriberArray[_cnt] != null) {
_subscriberArray[_cnt]($data);
}
_cnt++;
}
}
}
public function notify($name:String, $subscriber:Function): void {
if (_requests[$name] || _subscribers[$name]) {
$subscriber();
}else {
if (! _notify[$name]) {
_notify[$name] = new Array();
}
_notify[$name].push($subscriber);
}
}
public static function getInstance(): EventManager {
if (! __instance) {
__instance = new EventManager();
}
return __instance;
}
public static function get instance(): EventManager {
return getInstance();
}
}
}
I got this to work by creating a singleton: EventDispatchSingleton that extends EventDispatcher. It's basically an empty singleton that provides the dispatchEvent and add/removeEventListener methods (these are automatically provided by extending EventDispatcher).
Anywhere I want to dispatch an event I import EventDispatchSingleton and then call EventDispatchSingleton.instance.dispatchEvent(<someEvent>);.
Then, wherever I want to listen to that event, I just import EventDispatchSingleton and call EventDispatchSingleton.instance.addEventListener(eventName, callback);
You should look into event bubbling, specificly I think you will find the Capturing phase of the event propagation useful. Take a read of Event propagation from Adobe LiveDocs. It's in the Flex docs, but it is about AS3 Events.
Also Senocular has a good post on Flash Event Bubbling.