Timer in Action Script 3 - actionscript-3

I have problem that I need to create timer but I want to pass on a variable to it, how to do it? Is it possible in AS3?
I tried like this:
bonusPlayer1Timer = new Timer(5000);
bonusPlayer1Timer.addEventListener(TimerEvent.TIMER, bonusChanges(player1));
bonusPlayer1Timer.addEventListener(TimerEvent.TIMER_COMPLETE, bonusChangesRemove(player1));
bonusPlayer1Timer.start();
function bonusChanges(event:TimerEvent, playerBonus:Player):void {
switch (playerBonus.bonus) {
case 0 :
playerBonus.multipleShooting = false;
playerBonus.bonus = -1;
break;
...}}
But I have error:
1067: Implicit coercion of a value of type Player to an unrelated type flash.events:TimerEvent.
1136: Incorrect number of arguments. Expected 2.
And this error is in the bold line.
Can I use it in this way? Or I have to create two the same function for every of my players because I am not allow to pass on any different arguments to the timer function?
Thank you,

Create a class that extends the Timer class and add a property for the Player.
public class PlayerTimer extends Timer
{
public var thePlayer:Player;
public function PlayerTimer(delay:Number, repeatCount:int=0)
{
super(delay, repeatCount);
}
}
Using your example the code would be something like this:
bonusPlayer1Timer = new PlayerTimer(5000);
bonusPlayer1Timer.thePlayer = new Player();
bonusPlayer1Timer.addEventListener(TimerEvent.TIMER, bonusChanges);
bonusPlayer1Timer.addEventListener(TimerEvent.TIMER_COMPLETE, bonusChangesRemove);
bonusPlayer1Timer.start();
function bonusChanges(event:TimerEvent):void {
var playerBonus:Player = PlayerTimer(event.target).thePlayer;
switch (playerBonus.bonus) {
case 0 :
playerBonus.multipleShooting = false;
playerBonus.bonus = -1;
break;
...}}

You can never pass more than one argument into the function triggered by an EventListener. You need to find other ways of passing your information around, such as the solution provided by Nathan Smith.

you can also do it this way:
var x = setTimeout(yourfunction(/*arguments you need*/),1000);
function yourfunction(/*var*/){
//your code
}

Just Type
var bonusPlayer1Timer = new Timer(5000);

Related

Using tweenlite in action script 3

I am trying to make a square get bigger using tweenlite (from greensock).
Using the following line but it gives an error, any ideas?
public function getStarted ():void {
var juiceBox:Shape = new Shape();
var newValue:Number = new Number();
newValue = 0;
juiceBox.graphics.beginFill(0xcccccc);
juiceBox.graphics.drawRect(0, squareHeight-newValue, squareWidth, newValue);
juiceBox.graphics.endFill();
square.addChild(juiceBox);
var myTween:TweenLite = new TweenLite(juiceBox.graphics.drawRect, 5, {"y":squareHeight-60,"height":60 });
}
[Fault] exception, information=ReferenceError: Error #1069: Property y not found on builtin.as$0.MethodClosure and there is no default value.
Fault, PropTween() at PropTween.as:58
Thanks any help would be greatly appreciated.
You are tweening "juiceBox.graphics.drawRect" which is a function (class method). That class method has no property named 'y' or 'height'. I'm guessing what you want to tween is juicebox itself (that has such properties) so you would do:
TweenLite.to(juicebox, 5, etc ...
You are supposed to use the form TweenLite.to() (which return an instance) and not the constructor.
var myTween:TweenLite = TweenLite.to(etc ...)
This keeps the tween from being GC.

Passing arguments into mouseEvent function

This seems simple in other languages, but I don't understand the error. I have 7 buttons that I would like to each take my gallery movieclip to a certain frame when you click on them.
Error: 1067: Implicit coercion of a value of type int to an unrelated type flash.events:MouseEvent.
Error: 1136: Incorrect number of arguments. Expected 2.
Error: 1067: Implicit coercion of a value of type void to an unrelated type Function.
Any help?
function gotoImage(event:MouseEvent, frameParam:int):void
{
MovieClip(this.root).gallery.gotoAndStop(frameParam);
}
t1.addEventListener(MouseEvent.CLICK, gotoImage(1));
t2.addEventListener(MouseEvent.CLICK, gotoImage(2));
t3.addEventListener(MouseEvent.CLICK, gotoImage(3));
t4.addEventListener(MouseEvent.CLICK, gotoImage(4));
t5.addEventListener(MouseEvent.CLICK, gotoImage(5));
t6.addEventListener(MouseEvent.CLICK, gotoImage(6));
t7.addEventListener(MouseEvent.CLICK, gotoImage(7));
You've got two things off with your code:
First, in ActionScript, event handlers always have the same signature:
function someHandler(e:Event):void { .. }
Sometimes the Event argument is a more specific subclass of Event, such as MouseEvent, but there is always just one argument.
The addEventListener method needs a function itself, not the result of invoking a function.
// Here's a function:
function multiply(i1:int, i2:int):int { return i1 * i2; }
// Here's assigning the result of **invoking** a function:
var result:int = multiply(2,3);
// Here's assigning a **function itself** to a variable:
var f:Function = multiply;
// You can invoke the function via the variable f in two different ways:
var result1 = f(2,3);
var result2 = f.apply(null, [2,3]);
So, you'll need to change your code to follow the above to points. You'll have to associate the buttons with jumping to a specific frame one of two ways:
Simple but repetitive: Use a separate handler for each button, with the frame hard coded into each handler.
1a. Named functions (most verbose):
function onT1Click(e:MouseEvent):void {
MovieClip(this.root).gallery.gotoAndStop(1);
}
t1.addEventListener(MouseEvent.CLICK, onT1Click);
// etc. etc.
1b. Anonymous functions:
t1.addEventListener(MouseEvent.CLICK, function(e:Event):void {
MovieClip(this.root).gallery.gotoAndStop(1);
});
// etc. etc.
More elegant: Use the same handler, and store the association between button and frame elsewhere, such as in a Dictionary. If you stick with your naming convention you could even fill the Dictionary in a for loop getting the buttons by name:
var buttonToFrame:Dictionary = new Dictionary();
for(var i:int = 1; i < 8; i++) {
var btn:Button = this["t" + i.toString()];
buttonToFrame[btn] = i;
btn.addEventListener(MouseEvent.CLICK, onClick);
}
function onClick(e:MouseEvent):void {
var btn:Button = Button(e.currentTarget);
var frameNum:int = buttonToFrame[btn];
MovieClip(this.root).gallery.gotoAndStop(frameNum);
}
Just change this
t1.addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ gotoImage(me, 1)});
t2.addEventListener(MouseEvent.CLICK, function(me:MouseEvent):void{ gotoImage(me, 2)});
and so on...
This is possible with a roundabout approach. For the event handler, use a function that returns a nested anonymous function.
private var textFieldA:TextField = new TextField;
private var textFieldB:TextField = new TextField;
public function setParameterizedTextWhenTextFieldsAreClicked ():void {
addChild(textFieldA);
textFieldA.text = 'Text field A';
textFieldA.addEventListener(MouseEvent.CLICK, showCustomMessage("One"));
addChild(textFieldB);
textFieldB.text = 'Text field B';
textFieldB.y = 20;
textFieldB.addEventListener(MouseEvent.CLICK, showCustomMessage("Two"));
// NOTE: We must use strongly referenced listeners because weakly referenced
// listeners **will get garbage collected** because we're returning
// an anonymous function, which gets defined in the global namespace and
// thus, the garbage collector does not have anything pointing to it.
}
private function showCustomMessage (message:String):Function {
// NOTE: You can store the following function to a class variable
// to keep it in memory, which would let you use weakly referenced
// listeners when using this as an event handler. Many people
// would find that awkward. I would discourage that.
return function (e:MouseEvent):void {
var textField:TextField = e.target as TextField;
textField.text = message; // "message" argument is available because
// this function's scope is kept in memory.
}
}
Bear in mind, the use of anonymous functions and reliance on function scope being kept in memory seem to present garbage collection complications.

Why can't my class see an array on the timeline?

I have a class that controls an enemy. From within that class, it checks for collisions with an array on the main timeline. I've done it this way before and it works fine, so I have no idea what I've done wrong this time. It keeps giving me an
ReferenceError: Error #1069: Property
bulletArray not found on
flash.display.Stage and there is no
default value.
error from within the enemy class.
Here's my code (shortened to remove the unimportant parts):
On timeline:
var bulletArray:Array = new Array();
function shoot(e:TimerEvent)
{
var bullet:MovieClip = new Bullet(player.rotation);
bullet.x = player.x;
bullet.y = player.y;
bulletArray.push(bullet);
stage.addChild(bullet);
}
In class:
private var thisParent:*;
thisParent=event.currentTarget.parent;
private function updateBeingShot()
{
for (var i=0; i<thisParent.bulletArray.length; i++) {
if (this.hitTestObject(thisParent.bulletArray[i]) && thisParent.bulletArray[i] != null) {
health--;
thisParent.bulletArray[i].removeEventListener(Event.ENTER_FRAME, thisParent.bulletArray[i].enterFrameHandler);
thisParent.removeChild(thisParent.bulletArray[i]);
thisParent.bulletArray.splice(i,1);
}
}
Any help would be greatly appreciated! Thanks.
My guess is that event.currentTarget is the instance where you declared the bulletArray variable. Using event.currentTarget.parent will refer to stage outside your scope. I donĀ“t know how you declare the listeners. Try using event.target instead of event.currentTarget and see if you get the same error.
My advice is that you put all your code in a class.
If you are going to do it this way you need to pass in a reference to the timeline.
private var _timeline:Object;
// constructor
public function YourClass(timeline:Object) {
_timeline = timeline;
}
private function updateBeginShot() {
// ..
trace(_timeline.bulletArray); // outputs [array contents]
// ..
}

ActionScript - Dictionaries Best For Adding Bool Properties To Non-Dynamic Objects?

i'm currently using a dictionary to associate a boolean to my (non-dynamic) sprites, but i would like to know if there is a smarter way of doing this? i could just use MovieClips to assign my properties instead of Sprites since MovieClips are dynamic, but i will not be using any of the MovieClip properties or functions so it comes down to a best practice issue.
basically i want to create a state boolean property on my sprites - they are either on or off so my boolean variable is called isOn.
var mySprite:Sprite = new Sprite();
var isOn:Boolean = false;
var dict:Dictionary = new Dictionar();
dict[mySprite] = isOn;
then i will poll my sprite to check its "isOn" property. if it's on, i will turn it off - or set it to false.
if (dict[mySprite] == true)
{
dict[mySprite] = false;
}
this is the first time i'm actually using dictionaries, so please correct me if i'm using it wrong. and, of course, my original question stands: is this the best way of adding a boolean property to a non-dynamic object?
Can't you just write your own Sprite that has an isOn property? That seems like a much simpler way to achieve what you want, without using a MovieClip.
isOn could be a public var or a pair of getter/setter if you want to perform some logic when reading/writting it.
public class MySprite extends Sprite {
private var _isOn:Boolean;
public function get isOn():Boolean {
return _isOn;
}
public function set isOn(v:Boolean):void {
_isOn = v;
}
}
And then:
var mySprite:MySprite = new MySprite();
mySprite.isOn = false;
// at some later point...
if (mySprite.isOn)
{
mySprite.isOn = false;
}

AS3 Scope issue, How do I dynamically create a new MC in a package/class?

Thanks very much for your time! Here is my question,...
public function addNewMc():void{
var newMC:MovieClip= new MovieClip();
this.addChild(newMC);
}
public function removeOldMc(newMC):void{
this.removeChild(newMC);
}
How can I create a new MovieClip within a method, which can be used throughout the class, without defining it at the top of the class? And for extra points, without using return.
I can get it to work, if the first function addNewMc returns the value newMC, and passing that to any other methods... but for what I am writing, I hope to use up my return with something else. Thanks!
Don't know if I'm understanding you completely but it sounds like you want access to a dynamically created Movieclip without explicitly defining it?! is that right?
If so, then you could do what you have now but add a method for retrieval:
public function addNewMc():void{
var newMC:MovieClip= new MovieClip();
this.addChild(newMC);
}
public function getMC():MovieClip
{
var len:uint = this.numChildren;
while(len--)
{
var tempObj:* = this.getChildAt(len);
if(tempObj is MovieClip)
return MovieClip(tempObj);
}
return null;
}
You could also add a name property to the dynamically created movieclip:
public function addNewMc():void
{
var newMC:MovieClip= new MovieClip();
newMC.name = "new_MC";
this.addChild(newMC);
}
you could then retrieve like this:
this.getChildByName("new_MC");
Again don't know if I'm understanding your exact requirements
cheers
erick ;)