remove life from stage after mouseclick as3 code is not working - actionscript-3

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.

Related

Easy way to make a lot of buttons share a function? AS3

I am trying to do a simple light-up pegboard in flash. I have finished the general logic for 1 peg but there will be a total of 2,300 pegs and I don't want to have to add an event listener to each movieclip.
Here is my code:
import flash.events.Event;
var my_color:ColorTransform = new ColorTransform();
movieClip_1.addEventListener(MouseEvent.MOUSE_UP, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void
{
if (my_color.color == 0)
{
my_color.color = 0x0000FF;
event.target.transform.colorTransform = my_color;
}
else if (my_color.color == 255)
{
my_color.color = 0x00FF00;
event.target.transform.colorTransform = my_color;
}
else if (my_color.color == 65280)
{
my_color.color = 0xFF0000;
event.target.transform.colorTransform = my_color;
}
else if (my_color.color == 16711680)
{
my_color.color = 0xFFFFFF;
event.target.transform.colorTransform = my_color;
}
else if (my_color.color == 16777215)
{
my_color.color = 0x000000;
event.target.transform.colorTransform = my_color;
}
else
{
trace(my_color.color);
}
}
[
Here are 3 ways to accomplish this:
Put the code on the peg's own timeline. (or make a class file, and attach it to your peg object). This will re-use the same code for each peg instance automatically. Just take the same code you have, but use the this keyword instead of a hard reference to the movie clip:
var my_color:ColorTransform = new ColorTransform();
this.addEventListener(MouseEvent.MOUSE_UP, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void
{
//.....
Make a container Sprite/MovieClip and have all the pegs be the sole children of it. Then iterate over all the children of that container and attach the listener:
//loop through all children of the container and add an event listener
var i:int = container.numChildren;
while(i--){
container.getChildAt(i).addEventListener(....);
}
This is good because you don't have to give them instance names, which would be quite tedious.
Attach a click listener to a common parent of all pegs, and use the target property of the event to see if the click was on a peg.
Assuming you have right-clicked your peg library object, gone to properties and checked "export for actionscript" and given it the Class name "MyPeg", you could do this:
commonParent.addEventListener(MouseEvent.CLICK, parentClick);
function parentClick(e:Event):void {
if(e.target is MyPeg){
//it's a PEG, do something
}
}
Now, depending on how your peg object is structured, target could also refer to a child of your peg (instead of the peg itself). To avoid this if it's applicable, you can disable mouse input on the children of the peg. So on the first frame of your peg object, you could this: this.mouseChildren = false;
Now, even better (less tedious) would be to instantiate your pegs through code too. So as mentioned earlier, export your peg for actionscript in it's properties, and give it a class name ("MyPeg" for my example). Then something along these lines:
var curRow:int = 0;
var curCol:int = 0;
var totalRows:int = 25;
var totalCols:int = 92;
var startingY:int = 10;
var startingX:int = 10;
var padding:int = 2; //gap between pegs
var curPeg:MyPeg;
while(true){
//create the peg, and add it to the display.
curPeg = new MyPeg();
addChild(curPeg);
//add the click listener to this peg
curPeg.addEventListener(MouseEvent.CLICK, fl_mouseClickHandler);
//assign the position of this peg
curPeg.x = startingX + (curCol * (curPeg.width + padding));
curPeg.y = startingY + (curRow * (curPeg.height + padding));
//increment the column
curCol++;
//check if we've reached the last column in the row
if(curCol >= totalCols - 1){
//yes, so reset the column to 0 and increment the row
curCol = 0;
curRow++;
//break out of the loop if the curRow exceeds or is equal to the total rows var
if(curRow >= totalRows) break;
}
}
This way you could change your grid size simply by modifying the number assigned to totalCols and totalRows - no need to tediously move around 2300 objects in FlashPro.
One way to do it is loop through all the children of the parent of your 2300 pegs.
for (var i:int=0; i<numChildren; i++) {
var clip = getChildAt(i);
if (clip.name.indexOf('movieClip_')==0) {
clip.addEventListener((MouseEvent.MOUSE_UP, fl_MouseClickHandler);
}
}
Another way to do it is to add a handler to the entire parent clip and then in the handler check and see if what was clicked is one of your pegs. But you have to disable mouseChildren on the child clips for that to work.
Note that you may want to look at replacing that big if/then statement with switch/case, which is clearer and more compact in this type of situation.

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

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.

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;
}
}

actionscript for loop iterator to change movie clip name

I have a bunch of movie clips I created in flash CS5 and are all placed within the stage. I control each one of them dynamically with code using ActionScript 3. However I want to control all of them at the same time using a for loop and just change the width of each element but its not working.
Here is my code:
for(var i:Number = 0; i < 100; i++)
{
leftBar+i.width = ( Math.round(channel.rightPeak * 1.1) ) + 60;
}
So I have 100 bars each called leftBar and their number. So the firstBar is leftBar1, then leftBar2 and so on. I cant get it to work however. I have tried "leftBar"+i and also leftBari but none of them seem to work.
The correct way to select each of those MovieClips in your loop is:
this["leftBar" + i]
New code:
// Note: We've changed the initial value of i to 1 because you mentioned that
// your first MovieClip was called 'leftBar1' rather than 'leftBar0'.
for(var i:int = 1; i <= 100; i++)
{
var current:MovieClip = this["leftBar" + i];
current.width = Math.round(channel.rightPeak * 1.1) + 60;
}
Basically you want to select the property leftBar0, leftBar1, etc from this using square brackets. It is the same as doing this:
this.leftBar0
And can also be used for any properties or methods of any other class:
// Example of Square Bracket notation.
var sprite:Sprite = new Sprite();
sprite["x"] = 10;
trace(sprite.x);
this["addChild"](sprite);

Multiple movieclips all go to the same spot; What am i doing wrong?

So I'm trying to shoot multiple bullets out of my body and it all works except I have an odd problem of just one bullet showing up and updating to set position for the new ones.
I have a move able player thats supposed to shoot and I test this code by moving the player and shooting. Im taking it step by step in creating this.
The result of tracing the bulletContainer counts correctly in that its telling me that movieclips ARE being added to the stage; I Just know it comes down to some kind of logic that im forgetting.
Here's My Code (The Bullet it self is a class)
UPDATE*
Everything in this code works fine except for I stated earlier some code seems reduntned because I've resorted to a different approaches.
BulletGod Class:
public class bulletGod extends MovieClip{
//Register Variables
//~Global
var globalPath = "http://127.0.0.1/fleshvirusv3/serverside/"
//~MovieCLips
var newBullet:bulletClass = new bulletClass();
//~Boolean
var loadingBulletInProgress:Number = 0;
var shootingWeapon:Number = 0;
//~Timers
var fireBulletsInterval = setInterval(fireBullets, 1);
var bulletFireEvent;
//~Arrays
var bulletArray:Array = new Array();
var bulletType:Array = new Array();
var bulletContainer:Array = new Array();
//~Networking
var netBulletRequest:URLRequest = new URLRequest(globalPath+"bullets.php");
var netBulletVariables:URLVariables = new URLVariables();
var netBulletLoader:URLLoader = new URLLoader();
//~Bullet Image Loader
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest();
public function bulletGod() {
//Load every bullet for every gun
//Compile data to be requested
netBulletVariables.act = "loadBullets"
netBulletRequest.method = URLRequestMethod.POST
netBulletRequest.data = netBulletVariables;
netBulletLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
netBulletLoader.addEventListener(Event.COMPLETE, getBulletImages);
netBulletLoader.load(netBulletRequest);
}
private function getBulletImages(bulletImageData:Event){
//Request every bullet URL image
//Set vars
var bulletData = bulletImageData.target.data;
//Load images
for(var i:Number = 0; i < bulletData.numBullets; i++){
bulletArray.push(bulletData["id"+i.toString()]);
bulletType.push(bulletData["bullet"+i.toString()]);
//trace(bulletData["id"+i]+"-"+bulletData["bullet"+i]);
}
//All the arrays have been set start firing the image loader/replacer
var imageLoaderInterval = setInterval(imageReplacer, 10);
}
private function imageReplacer(){
//Check to see which image needs replacing
if(!loadingBulletInProgress){
//Begin loading the next image
//Search for the next "String" in the bulletType:Array, and replace it with an image
for(var i:Number = 0; i < bulletType.length; i++){
if(getQualifiedClassName(bulletType[i]) == "String"){
//Load this image
mRequest = new URLRequest(globalPath+"ammo/"+bulletType[i]);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadImage);
mLoader.load(mRequest);
//Stop imageReplacer() while we load image
loadingBulletInProgress = 1;
//Stop this for() loop while we load image
i = 999;
}
}
}
}
private function loadImage(BlackHole:Event){
//Image has loaded; find which array slot it needs to go into
for(var i:Number = 0; i <= bulletType.length; i++){
if(getQualifiedClassName(bulletType[i]) == "String"){
//We found which array type it belongs to; now replace the text/url location with the actual image data
var tmpNewBullet:MovieClip = new MovieClip;
tmpNewBullet.addChild(mLoader);
//Add image to array
bulletType[i] = tmpNewBullet;
//Restart loadingBullets if there are more left
loadingBulletInProgress = 0;
//Stop for() loop
i = 999;
}
}
}
//###############################################################################################################################################
private function fireBullets(){
//If player is holding down mouse; Fire weapon at rate of fire.
if(shootingWeapon >= 1){
if(bulletFireEvent == null){
//Start shooting bullets
bulletFireEvent = setInterval(allowShooting, 500);
}
}
if(shootingWeapon == 0){
//The user is not shooting so stop all bullets from firing
if(bulletFireEvent != null){
//Strop firing bullets
clearInterval(bulletFireEvent);
bulletFireEvent = null
}
}
}
private function allowShooting(){
//This function actually adds the bullets on screen
//Search for correct bullet/ammo image to attach
var bulletId:Number = 0;
for(var i:Number = 0; i < bulletArray.length; i++){
if(bulletArray[i] == shootingWeapon){
//Bullet found
bulletId = i;
//End For() loop
i = 999;
}
}
//Create new bullet
//Create Tmp Bullet
var tmpBulletId:MovieClip = new MovieClip
tmpBulletId.addChild(newBullet);
tmpBulletId.addChild(bulletType[bulletId]);
//Add To Stage
addChild(tmpBulletId)
bulletContainer.push(tmpBulletId); //Add to array of bullets
//Orientate this bullet from players body
var bulletTmpId:Number = bulletContainer.length
bulletTmpId--;
bulletContainer[bulletTmpId].x = Object(root).localSurvivor.x
bulletContainer[bulletTmpId].y = Object(root).localSurvivor.y
//addChild(bulletContainer[bulletTmpId]);
}
//_______________EXTERNAL EVENTS_______________________
public function fireBullet(weaponId:Number){
shootingWeapon = weaponId;
}
public function stopFireBullets(){
shootingWeapon = 0;
}
}
}
BulletClass:
package com{
import flash.display.*
import flash.utils.*
import flash.net.*
import flash.events.*
public class bulletClass extends MovieClip {
public var damage:Number = 0;
public function bulletClass() {
//SOME MOVEMENT CODE HERE
}
public function addAvatar(Obj:MovieClip){
this.addChild(Obj);
}
}
}
Well ... if I may say so, this code looks quite wrong. Either something is missing from the code or this code will never make the bullets fly.
First off, you can set x and y of the new bullet directly (replace everything after "orientate this bullet from players body" with this):
tmpBulletId.x = Object(root).localSurvivor.x;
tmpBulletId.y = Object(root).localSurvivor.y;
Perhaps this already helps, but your code there should already do the same.
But to let these bullets fly into any direction, you also need to add an event listener, like so:
tmpBulletId.addEventListener(Event.ENTER_FRAME, moveBullet);
function moveBullet(e:Event) {
var movedBullet:MovieClip = MovieClip(e.currentTarget);
if (movedBullet.x < 0 || movedBullet.x > movedBullet.stage.width ||
movedBullet.y < 0 || movedBullet.y > movedBullet.stage.height) {
// remove move listener, because the bullet moved out of stage
movedBullet.removeEventListener(Event.ENTER_FRAME);
}
// remove the comment (the //) from the line that you need
MovieClip(e.currentTarget).x += 1; // move right
// MovieClip(e.currentTarget).y -= 1; // move up
// MovieClip(e.currentTarget).x -= 1; // move left
// MovieClip(e.currentTarget).y += 1; // move down
}
This example lets your bullet fly to the right. If you need it flying into another direction, just comment out the line with the "move right" comment and uncomment one of the other lines.
This is of course a very simple example, but it should get you started.
I hope this helps, and that my answer is not the wrong answer to the question.
As far as I have expirienced it you can have only one copy of MovieClip object added to specific child. Best approach is to use ByteArray for the clip source and instantiate new MovieClip and pass the ByteArray as a source. It have something to do with child/parent relation since a DisplayObject can have only one parent (and a way to detach the object from scene too).
Well i ended up writeing the whole code from scratch for a 3rd time and ran into a similar problem and just for reference to anybody else that comes to a problem thats random as this one i found that problem was likly does to a conversion error somewhere that doesn't necessarily break any compiling rules. Just that i was calling a movieclip and not the class it self.