Add a movieclip but make sure it isn't in the same place as another movieclip. (as3) - actionscript-3

So I have this where you add movieclips by clicking, but it is unefficient and doesn't have some functionality that I want, I need to only add the movieclip if no other movieclip is in the same place.
private function onClick():void
{
if(placesound==false)
{
placepixel.play();
placesound = true;
}
if(erasetrue==false)
{
var pixel = new Pixel();
pixel.x = 0;
pixel.y = 0;
}
if(mouseY>30 && irontrue==true)
{
//var pixel = new Pixel();
pixel.x=(Math.round(mouseX/5)*5)-2.5;
pixel.y=(Math.round(mouseY/5)*5)-2.5;
pixel.graphics.beginFill(0x999999);
pixel.graphics.drawRect(0, 0, 5, 5);
pixel.graphics.endFill();
pixel.type=0;
pix.push(pixel);
//addChild(pixel);
}
if(mouseY>30 && woodtrue==true)
{
//var pixel = new Pixel();
pixel.x=(Math.round(mouseX/5)*5)-2.5;
pixel.y=(Math.round(mouseY/5)*5)-2.5;
pixel.graphics.beginFill(0x996600);
pixel.graphics.drawRect(0, 0, 5, 5);
pixel.graphics.endFill();
pixel.type=3;
pix.push(pixel);
//addChild(pixel);
}
if(erasetrue==true)
{
for (i=pix.length-1; i>=0; i--)
{
if(pix[i].x==(Math.round(mouseX/5)*5)-2.5 && pix[i].y==(Math.round(mouseY/5)*5)-2.5)
{
removeChild(pix[i]);
pix.splice(i, 1);
}
}
}
if(mouseY>30 && springtrue==true)
{
//var pixel = new Pixel();
pixel.x=(Math.round(mouseX/5)*5)-2.5;
pixel.y=(Math.round(mouseY/5)*5)-2.5;
pixel.graphics.beginFill(0x000000);
pixel.graphics.drawRect(0, 0, 5, 5);
pixel.graphics.endFill();
pixel.type=1;
pix.push(pixel);
//addChild(pixel);
}
if(mouseY>30 && portaltrue==true)
{
//var pixel = new Pixel();
pixel.x=(Math.round(mouseX/5)*5)-2.5;
pixel.y=(Math.round(mouseY/5)*5)-2.5;
pixel.graphics.beginFill(0x9999FF);
pixel.graphics.drawRect(0, 0, 5, 5);
pixel.graphics.endFill();
pixel.type=2;
pix.push(pixel);
//addChild(pixel);
}
if(erasetrue==false)
{
addChild(pixel);
}
}
I want to somehow only run the last if (the one that addChilds the pixel.) only if no other movieclip (see the array "pix") has is already in the spot it would be placed in. (I round the mouse before placing it.
Thanks for any help.
Edit: Spoilers failed.

Loop through the pix array to see if any of the pixels in the array match the x and y coordinates of the new pixel object. If not, the pixel should be added.
So instead of your final if statement:
...
if(erasetrue==false){
var canPlace:Boolean = true;
for (var i:int = 0; i < pix.length; i++){
var placedPixel:Pixel = pix[i] as Pixel;
if(pixel.x == placedPixel.x && pixel.y == placedPixel.y){
canPlace = false;
}
}
if(canPlace){
addChild(pixel);
}
}

Related

Make movieclip arrays not overlap to each other

I'm currently working on a game with AS3, wherein the player needs to avoid falling random objects by tilting the phone. These objects uses timer for delay to make them fall one time per row. So I'm working now on the level where there are two objects falling randomly on the screen, which are movieclips "mercury" with class name of planet1 and "venus" with class name of "planet2". The problem is, sometimes they overlapped with each other when falling. I want the two movieclips to not overlap with each other when they start to fall. I had look for scripts and tried it but it doesn't work. I'm beginner in AS3.
Here is the script:
var mercury:planet1;
var mercuryArray:Array = new Array();
var mercuryClock = new Timer(5000, 0);
mercuryClock.addEventListener(TimerEvent.TIMER, spawnMercury);
var venus:planet2;
var venusArray:Array = new Array();
var venusClock = new Timer(2000, 0);
venusClock.addEventListener(TimerEvent.TIMER, spawnVenus);
addEventListener(Event.ENTER_FRAME, onMyEnterFrame);
function onMyEnterFrame(e:Event)
{
galawMercury();
galawVenus();
checkCollision();
}
/*==================PLANET 1=====================*/
function spawnMercury(e:Event)
{
gawaMercury();
}
function gawaMercury()
{
var mercury:planet1 = new planet1();
mercury.x = Math.random() * 400;
mercury.y = 0;
addChild(mercury);
mercuryArray.push(mercury);
}
function galawMercury()
{
for(var ee:int = mercuryArray.length - 1; ee >= 0; ee--)
{
mercuryArray[ee].y += 13;
if(mercuryArray[ee].y > stage.stageHeight)
{
mercuryArray[ee].parent.removeChild(mercuryArray[ee]);
mercuryArray.splice(ee, 1);
}
}
}
/*==================PLANET 2=====================*/
function spawnVenus(e:Event)
{
gawaVenus();
}
function gawaVenus()
{
var venus:planet2 = new planet2();
venus.x = Math.random() * 400;
venus.y = 0;
venus.width = 126;
venus.height = 200;
addChild(venus);
venusArray.push(venus);
}
function galawVenus()
{
for(var yy:int = venusArray.length - 1; yy >= 0; yy--)
{
venusArray[yy].y += 12;
if(venusArray[yy].y > stage.stageHeight)
{
venusArray[yy].parent.removeChild(venusArray[yy]);
venusArray.splice(yy, 1);
}
}
}
function checkCollision()
{
for(var oo:int = mercuryArray.length - 1; oo >= 0; oo --)
{
if(stella.hitStella.hitTestObject(mercuryArray[oo]))
{
keme();
}
}
for(var uu:int = venusArray.length - 1; uu >= 0; uu --)
{
if(stella.hitStella.hitTestObject(venusArray[uu]))
{
keme();
}
}
}
function keme()
{
soundtrackChannel.stop();
soundtrackChannel = stellaDead.play();
removeEventListener(Event.ENTER_FRAME, onMyEnterFrame);
mercuryClock.stop();
venusClock.stop();
score.stop();
stella.play();
blah.text = lbl_iskor.text;
removeObjects();
}
function removeObjects()
{
for each (var mercury:planet1 in mercuryArray)
{
mercuryArray.splice(mercury, 0);
removeChild(mercury);
}
for each (var venus:planet2 in venusArray)
{
venusArray.splice(venus, 0);
removeChild(venus);
}
}

Random movide clip without loop?

I created some MovieClips and put all of them on the stage. I'm trying to move a random MovieClip, using it only once, but at the same time I need to know which one it is because it will conflict with other tween effects. Is there an easy way to do that?
Here is what I've tried:
var biryukseklev1, ikiyukseklev1, ucyukseklev1, dortyukseklev1, besyukseklev1:int;
var assignavalue1, assignavalue2:int;
stage.addEventListener(Event.ENTER_FRAME,survivordondurlev6);
function survivordondurlev6(e:Event) {
if (biryerlessurlev1 == 0) {
biryukseklev1 = 764;//36
} else if (biryerlessurlev1 == 1) {
biryukseklev1 = 680;//120
} else if (biryerlessurlev1 == 2) {
biryukseklev1 = 596;//204
} else if (biryerlessurlev1 == 3) {
biryukseklev1 = 512;//288
} else if (biryerlessurlev1 == 4) {
biryukseklev1 = 428;//372
}
if (assignavalue1 == 0 && rabbitstatus.text.length < 2) { //Make sure to not used before
var my:Tween = new Tween(rabbit, "y", Back.easeInOut, rabbit.y, rabbit.y -biryukseklev1, 3, true);
rabbitstatus.text = "okfull";
} else if((assignavalue1 == 1 && birdstatus.text.length < 2){ //Make sure to not used before
var mys:Tween = new Tween(bird, "y", Back.easeInOut, bird.y, bird.y -biryukseklev1, 3, true);
birdstatus.text = "okfull";
}
}
If you want to keep track of which clips you've animated, then you'll have to have some way of iterating through them. The easiest list would be an Array, though how you mark them as "animated" is up to you. If you never plan on animating them again, then simply removing the ones that you've animated, and leaving the rest for later will work.
Below is example code, which you should be able to run in a new scene. You should be able to apply it to your needs with some small edits.
import fl.transitions.Tween;
import fl.transitions.easing.*;
// We'll keep track of which blocks still need to be animated by including them in this list
// Once we animate a block, we remove it from the list.
var pool:Array = [];
// Populate the stage with blocks.
for (var i:int = 0; i < 30; i++) {
var block:Sprite = createBlock();
addChild(block);
block.y = 50;
if (i > 0) { block.x = block.width * i; }
pool.push(block);
}
// Create an interactive button.
var txt:TextField = new TextField();
txt.text = "Do something";
addChild(txt);
txt.addEventListener("click", animateNext);
function createBlock():Sprite {
// Creates a single, randomly colored block.
var block:Sprite = new Sprite();
block.graphics.beginFill(random(0x000000, 0xFFFFFF));
block.graphics.drawRect(0,0,16,16);
block.graphics.endFill();
return block;
}
function random(low:Number, high:Number):Number {
// Returns a random number between the low and high numbers.
return Math.floor(Math.random() * (1+high-low)) + low;
}
function animateNext(e:Event):void {
// Do this 5 times.
for (var i:int = 0; i < 5; i++) {
// As long as we have blocks in the pool...
if (pool.length > 0) {
// Pick a random block from the pool
var index:int = random(0, pool.length-1);
// Animate it
new Tween(pool[index], "y", Back.easeInOut, pool[index].y, pool[index].y + 50, 3, true);
// Remove it from the pool so it isn't picked again
pool.splice(index, 1);
} else {
// Otherwise, break the loop.
break;
}
}
}

Trouble with addChild/removeChild and display list order in ActionScript3

I am working on a project, which includes a Lake symbol that the player can throw stones into, which in turn causes octopi to rise out of the lake in the positions that each stone hits the lake.
There is also a symbol for the splash made by the stone which will appear after the stone hits and before the octopus appears.
It is likely that there will be many octopi on the screen at the same time and they need to be ordered in the display list so that the ones that should appear further back are behind the others.
Each instance of these symbols should only play once and then be removed.
My code for this makes use of the different add/remove child method alongside for loops, conditionals and arrays which I have put together with the help of various tutorials and forums.
The problem I have is that when you click on the lake two or more times in quick succession, the stone and the splash symbols aren't removed properly and often keep looping.
Here is the code I am using. Any ideas?
var stone:Stone;
var stoneSplash:StoneSplash;
var octopus1:Octopus1;
var octopus2:Octopus2;
var whichOctopus:Array = [addOctopus1, addOctopus2];
var octopusScale:Number;
var octopusContainer:MovieClip = new MovieClip;
lake.lakeHitArea.addEventListener(MouseEvent.CLICK, onClickLake);
//Add octopusContainer to the stage's display list just above the Lake
addChildAt(octopusContainer,getChildIndex(lake) + 1);
octopusContainer.x = 0;
octopusContainer.y = 0;
function onClickLake(e:MouseEvent):void
{
trace("CLICK");
throwStone(mouseX, mouseY);
}
function throwStone(stonePositionX:int, stonePositionY:int)
{
stone = new Stone();
stone.x = stonePositionX;
stone.y = stonePositionY;
addChild(stone);
addEventListener(Event.ENTER_FRAME, removeStone);
}
function removeStone(e:Event):void
{
var count:int = numChildren;
var children:Array = [count];
//load all the children of the component into an Array
for (var i:int=0; i<count/* -1*/; i++)
{
children[i] = getChildAt(i/* + 1*/);
}
for (i=0; i<count/* - 1*/; i++)
{
if (children[i] is Stone)
{
if (children[i].currentFrameLabel == "Splash")
{
stoneSplash = new StoneSplash();
octopusContainer.addChild(stoneSplash);
stoneSplash.x = children[i].x;
stoneSplash.y = children[i].y;
}
if (children[i].currentFrameLabel == "end")
{
octopusContainer.removeChild(stoneSplash);
var positionX:int = children[i].x;
var positionY:int = children[i].y;
addOctopus(positionX, positionY);
removeChild(children[i]);
}
}
}
}
function addOctopus(positionX, positionY)
{
var o:int = Math.round(randomNumber(0,1));
whichOctopus[o](positionX, positionY);
reorderDisplayList();
addEventListener(Event.ENTER_FRAME, removeOctopus);
}
function addOctopus1(positionX: int, positionY:int):void
{
// if (whichOctopus1 == true)
// {
// var octopus:* = octopus1_1;
// }
// else
// {
// octopus = octopus1_2;
// }
octopus1 = new Octopus1();
var octopus:DisplayObject = octopus1;
octopusContainer.addChild(octopus);
octopus.x = positionX;
octopus.y = positionY;
octopusScale = randomNumber(0.5,0.85);
octopus.scaleX = octopusScale;
octopus.scaleY = octopusScale;
trace("children = " + octopusContainer.numChildren);
testPosition(octopus);
}
function addOctopus2(positionX: int, positionY:int):void
{
// if (whichOctopus2 == true)
// {
// var octopus:* = octopus2_1;
// }
// else
// {
// octopus = octopus2_2;
// }
octopus2 = new Octopus2();
var octopus:DisplayObject = octopus2;
octopusContainer.addChild(octopus);
octopus.x = positionX;
octopus.y = positionY;
octopusScale = randomNumber(0.25,0.5);
octopus.scaleX = octopusScale;
octopus.scaleY = octopusScale;
trace("children = " + octopusContainer.numChildren);
testPosition(octopus);
}
function testPosition(octopus:Object):void
{
trace(octopus)
for (var i:int = 0; i < 200; i++)
{
if (lake.hitTestPoint(octopus.x + octopus.hitTestBox1.x * octopus.scaleX,octopus.y + octopus.hitTestBox1.y * octopus.scaleY,true))
{
break;
}
else
{
octopus.x++;
}
}
for (i = 0; i < 100; i++)
{
if (lake.hitTestPoint(octopus.x + octopus.hitTestBox2.x * octopus.scaleX,octopus.y + octopus.hitTestBox2.y * octopus.scaleY,true))
{
break;
}
else
{
octopus.y--;
}
}
for (i = 0; i < 200; i++)
{
if (lake.hitTestPoint(octopus.x + octopus.hitTestBox3.x * octopus.scaleX,octopus.y + octopus.hitTestBox3.y * octopus.scaleY,true))
{
break;
}
else
{
trace(i);
octopus.x--;
}
}
for (i = 0; i < 100; i++)
{
if (lake.hitTestPoint(octopus.x + octopus.hitTestBox1.x * octopus.scaleX,octopus.y + octopus.hitTestBox1.y * octopus.scaleY,true))
{
break;
}
else
{
octopus.y--;
trace(i);
}
}
}
function randomNumber(min:Number, max:Number):Number
{
return Math.random() * (max - min) + min;
}
function reorderDisplayList():void
{
//the number of children in our component
var count:int = octopusContainer.numChildren;
var children:Array = [count];
//load all the children of the component into an Array
for (var i:int=0; i<count; i++)
{
children[i] = octopusContainer.getChildAt(i);
}
//sort the Array children based on their 'y' property
children.sortOn("y", Array.NUMERIC);
//re-add the children to the component ;
//in the order of the sorted Array we just created.
//When we add the children using 'addChild' it will
//be added at the top of the component's displaylist
//and will automatically be removed from its original position.
for (i=0; i<count/* - 1*/; i++)
{
if (children[i] is Octopus1 || children[i] is Octopus2)
{
// trace("child = " + children[i] + " at i: " + i);
octopusContainer.removeChild(children[i]);
octopusContainer.addChild(children[i]);
}
}
}
function removeOctopus(e:Event):void
{
var count:int = octopusContainer.numChildren;
var children:Array = [count];
//load all the children of the component into an Array
for (var i:int=0; i<count/* -1*/; i++)
{
children[i] = octopusContainer.getChildAt(i/* + 1*/);
}
for (i=0; i<count/* - 1*/; i++)
{
if (children[i] is Octopus1 || children[i] is Octopus2)
{
trace(i);
trace("Is an octopus");
if (children[i].currentFrame >= 202)
{
octopusContainer.removeChild(children[i]);
}
}
}
}
I would greatly appreciate any advice to help me overcome this hurdle and continue with my project.
Thank you in advance.
Chris Collins.
Your issue (or at least one of them) is that your code will only remove the most recent StoneSplash. So if you click a bunch of times in between the splash and end animation , only the last clicked one will get removed.
This is because you are using a global var (stoneSplash) to reference the splash, and it gets overwritten to the new one. You need to either add a splash reference on the stone itself, or create a dictionary so you know which splash goes with which stone.
Here would be one way:
if (children[i].currentFrameLabel == "Splash")
{
stoneSplash = new StoneSplash();
MovieClop(children[i]).stoneSplash = stoneSplash; //add a reference the splash on the stone itself
Then later, instead of octopusContainer.removeChild(stoneSplash); do:
octopusContainer.removeChild(MovieClop(children[i]).stoneSplash);
This way your removing the correct splash that goes with this stone.
Here would be a much cleaner way to architect this instead of using an enter frame handler:
On your Stone class timeline, put the following code on your Splash and End frames respectively:
Splash frame: this.dispatchEvent(new Event("Splash"));
End frame: this.dispatchEvent(new Event("End"));
Listen for those events when you create a new stone instance:
stone = new Stone();
stone.x = stonePositionX;
stone.y = stonePositionY;
stone.addEventListener("Splash", splashHandler,false,0,true);
stone.addEventListener("End",removeStone,false,0,true);
addChild(stone);
Respond to those events appropriately:
function splashHandler(e:Event):void {
var stone:Stone = e.currentTarget as Stone;
stoneSplash = new StoneSplash();
//you need a reference to the splash from the stone class - it would be best to create a class file and add a public property called splashObj and then just use stone.splashObj = new StoneSplash();
MovieClip(stone).stoneSplash = stoneSplash; //so on the end event we can read this var to remove stoneSplash
octopusContainer.addChild(stoneSplash);
stoneSplash.x = stone.x;
stoneSplash.y = stone.y;
}
function removeStone(e:Event):void {
var stone:Stone = e.currentTarget as Stone;
octopusContainer.removeChild(MovieClip(stone).stoneSplash);
addOctopus(stone.x, stone.y);
removeChild(stone);
}

remove object from stage and array when leaving stage

To an extent this is working, but it's only removing the tempBullet object if its y position starts at < 200, not if it reaches that point after being spawned somewhere further down the stage:
if(firing && bulletTimeOut == 0)
{
var tempBullet = new Bullet();
bullets.push(tempBullet);
tempBullet.x = x;
tempBullet.y = y-10;
stage.addChild(tempBullet);
trace(bullets.length);
if(tempBullet.y < 200)
{
bullets.splice(tempBullet, 1);
stage.removeChild(tempBullet);
}
bulletTimeOut = 5;
}
Is this code happening in a loop?
I think that rather than just checking the position of tempBullet you intended to loop through the whole bullets array to remove any bullets that have gone past 200px.
if(firing && bulletTimeOut == 0)
{
var tempBullet = new Bullet();
bullets.push(tempBullet);
tempBullet.x = x;
tempBullet.y = y-10;
stage.addChild(tempBullet);
trace(bullets.length);
bulletTimeOut = 5;
}
// test bullet positions whether firing or not
for each (b:Bullet in bullets) {
if(b.y < 200)
{
bullets.splice(b, 1);
stage.removeChild(b);
}
}

Attempt at title... Spawning movie clips according to X/Y axis of mouse AND changing each MC copies' frame position

This is hard to explain.
My aim is to spawn sheep(symbol) each time i click placed according to the mouse's X/Y axis... . I want it to spawn copies of the sheep BUT i also want each copy to be a different image.. (each time the mouse is clicked, it will change the image inside the sheep's symbol (placed on different frames).
If anyone can help I will appreciate it so much!
This is the code:
stage.addEventListener (MouseEvent.CLICK, makeABox);
var i:Number = 1;
function makeABox(e:Event):void {
var newSheep:myMC = new myMC();
addChild(newSheep);
newSheep.x = stage.mouseX;
newSheep.y = stage.mouseY;
i++;
}
var numPressed:Number = 0;
stage.addEventListener(MouseEvent.CLICK, countUp);
function countUp(evt:MouseEvent):void {
numPressed++;
if (numPressed == 1) {
sheep.gotoAndPlay(1);
}
else if (numPressed == 2) {
sheep.gotoAndPlay(2);
}
else if (numPressed == 3) {
sheep.gotoAndPlay(3);
}
else if (numPressed == 4) {
sheep.gotoAndPlay(4);
}
else if (numPressed == 5) {
sheep.gotoAndPlay(5);
}
else if (numPressed == 6) {
sheep.gotoAndPlay(6);
}
else if (numPressed == 7) {
sheep.gotoAndPlay(7);
}
if(numPressed >= 7) numPressed = 0;
}
Replace all the code you posted in your question with this:
stage.addEventListener (MouseEvent.CLICK, addSheep);
var sheepCounter:int = 1;
function addSheep(event:MouseEvent):void {
//create new sheep
var newSheep:myMC = new myMC();
//position it at mouse click
newSheep.x = stage.mouseX;
newSheep.y = stage.mouseY;
//set frame of sheep to display
newSheep.gotoAndStop(sheepCounter);
//add sheep to display list
addChild(newSheep);
//update counter
sheepCounter++;
if (sheepCounter==8)
{
sheepCounter = 1;
}
}