ActionScript - Using "is" comparative in switch statement? - actionscript-3

i have many objects of the same custom class, and another many objects of another custom class. i would like to create a switch statement to determine from which of the classes the object belongs. the following code doesn't compile, so i'm not sure if this is possible. is the only alternative to use if statements?
function mouseClickEventHandler(evt:MouseEvent):void
{
switch (evt.currentTarget)
{
case (is customClassA): trace("is instance of customClassA"); break
case (is customClassB): trace("is instance of customClassB");
}
}

This should work:
function mouseClickEventHandler ( evt:MouseEvent ):void
{
switch ( evt.currentTarget.constructor )
{
case CustomClassA:
trace("is instance of customClassA");
break;
case CustomClassB:
trace("is instance of customClassB");
break;
}
}
See Object.constructor.

function clickHandler (event:MouseEvent):void
{
var target:Object = event.currentTarget;
switch (true)
{
case (target is CustomClassA):
trace("is instance of customClassA");
break;
case (target is CustomClassB):
trace("is instance of customClassB");
break;
}
}
Not sure if braces are needed

Related

Is it possible to make use of a value returned from a method called by a delegate?

While experimenting with a basic coding stuff, I wondered, if a value returned by a method called by a delegate, could be used or captured. In other words, where will the return value will go ?
For example :
class Main extends Sprite
{
public var mc:MyMc;
function Main()
{
mc.addEventListener( "myClick" , myClick);
}
function myClick(e:Event):String //returning a string
{
return "What happens to this return value ???"
}
}
class MyMc extends MovieClip
{
function MyMc()
{
addEventListener( MouseEvent.CLICK , onClick);
}
function onClick(e:Event):String //returning a string
{
dispatchEvent(new Event("myClick"));
}
}
As I know it's not possible to do, but, there are at least some ways to implement the logic similar to what you've told about.
For example, you may call a method of a dispatcher, from a listener method:
class Main extends Sprite
{
public var mc:MyMc;
function Main()
{
mc.addEventListener("myClick" , myClick);
}
function myClick(e:Event):void
{
mc.specialMethod("some string");
}
}
class MyMc extends MovieClip
{
function MyMc()
{
addEventListener(MouseEvent.CLICK , onClick);
}
function onClick(e:Event):void
{
dispatchEvent(new Event("myClick"));
}
public function specialMethod(param:String):void
{
// Do something to the param
}
}
Also, you may think about dispatching an event from the Main class, and listen to it in the MyMc class, or pass a callback, which returns a string, from Main to the MyMc.
It's according to you and your needs to return something from the listener function because normally it must return nothing :
... This function must accept an Event object as its only parameter and must return nothing, ...
but you can of course get the returned value(s), take a look on this little example :
var light_on:Boolean = false;
btn_light_on.addEventListener(MouseEvent.CLICK, btn_on_onPress);
btn_light_off.addEventListener(MouseEvent.CLICK, btn_off_onPress);
function btn_on_onPress(e:MouseEvent): Boolean {
light_on = true;
if(e.target === btn_light_off){
light_on = false;
}
return light_on;
}
function btn_off_onPress(e:MouseEvent): void {
trace('The light is', btn_on_onPress(e) ? 'on' : 'off');
}
Hope that can help.

1180:Call to a possibly undefined method Punch

I'm trying to call the punch function from my player class inside another class but for some reason it gives me this error:
1180: Call to a possibly undefined method Punch.
I'm not sure why it gives me this error. I even made the functions public.
This is the class where i am calling it from:
package
{
public class Player extends MovieClip
{
public function Player()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyPressed);
addEventListener(Event.ENTER_FRAME,Update);
}
function KeyPressed(event:KeyboardEvent):void
{
//If on floor
if (CanJump)
{
//If A key is down
if (event.keyCode == 65)
{
//Punch
Punch(true);
}
}
}
function Update(event:Event)
{
//Do stuff
}
}
}
and this is what I am trying to call:
package
{
public class ComboSequence extends ComboHandler
{
public function ComboSequence(clipName:String, par:BaseObject, _oList:ObjectList)
{
// constructor code
super(clipName, par, _oList);
}
public function Punch(PunchKey:Boolean)
{
if (currentAttack != null)
{
if (Recovery <= 0 && FollowUpTime > 0)
{
currentAttack = currentAttack.GetNextAttack(PunchKey);
if (currentAttack != null)
{
SetAnimation(currentAttack.animName);
Recovery = currentAttack.Recovery;
FollowUpTime = currentAttack.Recovery + 25;
}
}
}
if (FollowUpTime > 0)
{
FollowUpTime--;
}
else
{
currentAttack = null;
}
if (Recovery > 0)
{
Recovery--;
}
}
}
}
When you call Punch() on its own inside the player class, ActionScript is looking for a Player.Punch() method. Your method is on the ComboSequence class. You're probably trying to do something like this:
var comboSequence:ComboSequence = new ComboSequence();
comboSequence.Punch()
Keep in mind that while this code will run, it probably won't do what you want it to do. I guess you want to keep an instance of ComboSequence in your player object. If that doesn't make sense to you, it would be a good idea to do some background reading on ActionScript and object-oriented programming in general.
You need to import ComboSequence into the Player class and call Punch though that like
ComboSequence.Punch. andypaxo is right in his post, you'd need to instantiate it somewhere within the Player class.
One note about your code, though, you should not name functions with a capital letter. Class names typically start with a capital letter, but not the methods within.
package
{
import ComboSequence; //you may need the package path if its in a package, something like com.classes.ComboSequence, where com.classes is the folder that ComboSequence is saved.
public class Player extends MovieClip
{
public function Player()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN,KeyPressed);
addEventListener(Event.ENTER_FRAME,Update);
}
function KeyPressed(event:KeyboardEvent):void
{
//If on floor
if (CanJump)
{
//If A key is down
if (event.keyCode == 65)
{
//Punch
ComboSequence.Punch(true);
}
}
}
function Update(event:Event)
{
//Do stuff
}
}
}
also, regarding your "missing rightParen" error, rightParen means right parenthesis, or ), leftParen would be (. That error means you are missing a ) somewhere. Often times it can mean you added an extra one somewhere, thus closing a section of parenthesis you didn't mean to close, which would leave one unpaired parenthesis somewhere.

Switch/Case on a Type/Class instance?

I have a set of different MovieClips:
Pink
Yellow
Red
and I create an item
item = new Pink();
item = new Red();
etc...
How do I write a switch case to see which MovieClip I have?
switch (item) {
case Pink:
// do something
break;
case Red:
// do something
break;
}
i only know how to write switch cases for Strings...
You can get the class name as a string and do a switch on that as you normally would using this method...
switch (getQualifiedClassName(item)) {
case "Pink":
// do something
break;
case "Red":
// do something
break;
}
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/package.html#getQualifiedClassName()
Simple answer: don't.
Pink and Red are both Colors so make Color have a function:
interface IColor
{
public function doSomething():void;
}
and have Pink and Red extend the function:
class Pink extends MovieClip implements IColor
{
...
public override function doSomething():void
{
//different code
}
}
class Red extends MovieClip implements IColor
{
...
public override function doSomething():void
{
//more different code
}
}
then in your code you can just call:
item.doSomething();
and it will do the right thing for either case.
There's already an answer for this question but for anyone who is interested you can also do this:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var cat:Cat = new Cat();
switch(Class(Object(cat).constructor))
{
case Cat : trace("instance of " + Cat); break;
case Dog : trace("instance of " + Dog); break;
}// end switch
// output:
}// end function
}// end class
}// end package
internal class Cat
{
public function Cat() { }
}// end class
internal class Dog
{
public function Dog() { }
}// end class
Use the “is” keyword:
if (item is Pink) // do something
Using “is” in a case statement would look like this:
switch(true)
{
case item is Pink :
// do something
break;
case item is Red :
// do something
break;
}
The powerful thing about the “is” statement is that works for inherited types. So, for instance, if I wanted to check for a MovieClip, a Sprite or a SimpleButton, I could just write:
if (item is DisplayObject) // do something
Since all these types inherit from DisplayObject.
Another benefit is that there is no unnecessary introspection (such as with getQualifiedClassName). Thus, the “is” keyword has far better performance and requires no additional code.

what to addEventListener to when listening for custom events?

I am sending an event when an sql query returns no matches so that I can continue with the addition to the database.. It seems like actionscript is requiring that I attach the listener to something, but I don't really have any variables that seem like logical candidates at the point where I am in my code.
I just want to listen for the isNewRecord event to be called so that I can then run the insert query; right now it's saying call to possibly undefined method for addEventListern and for dispatchEvent
public function addBG(BG:Number, datetime:String, batch:Boolean = false):void{
checkRecord('Gb', datetime, matchRecord);
addEventListener("isNewRecord", recordExists);
function recordExists()
{/*code to execute query*/}
public function matchRecord(result:SQLResult):void {
var match:String = result.data[0];
if (match == null) {
var allClear:Event = new Event("isNewRecord");
dispatchEvent(allClear);
}
}
Your code is buggy. You have a function within a function.
Also, is your code extending EventDispatcher class (or any class that extends it, like Sprite, MovieClip, etc.?) Make sure it is.
Try this:
public function addBG(BG:Number, datetime:String, batch:Boolean = false):void
{
// note, you're adding this event listener EVERY TIME you call the
// addBG function, so make sure you remove it OR add it somewhere in the
// init or complete functions
addEventListener("isNewRecord", recordExists);
checkRecord('Gb', datetime, matchRecord);
}
public function recordExists():void
{/*code to execute query*/}
public function matchRecord(result:SQLResult):void {
var match:String = result.data[0];
if (match == null) {
var allClear:Event = new Event("isNewRecord");
dispatchEvent(allClear);
}
}
You don't need to use events. Your processing of the SQLResult seems synchronous, there is no latency due to any interaction with the user, the server or anything that may take some time.
When Flash executes your code it does the folowing:
checkRecord('Gb', datetime, matchRecord);
//then
var match:String = result.data[0];
if (match == null) {
var allClear:Event = new Event("isNewRecord");
dispatchEvent(allClear);
}
//and finally
addEventListener("isNewRecord", recordExists);
The event is dispatched before the listener is added.
Here is what you should do:
public function addBG(BG:Number, datetime:String, batch:Boolean = false):void
{
if (checkRecord('Gb', datetime, matchRecord))
{
recordExists();
}
}
public function recordExists():void
{/*code to execute query*/}
public function matchRecord(result:SQLResult):Boolean{
var match:String = result.data[0];
if (match == null) {
return true;
}
return false;
}
Cheers

Problem with switch

My problem is that I can't (don't know) make work my switch. Here in my first case, I input "hache", and it doesn't pass trough. Strangely, in my trace(traget); [Object hache] or [Object extincteur] (depending on wich mc I click on) comes out... Why does it don't go trough the first case? I have no clue. I tried removing the " ".
package cem
{
import flash.display.MovieClip;
public class actionObjets{
/*--inventaire--*/
private static var inventaireHache:Boolean = false;
private static var inventaireExtincteur:Boolean = false;
private var objetClique:MovieClip;
public function actionObjets(target) {
this.objetClique = target;
switch(objetClique){
case "hache":
inventaireHache = true;
ajouterInventaire(objetClique);
break;
case "extincteur":
inventaireExtincteur = true;
ajouterInventaire(objetClique);
break;
}
trace(target);
}
private function ajouterInventaire(objetEnlever):void{
objetClique.parent.removeChild(objetClique);
trace(inventaireHache + " - Hache");
trace(inventaireExtincteur + " - Extincteur");
}
}
}
btw, target is the movieClip I clicked on a.k.a. Object extincteur, or Object hache.
The problem is that objetClique isn't a string. You probably want to do something like switch (objetClique.name).
If you want to understand what's going on, rewrite the code this way:
if (objetClique == "hache") {
// ...
} else if (objetClique == "extincteur") {
// ...
}
I hope this illustrates more clearly why the switch doesn't work. objetClique couldn't be equal to the string "hache", because it's not a string. From the looks of it objetClique refers to a DisplayObject and they have a property called name, which is what you want to compare:
if (objetClique.name == "hache") {
// ...
} else if (objetClique.name == "extincteur") {
// ...
}
that code would work, and it's equivalent to a switch that looks like this:
switch (objetClique.name) {
case "hache":
// ...
break;
case "extincteur":
// ...
break;
}