AS3 - How do I stop a function? - actionscript-3

I have a function in my "enterFrameHandler* function and it is structured like this:
private function addBoss():void{
if(kills >= 3){
trace("boss time");
}
}
Since "addBoss" is a part of my ENTER_FRAME event listener function, "boss time" is traced infinitely as soon as kills reaches 3. I would like this function to stop as soon as it activates 1 time.
Is there another event listener I could use that will check for the function, but then stop as soon as it goes off?
Any suggestions would be appreciated. Thanks!

private function addBoss():void{
if(kills >= 3){
trace("boss time");
removeBossEnterFrame();
}
}
private function removeBossEnterFrame():void{
removeEventListener(Event.ENTER_FRAME, addBoss);
}
I'd prob remove the Enterframe event listner thats calling the addBoss function once you trace out "boss time".

This should do it.
private var isBossTime:Boolean = false;
private function addBoss():void
{
if(kills >= 3 && isBossTime == false)
{
trace("boss time");
isBossTime = true;
}
}

Related

AS3 - How do you call previous currentTarget from within a different event?

I have a dropdown menu that lets you select an item to be placed on the stage. The item is drag and droppable so I use event.currentTarget.startDrag(); to start the drag. Ok, everything works fine so far.
However, I also need to be able to rotate the item while it is being dragged (using the spacebar).
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e:KeyboardEvent):void{
if (e.keyCode == Keyboard.SPACE){
rotate++;
if (rotate == 5){
rotate = 1;
}
WHATGOESHERE?.gotoAndStop(rotate);
}
If I hardcode in an instance name of an object everything works fine - so the rotate function is working properly. The problem is, how can I reference event.currentTarget from the startDrag function while inside of the keyDown event?
My first thought was to set event.currentTarget to a variable and then calling the variable from within the keyDown event. However, targetHold = event.currentTarget; does not seem to record the instance name of the object being clicked...
public var targetHold:Object = new Object;
function ClickToDrag(event:MouseEvent):void {
event.currentTarget.startDrag();
targetHold = event.currentTarget;
trace ("targetHold " + targetHold);
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e:KeyboardEvent):void{
if (e.keyCode == Keyboard.SPACE){
rotate++;
if (rotate == 5){
rotate = 1;
}
targetHold.gotoAndStop(rotate); //does not work
}
}
function ReleaseToDrop(event:MouseEvent):void {
event.currentTarget.stopDrag();
}
As you click the object, it should have focus. If you register the listener for the KeyboardEvent on the object and not on the stage, it will be .currentTarget.
Here's an example of what I have in mind. Right after starting the drag, add the listener to the same object instead of the stage.
event.currentTarget.startDrag();
event.currentTarget.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
The proper way of doing this would be to define all the functionality in a class. Within a self contained class, you would not need any .currentTarget.
Here is how I would do this: (well, actually I'd follow #null's advice and encapsulate it in a sub class that all your dragable objects would extend, but that is a little broad so this will do)
public var targetHold:MovieClip; //don't make a new object, just create the empty var
public function YourConstructor(){
//your other constructor code
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown); //don't add the listener in the click function
}
private function clickToDrag(event:MouseEvent):void {
if(targetHold) ReleaseToDrop(null); //safeguard in case flash lost the focus during the mouse up
targetHold = event.currentTarget as MovieClip; //assign the current target. Might as well cast it as MovieClip and get code completion benefits
targetHold.startDrag();
trace ("targetHold " + targetHold);
}
private function myKeyDown(e:KeyboardEvent):void{
//check if target hold exists
if (targetHold != null && e.keyCode == Keyboard.SPACE){
rotate++;
if (rotate == 5){
rotate = 1;
}
targetHold.gotoAndStop(rotate);
}
}
private function ReleaseToDrop(event:MouseEvent):void {
if(targetHold) targetHold.stopDrag();
targetHold = null;
}

AS3 - How to get function to run after currentFrame updates?

I have 2 copies of a MovieClip (mcA) on my main timeline. Within mcA, I have 5 more MovieClips (mcB) and this code:
addEventListener(MouseEvent.CLICK, clickedPoint);
function clickedPoint(e:MouseEvent) {
e.target.play();
setStat(e.target.parent);
}
So I toggle the frame of the mcB that was clicked, and I run a function that references the corresponding mcA on the main timeline.
In setStat, I call another function that checks the currentFrame of all the mcBs in the mcA.
getPoints(stat) {
var points = 0;
for(var i = 1; i <= 5; i++)
{
if(stat["pnt"+i].currentFrame == 2) points++;
}
trace(points);
return points;
}
My problem is that the setStat function seems to run before the currentFrame of the mcB that has been clicked on updates.
How should I change my code so that the mcB that is clicked on registers as having changed its currentFrame when I call setStat?
You could call setStat() after the next frame update. A simple way to do this is to add an ENTER_FRAME event handler which removes itself when first invoked:
function clickedPoint(e:MouseEvent) {
e.target.play();
e.target.addEventListener(Event.ENTER_FRAME, function(e:Event):void {
e.target.removeEventListener(Event.ENTER_FRAME, arguments.callee);
setStat(e.target.parent);
});
}
You can encapsulate this behavior in a function that behaves like setTimeout:
function callNextFrame(target:DisplayObject, callback:Function, ...params:Array):void {
target.addEventListener(Event.ENTER_FRAME, function(e:Event):void {
target.removeEventListener(Event.ENTER_FRAME, arguments.callee);
callback.apply(null, params);
});
}
// Usage:
callNextFrame(e.target as DisplayObject, setStat, e.target);

How to register hitTest only if Mouse Down is true?

I was wondering on how to register a Hittest between two Movie Clips only if the MOUSE_DOWN event is equal to true.
So I have a Movie Clip called playerHook that acts as the Mouse and whenever that movie clip comes in contact with another movie clip called octopusBoss and Clicks on it I want it to register a hittest and subtract a point from its health.
Here is what I have so far but not sure what to do next:
In my main constructor function:
playerHook.addEventListener(Event.ENTER_FRAME, playerHookMove);
playerHook.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
playerHook.addEventListener(MouseEvent.MOUSE_UP, onMUp);
Then I have two booleas set up in the two functions onMDown and onMUp:
private function onMDown(e:MouseEvent):void
{
mouseIsDown = true;
}
private function onMUp(e:MouseEvent):void
{
mouseIsUp = false;
}
Then I have this function which is currently in my gameloop that I would want to happen only if the user clicks on the OctopusBoss:
private function checkPlayerHitOctopusBoss():void
{
if (playerHook.hitTestObject(octopusBoss))
{
trace("Hit Octopus");
octopusBossHealth --;
}else
if (octopusBossHealth <= 0)
{
octopusBoss.destroyOctopusBoss();
}
}
But I am having trouble passing the mouse booleans to the if statement. I know I am missing something crucial!
First you need some name to your octopusBoss like so:
octopusBoss.name = "octopusBoss";
Modify your onMDown function like so:
private function onMDown(e:MouseEvent):void
{
if(e.target.name == "octopusBoss") //Check if octopusBoss is under mouse
mouseIsDown = true;
}
And your checkPlayerHitOctopusBoss function like so:
private function checkPlayerHitOctopusBoss():void
{
if (playerHook.hitTestObject(octopusBoss) && mouseIsDown) // check mouse down
{
trace("Hit Octopus");
octopusBossHealth --;
}else
if (octopusBossHealth <= 0)
{
octopusBoss.destroyOctopusBoss();
}
}
UPDATE:
If it's ok to add MouseEvents directly to octopusBoss like so:
octopusBoss.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
octopusBoss.addEventListener(MouseEvent.MOUSE_UP, onMUp);
Then, you can also use e.currentTarget.name.

Actionscript 3 Timer on click hold

I have a function where I need to click and cube once and the cube will rotate to that side, then when i click and hold for 2 seconds will go to fifth page or when i click with no hold will start the cube rotating.
This is what I have
var numPressed:Number = 0
function side6(event:MouseEvent):void {
numPressed++;
if (numPressed % 2) {
SimpleZSorter.sortClips(container);
TweenLite.to(container, 1, {rotationX:-8,rotationY:193});
addEventListener(Event.ENTER_FRAME, rotateStop);
removeEventListener(Event.ENTER_FRAME, rotateThis);
}else if (NEED SOEMTHING HERE TO DETECT MOSUE HOLD AFTER SECONDS) {
gotoAndStop(5);
}
else{
addEventListener(Event.ENTER_FRAME, rotateThis);
}
}
The idea atm is numpressed calculates if the presses are odd or even, meaning 1 click will stop the cube rotating, 2 will start it again, a third will stop if and so forth, i need this to keep acting like that.
I need something in the second if statement, everything works well apart from getting it to work on holding the mouse.
Any help appreciated
Ian
I would suggest using MouseEvent.DOWN and MouseEvent.UP and store Date.time for this.
EG: This set of functions would track the ammount of millisenconds elapsed between the MouseEvent.DOWN and the MouseEvent.UP event.
private var mouseDownTime:Number = NaN,mouseUpTime:Number = NaN;
private function init():void
{
yourCubeObject.addEventListener(MouseEvent.DOWN,onMouseDown);
yourCubeObject.addEventListener(MouseEvent.UP,onMouseUp);
yourCubeObject.addEventListener(MouseEvent.OUT,onMouseOut);
}
private function onMouseOut(event:MouseEvent):void
{
mouseDownTime = mouseUpTime = NaN;//clear storage
}
private function onMouseDown(event:MouseEvent):void
{
mouseDownTime = new Date().time;//store system time in milliseconds since epoc
}
private function onMouseUp(event:MouseEvent):void
{
mouseUpTime = new Date().time;
if (!isNaN(mouseDownTime))//avoid error case where mouse went down outside object
{
if ((mouseUpTime - mouseDownTime) >= 2000)
{
//mouse held down for more the 2 seconds, your function here.
}
}
onMouseOut(event);//reset counters
}

Disabling repeating keyboard down event in as3

now I'm trying to make the keyboard events to stop repeating.
My idea was to have a true and false condition for when the key is pressed so that it wont repeat if the key is down already.
//Mouse Event Over
keyCButton.addEventListener(MouseEvent.MOUSE_OVER, function(){gotoAndStop(2)});
//Variable
var Qkey:uint = 81;
//Key Down Event
stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
var soundplayed = false;
function keydown(event:KeyboardEvent){
if (event.keyCode==Qkey) {
this.soundplayed=true;
}
}
if (this.soundplayed==false){
gotoAndPlay(3);
}
//Key Up Event
stage.addEventListener(KeyboardEvent.KEY_UP, keyup);
function keyup(event:KeyboardEvent){
this.soundplayed=false;
gotoAndStop(1);
}
doing this makes the key loop over and over without a keyboard event
I think i need to add a "&& keyDown..." to "if (this.soundplayed==true)" but i dont know how to do it without getting errors
here is the keyboard player i'm trying to fix http://soulseekrecords.org/psysci/animation/piano.html
Just another (perhaps a bit more general) way to write what Kishi already suggested:
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,keyUp);
var downKeys:Dictionary = new Dictionary();
function keyDown(e:KeyboardEvent):void {
if(!downKeys[e.keyCode]) {
downKeys[e.keyCode] = true;
processKeyDown(e);
}
}
function keyUp(e:KeyboardEvent):void {
delete downKeys[e.keyCode];
}
function processKeyDown(e:KeyboardEvent):void {
trace(e.keyCode);
}
The processKeyDown function will be called as if keydown repeating was disabled. If you need to do something when the key is up, put that code in the keyUp function, or maybe call a processKeyUp function defined like processKeyDown.
I'm not sure what you are doing on these frames..
Is that the complete code?
Anyway, you should try something like this:
// Mouse Events
this.keyCButton.addEventListener(MouseEvent.MOUSE_OVER, function():void{ gotoAndStop(2) });
// Variables
var Qkey:uint = 81;
var soundplayed = false;
// Keyboard events
this.stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
this.stage.addEventListener(KeyboardEvent.KEY_UP, keyup);
// Event listeners
function keydown(event:KeyboardEvent){
if (event.keyCode == Qkey && !this.soundplayed) {
this.soundplayed = true;
this.gotoAndPlay(3);
}
}
function keyup(event:KeyboardEvent){
this.soundplayed = false;
this.gotoAndStop(1);
}
Notice that the keydown event listener will now execute once -- I mean.. at least the if branch -- as the soundplayed variable is used as a locking mechanism.
It'll only execute again after keyup's been executed (this.soundplayed = false).