Order of instances in 3D Flash - actionscript-3

I'm making cube of 9 cubes in Flash As3. However i cant rotate it properly due to order of indexes whole adding then to stage.
First im creating cube of 6 squares, then wall of 9 cubes, and at the end cube of 3 walls.
It is all fine, however when i rotate it to the left, order of cubes is inverted and it ruins whole composition. I know i coul dinamicly change index based on rotation but it would be a loooooooot of work.
Any ideas how could i do it better way?
Here is actual model:
http://test.mrowa.topdivision.pl/kostka/3DTest.html

If you are using the Flash's display list you would have to sort the sprites based on their z.
Here is some code that would sort the children of a DisplayObjectContainer based on their z position, call this whenever some object changes its position.
public function sortChildren(container:DisplayObjectContainer):void
{
var objects:Vector.<DisplayObject> = new Vector.<DisplayObject>;
for (var i:int = 0; i < container.numChildren; i++)
{
objects.push(container.getChildAt(i));
}
objects.sort(sortCompare);
var index:int = 0;
for (var j:int = 0; j < objects.length; j++)
{
index = container.getChildIndex(objects[j]);
if (index != j)
container.setChildIndex(objects[j], j);
}
}
private function sortCompare(a:DisplayObject, b:DisplayObject):int
{
return (a.z - b.z);
}
You can move the objects member to be a class member and add/remove items to it whenever you add/remove items to/from the stage so that you don't have to fill the whole array every time this function is called.

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

AS3 - How to animate all movie clips in the stage if i click a certain button

Hi have been reading on this great website, here is what i want to accomplish,
on this certain page in the app im doing, there are movie clips (buttons, texts, menus) , now what i want is if i click this "close" button, i want everything to animate e.g shrink one by one. Question: Is there a great way to code this efficiently, and not coding it one by one e.g menu_mc.gotoAndPlay("out");, text_mc.gotoAndPlay("out"); image.gotoAndPlay("out"); ...something like that. Sorry im so new to this, any help will be greatly appreciated.
You could iterate the DisplayList, and call your method...
for (var i:int = 0; i < this.numChildren; i++) {
var obj:* = this.getChildAt(i);
if (obj is MovieClip) {
obj.gotoAndPlay("out");
}
}
Or you could animate with an animation library (such as Greensock)...
for (var i:int = 0; i < this.numChildren; i++) {
var obj:* = this.getChildAt(i);
TweenLite.to(obj, .35, {scaleX:0.5, scaleY:0.5, delay:0.25*i});
}
Or you could reference an Array for the objects you want to animate; a superior choice (if your objects aren't in the same container).
var a:Array = [menu_mc, text_mc, image];
for (var i:int = 0; i < a.length; i++) {
TweenLite.to(a[i], .35, {scaleX:0.5, scaleY:0.5, delay:0.25*i});
}

How to check if objects position is greater than an array of objects AS3

Hey everyone so I'm trying to figure out how to check if one movie Clips x position which is called ball is greater than an array of objects x position which is called car. So I have an array setup with the car the car's main timeline consist of 4 frames that holds the same movie Clip just different sizes on each frame to make the game harder.
So what I want to do is check whenever the ball has jumped over the current car then add plus one to the score. But I am having trouble trying to figure this out. Here is what I have so far:
In my Enter Frame Game Loop I have the Function checkAddPoints:
private function gameLoop(e:Event):void
{
checkBunnyHitObstacles();
checkAddPoints();
}
Then The function:
private function checkAddPoints():void
{
for (var i:int = 0; i < aCarArray.length; i++)
{
var currentCar:car = aCarArray[i];
if (ball.x > currentCar.x)
{
nScore ++;
updateCurrentScore();
}
}
}
So I am getting the current car in the loop and trying to check if the ball has jumped over it. I thought the most logical thing to do was to check if the ball x position was greater than the car x position then it would work. But it just adds a endless amount of numbers and not just one like I want.
Does anyone know what i need to do?
UPDATE: This seems to work haven't had any errors yet
if (currentcar.x - 15 < ball.x && currentCar.x + 15 > ball.x)
{
trace("AddPoint Success");
nScore++;
updateCurrentScore();
}
Storing flag aboud award status in the car should help in your task. If you add flag to the car, let's say car.isAwarded, by default isAwarded is false, you will be able award only once for every car:
private function checkAddPoints():void {
var i:uint, len:uint = aCarArray.length, currentCar:car;
for (i; i < len; ++i) {
currentCar = aCarArray[i];
//Award only once
if (!currentCar.isAwarded && ball.x > currentCar.x) {
nScore++;
currentCar.isAwarded = true;
updateCurrentScore();
}
}
}

removing multiple movieclips

I'm developing a game.I've attached random movieClips from library. I've movieClips named picLeft1, picLeft2, picLeft3 and so on in library. Its working fine but i'm having problem removing it. the code below is for the attachment of movieclip. Here ranque is an array which stores randomly generated numbers up to 5 and HolderL is the movieClip in which I want to attach the movieClip. And q is a sprite.
for (var i:int = 0; int<3; i++) {
que_mc.push("picLeft"+ranque[i]);
var que_mc_class:Class = getDefinitionByName(que_mc[i]) as Class;
q = new que_mc_class();
this["HolderL"+(i+1)].addChild(q);
}
my code for removing the movieclip is given below.I want to remove all the movieclip attached in HolderL. but this code is not working.
for(var j:int = 1; j<=3; j++) {
this["HolderL"+j].removeChild(q);
}
Flash Player 11 allows you to use this:
for (var j:int = 1; j<=3; j++) {
var container : DisplayObjectContainer = this["HolderL"+j];
container.removeChildren();
}
Earlier versions don't have the removeChildren() command; you have to have two loops: One to loop to iterate over the container movie clips, one to traverse the display list and remove all children.
Shortest way to remove all children of a container prior to FlashPlayer 11:
while (container.numChildren > 0) container.removeChildAt(0);
It's not clear from your code what q is, but basically if you want to remove all the children from one movie clip, the simplest is to loop through all the children and remove them one by one. For example:
for (var i:int = container.numChildren - 1; i >= 0; i--) {
container.removeChildAt(i);
}

problem with tweenlite

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