Animation code not fired when mouse is out Clip1 but mouse is inside clip 2 - actionscript-3

Problem:
When I move the mouse cursor out of Clip 1 but is above Clip 2, the MOUSE_OUT of Clip 1 does not work.
Expectation:
Granted that the mouse is inside Clip 2, the location of the mouse is outside of Clip 1 already, so the function mouse_out() of Clip 1 should fire the code inside it.
Full code:
I am attaching the full code so far.
import flash.display.MovieClip;
cat1.addEventListener(MouseEvent.MOUSE_OVER,mouse_over);
cat1.addEventListener(MouseEvent.MOUSE_OUT,mouse_out);
cat2.addEventListener(MouseEvent.MOUSE_OVER,mouse_over);
cat2.addEventListener(MouseEvent.MOUSE_OUT,mouse_out);
cat3.addEventListener(MouseEvent.MOUSE_OVER,mouse_over);
cat3.addEventListener(MouseEvent.MOUSE_OUT,mouse_out);
cat4.addEventListener(MouseEvent.MOUSE_OVER,mouse_over);
cat4.addEventListener(MouseEvent.MOUSE_OUT,mouse_out);
cat5.addEventListener(MouseEvent.MOUSE_OVER,mouse_over);
cat5.addEventListener(MouseEvent.MOUSE_OUT,mouse_out);
function mouse_over(e:MouseEvent)
{
squareEaseOut(e.currentTarget,["scaleX",1.5,"scaleY",1.5]);
}
function mouse_out(e:MouseEvent)
{
squareEaseOut(e.currentTarget,["scaleX",1,"scaleY",1]);
}
var iSquareEasingInterval:int;
//simple square easing, this can capture several properties to be animated
function squareEaseOut(mc:Object,vars:Array)
{
var checker:int = 0;
clearInterval(iSquareEasingInterval);
var ini:Array = new Array();
var accelNum:Number = 0;
var jerkNum:Number = 0;
var varsLength:uint = vars.length / 2;
for (var i:uint = 0; i<varsLength; i++)
{
ini[i] = mc[vars[2 * i]];
}
function animateEasing()
{
checker++;
if (compare(mc[vars[0]]+(0.25 * (vars[1] - ini[0])) / ((1 + accelNum) * (1 + accelNum)),vars[1]))
{
var end = new Date();
trace("Time lapse: "+(end - startD));
clearInterval(iSquareEasingInterval);
accelNum = 0;
jerkNum = 0;
for (var j:uint = 0; j<varsLength; j++)
{
mc[vars[2 * j]] = vars[(2 * j) + 1];
}
return;
}
for (var k:uint = 0; k<varsLength; k++)
{
mc[vars[2*k]] += (0.26 * (vars[(2*k)+1] - ini[k])) / ((1 + accelNum) * (1 + accelNum));
}
accelNum += 0.150+(jerkNum*jerkNum*jerkNum);
jerkNum += 0.09;
}
function compare(a:Number,b:Number)
{
if (vars[1]>ini[0])
{
return a>b;
}
else if (vars[1]<ini[0])
{
return a<b;
}
}
var startD = new Date();
iSquareEasingInterval = setInterval(animateEasing,20);
};

The problem is that you are calling the same method squareEaseOut when any mouse over or mouse out event occurs. Since you are moving your mouse immediately out of one Movie Clip and on to the other, the same method gets called twice, first for the mouse out (for the old movie clip) and then for the mouse over of the new Movie Clip. This will not result in correct behavior as the second call will override the first one as you are using setInterval and clearing the interval as well on every call.
While there may be multiple ways to solve this, easiest way would be to have separate methods for mouse out and mouse over, although that might lead to some code repetition. Or, you could wait for the first animation to finish and then call the other one.
You can also look at various tweening libraries available to achieve what you want, but thats not something that I would advertise here.
Hope this helps.

Related

remove life from stage after mouseclick as3 code is not working

i have added 5 life icons on a container in stage..now i want to remove them one by one by mouse click.it is working for first click(one child is removing from stage).but it is not working after that.what should i do.there is no error in code but not working.here is the code
var Lives:Number = 5;
var Spacing:Number = 5;
var nextX:Number = 0;
for(var i:int = 0; i < Lives; i++ )
{
var mc:MovieClip = new mcPlayerLives();
mc.x = nextX;
lives_container.addChild(mc );
nextX += mc.width + Spacing;
}
attackButton.addEventListener(MouseEvent.CLICK, removeLife);
function removeLife(event:MouseEvent):void
{
// Lives= Lives - 1;
if (lives_container.contains(mc))
lives_container.removeChild(mc);
}
You've defined the variable mc in the loop. When loop end, mc point to the last instance of the mcPlayerLives class. In the removeLife function you remove only last instance of the mcPlayerLives class.
Instead of
if (lives_container.contains(mc))
lives_container.removeChild(mc);
use
if (lives_container.numChildren)
lives_container.removeChildAt(0);
It means: if lives_container contains at least one child, remove the child.

AS3 Add Child at the position of another Child

Hey I have got some cavemen that when they build huts I want the huts to be added at the coords of the caveman I last clicked on which requires the ability to know exactly what caveman the user clicked on/tapped. Here is the code for spawning in the cavemen:
//////////////////////
///Starting Cavemen///
//////////////////////
var cavemanVar:Array = new Array(50);
for (var i:Number = 0; i < 50; i++)
{
cavemanVar[i] = 0;
}
var foo:MovieClip = new btn_caveman();
cavemanVar[0] = addChildAt(foo, 7);
var bar:MovieClip = new btn_caveman();
cavemanVar[1] = addChildAt(bar, 7);
cavemanVar[0].x = 335.50;
cavemanVar[0].y = 316.55;
cavemanVar[1].x = 335.50;
cavemanVar[1].y = 369.5;
stage.addEventListener(Event.ENTER_FRAME, example2);
function example2 (evt:Event) {
for (i = 0; i < 50; i++)
{
if (cavemanVar[i] != 0)
{
cavemanVar[i].addEventListener(TouchEvent.TOUCH_TAP, btn_cavemanMenu3);
}
}
}
function option1CavemenSpawn():void {
trace("using option 1")
actions += 1;
score += 5;
remaningActions += 1;
updateTextBox();
var foo6:MovieClip = new btn_caveman();
cavemanVar[2] = addChildAt(foo6, 7);
cavemanVar[2].x = 352.10;
cavemanVar[2].y = 260.80 + Math.random() * (392.40 - 260.80);
}
Any help would be great, I have tried using 'cavemanVar', 'cavemanVar[2]', 'cavemanVar[i]' and nothing is what I want it to be.
Hope I explained it properly it's a tricky thing to explain. I also have a move caveman feature I want to implement which would select the last clicked/tapped caveman and move it where the user clicks/taps so can any of this be done and if so how?
EDIT:
function btn_cavemanMenu3(event:TouchEvent):void {
btn_cavemanM.gotoAndStop(2);
trace('2');
allowBuildHut();
cancelTapCaveman();
allowTapCavemanClose();
if (remaningActions <= 2 || stone <= 29) {
cancelBuildHut();
}
}
Do you mean something like,
cavemanVar[i].addEventListener(TouchEvent.TOUCH_TAP, onTap);
function onTap(e:TouchEvent):void {
var caveman:btn_caveman = e.currentTarget as btn_caveman;
trace("caveman tapped --- (" + caveman.x + ", " + caveman.y + ")");
}
Okay, some things I noticed right away:
Attaching eventListeners with each frame, again and again. This will make your game slow if you make your game bigger. I'm not sure, but I think multiple event listeners with the same arguments don't stack, so it's not THAT bad.
Missing a return type for example2.
But aside from that, I think the reason that what you're trying to do doesn't work is because you're not referencing the selected caveman in your btn_cavemanMenu3 function. Via event.currentTarget you can reference the tapped caveman.
Currently, your question name and your question description conflict. What exactly do you wish to achieve? What is working and what isn't working right now?

How to loop falling object in flash AS3 once it has hit bottom of the scene

This is the code i have got so far for a single falling object. The 'DangerIN' is the instance name for the object that is falling down. The class is named 'Danger'. So how can i make it loop so it falls continuously and when it reaches certain y value it will remove it self. Also i want more than one(abount 5) objects falling down at once.
var randomX:Number = Math.random() * 550;
DangerIN.x = randomX;
DangerIN.y = 96;
var speed:Number = Math.random()*10;
DangerIN.addEventListener(Event.ENTER_FRAME, moveDown);
function moveDown(e:Event):void {
e.target.y += speed;
if(e.target.y >= 610) {
DangerIN.removeEventListener(Event.ENTER_FRAME, moveDown);
}
}
It's easy. But to do that, you first need an Array of falling stuff, and then you need to reposition your e.target to the top once it's below your threshold.
function moveDown(e:Event):void {
e.target.y += speed;
if (e.target.y >= 610) {
// reposition
e.target.x=math.random()*550;
e.target.y=96;
}
}
Assign this function to every object you want to fall down, reach bottom and reappear back up.
To remove itself you can add a following line after the removeEventListener():
parent.removeChild(this);
But it's not pretty and you probably should to it the right way:
Store all the Danger objects in the array, in the Danger class create a function like go(), moveDown() or something:
public function go():void
{
y+= speed;
}
and in the class where you create the Danger objects make a loop like this:
private function loop():void
{
for (var i:int = dangerObjArray.lenght - 1; i >= 0; i--)
{
dangerObjArray[i].go();
if (dangerObjArray[i].y >= maxY)
dangerObjArray.splice(i , 1);
}
}

My Actionsript is Skipping Frame 3 and Going Straight to Frame 4

I'm trying to make a primitive game in Flash. I'm using AS3 to build it. So far everything I have coded is working fine. Until now, I've only had 3 frames. However, I am ready to move on so I added a fourth frame. But, when I test the animation, it skips from frame 2 to frame 4. I put a trace in Frame 3 to see if Flash was even running it, and the trace executes the trace so I know Flash isn't completely ignoring Frame 3. But, I have a stop(); at the end of frame 3 and I have a stop(); on Frame 4. So, I'm not sure why Frame 3 is being skipped. The game doesn't have any tweens or actual animations so it shouldn't be anything of that sort. The only interaction is clicking on dots. I've put the code for all 4 of my frames below (I'm not sure if this is frowned upon. If it is, please tell me and I'll remove it but I'm putting it because it seems like it may be helpful). I'm also uploading a link to my .FLA file in case someone wants to see the whole thing.
Frame 1:
import flash.events.MouseEvent;
var dotList = new Array(); var level:int = 10; var invisoDotList = new Array();
var loop:int;
for(loop = 0; loop < level; loop++)
{
var dot:Dot = new Dot();
var invisoDot:InvisoDot = new InvisoDot();
var tester:Boolean = true;
var xval:int = Math.floor(Math.random()*(1+520))+14;
var looper:int = 0;
while(looper < dotList.length)
{
if(Math.abs(xval - dotList[looper].x) > 30)//minimum spacing
{
looper++;
}
else
{
looper = 0;
xval = Math.floor(Math.random()*(1+520))+14;
}
}
dot.x = xval;
dot.y = 187;
invisoDot.x = xval;
invisoDot.y = 187;
invisoDot.alpha = 0;
dotList[loop] = dot;
invisoDotList[loop] = invisoDot;
addChild(invisoDot);
addChild(dot);
}
//trace(dotList); test to ensure that dots are added to the array
button.addEventListener(MouseEvent.CLICK, hideDots);
function hideDots(e:MouseEvent)
{
for(var loop:int = 0; loop < dotList.length; loop++)
{
dotList[loop].alpha = 0;//make dots disappear
}
nextFrame();
}
stop();
Frame 2:
import flash.events.MouseEvent;
button.addEventListener(MouseEvent.CLICK, next);
function next(e:MouseEvent)
{
nextFrame();
}
stop();
Frame 3:
import flash.events.MouseEvent;
removeChild(button);
var clicks:int = -1;
//trace(dotList.length);
stage.addEventListener(MouseEvent.CLICK, clickCount);
for(var loopvar:int = 0; loopvar < dotList.length; loopvar++)
{
//trace("loop");
dot = dotList[loopvar];
invisoDot = invisoDotList[loopvar];
dot.addEventListener(MouseEvent.CLICK, onClick);
invisoDot.addEventListener(MouseEvent.CLICK, onClick);
//trace("event");
}
//trace(dotList.length);
function onClick(e:MouseEvent)
{
//e.currentTarget.alpha = .5;
for(var hitcheck:int = 0; hitcheck < dotList.length; hitcheck++)
{
if(dotList[hitcheck].x == e.currentTarget.x)
{
dotList[hitcheck].alpha = 1;
}
}
//trace("check");
}
function clickCount(e:MouseEvent)
{
clicks++;
//trace(clicks);
var numChanged:int = 0;
for(var index:int = 0; index < dotList.length; index++)//check whether the user has gotten all the dots
{
if(dotList[index].alpha == 1)
{
numChanged++;
}
}
if(numChanged == level)//if the user has gotten all the dots
{
trace("next screen for sucess");
trace(clicks);
}
else if((clicks - numChanged) >= 2)//this ends the session as soon as 2 mistakes are made
{
trace("next screen for failed number of clicks");
trace(clicks);
}
/*else if((clicks - level) >= 2)//if the user has made too many mistakes. This ends the session after the maximum number of tries have been used
{
trace("next screen too many clicks");
trace(clicks);
}*/
}
trace("end");
stop();
Frame 4:
stop();
Link to the .FLA file: https://www.dropbox.com/s/x1vim49tnz227id/Game.fla
If any of the conventions I've used in this question are wrong or frowned upon, please let me know and I'll correct them. It's been over a year since I've last posted on StackOverflow.
Does the same button instance exist on both frame 1 and 2?
If so you will end up with two click event handlers on the button on frame 2 (hideDots() and next()). If you click on the button then they both call nextFrame() which would skip frame 3.
Possible solutions:
Remove the first event listener before moving to the next frame:
button.addEventListener(MouseEvent.CLICK, hideDots);
function hideDots(e:MouseEvent)
{
for(var loop:int = 0; loop < dotList.length; loop++)
{
dotList[loop].alpha = 0;//make dots disappear
}
// Remove the event listener here:
button.removeEventListener(MouseEvent.CLICK, hideDots);
nextFrame();
}
OR
Have different instances of the button on frame 1 and 2.
You can do this by having a keyframe for the button on frame 1 and 2 - Flash will create a new instance of the button when it hits that frame.

Dragging Sprite Array in Actionscript 3

My goal is to spawn a circle on the MOUSE_WHEEL event, and move all of them when a dragging occurs, as detected with MOUSE_DOWN and MOUSE_UP. I've done this by adding each Sprite created into an array, and iterating through it when mouse up/down. Note: Node is just an extension of the Sprite type.
However, for some reason, only the most recently drawn Sprite in the array is being moved. Any ideas why?
My Canvas class:
public function Canvas() {
trace("Starting it");
const background:Sprite = new Sprite();
background.graphics.beginFill(0x00000000);
background.graphics.drawRect(0, 0, this.stage.stageWidth, this.stage.stageHeight);
background.graphics.endFill();
addChild(background);
background.addEventListener(MouseEvent.MOUSE_WHEEL, createNode);
background.addEventListener(MouseEvent.MOUSE_DOWN, startObjectMove);
background.addEventListener(MouseEvent.MOUSE_UP, endObjectMove);
mNodeList = new Array();
}
...
}
My startObjectMove and endObjectMove methods:
public function startObjectMove(pEvent:MouseEvent) : void {
trace("Starting drag...");
trace("There are " + mNodeList.length + " in list");
for (var i:int = 0; i < mNodeList.length; i++) {
var node:Node;
node = Node(mNodeList[i]);
node.startMove(pEvent);
}
}
public function endObjectMove(pEvent:MouseEvent) : void {
trace("Ending drag...");
trace("There are " + mNodeList.length + " in list");
for (var i:int = 0; i < mNodeList.length; i++) {
var node:Node;
node = Node(mNodeList[i]);
node.endMove(pEvent);
}
}
The endMove and startMove methods simply call this.startDrag() and this.endDrag().
You can only use startDrag and stopDrag on one object at a time.
You need to listen for mouse down events on the stage itself - when the user clicks, store the initial position of each node (create two public vars/properties in the Node class), and also record where the mouse starts out.
Then, whenever the mouse moves until it's released, work out how far it's moved since mouse down, and add this amount to the initial position of each node to set its position.
You need to do something like this:
var initX:int;//Variables to store the mouse position on click:
var initY:int;
stage.addEventListener(MouseEvent.MOUSE_DOWN):void {
initX = stage.mouseX;//Store the starting mouse position
initY = stage.mouseY;
//Store the node positions:
for(var i:int = 0; i < mNodeList.length; i++){
var node:Node = Node(mNodeList[i]);
node.startX = node.x;
node.startY = node.y;
}
//Listen for mouse move events
stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMove);
}
stage.addEventListener(MouseEvent.MOUSE_UP):void {
//Stop listening for mouse move events
stage.removeEventListener(MouseEvent.MOUSE_MOVE,mouseMove);
}
//MouseMove event handler:
function mouseMove(e:MouseEvent):void{
for(var i:int = 0; i < mNodeList.length; i++){
var node:Node = Node(mNodeList[i]);
// Position each as amount the mouse has moved
// to each node's initial position:
node.x = (stage.mouseX-initX) + node.startX;
node.y = (stage.mouseY-initY) + node.startY;
}
}