I want to send data from mainClass (Flash class) to my Starling class. Here is the code of two classes. I need to pass data between them.
package
{
import flash.display.Sprite;
import flash.events.Event;
public class mainClass extends Sprite
{
private var myStarling:Starling;
public function mainClass ()
{
super();
stage.addEventListener(Event.RESIZE,onResize);
}
private function shangedOr(e:StageOrientationEvent):void
{
// code
}
private function onResize(e:Event):void
{
myStarling = new Starling(Main,stage);
myStarling.start();
}
}
}
Main.as class of starling :
package
{
import starling.core.Starling;
import starling.display.Sprite;
public class Main extends starling.display.Sprite
{
private var theme:AeonDesktopTheme;
public function Main()
{
super();
this.addEventListener(starling.events.Event.ADDED_TO_STAGE,addToStage);
}
private function addToStage(e:starling.events.Event):void
{
this.theme = new AeonDesktopTheme( this.stage );
drawComponent();
}
private function drawComponent():void
{
//code
}
}
}
Is there a way to pass data between Flash and Starling? I created an Event class to listen from Flash, then dispatch from Starling class to get the data I need from the Flash class but it didn't work.
Fast solution , useful in some cases: make static function in mainClass and call it when your Main instance is ready (in addToStage for example)
definately we can't write any event or class to interact with flash and starling for this issue we can use CALL_BACK Function. so that you can interact or send data from core flash to starling and starling to core flash. Function call won't give any error.
Related
I have a weird problem in a game which I want to create. At first I have created a project without external classes.
On the root I have three Characters and one Level. Also there is a script for the key listeners and I have eventListeners to register the level, levelElements, coins and the characters. Then I have a CharacterControl MovieClip in the library. This MovieClip contains the character behaviour. As example walk, jump, idle, gravity if not colliding to the ground. There are also different events and eventListeners.
The scripts are on the timeline. If I call in both timelines a trace-function, the root was called before the CharacterController.
After that in my next exercise I created a document class Main. Now there are all root scripts. And for the CharacterController I also copied the timeline code and put it into an external class.
Now my problem is that the CharacterController class is called before the main class gets called. This leads to the problem that the eventListener and events can't get called in right order. There are happening a few errors. No Coin and no Character collides on the ground or a plattform. Everything is falling down.
How can I achieve that the Main gets called at first? Should I remove the characters and create them by script?
EDIT:
Ok, I give a short example which shows the basic problem without the complex code of my game.
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
trace("main was called");
}
}
}
package {
import flash.display.MovieClip;
public class My_Circle extends MovieClip {
public function My_Circle() {
// constructor code
trace("circle was called");
}
}
}
Here are some pictures of the configuration and structure of my project:
I need Main called as first. I think it's a basic problem in as3.
You'd make the class file of your stage Main.as in the properties pane.
Edit: Interesting. Just replicated this. I believe then that flash/air constructs elements so they're ready to be put on the stage instead of constructing the stage first and elements after. You should put the code you want to execute for your circle in some sort of init function and execute it in.
package
{
import flash.display.MovieClip;
public class Main extends MovieClip
{
public function Main()
{
super();
trace("Hello");
(circle_mc as Circle).init();
}
}
}
Circle:
package
{
import flash.display.MovieClip;
public class Circle extends MovieClip
{
public function Circle()
{
super();
}
public function init():void
{
trace("World");
}
}
}
ok, I figured out a simple solution how you can make it by code. At first I think it's a better solution to create the object (circle, character, whatever) by code.
The timeline code:
import flash.events.Event;
Main.setStageRef(this.stage); //Super-important
stop();
The Main class code:
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.DisplayObject;
import flash.events.Event;
public class Main extends MovieClip {
public static var stageRef : Object = null;
var movieClipExample : My_Circle;
public function Main() {
this.addEventListener(Event.ENTER_FRAME,this.afterMainTimeLine);
stage.addEventListener("myEvent", myEventFunction);
}
public function afterMainTimeLine(e:Event) {
trace("Hello");
movieClipExample = new My_Circle;
movieClipExample.init();
stageRef.addChild(movieClipExample);
removeEventListener(Event.ENTER_FRAME, this.afterMainTimeLine);
this.addEventListener(Event.ENTER_FRAME,this.updateFunction);
}
public function updateFunction(e:Event){
movieClipExample.moveFunction();
}
public function myEventFunction(_event: Event) {
trace("myEvent was triggered");
}
//Getter/setter for stage
public static function setStageRef(_stage : Object) : void
{
stageRef = _stage;
}
public static function getStageRef() : Object
{
return stageRef;
}
}
}
The Object code (as example My_Circle):
package {
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.DisplayObject;
public class My_Circle extends MovieClip {
public function My_Circle()
{
stageRef = Main.getStageRef();
trace("World");
this.x = x;
this.y = y;
var evt = new Event("myEvent", true);
stageRef.dispatchEvent(evt);
}
public function init():void
{
trace("Created Circle");
this.x = 300;
this.y = 100;
}
function moveFunction(){
this.y += 1;
}
}
}
The output is following:
Hello
World
myEvent was triggered
Created Circle
Maybe this could be helpful for others.
Just one thing. For different objects from the same class it's better to use an array. The position (maybe) should be random.
I'm new to AS3 and seem to be overlooking something related to classes and/or targeting. I have a MovieClip in my Library that is linked to a class called 'cloud' (yes cloud is just a picture of a rain cloud). I want to add cloud to the stage. I understand there are two ways to do this:
Drag it directly across from the Library to the Stage.
Use AS3 to addChild to the Stage.
The class works when I publish my swf using the "drag it directly across from the Library to the Stage" approach. But it doesn't work when I try using the AS3 approach.
The class is as follows:
package {
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
public class cloud extends MovieClip {
public function cloud() {
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyMapping);
}
private function keyMapping(event:KeyboardEvent):void {
if (event.charCode == 13) {
MovieClip(parent).testme.text = "hello world!";
}
}
}
}
The AS3 I have been using on Frame 1 of my main timeline:
stop();
var cloud_mc:cloud = new cloud();
addChild(cloud_mc);
==================================================================================
SUGGESTED FIX
Class:
package {
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
public class cloud extends MovieClip {
public function cloud() {
}
public function tralala() {
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyMapping);
}
private function keyMapping(event:KeyboardEvent):void {
if (event.charCode == 13) {
MovieClip(parent).testme.text = "hello world!";
}
}
}
}
AS3:
stop();
var cloud_mc:cloud = new cloud();
addChild(cloud_mc);
cloud_mc.tralala();
Use the linkage name of the library object, not the class that it extends.
Your library object extends the cloud class which extends movie clip. If you instanciate the cloud class you miss the library object.
The process is described in detail here:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b8ea63-7fee.html
I have built a basic preloader that runs in my document class. I'm having trouble with it. I'm guessing its due to what a class can and can not access from the stage?
theres 2 problems. the first is that I cant change the keyframe the stage is on from the class. the second is im getting an error 1009 if I comment that out.
package
{
import flash.display.MovieClip
import flash.events.Event;
import flash.events.ProgressEvent;
public class Pre extends MovieClip
{
public function Pre()
{
loaderInfo.addEventListener(Event.COMPLETE,downloadFin);
loaderInfo.addEventListener(ProgressEvent.PROGRESS,preloadProgress);
function preloadProgress(progressEvent:ProgressEvent):void
{
var floatLoaded:Number=loaderInfo.bytesLoaded/loaderInfo.bytesTotal;
var newW:Number=this.width*floatLoaded;
this.Fill.width=newW;
}
function downloadFin(event:Event):void
{
trace('fin')
//stage.gotoAndStop(3);//frame with game
}
}
}
}
I recommend you to dispatch an event when the preloader is ready, making yor preloader more generic. Then add a listener in the document class like this:
private function setupPreloader() : void
{
preloader.addEventListener(Event.COMPLETE , onPreloaderComplete);
preloader.start();
}
private function onPreloaderComplete(event : Event) : void
{
preloader.removeEventListener(Event.COMPLETE, onPreloaderComplete);
preloader.dispose();
gotoAndStop(3);
}
I've got 3 classes:
The class that recognizes the change in URL (using SWFAddress by Asual):
package swfaddress {
import flash.display.MovieClip;
import com.asual.swfaddress.*;
public class SwfAddress extends MovieClip {
private var dispatcher:Dispatch = new Dispatch;
public function SwfAddress():void {
SWFAddress.addEventListener(SWFAddressEvent.CHANGE, onChange);
}
private function onChange(e:SWFAddressEvent):void {
dispatcher.changed();
}
}
}
The class "Dispatch" that validates the URL and dispatching Event when finished
package swfaddress {
import flash.events.Event;
import flash.events.EventDispatcher;
public class Dispatch extends EventDispatcher {
public static const CHANGED:String = "changed";
public function changed ():void {
// some operations validating the URL
dispatchEvent(new Event(Dispatch.CHANGED));
}
}
}
Other class in other package that should receive info when the validation process has finished.
package menu {
import swfaddress.*
public class MenuPanel extends MovieClip {
var swfRead:Dispatch = new Dispatch;
public function MenuPanel():void {
swfRead.addEventListener(Dispatch.CHANGED, onChange);
}
private function onChange(e:Event):void {
trace("Hello World");
}
}
And the "Hello World" never appeared in the output window - so I'm not sure if it's possible that my MenuPanel has a chance to receive an info about completing the validation triggered by some other class?
You are creating two different instances of the dispatcher, and so the instance that is being called to validate your URL is not the same instance that you are listening to in the MenuPanel class.
A simple way around this would be to make the Dispatch class a singleton, so that only one instance of it exists and you can reference it from different points in your application. This works by giving the Dispatch class a static method that returns a self-contained instance of itself. You then call Dispatch.getInstance() whenever you want a reference to the class instead of using the new keyword.
Dispatch:
package swfaddress
{
import flash.events.Event;
import flash.events.EventDispatcher;
public class Dispatch extends EventDispatcher
{
// singleton instance
private static var _instance:Dispatch;
private static var _allowInstance:Boolean;
public static const CHANGED:String = "changed";
// get singleton instance of Dispatch
public static function getInstance():Dispatch
{
if (Dispatch._instance == null) {
Dispatch._allowInstance = true;
Dispatch._instance = new Dispatch();
Dispatch._allowInstance = false;
}
return Dispatch._instance;
}
public function Dispatch()
{
if (!Dispatch._allowInstance)
{
throw new Error("Error: Use Dispatch.getInstance() instead of the new keyword.");
}
}
public function changed():void {
//some operations validating the URL
dispatchEvent(new Event(Dispatch.CHANGED));
}
}
}
Getting a reference:
private var dispatcher:Dispatch = Dispatch.getInstance();
EDIT: For whatever reason, it works in the browser but not when compiled/debugged within the IDE.
I can't get my external SWFs to pick up on dispatches from my singleton event manager (EventDispatcher). Here are the particulars:
I add children from an external SWF using the getDefinition method to my main SWF.
I'm using a singleton EventDispatcher that is in charge of listeners and dispatching.
Using a custom event class.
In this code, I am trying to get a mute button to tell the main SWF that the mute icon has been clicked (SoundClipEvent.MUTE_CLICK). After the sound has been muted, it should dispatch the event (SoundClipEvent.STATE) and confirm to the muteIcon the state. Currently, the mute icon successfully dispatches the MUTE_CLICK event and the main SWF document class is able to pick it up. MuteIcon (child SWF MC) hears nothing from the singleton.
Your help in this problem is greatly appreciated!
SoundClipManager.as:
import flash.events.Event;
import flash.events.EventDispatcher;
public dynamic class SoundClipManager extends EventDispatcher {
private static var isMuted:Boolean;
public function SoundClipManager(blocker:SingletonBlocker):void {
super();
//
if (blocker == null) {
throw new Error("Error: Instantiation failed; Use SoundClipManager.getInstance()");
}
}
public static function get muted():Boolean {
return SoundClipManager.isMuted;
}
public static function set muted(value:Boolean) {
SoundClipManager.isMuted = value;
//
SoundClipManager.getInstance().dispatchEvent(new SoundClipEvent(SoundClipEvent.STATE,SoundClipManager.muted));
}
public static function getInstance():SoundClipManager {
if (instance == null) {
instance = new SoundClipManager(new SingletonBlocker());
}
return instance;
}
public override function dispatchEvent(evt:Event):Boolean {
return super.dispatchEvent(evt);
}
private static function stateChanged(evt:*) {
trace('state changed!');
}
}
internal class SingletonBlocker {}
MuteIcon.as
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
//
public dynamic class IconMute extends MovieClip {
public function IconMute() {
this.addEventListener(Event.ADDED_TO_STAGE,this.addedToStage);
//
SoundClipManager.getInstance().addEventListener(SoundClipEvent.STATE,this.soundClipManagerStateChanged);
}
//
// Methods, Private
//
//
// Events
//
private function muteClick(evt:MouseEvent) {
SoundClipManager.getInstance().dispatchEvent(new SoundClipEvent(SoundClipEvent.MUTE_CLICK));
}
//
private function addedToStage(evt:Event) {
this.addEventListener(MouseEvent.CLICK,this.muteClick);
}
//
private function soundClipManagerStateChanged(evt:*) {
trace("state changed!");
}
}
SoundClipEvent.as
package {
//
import flash.events.Event;
//
public class SoundClipEvent extends Event {
public static const MUTE_CLICK:String = "muteClick";
public static const STATE:String = "state";
//
public var muted:Boolean;
public function SoundClipEvent(type:String,muted:Boolean = false) {
if(muted) this.muted = muted;
//
super(type,true,false);
}
}
}
getDefinitionByName(className) method will work only if className was mensioned somewhere in your code. You may just import className class in a file where you're going to call getDefinitionByName(className). That should help!