Some balls are flood in to the floor - actionscript-3

The problem is when i have 2 or more balls on stage,some balls are bouncing perfect and some other are sink in floors.
The floors on stage are already on stage.
Is that a drawing problem or its something else?
stop();
//ARRAYS
var ballArray:Array = new Array();
//ADD BALLS
var mediumBall1f2:Ball = new Ball ;
ballArray.push(mediumBall1f2);
this.addChild(mediumBall1f2);
mediumBall1f2.ballX = 3;
mediumBall1f2.ballY = 8;
mediumBall1f2.x = 300;
mediumBall1f2.y = 250;
mediumBall1f2.width = 120;
mediumBall1f2.height = 120;
var mediumBall1f3:Ball = new Ball ;
ballArray.push(mediumBall1f3);
this.addChild(mediumBall1f3);
mediumBall1f3.ballX = -3;
mediumBall1f3.ballY = 8;
mediumBall1f3.x = 200;
mediumBall1f3.y = 350;
mediumBall1f3.width = 140;
mediumBall1f3.height = 140;
var mediumBall1f4:Ball = new Ball ;
ballArray.push(mediumBall1f4);
this.addChild(mediumBall1f4);
mediumBall1f4.ballX = -3;
mediumBall1f4.ballY = 8;
mediumBall1f4.x = 300;
mediumBall1f4.y = 250;
mediumBall1f4.width = 50;
mediumBall1f4.height = 50;
var mediumBall1f5:Ball = new Ball ;
ballArray.push(mediumBall1f5);
this.addChild(mediumBall1f5);
mediumBall1f5.ballX = -3;
mediumBall1f5.ballY = 8;
mediumBall1f5.x = 400;
mediumBall1f5.y = 350;
mediumBall1f5.width = 80;
mediumBall1f5.height = 80;
var mediumBall1f6:Ball = new Ball ;
ballArray.push(mediumBall1f6);
this.addChild(mediumBall1f6);
mediumBall1f6.ballX = 3;
mediumBall1f6.ballY = 8;
mediumBall1f6.x = 400;
mediumBall1f6.y = 320;
mediumBall1f6.width = 30;
mediumBall1f6.height = 30;
var mediumBall1f7:Ball = new Ball ;
ballArray.push(mediumBall1f7);
this.addChild(mediumBall1f7);
mediumBall1f7.ballX = 3;
mediumBall1f7.ballY = 8;
mediumBall1f7.x = 400;
mediumBall1f7.y = 230;
var mediumBall1f8:Ball = new Ball ;
ballArray.push(mediumBall1f8);
this.addChild(mediumBall1f8);
mediumBall1f8.ballX = 3;
mediumBall1f8.ballY = 8;
mediumBall1f8.x = 400;
mediumBall1f8.y = 240;
var mediumBall1f9:Ball = new Ball ;
ballArray.push(mediumBall1f9);
this.addChild(mediumBall1f9);
mediumBall1f9.ballX = 3;
mediumBall1f9.ballY = 8;
mediumBall1f9.x = 400;
mediumBall1f9.y = 110;
//FLOOR
var downArray:Array = new Array();
for (var dA:int = numChildren - 1; dA>= 0; dA--)
{
var childdA:DisplayObject = getChildAt(dA);
if (childdA.name == "downfloor")
{
downArray.push(MovieClip(childdA));
}
}
var upArray:Array = new Array();
for (var uA:int = numChildren - 1; uA>= 0; uA--)
{
var childuA:DisplayObject = getChildAt(uA);
if (childuA.name == "upfloor")
{
upArray.push(MovieClip(childuA));
}
}
var rightArray:Array = new Array();
for (var rA:int = numChildren - 1; rA>= 0; rA--)
{
var childrA:DisplayObject = getChildAt(rA);
if (childrA.name == "rightfloor")
{
rightArray.push(MovieClip(childrA));
}
}
var leftArray:Array = new Array();
for (var lA:int = numChildren - 1; lA>= 0; lA--)
{
var childlA:DisplayObject = getChildAt(lA);
if (childlA.name == "leftfloor")
{
leftArray.push(MovieClip(childlA));
}
}
//USE ONCE
stageclear.visible = false;
stageclear.gotoAndStop(1);
stage.addEventListener(Event.ENTER_FRAME,ballLoop);
function ballLoop(evt:Event)
{
//BALL
for (var j = 0; j<ballArray.length; j++)
{
var ball:Ball = ballArray[j] as Ball;
ball.ballY--;
ball.y -= ball.ballY;
ball.x -= ball.ballX;
if (player.hitTestObject(ball))
{
ball.y = 600;
}
if(ball.x - ball.width/2 < 0)
{
ball.ballX = -3;
}
if(ball.x + ball.width/2 > 800)
{
ball.ballX = 3;
}
if(ball.y + ball.height/2 > 384.45)
{
ball.ballY = 20;
}
if(ball.y - ball.height/2 < 0)
{
ball.ballY = -2;
}
for (var d = 0; d<downArray.length; d++)
{
var down:DownFloor = downArray[d] as DownFloor;
if (ball.hitTestObject(down))
{
ball.ballY = 20;
}
}
for (var r = 0; r<rightArray.length; r++)
{
var right:RightFloor = rightArray[r] as RightFloor;
if (ball.hitTestObject(right))
{
ball.ballX = 3;
}
}
for (var l = 0; l<leftArray.length; l++)
{
var left:LeftFloor = leftArray[l] as LeftFloor;
if (ball.hitTestObject(left))
{
ball.ballX = -3;
}
}
for (var u = 0; u<upArray.length; u++)
{
var up:UpFloor = upArray[u] as UpFloor;
if (ball.hitTestObject(up))
{
ball.ballY = -2;
}
}
if (ball.y >= 600)
{
ball.parent.removeChild(ball);
ballArray.splice(j,1);
}
if (ballArray.length <= 0)
{
stageclear.visible = true;
stageclear.gotoAndPlay(1);
}
}
if(stageclear.currentFrame == stageclear.totalFrames)
{
stage.removeEventListener(Event.ENTER_FRAME,ballLoop);
MovieClip(this.root).gotoAndPlay(1, "Scene 2");
}
}

the reason this is happening
This is happening because hitTest is only true if the MCs overlap. If you could look more closely, you'd see that this happens to all of the balls (it's just more apparent with some than others).
the only fix that I know of
Make your own collision detection.
It could look like this:
function collisionTest (mc1:MovieClip,mc2:MovieClip){
// test if mc1 is going to hit mc2's left side *on the next frame*
if (mc1.x + mc1._xSpeed + mc1.width>= mc2.x){
mc1.x = mc2.x; // this may cause a momentary pause... The ball may seem to stick to the wall for a frame... If this is a problem let me know and I'll show you how to fix that
mc1._xSpeed *= -1;
}
// test if mc1 is going to hit top edge of mc2 *on the next frame*
if (mc1.y + mc1._ySpeed + mc1.height >= mc2.y){
mc1.y = mc2.y; // same possible sticking here
mc1._ySpeed *= -1;
}
}
note
For this to work, the registration point for the MCs should be top-left (which is the default).
Also, my code only works for object 1 moving down, colliding with the top of object2 or object 1 moving right colliding with left side of object 2.
_xSpeed and _ySpeed are things you will need to add as properties to your ball class and use that property to dictate motion of the balls. This is the key: it allows you to look ahead, into the future, and see if the ball is going to hit the wall on the next frame, and if it is, run the result of collision now, instead of after they overlap.
You'll need to add similar code for if the ball is moving left and you want it to detect collision with the right edge of a wall. Also for if the ball is moving up and you want to detect collision with the bottom of a wall
Don't forget to include an adjustment for the width of the wall or the width of the ball (since we are using the registration point which is top left of the bounding box)

Related

Use a child in as3 adobe animate

I making a card game and i call some cards from the library randomly.
But i cant use this cards.
Is there any way to make this childs clickable?
And another question please.
If there any chance to use one print array for all the 22 cards i need to show on stage?Or i must to create a new printarray and a new random number for each card?
Note:each card has different points.
var cards:Array = [k1, p1, s1, r1, r3,k4,p4,s4,r4,k5,p5,s5,r5
,k6,p6,s6,r6,k7,p7,s7,r7,k8,p8,s8,r8,k9,p9,s9,r9,k10,p10,s10,r10,
kj,pj,sj,rj,kq,pq,sq,rq,kk,pk,sk,rk];
var printArray:Array = [];
for (var n:int = 1; n <= 1; n++)
{
var randNo:int = int(Math.random() * 51);
printArray.push(randNo);
}
for (var c:int = 0; c < printArray.length; c++)
{
trace(printArray[c]);
var mc:MovieClip = new cards[printArray[c] ];
addChild(mc);
mc.width = 60;
mc.height = 80;
mc.x = 100;
mc.y = 50;
}
var print1Array:Array = [];
for (var n1:int = 1; n1 <= 1; n1++)
{
var rand1No:int = int(Math.random() * 51);
print1Array.push(rand1No);
}
for (var c1:int = 0; c1 < print1Array.length; c1++)
{
trace(print1Array[c1]);
var mc1:MovieClip = new cards[print1Array[c1] ];
addChild(mc1);
mc1.width = 60;
mc1.height = 80;
mc1.x = 70;
mc1.y = 80;
}
stage.addEventListener(Event.ENTER_FRAME,looping);
function looping(event:Event):void
{
//here ia want use the cards.Let say i want to if(mc1 is clicked)
}
mc1.addEventListener(MouseEvent.CLICK, clickCard);
Put that where you have your other mc1's. Then elsewhere, outside any other functions put this:
private function clickCard(e:MouseEvent):void{
//trace(e.target);
}

AS3: Removed Child Still Passes HitTest

I am making a game similar to doodle jump and I have a powerup MovieClip that appears every time the character bounces up. When the character collides with the powerup, I want it to add to the live score, and then disappear. But I want it to reappear after is has been removed so there is a constant stream of powerups (one for each time the character jumps).
The problem I'm having is that as soon as the first powerup is hit, it visually removes all future powerups but the character is still able to collide with them - constantly adding to the score rather than just once.
I made a recording that I think would help explain.
Here's the block of code I'm trying to fix:
//IF MyChicken TOUCHES CHICKEN LEG, SCORE GOES UP BY 2000
for (var c:int=0; c< 1; c++){
chickMc = powerUp[c];
if (MyChicken.hitTestObject(chickMc))
{
liveScore += 2000;
theScore.text = liveScore.toString();
tapSnd.play();
removeChild(chickMc);
}
}
In case it's something outside of this chunk, here's my whole code:
import flash.events.Event;
import flash.sensors.Accelerometer;
import flash.events.AccelerometerEvent;
import flash.display.MovieClip;
import flash.media.Sound;
import flash.events.MouseEvent;
var firstPass:int = 1;
var liveScore:int;
var accX:Number;
var myVect:Vector.<MovieClip> = new Vector.<MovieClip>(5,true);
var powerUp:Vector.<MovieClip> = new Vector.<MovieClip>(1, true);
var vAcceleration:Number = 0.5;
var vVelocity:Number = -20;
var middleScreen:Number = stage.height / 2;
//var newEnemy:enemy;
//var nmeMc:MovieClip;
var newChicken:chicken;
var chickMc:MovieClip;
var newBouncer:bouncer;
var tmpMc:MovieClip;
var poolSnd:poolSound = new poolSound();
var tapSnd:tapSound = new tapSound();
var btnAgain:gameOver;
stop();
// MONITOR THE ACCELEROMETER
var myAcc:Accelerometer = new Accelerometer();
myAcc.addEventListener(AccelerometerEvent.UPDATE, onAccUpdate);
function onAccUpdate(evt:AccelerometerEvent):void{
accX = evt.accelerationX;
}
//MONITOR THE ENTER_FRAME EVENT
stage.addEventListener(Event.ENTER_FRAME, onMyEnterFrame);
//INIT STAGE WITH PLATFORMS (bouncer)
if (firstPass == 1){
liveScore = 0;
accX = 0;
for (var i:int=0; i< 5; i++){
newBouncer = new bouncer;
newBouncer.x = Math.random()*stage.stageWidth;
newBouncer.y = 0 + i*stage.stageHeight/6;
myVect[i] = newBouncer;
addChild(newBouncer);
newBouncer.cacheAsBitmap = true;}
for (var c:int=0; c< 1; c++){
newChicken = new chicken;
newChicken.x = Math.random()*stage.stageWidth;
newChicken.y = 0 + c*stage.stageHeight/6;
powerUp[c] = newChicken;
addChild(newChicken);
newChicken.cacheAsBitmap = true;}
firstPass = 2;
}
function onMyEnterFrame(evt:Event):void{
//MOVE X DEPENDING ON THE ACCELEROMETER
MyChicken.x += (MyChicken.x - (MyChicken.x + accX * 20))*0.6;
//MOVE CHAR TO THE LEFT OR TO THE RIGHT
if(accX < 0) {
MyChicken.gotoAndStop(2);
}else{
MyChicken.gotoAndStop(1);
}
// VERTICAL SPEED OF MyChicken
vVelocity += vAcceleration;
if((MyChicken.y > middleScreen) && (vVelocity < 0)){
// MyChicken IS GOING UP
MyChicken.y += vVelocity;
}else{
if(vVelocity > 0){
// MyChicken IS GOING DOWN
MyChicken.y += vVelocity;
// TEST IF MyChicken HITS PLATFORM
for (var i:int=0; i< 5; i++){
tmpMc = myVect[i];
if (MyChicken.hitTestObject(tmpMc))
{
vVelocity = -20;
tapSnd.play();
}
}
//IF MyChicken TOUCHES CHICKEN LEG, SCORE GOES UP BY 2000
for (var c:int=0; c< 1; c++){
chickMc = powerUp[c];
if (MyChicken.hitTestObject(chickMc))
{
liveScore += 2000;
theScore.text = liveScore.toString();
tapSnd.play();
removeChild(chickMc);
}
}
}else{
// THE WORLD IS GOING DOWN
// WHEN MyChicken IS IN THE MIDDLE OF THE SCREEN
for (var m:int=0; m< 1; m++){
chickMc = powerUp[m];
chickMc.y -= vVelocity;
}
for (var j:int=0; j< 5; j++){
tmpMc = myVect[j];
tmpMc.y -= vVelocity;
}
liveScore += 5;
theScore.text = liveScore.toString();
}
}
//CHECK IF PLATFORMS ARE OUT OF THE SCREEN
if(myVect[0] != null){
for (var k:int=0; k< 5; k++){
tmpMc = myVect[k];
if(tmpMc.y > stage.stageHeight){
tmpMc.y = -5;
tmpMc.x = Math.random()*stage.stageWidth;
}
}
}
if(powerUp[0] != null){
for (var p:int=0; p< 1; p++){
chickMc = powerUp[p];
if(chickMc.y > stage.stageHeight){
chickMc.y = -5;
chickMc.x = Math.random()*stage.stageWidth;
}
}
}
//FAIL - IF CHICKEN FALLS OUT OF THE SCREEN
if (MyChicken.y > stage.stageHeight) {
btnAgain = new gameOver();
addChild(btnAgain);
btnAgain.x = 160;
btnAgain.y = 230;
btnAgain.theScoreFinal.text = liveScore.toString();
theScore.visible = false;
btnAgain.addEventListener(MouseEvent.MOUSE_DOWN, onPlayAgain);
//PAUSE GAME
MyChicken.y = -300;
vVelocity = 0;
vAcceleration = 0;
// PLAY FAIL SOUND
poolSnd.play();
}
// CLICKS ON THE PLAY AGAIN BUTTON
function onPlayAgain(evt:MouseEvent):void{
removeChild(btnAgain);
//NEW GAME
MyChicken.y = stage.stageHeight - 50;
MyChicken.x = stage.stageWidth / 2;
theScore.text = "0";
liveScore = 0;
vVelocity = -20;
vAcceleration = 0.5;
theScore.visible = true;
}
//STAGE BOUNDS MyChicken ON THE LEFT OR RIGHT OF THE SCREEN
if(MyChicken.x < 0) MyChicken.x = stage.stageWidth;
if(MyChicken.x > stage.stageWidth) MyChicken.x = 0;
}
Removing an object does not change its x/y coordinates or width/height (bounds). hitTestObject checks the two objects bounds - it does not take into consideration if an object is actually on the display tree or not. So even though you've successfully removed the object, the hit test will keep checking it. (as the object still exists, it just can't be seen)
You can remedy this by doing a check first to see if chickMc has been removed:
if (chickMc.parent && MyChicken.hitTestObject(chickMc))
The parent property of a display object will null after being removed from the stage.
Though instead of that, you may want to null the reference to the object so it can be garbage collected later:
for (var c:int=0; c< 1; c++){
chickMc = powerUp[c];
if (chickMc != null && MyChicken.hitTestObject(chickMc)){
liveScore += 2000;
theScore.text = liveScore.toString();
tapSnd.play();
removeChild(chickMc);
powerUp[c] == null; //now that powerup object isn't referenced anywhere and can be garbage collected (destroyed from memory)
}
}

testHitObject is returning an incorrect "true" value on the first few frames

if I add the else statement I do receive the "not hit" in my output window, so it looks like the statement only returns true on the first few frames, when it is supposed to return false. Now my problem is that the code wants to remove child objects before they've even been created. I just want to achieve basic collision detection between the enemy and the bullet so that i can remove both children when an enemy is shot. Please keep in mind that there will be multiple enemies and bullets on the stage at a given time.
I seemed to narrow down my problem. What was happening was the instance of an enemy would still exist, after i used the removeChild() function. Only now I couldn't see it for some reason. And its x and y properties were equal to 0. Therefore if I moved the ship to x = 0, it would have an "invisible" enemy collide with it. So I think my problem is I am not removing the instance properly? if not could you please help me?
` <pre>
var BulletsArr:Array = new Array();
var EnemysArray:Array = new Array();
for(i = 0; i < 5; i++)
{
BulletsArr[i] = new Bullet();
}
for(i = 0; i < 5; i++)
{
EnemysArray[i] = new Enemy();
//EnemysArray[i].x = 2000; //Fix
//EnemysArray[i].y = 2000; //Fix
}
stage.addChild(Ship);
Ship.addEventListener(Event.ENTER_FRAME, fnEnterFrame);
function fnEnterFrame(event:Event)
{
txtScore.text = "Score: " + score;
//Make Ship follow cursor
Ship.x = stage.mouseX;
//Boundries
if (Ship.x > 500)
{
Ship.x = 550 - 50;
}
if (Ship.x <= 0)
{
Ship.x = 0 ;
}
for(var i = 0; i < 5; i++){
for(var p = 0; p < 5; p++)
{
if(BulletsArr[i].hitTestObject(EnemysArray[p]))
{
remove(BulletsArr[i]);
removeChild(EnemysArray[p]);
}
for(i = 0; i < 5; i++)
{
BulletsArr[i].y -= 15;
}
for(i = 0; i < 5; i++)
{
EnemysArray[i].y += 5;
}
for(var z = 0; z < 5; z++)
{
if(Ship.hitTestObject(EnemysArray[z])
{
Ship.parent.removeChild(Ship);
EnemysArray[z].parent.removeChild(EnemysArray[z]);
trace("Game over");
}
}
for(i = 0; i < 5; i++)
{
var found:Boolean = false;
for(var p = 0; p < 5; p++)
{
if(BulletsArr[i].hitTestObject(EnemysArray[p]))
{
BulletsArr[i].parent.removeChild(BulletsArr[i]);
BulletsArr[i] = new Bullet();
EnemysArray[p].parent.removeChild(EnemysArray[p]);
EnemysArray[p] = new Enemy();
//EnemysArray[p].x = 2000;//fix
//EnemysArray[p].y = 2000;//fix
score += 50;
found = true;
break;
}
if(found)
{
break;
}
}
}
}
var count_Enemys:int = 0;
var Timer_3_sec:Timer = new Timer(3000, 0);
Timer_3_sec.start();
Timer_3_sec.addEventListener(TimerEvent.TIMER,spawn_ship);
function spawn_ship(Event:TimerEvent):void
{
if(count_Enemys >= 5)
{
count_Enemys = 0;
EnemysArray[count_Enemys].x = fl_GenerateRandomNumber(450) + 70;
EnemysArray[count_Enemys].y = 0 - fl_GenerateRandomNumber(250) - 100;
addChild(EnemysArray[count_Enemys]);
count_Enemys++;
}
else
{
EnemysArray[count_Enemys].x = fl_GenerateRandomNumber(450) + 70;
EnemysArray[count_Enemys].y = 0 - fl_GenerateRandomNumber(250) - 100;
addChild(EnemysArray[count_Enemys]);
count_Enemys++;
}
}
`</code>

Putting displacement between circles

I would like to set a displacement between the circles that are drawn here. Besides, I would like to copy the circles positions to the head circle, but the offset of course is cleared due to that.
public var circles:Vector.<circle> = new Vector.<circle>(5);
public function t()
{
var offset:int = 10;
for ( var i:int = 0; i<5; i++)
{
var c:circle = new circle();
c.xPosition= 120+offset;
c.yPosition = 120;
c.vx = 1;
c.vy = 0;
circles[i] = c;
offset+=40;
}
addEventListener(Event.ENTER_FRAME, gameLoop);
}
public function gameLoop(event:Event):void
{
for ( var i:int = 0; i<5; i++)
{
addChild(circles[i]);
circles[i].drawCircle(circles[i].xPosition, circles[i].yPosition);
}
for ( var i:int = 0; i<5; i++)
{
if ( i != 0 )
{
circles[i].xPosition = circles[i-1].xPosition;
circles[i].yPosition = circles[i-1].yPosition;
}
else {
}
}
circles[0].xPosition-=circles[0].vx*(2*5);
circles[0].yPosition-=circles[0].vy*(2*5);
}
Do the loop from back to front. What you did change every circle's position same with circle 0
for ( var i:int = 4; i > 0; i--)
{
circles[i].xPosition = circles[i-1].xPosition;
circles[i].yPosition = circles[i-1].yPosition;
}

Change the "alpha","scale"and"depth" according to the y position of the MovieClip in Flash&AS3

i am making a interactive slideshow with all the image slide automatically at the beginning in the swf.
the first step is successful that i made all the MovieClip running just relative to the center of the circle,the code is here
var menu:Sprite = new Sprite();
menu.x = 275;
menu.y =180;
menu.addEventListener(Event.ENTER_FRAME,moveMenu);
addChild(menu);
var disX:Number = 200;
var disY:Number = 10;
var speed:Number = 0;
initMenu(3)
function initMenu(n:int){
for(var i:int;i<n;i++){
var mc:MovieClip = new IconMenu();
mc.scaleX = mc.scaleY = .5;
menu.addChild(mc);
}
}
function moveMenu(e:Event):void{
var iconCount = menu.numChildren;
var depthArray:Array = new Array();
var angle:Number = 360/iconCount;
for(var z:int;z<iconCount;z++){
var mc:MovieClip = MovieClip(menu.getChildAt(z));
mc.gotoAndStop(z+1);
mc.x = cosD(speed+angle*z)*disX;
mc.y = sinD(speed+angle*z)*disY;
}
speed+=2;
}
but after this i am not able to calculate the other value like "alpha","scale"and"depth" to make the slideshow more realistic
all the three value should be calculated according to the mc.y,since i think there should be a Perspective effect
and i am really new to Flash and Actionscript3 ,anyone could help me here?!
really thanks a lot!
Hope that will help you.
Alpha & Scale:
Up -> Low
Down -> High
mc.alpha = mc.y / menu.height;
mc.scaleX = mc.scaleY = mc.y / menu.height;
Up -> High
Down -> Low
mc.alpha = 1 - mc.y / menu.height;
mc.scaleX = mc.scaleY = 1 - mc.y / menu.height;
Depth:
Up -> Behind
Down -> Front
for(var i:int = menu.numChildren - 1; i > -1; i--)
{
var mc1:MovieClip = menu.getChildAt(i) as MovieClip;
var mc2:MovieClip = menu.getChildAt(i) as MovieClip;
if(mc1.y < mc2.y)
{
if(menu.getChildIndex(mc1) > menu.getChildIndex(mc2))
{
menu.swapChildren(mc1, mc2);
}
}
}
Up -> Front
Down -> Behind
for(var i:int = menu.numChildren - 1; i > -1; i--)
{
var mc1:MovieClip = menu.getChildAt(i) as MovieClip;
var mc2:MovieClip = menu.getChildAt(i) as MovieClip;
if(mc1.y > mc2.y)
{
if(menu.getChildIndex(mc1) < menu.getChildIndex(mc2))
{
menu.swapChildren(mc1, mc2);
}
}
}