Generate random falling objects in AS3 - actionscript-3

I want to create a set of random objects to fall down the stage in a loop.
So far I have created a test object to fall at a random x coordinate. I am having trouble working out how to loop the falling function so multiple instances of the object continuously fall.
var randomX:Number = Math.random() * 800;
test_mc.x = randomX;
test_mc.y = 0;
var speed:Number = 10;
test_mc.addEventListener(Event.ENTER_FRAME, moveDown);
function moveDown(e:Event):void
{
e.target.y += speed;
if(e.target.y >= 480)
{
test_mc.removeEventListener(Event.ENTER_FRAME, moveDown);
}
}

refer my a falling snow effect code.
The starting position of the snow is all random, almost same effect that real snow falling circumstance. If you run You'll be amazed.
The Snow is My Custom MovieClip (white circle shape, width 15, height 15)
here is my demo: SnowEffect
here is my source: SnowEffect Down
this.addEventListener( Event.ENTER_FRAME, onEnter );
function onEnter( e: Event ):void {
var s: Snow = new Snow();
s.x=550*Math.random();
s.y=-20;
s.width=s.height=1+9*Math.random();// 1 ~ 9
s.xSpeed=-2+4*Math.random();// -2 ~ 2
s.ySpeed=1+4*Math.random();// 1 ~ 5
s.at = -0.001 -0.001*Math.random();
s.vt = 0;
this.addChild( s );
s.addEventListener( Event.ENTER_FRAME, onSnowEnter );
}
function onSnowEnter( e: Event ):void {
var s:Snow=e.currentTarget as Snow;
s.x+=s.xSpeed;
s.y+=s.ySpeed;
if (s.y>=480) {
s.addEventListener( Event.ENTER_FRAME, onMeltingEnter );
}
}
function onMeltingEnter( e: Event ): void {
var s:Snow=e.currentTarget as Snow;
this.addChild( s );
s.removeEventListener( Event.ENTER_FRAME, onSnowEnter );
s.vt += s.at;
s.alpha += s.vt;
if ( s.alpha <=0){
s.removeEventListener( Event.ENTER_FRAME, onMeltingEnter );
this.removeChild( s );
}
}

Create a bunch of objects, add them to an array and then loop through the array:
var numOfObjects:int = 10;
var fallingObjectArray:Array = [];
var speed:Number = 10;
// Add 10 falling objects to the display and to the array
for(var i:int = 0; i < numOfObjects; i++) {
var fallingObject:Sprite = new Sprite();
fallingObject.graphics.beginFill(0xFF0000);
fallingObject.graphics.drawCircle(0, 0, 15);
fallingObject.graphics.endFill();
addChild(fallingObject);
fallingObject.x = Math.random() * stage.stageWidth;
fallingObjectArray.push(fallingObject);
}
addEventListener(Event.ENTER_FRAME, moveDown);
function moveDown(e:Event):void
{
// Go through all the objects in the array and move them down
for each(var fallingObject in fallingObjectArray) {
fallingObject.y += speed;
// If the object is past the screen height, remove it from display and array
if(fallingObject.y+fallingObject.height >= stage.stageHeight) {
removeChild(fallingObject);
fallingObjectArray.splice(fallingObjectArray.indexOf(fallingObject), 1);
}
}
// Once all objects have fallen off the screen, remove the listener
if(fallingObjectArray.length <= 0) {
removeEventListener(Event.ENTER_FRAME, moveDown);
}
}
The code above is just using red circles - you will have to use whatever image you have instead (unless you like red circles...).

Related

How do i detect collision and stack falling objects in as3 flash?

I have a little problem when I'm trying to get the sqares to stack, almost like in tetris.
I don't know how I can controll the different squares so i can check for collision. I have made one square with as3 linkage name Square.
var timer:Timer = new Timer(12);
timer.addEventListener(TimerEvent.TIMER, doStuff);
timer.start();
var newSquare= new Square();
nyFirkant.y = 0;
nyFirkant.x = Math.floor( Math.random() * 4) * 100;
addChild(newSquare);
stage.addEventListener(KeyboardEvent.KEY_DOWN, tastLytter);
function keyListener(evt:KeyboardEvent)
{
var key:int = evt.keyCode;
if (key== Keyboard.RIGHT && newSquare.x < 400)
{
newSquare.x += 100;
}
if (key== Keyboard.LEFT && newSquare.x > 0)
{
newSquare.x -= 100;
}
}
function doStuff(evt:TimerEvent)
{
if (newSquare.y <= 400 - newSquare.height)
{
newSquare.y = newSquare.y + 2;
}
if (newSquare.y == 350)
{
newSquare= new Square();
newSquare.y = 0;
newSquare.x = Math.floor( Math.random() * 4) * 100;;
addChild(newSquare);
}
}
Use hitTestObject, it's a method in the MovieClip class.
if (firstBlock.hitTestObject(secondBlock)) {
trace("This block hit the other block");
//Do stuff
}
Obviously this isn't a "drop-in" solution - you'd be much better off using a physics engine such as Box2D, but hitTestObject should do fine for your purposes.

Why can't I reset this game? I tried resetting variables etc

I have this flash game coded with AS3. It works on the first round. When you die, the program will loop it back to the game frame in which a couple or errors occur. One. the dead characters from last round still remain still. Two. The speed doubles everytime. Why????
I create a resetEverything() function to reset all variables, remove Event Listeners and a clear.graphics()
Why doesn't anything work?
Here is my code..
stop();
var leftBorder:verticalwall = new verticalwall(); // defining a variable to hold the left wall
addChild(leftBorder); // adding the left wall to the stage
var rightBorder:verticalwall = new verticalwall(); // defining a variable to hold the left wall
rightBorder.x = 790; // pushing the right wall to the edge of the stage
addChild(rightBorder); // adding the right wall to the stage
var topBorder:horizontalwall = new horizontalwall(); // defining a variable to hold the left wall
addChild(topBorder); // adding the top wall to the stage
var bottomBorder:horizontalwall = new horizontalwall(); // defining a variable to hold the bottom wall
bottomBorder.y = 790; // pushing the bottom wall to the base of the stage
addChild(bottomBorder); // adding the bottom wall to the stage
var P1positions:Array = new Array(); //defining a new variable to hold the poistions of Player 1
var P2positions:Array = new Array(); //defining a new variable to hold the poistions of Player 2
graphics.beginFill( 0x000000 ); // defining a colour for the background
graphics.drawRect( 0, 0, 800, 800); // drawing a rectangle for background
graphics.endFill(); // ending the background creating process
stage.addEventListener(Event.ENTER_FRAME, checkPlayersSpeed);
function checkPlayersSpeed(event:Event)
{
if(P1speed == 0 || P2speed == 0){
P1speed = 0;
P2speed = 0;
gotoAndStop(1, "Conclusion");
}
}
//Player 1
var player1col = "0xFF0000";
var Player1:Shape = new Shape(); //defining a variable for Player 1
Player1.graphics.lineStyle(10,0xffff00); //defining the colour of the style
Player1.graphics.beginFill(0xffff00); //begin filling the shape
Player1.graphics.drawRoundRect(0,0,3,3,360);
Player1.graphics.drawCircle(Player1.x, Player1.x, 2.4) //draw a circle
Player1.graphics.endFill(); //finish the filling process
addChild(Player1); //add player 1 to stage
Player1.x = 250;
Player1.y = 250;
var P1leftPressed:Boolean = false; //boolean to check whether the left key for Player 1 was pressed
var P1rightPressed:Boolean = false; //boolean to check whether the right key for Player 1 was pressed
var P1speed = 3.5; //variable to store the speed of which player 1 moves
var P1Dir = 45; //variable containing the direction in which player 1 moves
var P1position, P2position;
Player1.addEventListener(Event.ENTER_FRAME, P1fl_MoveInP1DirectionOfKey); //adding a listener to the player
stage.addEventListener(KeyboardEvent.KEY_DOWN, P1fl_SetKeyPressed); //listener for a key to be pressed
stage.addEventListener(KeyboardEvent.KEY_UP, P1fl_UnsetKeyPressed); // listener for a key to be released
function P1fl_MoveInP1DirectionOfKey(event:Event) //Moves the player depedning on what key was pressed
{
if(Player1.hitTestObject(leftBorder) || Player1.hitTestObject(rightBorder) || Player1.hitTestObject(topBorder) || Player1.hitTestObject(bottomBorder)){ //checking to see whether Player 1 has hit the wall
P1speed = 0; //stopping Player 1 from moving
Player1.removeEventListener(Event.ENTER_FRAME, P1fl_MoveInP1DirectionOfKey); //adding a listener to the player
stage.removeEventListener(KeyboardEvent.KEY_DOWN, P1fl_SetKeyPressed); //listener for a key to be pressed
stage.removeEventListener(KeyboardEvent.KEY_UP, P1fl_UnsetKeyPressed); // listener for a key to be released
}
if (P1leftPressed)
{
P1Dir -= 0.1; //changes the direction to make Player 1 rotate
}
if (P1rightPressed)
{
P1Dir += 0.1; //changes the direction to make Player 1 rotate
}
P1position = [Player1.x, Player1.y]; //defining a variable for Player 1's constant positions
P1positions.push(P1position); //pushes every position of Player 1 to the array
for (var i = 0; i < P1positions.length - 10; i++) { //a loop that opperates for as long as the array is receiving positions
var P1x = P1positions[i][0]; //saving x positions into array with a unique identifier
var P1y = P1positions[i][1]; //saving y positions into array with a unique identifier
if (distanceBetween(P1x, P1y, Player1.x, Player1.y) < 15) { //checking distance between Player 1 and its trail
P1speed = 0;
}
}
Player1.x += P1speed * Math.cos(P1Dir); //this makes player 1 move forard
Player1.y += P1speed * Math.sin(P1Dir); //this makes player 2 move forward
var P1trail:Shape = new Shape; //defining a variable for player 1's trail
graphics.lineStyle(8, player1col); //setting the format for the trail
graphics.drawCircle(Player1.x, Player1.y, 1.4); //drawing the circles within the trail
addChild(P1trail); //adding the circles to the stage
}
function P1fl_SetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.LEFT:
{
P1leftPressed = true; //tells the computer that left has been pressed
break;
}
case Keyboard.RIGHT:
{
P1rightPressed = true; //tells the computer that right has been pressed
break;
}
}
}
function P1fl_UnsetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.LEFT:
{
P1leftPressed = false; //tells the computer that left has been released
break;
}
case Keyboard.RIGHT:
{
P1rightPressed = false; //tells the computer that left has been released
break;
}
}
}
function distanceBetween (x1:Number, y1:Number, x2:Number, y2:Number) { // creating a function
// return d = Math.sqrt(x2 - x1)^2 +(y2 - y1)^2);
var diffX = x2 - x1; // creating variable to tidy up the pythagoras line below
var diffY = y2 - y1; // creating variable to tidy up the pythagoras line below
return Math.sqrt(diffX * diffX + diffY * diffY); // using pythagras theorem
}
// Player 2
var player2col = "0x0066CC";
var Player2:Shape = new Shape(); //defining a variable for Player 1
Player2.graphics.lineStyle(10,0xffff00); //defining the colour of the style
Player2.graphics.beginFill(0xffff00); //begin filling the shape
Player2.graphics.drawRoundRect(0,0,3,3,360);
Player2.graphics.drawCircle(Player2.x, Player2.x, 2.4) //draw a circle
Player2.graphics.endFill(); //finish the filling process
addChild(Player2); //add player 1 to stage
Player2.x = 500;
Player2.y = 500;
var P2leftPressed:Boolean = false;
var P2rightPressed:Boolean = false;
var P2speed = 3.5;
var P2Dir = 180;
Player2.addEventListener(Event.ENTER_FRAME, P2fl_MoveInP1DirectionOfKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, P2fl_SetKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, P2fl_UnsetKeyPressed);
function P2fl_MoveInP1DirectionOfKey(event:Event)
{
if(Player2.hitTestObject(leftBorder) || Player2.hitTestObject(rightBorder) || Player2.hitTestObject(topBorder) || Player2.hitTestObject(bottomBorder)){
P2speed = 0;
Player2.removeEventListener(Event.ENTER_FRAME, P2fl_MoveInP1DirectionOfKey);
stage.removeEventListener(KeyboardEvent.KEY_DOWN, P2fl_SetKeyPressed);
stage.removeEventListener(KeyboardEvent.KEY_UP, P2fl_UnsetKeyPressed);
}
if (P2leftPressed)
{
P2Dir -= 0.1;
}
if (P2rightPressed)
{
P2Dir += 0.1;
}
P2position = [Player2.x, Player2.y];
//trace(P2position);
P1positions.push(P2position);
for (var a = 0; a < P1positions.length - 10; a++) {
var P2x = P1positions[a][0];
var P2y = P1positions[a][1];
if (distanceBetween(P2x, P2y, Player2.x, Player2.y) < 15) {
P2speed = 0;
}
}
Player2.x += P2speed * Math.cos(P2Dir);
Player2.y += P2speed * Math.sin(P2Dir);
var P2trail:Shape = new Shape;
graphics.lineStyle(8, player2col);
graphics.drawCircle(Player2.x, Player2.y, 1.4);
addChild(P2trail);
}
function P2fl_SetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case event.keyCode = 90:
{
P2leftPressed = true;
break;
}
case event.keyCode = 67:
{
P2rightPressed = true;
break;
}
}
}
function P2fl_UnsetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case event.keyCode=90:
{
P2leftPressed = false;
break;
}
case event.keyCode=67:
{
P2rightPressed = false;
break;
}
}
}
Please help!

hitTestObject doesn't work with veritable

trying to make bomb explode on impact when it hit the balls at the bottom of the stage, with if (bomb1.hitTestObject(ball)) { .But when the bomb hit one of the balls nothing happened. it works with other objects that are placed on stage but not with the balls.ball is a variable for 8 balls spread randomly on the bottom of the stage.
import flash.events.Event;
bomb1.gotoAndStop(1);
var minLimit: int = 31;
var maxLimit: int = 42;
var range: int = maxLimit - minLimit;
var balls: Array = [],
ball: bomb30a;
for (var i: int = 0; i < 8; i++) {
ball = new bomb30a();
ball.x = 150 + i * (Math.ceil(Math.random() * range) + minLimit);
ball.y = 350;
balls.push(ball);
addChild(ball);
}
thisButton.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event: MouseEvent): void {
bomb1.gotoAndPlay(1);
this.addEventListener(Event.ENTER_FRAME, handleCollision);
}
function handleCollision(evt: Event): void {
if (bomb1.hitTestObject(ball)) {
this.removeEventListener(Event.ENTER_FRAME, handleCollision);
bomb1.stop();
bomb1.bomb2.gotoAndPlay(31);
}
}
stop();
You are making eight bomb30a Objects, but you keep assigning them to the same variable, ball. This means that ball will, after your loop, refer to the last one only. So, when you do the hitTest, it is checking only the last ball you created. You will need to do a loop through your balls Array and try the hitTest on each on separately, as in...
for ( var i:int = 0; i < balls.length; ++i )
{
if ( bomb1.hitTestObject( balls[i] ) )
{
...
}
}

ActionScript 3 Looping

I just started using Looping in AS3 recently and I have much to learn. here is the question. Below is a Loop that puts 5 balls one on top of the other on the stage. So far so good. however, I'd like to create a situation when clicking on a button, the bottom ball is removed, and then each ball take the place of the ball below it one by one, continue this for each click until all the balls are gone. . I have created this situation with add/remove child and I thought it could be more efficient with looping. I just don't know how to access the balls since I don't have instance name or class name that I can reference too.
var ball: gBall4M;
var i: Number;
for (i = 0; i < 5; i++) {
ball = new gBall4M();
ball.x = 331.30;
ball.y = 25 + i * 17
addChild(ball);
}
function release2Ball2(event: MouseEvent): void {
This is the effect I want to get https://youtu.be/B4GLolw8QVA
As mentioned in the answer of #daniel-messer, you can use an Array to store your balls, and for the second part of your question, when removing the last ball and moving the other ones, you can use array.pop() to remove the last element of the array, and then you can use array.map() to move the other balls :
function release2Ball2(event:MouseEvent): void
{
if(balls.length > 0){
ball = balls.pop(); // remove and get the last element of the array
ball.parent.removeChild(ball); // remove that element from the DisplayObjectContainer
function move_ball(item:Ball, index:int, array:Array):void {
item.y += 17;
}
// move the rest of elements
balls.map(move_ball, this);
}
}
EDIT :
Take a look on the code working, I added numbers to understand how balls are moving :
Your full code can be like this :
var balls:Array = [],
ball:gBall4M;
for (var i:int = 0; i < 5; i++) {
ball = new gBall4M();
ball.x = 331.30;
ball.y = 25 + i * 17;
balls.push(ball);
addChild(ball);
}
btn.addEventListener(MouseEvent.CLICK, release2Ball2);
function release2Ball2(event:MouseEvent):void {
if (balls.length > 0) {
ball = balls.pop();
ball.parent.removeChild(ball);
function move_ball(item:gBall4M, index:int, array:Array):void {
item.y += 17;
}
balls.map(move_ball, this);
}
}
EDIT 2:
To do that kind of animation, you can use a Timer like this :
var balls:Array = [],
ball:gBall4M;
for (var i:int = 0; i < 5; i++) {
ball = new gBall4M();
ball.x = 30;
ball.y = 25 + i * 17;
balls.push(ball);
addChild(ball);
}
btn.addEventListener(MouseEvent.CLICK, release2Ball2);
function release2Ball2(event:MouseEvent):void {
if (balls.length > 0) {
ball = balls.pop();
ball.parent.removeChild(ball);
if(balls.length > 0){
timer.start();
}
}
}
var timer:Timer = new Timer(150);
timer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent){
if(balls.length >= timer.currentCount){
balls[balls.length - timer.currentCount].y += 17;
} else {
timer.reset();
}
})
Which will give you something like this :
Hope that can help.
Just save the instances inside an array or similar that you can use later.
I hope you are using a code file and not writing the code directly inside a frame inside the flash editor. Otherwise you might end up with issues.
Something similar to this should work
package {
class Main {
var balls:Array = [];
function createBalls() {
var ball: gBall4M;
var i: Number;
for (i = 0; i < 5; i++) {
ball = new gBall4M();
ball.x = 331.30;
ball.y = 25 + i * 17;
balls.push(ball); //Save them to array
addChild(ball);
}
}
function release2Ball2(event: MouseEvent): void {
var clickedBall:gBall4M = event.currentTarget as gBall4M; //this might be wrong depending on what you are listening for, and what type of object gBall4M is...
for(var i=0; i<balls.length; ++i) {
if(balls[i] == clickedBall) {
balls[i].splice(i, 1); //remove instance from array
removeChild(clickedBall); //remove instance from display list
break;
}
}
}
}
}
OK I figured it out. using this code on frame 1
function release2Ball2(event: MouseEvent): void {
if (ballA.length > 0) {
ball = ballA.pop();
removeChild(ball);
ball = null
gotoAndPlay(2);
}
}
stop();
using this code on frame 10:
for (i = 0; i < ballA.length; i++) {
ballA[i].y += 17;
stop();
That does the trick.
Thank you so much for your help

How can I turn an AS2 snow effect into a AS3 snow effect?

So I manage to find a snow effect that I like and wanted to use it but I realized it was in AS2 and I need it to be in AS3. Since there isn't a small difference between AS2 and AS3 I'm here to find some in these matter.
As you can see in the fla provided I also want to control the wind and speed by buttons.
Here is a link to the AS2 snow effect: http://www.freeactionscript.com/download/realistic-snow-fall-snowflake-effect.zip
This is the code in AS2:
//settings
var speed:Number = 2;
var wind:Number = -2;
var movieWidth:Number = 550;
var movieHeight:Number = 400;
createSnow(_root, 100);
function createSnow(container:MovieClip, numberOfFlakes:Number):Void
{
//run a for loop based on numberOfFlakes
for (var i = 0; i < numberOfFlakes; i++)
{
//set temporary variable and attach snowflake to it from the library
var tempFlake:MovieClip = container.attachMovie("snow_mc", "snow"+container.getNextHighestDepth(), container.getNextHighestDepth());
//variables that will modify the falling snow
tempFlake.r = 1+Math.random()*speed;
tempFlake.k = -Math.PI+Math.random()*Math.PI;
tempFlake.rad = 0;
//giving each snowflake unique characteristics
var randomScale:Number = random(50)+50;
tempFlake._xscale = randomScale;
tempFlake._yscale = randomScale
tempFlake._alpha = random(100)+50;
tempFlake._x = random(movieWidth);
tempFlake._y = random(movieHeight);
//give the flake an onEnterFrame function to constantly update its properties
tempFlake.onEnterFrame = function()
{
//update flake position
this.rad += (this.k / 180) * Math.PI;
this._x -= Math.cos(this.rad)+wind;
this._y += speed;
//if flake out of bounds, move to other side of screen
if (this._y >= movieHeight) {
this._y = -5;
}
if (this._x >= movieWidth)
{
this._x = 1
}
if (this._x <= 0)
{
this._x = movieWidth - 1;
}
}
}
}
//buttons
//wind
left_btn.onRelease = function()
{
wind = 2;
}
none_btn.onRelease = function()
{
wind = 0;
}
right_btn.onRelease = function()
{
wind = -2;
}
//speed
slow_btn.onRelease = function()
{
speed = .5;
}
normal_btn.onRelease = function()
{
speed = 1
}
fast_btn.onRelease = function()
{
speed = 3
}
It's going to be really quite similar.
The first thing would be, instead of:
var tempFlake:MovieClip = container.attachMovie("snow_mc", "snow"+...
you want something like:
var tempFlake = new snow_mc();
container.addChild(tempFlake);
Then convert all the property names such as _x etc to their AS3 equivalents (no underscore, scaleX in place f _xscale etc), Math.random() * 50 in place of random(50).
Replace all onRelease with addEventListener(MouseEvent.CLICK, function() {})
Finally instead of tempFlake.onEnterFrame you'll need one frame loop something like:
function onFrame(event: Event): void {
foreach(var child: MovieClip in container) {
child.rad += ... etc
}
}
addEventListener(Event.ENTER_FRAME, onFrame);
These steps should be sufficient to get it working as AS3. Once it's running, you could go further to make it more AS3 by creating a SnowFlake class that encapsulates all the properties and updates for one snowflake.