problem with tweenlite - actionscript-3

i have a bit of a problem.
i have the following function:
private function elementsLoadedHandler(e:Event):void
{
elementContainer=new Sprite();
var currentItem:uint;
for (var i:uint=0; i < numberItems; i++)
{
var element:Element=new Element(elementModel.elements[currentItem]);
element.x=xPos;
element.alpha=.5;
addChild(element);
xPos+=130;
currentItem++;
elementsArr.push(element);
if (currentItem >= elementModel.elements.length)
{
currentItem == 0;
}
}
movementTimer=new Timer(_movementSpeed, 0);
movementTimer.addEventListener(TimerEvent.TIMER, moveItems);
movementTimer.start();
layout();
}
What this basicly does is place elements from an array onto the stage next to eachother. Now i want them to move to the right together. i do this as following:
private function moveItems(e:TimerEvent):void
{
var alphaVal:Number=.5;
movementTimer.delay+=25;
for (var i:uint=0; i < elementsArr.length; i++)
{
xPos=elementsArr[i].x + 130;
TweenLite.to(elementsArr[i], .5, {x: "130"});
if (elementsArr[i].x > _width)
{
elementsArr[i].x=0;
}
}
}
So i'm moving the items to the right and then i check if the last item is outside of the stage, if so i reset its position to 0 so it goes back to the left and this way i have a continious loop of items moving to the right.
The problem is that the way i do it, i have 11 tweens being executed per second, wich makes it laggy. I was thinking about putting the items in an container and tweening the container but i dont seem to be getting a nice continious flow then. Does anyone know how to solve this?
Also, in the first function you can see that i'm doing a for loop. the numberItems variable represents 11, but the amount of items in elementModel.elements is only 6, so for the other 5 elements i just pick the first 5 items from the array again. The problem is that when i trace these items it gives me 0. How can i take items from an array multiple times without overwriting the previous version of it?

You don't need to use tween lite for this. All you need to do in the moveItems function is move each item a little (elemtsArr[i].x += 5, for example) and if elementsArr[i].x > _width, then replace it a 0.
Something like this should work:
function moveItems( e:TimerEvent ):void
{
for (var i:int = 0; i < elemntsArr.length; i++)
{
elementsArr[i].x += 5;
if (elementsArr[i].x > _width)
elementsArr[i].x = 0;
}
}

Related

How to hitTest same Objects in one Array?

I want to create a stacking Game. Where when you tap the screen for instance a block falls down and a new one appears where the other one originally was. Now when the User taps the screen again the same block falls down and if aligned correctly stacks on top of the first one so one and so one. Keep stacking until you miss.
I thought creating an array and pushing each new object to that array would be able to hitTest between each new one etc and have them stack on each other. I realized I don't quite understand how to go about doing this. New instances are created so I got that down. Here is my code so far:
private function engineLogic(e:Event):void
{
stackingHandler();
}
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
//HIT TEST CATS
}
trace("NUMBER OF CATS: " + aCatArray.length);
}
private function onTap(e:MouseEvent):void
{
//Move Down
TweenLite.to(cats, 1.0, {y:(stage.stageHeight / 2) + 290, onComplete: addCats});
}
private function addCats():void
{
//Create Instance
cats = new mcCats();
//Add Objects
addChild(cats);
//Push to Array
aCatArray.push(cats);
}
I would appreciate any help from you guys. Maybe if you can push me in the right direction. Thank you in advance!
It looks like the cats variable holds the object that is currently falling?
In that case you'd do something like this:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
if(cats.hitTestObject(aCatArray[i])) {
// collision detected!
// kill the Tween
// set the y position of the `cats` object
// so it appears on top of the object it collided with (`aCatArray[i]`)
// (it may have moved slightly past the object before doing this check)
}
}
}
So you're looping through the array and hit testing cats against every object in the array one at a time.
It might make more sense to use a basic gravity simulation, or just linearly increasing the y value instead of using a Tween, but you didn't ask about that.
You might also want to set a flag for whether or not an object is currently falling and use that to determine whether or not to run the stackingHandler. Otherwise, you'll just be continually hit testing all the objects when nothing is moving.
This is how I was able to fix it. Creating a double for loop. Checking if they are equal to each other continue and check for hitTest:
private function stackingHandler():void
{
for (var i:int = 0; i < aCatArray.length; i++)
{
var currentCat:mcCats = aCatArray[i];
for (var j:int = 0; j < aCatArray.length; j++)
{
var newCat:mcCats = aCatArray[j];
if (currentCat == newCat) continue;
//Hit Test between Objects
if (newCat.hitTestObject(currentCat.mcHit) && newCat.bFlag == false)
{
//Stop Moving
newCat.stopMoving();
trace("HIT");
if (highScore == 0)
{
addCats();
trace("ADD CATS 1");
}else
{
TweenLite.delayedCall(0.6, addCats);
trace("ADD CATS 2");
}
//Add Points
highScore ++;
trace(highScore + " Score");
//Set Flag boolean
newCat.bFlag = true
}
}
}
}

Removing items of an array from stage in as3- one each time

I am trying to remove movieclips of an array from the stage. I want to remove one item of the circles array every time there is a click in an item from the square array. I wrote this code but something is missing and i can not figure it out because all the items of the circles array disappear from stage with the first click. Can you please help me.
var circles:Array = [circle1, circle2, circle3, circle4,circle5, circle6];
var counter:int = 0;
var square:Array = new Array(square1,square2,square3,square4,square5,square6,square7,square8,square9,square10,square11,square12,square13,square14,square15,square16,square17,square18,square19,square20,square21);
for(var i:int = 0; i < square.length; i++)
{
square[i].addEventListener(MouseEvent.CLICK, clickTomove);
function clickTomove(e:MouseEvent):void
{
trace("square");
var len:int=circles.length;
for(var o:int=0; o<circles.length; o++)
this.removeChild(circles[o]);
circles.splice(o,1);
}
}
Your click handler loops through the circles and removes them all, so what you're describing is expected.
You shouldn't put function declarations inside a loop.
It looks like you're trying to do something like this:
for each (var square:MovieClip in squares) {
square.addEventListener(MouseEvent.CLICK, clickTomove);
}
function clickTomove(e:MouseEvent):void {
if (circles.length > 0) {
var circle:MovieClip = circles.pop();
removeChild(circle);
}
}
pop() removes and returns the last item from the circles array.

Trying to remove object throws error 1009 cannot access a property or method of null object reference

Working on a flash game, in a previous game I had enemies come in by using an array and when they were killed or moved off the stage I would just remove them from the array. For some reason when I use exactly the same code in this game, it throws a 1009: error when I try to remove the array object, basically saying that there's nothing there. . . Which is strange.
Here's the code:
public function addZombie()
{
var zom:Zombie = new Zombie();
zom.y = 20;
zom.x = Math.floor(Math.random()*(1 + 500 - 30)) + 30;
addChild(zom);
zombies.push(zom);
numZombies++;
}
That's the function where it's added in, zombies is the array and it's pushed into the array in this function. Here's the code where I'm attempting to remove it:
for (var i:int = 0; i < zombies.length; i++)
{
if (zombies[i].y + zombies[i].height / 2 > 400) {
removeChild(zombies[i]);
zombies.splice(i,1);
numZombies--;
addZombie();
}
}
removeChild(zombies[i]); <-- This is the part that throws the error when it attempts to remove it. It removes some of them strangely enough, but not all of them.
I don't believe the loop is doing quite what you expect it to. When you remove an element from an array in this way, all the elements after the removed elements are moved down. So, if you have code like:
var testArr:Array = new Array();
testArr.push('First');
testArr.push('Second');
testArr.push('Third');
testArr.push('Fourth');
for (var i:int = 0; i < testArr.length; i++) {
testArr.splice(i,1);
}
The results of the loop will be:
i=0, testArr = ['Second', 'Third', 'Fourth']
i=1, testArr = ['Second', 'Fourth']
i=2 END OF LOOP
It would probably be better to use a while loop, incrementing the index only if the element is not removed (since removing the element moves a new element to that index position).
I don't see why you're getting the null object reference, but this would be causing other problems (why some are removed but not all).
The explanations of Bill Turner are the correct ones, but as it didn't seem to help you fix your issue, you might want to try this:
var zombieCount:int = zombies.length;
for (var i:int = 0; i < zombies.length; i++)
{
var zombie = zombies[i];
if (zombie.y + (zombie.height / 2) > 400) {
removeChild(zombie);
zombies.splice(i,1);
i--; // So that the loop will pass with the same value next time
numZombies--;
}
}
for (var j:int = zombies.length; j < zombieCount; j++)
{
addZombie();
}

Problems getting objects in Stage

So, im using this code to remove a couple of movie clips from my stage:
for (var i:uint = 0; i < this.numChildren; i++)
{
if (this.getChildAt(i) is MovieClip
&& pecasInGame.indexOf(this.getChildAt(i)) >= 0)
{
removeChild(this.getChildAt(i));
}
}
But its not really working well... I have 5 movie clips to remove and they are all added dinamically, when these movieclips are added i insert then into this array "pecasInGame", and when there is five of then I try to remove using the aforementioned loop.
The problem is, it only removes 3 of then, the 0, 2 and 4 objects.. The 1 and 3 arent even listed in the loop. Any idea why would that happen??
You're removing the display objects, so the indexes are changing WHILE your loop goes on.
Change it this way:
for (var i:uint = this.numChildren-1; i >= 0 ; i--)
{
if (this.getChildAt(i) is MovieClip && pecasInGame.indexOf(this.getChildAt(i)) >= 0)
{
removeChild(this.getChildAt(i));
}
}
Other option: use your array to remove the objects, like this
for (var i:int=0; i<pecasInGames.length; i++) {
removeChild (pecasInGames[i]);
}
The problem is you are iterating over the children and removing at the same time, so the indices of the children are changing, which is causing the problem.
If you want to remove all the movie clips from the display list, do something like this :
for each(var mc:MovieClip in pecasInGame)
{
if(getChildIndex(mc) != -1)
removeChild(mc);
}

Detect when the last item in an array has come to a stop

I've got an array of sprites which I'm animating by incrementing their rotationX property. What I want is for them all to disappear once the last item in the array has come full circle. The problem is that their rotation speeds are being generated by a randomized function, so I can't just go to the end of the array to find the last one. Each time it will be a different one.
So I have an array of Sprites:
for(var i:int=0; i<arrSprites.length; i++)
{
addChild(arrSprites[i]) ;
}
Then I have my event listener:
addEventListener(Event.ENTER_FRAME, loop);
And my handler:
private function loop(e:Event):void
{
for(var i:int=0; i<arrSprites.length; i++)
{
var currentSprite:Sprite = arrSprites[i];
if(currentSprite.rotationX < 361) //this will detect the first one
//to finish but I want the last
{
currentSprite.rotationX += arrSprites[i].speed; //random speed
}
else
{
deleteTheSprites(); //removes all sprites and does other stuff
}
}
}
There's got to be an elegant way to do this. Anyone know what it is?
Thanks,
David
private function loop(e:Event):void
{
var finished : int = 0; // will count the number of sprites finished
for each (var current:Sprite in arrSprites)
{
if (current.rotationX < 361) current.rotationX += current.speed;
else if (++finished == arrSprites.length) deleteTheSprites(); // executes only if all sprites have finished
}
}