How to remove all of one class of children from screen in Flash CS4 AS3? - actionscript-3

Ok, so I've been stuck on this for about three hours now and I finally feel like asking for help.
Basically, I am trying to remove all instances of an enemy object from the screen when my player ship makes contact with one of them, as he then loses a life and is put back into a safe position on the screen.
EDIT: This is all the code from my Enemy Dude .as file, a bit overboard maybe but nonetheless.
package
{
import flash.display.MovieClip;
import flash.events.*;
import flash.media.Sound;
import flash.media.SoundChannel;
public class Enemydude extends MovieClip
{
private var _root:Object;
private var speed:int = 6;
private var shipps = this
public function Enemydude()
{
addEventListener(Event.ADDED, beginclass);
addEventListener(Event.ENTER_FRAME, entFrame);
}
private function beginclass(event:Event):void
{
_root = MovieClip(root);
}
private function entFrame(event:Event):void
{
x -= speed;
if(this.x < -64)
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.removeChild(this)
}
if(_root.gameover)
{
x = -700
removeEventListener(Event.ENTER_FRAME, entFrame);
removeEventListener(Event.ADDED, beginclass);
}
for (var i:int = 0; i<_root.playerBulletContainer.numChildren; i++)
{
var bulletTarget:MovieClip = _root.playerBulletContainer.getChildAt(i)
if (hitTestObject(bulletTarget))
{
removeEventListener(Event.ENTER_FRAME, entFrame);
_root.removeChild(this);
_root.playerBulletContainer.removeChild(bulletTarget);
bulletTarget.removeListeners();
_root.Score += 10
makeExplosion();
}
}
if(hitTestObject(_root.mcship))
{
makeExplosion();
shipPos();
removethis();
}
}
private function makeExplosion()
{
var sndExplode:snd_explosion1;
var sndExplodeChannel:SoundChannel;
sndExplode=new snd_explosion1();
sndExplodeChannel=sndExplode.play();
var newExplosion01:explosionEffect=new explosionEffect ;
newExplosion01.x=this.x;
newExplosion01.y=this.y;
_root.explosionContainer.addChild(newExplosion01);
}
private function shipPos()
{
_root.lives -= 1;
_root.mcship.x = 80;
_root.mcship.y = 225;
for each(var i:Enemydude in _root.enemies)
{
removethis();
}
_root.enemies.length = 0;
}
public function removethis():void
{
if(parent) parent.removeChild(this)
removeEventListener(Event.ENTER_FRAME, entFrame);
}
}
}
EDIT: And this is the code I now have that relates to the Enemydude in my main timeline, quite sorry about all this.
var enemies:Array = [];
var Shipheight:Number = 300;
var Enemytime:int = 0;
var Enemylimit:int = 16;
if (Enemytime<Enemylimit)
{
Enemytime ++;
}
else
{
var newEnemy01 = new Enemydude();
newEnemy01.y = Shipheight;
newEnemy01.x = stage.stageWidth + 64;
addChild(newEnemy01);
enemies.push(newEnemy01);
Enemytime = 0
function shipY(event:Event):void
{
Shipheight = Math.ceil(Math.random()* 250) + 80;
}
Thank you for your help in advance, any advice is appreciated.

I suggest storing your enemies in an Array.
For example, create the array enemies:
var enemies:Array = [];
And then amend your code to:
else
{
var newEnemy01 = new Enemydude();
newEnemy01.y = Shipheight;
newEnemy01.x = stage.stageWidth + 64;
addChild(newEnemy01);
enemies.push(newEnemy01);
Enemytime = 0;
}
That way you can remove all of the enemies using this new array:
for each(var i:Enemydude in enemies)
{
i.remove(); // Or whatever function Enemydude has to remove itself.
}
// Empty the enemies Array.
enemies.length = 0;
Here's the .remove() method you could make for Enemydude:
public function remove():void
{
if(parent) parent.removeChild(this);
// Remove any event listeners etc from this object.
}

A common and easy way of doing this is to create a subcontainer to hold the objects and destroy this object instead. It makes easy for some collision checks too, since you can use the holder object to make one check against the player.
If you don't want to create this, you can use an array or a vector to store references to this objects, what makes easy to traverse the list.
I persoally recommend the vector aprouch:
var enemyList:Vector.<Enemy> = new Vector.<Enemy>();
Then you can loop almost like an array (as Marty Wallace showed on his answer):
for each(var e:Enemy in enemyList) {
container.removeChild(e);
}
enemyList.length = 0; // empty vector
Vectors are a bit slower than normal arrays, but are type safe. The difference in performance is almost negligible in most cases.

Related

Some of the collisions are not responding

im developing a game; its like a space craft going horizontally and enemy crafts coming oppositely..Enemies are destroyed only when it collides with the trail of the craft.
Here is the main class:
public function Velocity() {
//int static var
trailspeed = 10;
shipspeed = 5;
//init ship//
ship = new Ship();
ship.x = 337;
ship.y = 216;
//int arrays
enemies = new Array();
//init starting state
score = 0;
health = 100;
//Events
addEventListener(Event.ENTER_FRAME, motion);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
stage.addEventListener(KeyboardEvent.KEY_UP, keyup);
//init container and trail
_cont = new MovieClip();
//addChild
addChild(_cont);
addChild(ship);
timerset();
}
public function motion(e:Event){
//adding the trails
trail = new Trail();
trail.x = ship.x;
trail.y = ship.y;
_cont.addChild(trail);
checkcollision();
}
public function checkcollision(){
for(var _e:int = enemies.length - 1; _e >=0; _e--){
for(var _t:int = _cont.numChildren - 1; _t >=0; _t--){
if(enemies[_e].hitTestObject(_cont.getChildAt(_t))){
enemies[_e].remove();
return;
}
}
}
}
public function removeenemies(_e:Enemy){
for(var i in enemies){
if(enemies[i] == _e){
enemies.splice(_e);
}
}
}
and here is the Enemy class:
public class Enemy extends MovieClip {
private var _speed:Number;
public function Enemy(ypos, speed) {
this.x = 550;
this.y = ypos;
_speed = speed;
addEventListener(Event.ENTER_FRAME, motion);
}
public function motion(e:Event){
this.x -= _speed;
checkoffscreen();
}
public function remove(){
MovieClip(parent).removeenemies(this);
MovieClip(parent).removeChild(this);
removeEventListener(Event.ENTER_FRAME, motion);
return;
}
public function checkoffscreen(){
if(this.x < 0){
MovieClip(parent).removeenemies(this);
MovieClip(parent).removeChild(this);
removeEventListener(Event.ENTER_FRAME, motion);
}
}
}
}
The problem here is after 2 or 3 successful collision detections one goes undetected.. and hence the chances is like 2/3 ...how can i program a 100% successful collision???pls help
I want to recommend not to delete objects from within themselves, instead have a simple isDead boolean inside the the Enemy and in the main class when you loop through enemies check if isDead is set to true, if so then remove the object from the array and delete it from the Stage; no need for removeenemies().
Back to the real problem you're having. You're doing a good job iterating through the list of enemies in reverse since you do expect to remove some objects, that of course results in shift of entries in the array.
It's hard to say what's wrong with this code. I'd say lose removeenemies(). Move any collision testing inside the Enemy and in the Main keep everything in a nice linear update function like so:
public function update() {
for(var i:int = enemies.length - 1; i >=0; i--){
var enemy:Enemy = enemies[i];
enemy.checkCollision(); // Can set isDead = true;
if(enemy.isDead) {
enemies.splice(i);
removeChild(enemy);
}
}
}
Finally I found out the answer.
the problem was with the removeenemies function
replacing splice(_e) wtih splice(_e, 1) solved the problem

AS3 - Remove a Specific Instance of a MovieClip with removeChild() Function

I'm working on a Flash game for an assignment. It's a pretty standard missile defense-type game, with a rotating missile launcher in the center firing up at passing bombers above. The missiles and bombers are functioning correctly by themselves, but I'm running into a problem when I try to get the two to interact. Specifically, when a missile hits a bomber, I want the specific instances of that missile and that bomber to be removed from the screen and have their respective event listeners removed, but everything I've tried has failed and I can't seem to figure out just how to do it.
Here are the Main, Bomber, and Missile classes I'm working with:
The Main Class:
package {
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip {
public var background:Background;
public var launcher:Launcher;
public var mount:Mount;
public var missile:Missile;
public var salvo:Array = [];
public var bomber:Bomber;
public var squadron:Array = [];
/*
* This function sets up the permanent items (items that remain on-stage for
* the duration of the game) and adds event listeners that call functions to
* add non-permanent items to the stage
*/
public function Main() {
// Add background to the stage
background = new Background(stage);
stage.addChild(background);
stage.setChildIndex(background, 0);
// Add the rotating launcher to the stage
launcher = new Launcher(stage);
stage.addChild(launcher);
stage.setChildIndex(launcher, 1);
// Add the static mount to the stage (on top of launcher)
mount = new Mount(stage);
stage.addChild(mount);
stage.setChildIndex(mount, 2);
// Call loop() every new frame
stage.addEventListener(Event.ENTER_FRAME, loop);
// Call fire() every time the mouse is clicked
stage.addEventListener(MouseEvent.CLICK, fire);
}
/*
* This function runs every time the program enters a new frame, or 60 times
* every second. Each time this function runs, it tries to add a new Bomber
* to the squadron array and checks to see if there are any Missiles or
* Bombers currently in their respective arrays (and if so, calls a function
* to make them move).
*/
public function loop(evt:Event) {
// If the random number generated by Math.random() is less than
// waveLimiter, create a new Bomber and add it to the squadron array.
if(Math.random() < 0.02 /* Change this number to change how fast bombers spawn */) {
bomber = new Bomber(stage);
bomber.addEventListener(Event.REMOVED_FROM_STAGE, removeBomber); // If the Bomber is removed from the stage, call removeBomber() to remove its event handler.
squadron.push(bomber);
stage.addChild(bomber);
stage.setChildIndex(bomber, 1);
}
// Check to see if there is at least one missile in the salvo array, and
// if so, call Missile.velocity() to make it move.
if(salvo.length > 0) {
for(var i:int = salvo.length - 1; i >= 0; i--) {
salvo[i].velocity();
}
}
// Check to see if there is at least one bomber in the squadron array,
// and if so, call Bomber.fly() to make it move.
if(squadron.length > 0) {
for(var j:int = squadron.length - 1; j >= 0; j--) {
squadron[j].fly();
}
}
}
/*
* This function checks for a mouse click, and if it detects one, creates a
* new Missile and adds it to the salvo array.
*/
public function fire(evt:MouseEvent) {
missile = new Missile(stage, launcher.rotation);
missile.addEventListener(Event.REMOVED_FROM_STAGE, removeMissile); // If the Missile is removed from the stage, call removeMissile() to remove its event handler.
salvo.push(missile);
stage.addChild(missile);
stage.setChildIndex(missile, 1);
}
/*
* This function removes the EVENT LISTENER for the current Missile instance.
* It does not remove the Missile itself from the stage.
*/
public function removeMissile(evt:Event):void {
evt.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, removeMissile);
salvo.splice(salvo.indexOf(evt.currentTarget), 1);
}
/*
* This function removes the EVENT LISTENER for the current Bomber instance.
* It does not remove the Bomber itself from the stage.
*/
public function removeBomber(evt:Event) {
evt.currentTarget.removeEventListener(Event.REMOVED_FROM_STAGE, removeBomber);
squadron.splice(squadron.indexOf(evt.currentTarget), 1);
}
}
}
The Bomber class:
package {
import flash.display.Stage;
import flash.display.MovieClip;
public class Bomber extends MovieClip {
var stageInstance:Stage;
var randomNumber:Number = Math.round(Math.random() * 1);
public function Bomber(stageInstance:Stage):void {
this.stageInstance = stageInstance;
if(randomNumber == 1) {
x = -39;
y = (Math.random() * 120) + 30;
}
else if(randomNumber == 0) {
scaleX *= -1;
x = 679;
y = (Math.random() * 120) + 30;
}
}
public function fly():void {
if(randomNumber == 1) {
x = x + 4;
}
else if(randomNumber == 0) {
x = x - 4;
}
if(x > 680 || x < -40) {
this.parent.removeChild(this);
}
}
}
}
The Missile Class:
package {
import flash.display.Stage;
import flash.display.MovieClip;
public class Missile extends MovieClip {
var stageInstance:Stage;
var velocityX:Number;
var velocityY:Number;
var speed:Number = 10;
var rotationRadians:Number;
var rotationDegrees:Number;
public function Missile(stageInstance:Stage, rotationDegrees:Number):void {
this.stageInstance = stageInstance;
x = 320;
y = 363;
rotation = rotationDegrees;
rotationRadians = rotationDegrees * Math.PI / 180;
}
public function velocity():void {
velocityX = Math.cos(rotationRadians) * speed;
velocityY = Math.sin(rotationRadians) * speed;
x += velocityX;
y += velocityY;
if(x > 640 || x < 0 || y > 480 || y < 0) {
this.parent.removeChild(this);
}
}
}
}
In the Main Class, I've tried adding something like this:
if(squadron.length > 0) {
for(var j:int = squadron.length - 1; j >= 0; j--) {
squadron[j].fly();
if(salvo.length > 0) {
if(missile.hitTestObject(squadron[j])) {
this.parent.removeChild(this);
}
}
}
}
But no luck. I've also tried using a trace statement, and it doesn't even give me an output, which leads me to think it's not even detecting collision at all. Any ideas?
Update: I added a few more details.
this represents the object on which the function is called. So
this.parent.removeChild(this); makes no sense when it is written in the main class.
When you write it in the Missile Class, this is the Missile instance, and this.parent is the stage.
Try replacing it with: stage.removeChild(missile), in the last sample of code you posted, and call removeMissile() just after.
Try to use stage.removeChild instead this.parent.removeChild(this);
Actually you have many problems in your code. First of all, you don't need to work with Stage. You can work with your main container Main. When you add object to the display list, don't do after setChildIndex. In your code It doesn't have any sense. Also you don't need any length conditions. And create light objects by extending Sprite, not MovieClip.
Code for your loop, for missiles:
private function loop(e: Event):void {
//...not full listing
var i:uint, j:uint, salvos:uint = salvo.length, bombers:uint = squadron.length, missile:Missle, bomber:Bomber;
var disposeMissiles:Array = [];
var disposeBombers:Array = [];
//Rendering missiles
for (i = 0; i < salvos; ++i) {
missile = salvo[i];
missile.valocity();
for (j = 0; j < bombers; ++j) {
bomber = squadron[j];
if (!bomber.isHitted() && missile.hitTestObject(bomber)) {
//Dispose both missile and bomber
bomber.setHitted = true;
disposeMissiles.push(missile);
disposeBombers.push(bomber);
}
}
}
//Clear lists and display list
disposeObjects(disposeMissiles, salvo);
disposeObjects(disposeBombers, squadron);
}
private function disposeObjects(objects:Array, from:Array):void {
//Create interface for both missiles and bombers, like IGameActor
var i:uint, len:uint = objects.length, objectToRemove:IGameActor;
for (i; i < len; ++i) {
objectToRemove = objects[i];
//Remove from the display list, in your design Parent is Stage
this.stage.removeChild(DisplayObject(objectToRemove));
//Release memory, links, event listeners
objectToRemove.dispose();
//Try manage also indexes, splice is slow operation
from.splice(from.indexOf(objectToRemove), 1);
}
}

Reaching variables in other functions

Im making a game as a graduation project and have encountered a little issue. The goal of the game is to maneuver a ship and avoid asteroids as long as possible. I'm almost done but I'm now trying to solve the collision detection.
My problem is how do I reach the enemy in the loop variable so that it can check for collision with it? Here is the code:
package com.asgamer.basics1
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class Engine extends MovieClip
{
private var numStars:int = 80;
private static var enemyList:Array = new Array();
private var ourShip:Ship;
public function Engine() : void
{
ourShip = new Ship(stage);
ourShip.x = stage.stageWidth / 2;
ourShip.y = stage.stageHeight / 2;
stage.addChild(ourShip);
for (var i:int = 0; i < numStars; i++)
{
stage.addChildAt(new Star(stage), 1)
}
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
stage.addEventListener(Event.ENTER_FRAME, krash);
}
private function krash(e:Event) : void
{
function krash(e:Event):void
{
if (enemy.hitTestObject(ourShip)==true)
{
stage.removeChild(ourShip);
stage.removeEventListener(Event.ENTER_FRAME, krash);
}
}
}
private function loop(e:Event) : void
{
if (Math.floor(Math.random() * 10) == 5)
{
var enemy:Asteroid = new Asteroid(stage);
enemy.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemy, false, 0, true);
enemyList.push(enemy);
stage.addChild(enemy);
}
}
private function removeEnemy(e:Event)
{
enemyList.splice(enemyList.indexOf(e.currentTarget), 1);
}
}
}
As you can see I have a function for making enemies which is called loop, and a function for collision detection called krash. But since enemy is a variable inside loop, how can I check for collision with it in the krash function. (Sort of new to actionscript, so I dont know the terminology all to well)
In krash you will need to check each enemy in enemyList.
example:
private function krash(e:Event) : void
{
function krash(e:Event):void
{
for(var i:int = 0; i < enemyList.length; i++)
{
if (enemyList[i].hitTestObject(ourShip)==true)
{
stage.removeChild(ourShip);
stage.removeEventListener(Event.ENTER_FRAME, krash);
}
}
}
}
Unfortunately, if you have a lot of enemies on the stage the program will lag a bit because you're checking for collisions with all of them every frame.
Also, I'd reccommend you add something to remove you enemies from the screen :P
private function removeEnemy(e:Event)
{
enemyList.splice(enemyList.indexOf(e.currentTarget), 1);
stage.removeChild(enemyList.indexOf(e.currentTarget));
}
Hope this helps.

How do I add Child when two instances collide?

I'm trying to create a virtual life simulation, where when a boy fish and a girl fish collide they reproduce. This is my first time using external class files and I'm quite confused.
package {
import flash.display.MovieClip;
import flash.events.Event;
public class Main extends MovieClip
{
var numBalls:Number = 3;
var bFishList:Array = new Array();
var gFishList:Array = new Array();
public static var bFish:BoyFish = new BoyFish ;
public static var gFish:GirlFish = new GirlFish ;
var fishName:Object = bFish.name;
public function Main()
{
addEventListener(Event.ADDED_TO_STAGE, enterFrameNow);
function enterFrameNow(event:Event):void {
// constructor code
for (var i = 0; i < numBalls; i++) {
var bFish:MovieClip = new BoyFish();
bFish.name = "bFish"+i;
addChild(bFish);
//variable ball a movieclip is a new instance of Ball
var gFish:MovieClip = new GirlFish();
// ball x and y value was in the middle of the stage
bFish.x = stage.stageWidth / 2;
bFish.y = stage.stageHeight / 2;
// add ball to stage
bFishList.push(bFish);
// ball x and y value was in the middle of the stage
gFish.x = stage.stageWidth / 2;
gFish.y = stage.stageHeight / 2;
// add ball to stage
addChild(gFish);
gFishList.push(gFish);
addEventListener(Event.ENTER_FRAME, hitTest);
function hitTest(event:Event):void {
for (i = 0; i < bFishList.length; i++) {
if (gFish.hitTestObject(bFishList[i]) == true) {
addChild(gFish);
gFishList.push(gFish);
trace("hit");
}
}
}
}
}
trace(bFishList);
trace(gFishList);
}
}
}
Here's the code from my Main.as file. I've tried for so long with the hitTestObject thing, and it's just not working for me.
Can anyone help me? I want it to add another instance to the stage when a bFish and a gFish collide.
You shouldn't add that many enterFrame events.
Add just one enterFrame handler, in your class, not as a local function, and add a nested loop into it.
//Somewhere in your Main() function :
addEventListener(Event.ENTER_FRAME, this.hitTest);
//In class Main
public function hitTest(event:Event):void
{
for (var i = 0; i < bFishList.length; i++)
{
for (var j = 0; j < gFishList.length; j++)
{
if (gFishList[j].hitTestObject(bFishList[i]))
{
var newFish:MovieClip = new GirlFish(); //Create it.
addChild(newFish);
gFishList.push(newFish);
}
}
}
}
Please note that if you aren't doing any more action, that could result of the creation of many girl fish each frame, which could eventually freeze the flashplayer.

A loop in enterframe?

I'm animating a bunch of words in AS3. Because I'm going to be using this on a mobile device, I want to use bitmaps rather than Sprites. So I've created WordObjects, which have a .bitmap property that I can access.
I have the following code, which fires on the click event and loops through an array inside an enterframe event. This is probably a bad idea, but I'm not sure how to do it better. (What is surprising is that it runs just fine in Flashbuilder, but slows to a crawl in Flash CS5.)
Is there some better way to do this? I just want an efficient way to animate the array of bitmaps.
private function clickhandler (e:MouseEvent){
this.addEventListener(Event.ENTER_FRAME, blowemup);
}
private function blowemup(e:Event){
var newPosition:Number;
for(var i:int=0; i<arrWordObjects.length; i++)
{
newPosition = updatePosition(arrWordObjects[i].bitmap);
arrWordObjects[i].bitmap.x += newPosition;
arrWordObjects[i].bitmap.y += getRandomNumber();
}
}
Something that will make a huge difference is using for each(Object in Array) rather than the standard for loop.
private function blowemup(e:Event):void
{
var newPosition:Number;
var i:ArrWordsObjectClass; // <-- don't know what the class for this is, just replace
for each(i in arrWordObjects)
{
newPosition = updatePosition(i.bitmap);
i.bitmap.x += newPosition;
i.bitmap.y += getRandomNumber();
}
}
A for each loop is typed, meaning a lot of time is saved where normally it'd be trying to work out what arrWordObjects[i] is every iteration.
Also, side note: using one ENTER_FRAME driven function and looping through everything in your application that you want to handle each frame is much more efficient than applying hundreds of listeners for objects.
I normally create a handler class that contains the ENTER_FRAME and an array storing my objects, like so:
package
{
import flash.events.Event;
import flash.display.Sprite;
public class Handler extends Sprite
{
// vars
public var elements:Array = [];
/**
* Constructor
*/
public function Handler()
{
addEventListener(Event.ENTER_FRAME, _handle);
}
/**
* Called on each dispatch of Event.ENTER_FRAME
*/
private function _handle(e:Event):void
{
var i:Element;
for each(i in elements)
{
i.step();
}
}
}
}
Then I create a base class for all the objects that I want to handle, containing the step() function called above.
package
{
import flash.display.DisplayObject;
public class Element extends Object
{
// vars
public var skin:DisplayObject;
/**
* Called on each dispatch of Event.ENTER_FRAME at Handler
*/
public function step():void
{
// override me
}
}
}
Now just extend Element with your objects:
package
{
import flash.display.Sprite;
public class MyThing extends Element
{
/**
* Constructor
*/
public function MyThing()
{
skin = new Sprite();
skin.graphics.beginFill(0);
skin.graphics.drawCircle(0,0,40);
skin.graphics.endFill();
}
/**
* Override step
*/
override public function step():void
{
skin.x += 4;
}
}
}
And get it all going!:
var handler:Handler = new Handler();
var m:MyThing;
var i:uint = 0;
for(i; i<10; i++)
{
m = new MyThing();
m.y = Math.random()*stage.stageHeight;
handler.elements.push(m);
addChild(m.skin);
}
How many bitmaps do you plan to have on the stage at a time?
I have had 40 900x16px bitmaps animating on the stage at full speed running on my iphone using air 2.6.
I used a foreach loop in an enterframe event which i added on mouseclick and removed once the animation was finished.
Remember to compile it for the mobile with gpu rendering enabled. (gpu in your app.xml if you are using air 2.6)
This is worth a read too, it explains a lot about performance for mobile devices
http://help.adobe.com/en_US/as3/mobile/WS901d38e593cd1bac-3d719af412b2b394529-8000.html
Here is a basic example of what I had...
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
[SWF(frameRate="30", backgroundColor="#FF00FF")]
public class Test extends Sprite
{
private var fields:Vector.<Bitmap> = new Vector.<Bitmap>();
public function Test()
{
this.stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.align = StageAlign.TOP_LEFT;
for(var i:int = 0; i< 37; i++){
var bd:BitmapData = new BitmapData(960, 16, true, 0x000000);
bd.fillRect(new Rectangle(0, 0, 900, 16), Math.round( Math.random()*0xFFFFFFFF ));
var b:Bitmap = new Bitmap(bd);
b.x = 0;
b.y = i*16;
stage.addChild(b);
fields.push(b);
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private var inertia:Boolean = false;
private var yCurrent:Number;
private var ySpeed:Number;
private var startY:Number;
private var cy:Number = 0;
private function onEnterFrame(e:Event):void{
if(!inertia){
ySpeed = (startY - yCurrent) ; // / 16;
startY = yCurrent
} else {
ySpeed *= 0.8;
if(ySpeed < 0.01 && ySpeed > -0.01){
inertia = false;
stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
}
}
cy += ySpeed;
if(cy > 640)
cy -= 640;
var ty:Number = cy;
for each(var tf:Bitmap in fields){
tf.y = ty;
ty += 16;
if(ty > 640)
ty -= 640;
}
}
private function onMouseDown(e:MouseEvent):void{
inertia = false;
startY = e.stageY;
yCurrent = e.stageY;
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseMove(e:MouseEvent):void{
yCurrent = e.stageY;
}
private function onMouseUp(e:Event):void{
inertia = true;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
}
I would suggest looking at writing a custom effect on Adobe's website over registering for ENTER_FRAME event. What you've put up there means this code will forever run as long as the program is running. If you wanted to stop the effect or run for 10 frames and stop then you'll have to write more code. It gets even more complex if you want to apply this to several instances. You're going to have to resolve problems that custom effects framework solves.
I'd read how to write custom effects here:
http://livedocs.adobe.com/flex/3/html/help.html?content=createeffects_1.html