My class has some timing issues - actionscript-3

I have a class that I use to display text on stage, with some number effects. It works pretty well, but when I chain it like this
public function onAdd(e:Event) {
//stuff
addChild(new messager("Welcome."));
addChild(new messager("WASD to move, mouse to shoot."));
addChild(new messager("Kill zombies for XP and collect ammo boxes.",waveOne));
}
public function waveOne(){
addChild(new messager("Good luck and have fun.",newWave));
}
The text (Good luck and have fun) is not displayed, but newWave is called. The reason why I don't call waveOne in onAdd is so that it doesn't happen too quick - my class just throws the text at the user once every 50 frames (which is intended, for later when you kill enemies and the text needs to catch up).
Here is my class (with the effects removed):
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.Timer;
public class Messager extends MovieClip{
var actualText:String;
var callback:Function;
var upTo:int = 0;
static var waitingFor:int = 0;
public function Messager(text:String,callback:Function=null) {
this.callback = callback;
actualText = text;
x = 320 - actualText.length * 6.5;
y = 0 - waitingFor * 60;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
waitingFor++;
}
public function onEnterFrame(e:Event) {
y+= 1;
if(y > 60){
waitingFor--;
}
if(y > 200){
alpha -= 0.03;
if(alpha <= 0){
if(callback != null){
callback();
}
removeEventListener(Event.ENTER_FRAME, onEntFrm);
this.parent.removeChild(this);
}
}
}
}
It is set to linkage with a movieclip that has a textfield.
Thanks for any help.

y = 0 - waitingFor * 60; Maybe y of the last Mesager is a big negative number? Have you tried to trace waitingFor?

Related

AS3 Projectile moves incorrectly

So I'm currently attempting to make a prototype for a Bullet Hell game and I've run into a bit of a dead end.
So far I can move my player perfectly, the boss moves back and forth as he is supposed to, however the projectiles have some funny behaviour. Basically, when the boss moves left/right, so do the projectiles as if they are stuck to him. They move on the y as they are supposed to, except they stop just short of the player and move no further, so I'm hoping anyone can take a look at my code and give me a hand with what's going on.
Note: Ignore the rotation stuff, that's for later implementation, I was just laying the ground work.
Projectile.as
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Projectile extends MovieClip
{
private var stageRef:Stage;
private var _xVel:Number = 0;
private var _yVel:Number = 0;
private var rotationInRadians = 0;
private const SPEED:Number = 10;
public function Projectile(stageRef:Stage, x:Number, y:Number, rotationInDegrees:Number)
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
this.rotation = rotationInDegrees;
this.rotationInRadians = rotationInDegrees * Math.PI / 180;
}
public function update():void
{
this.y += SPEED;;
if(x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
{
//this.removeChild(this); <- Causing a crash, will fix later
}
}
}
}
Boss.as
package
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class Boss extends MovieClip
{
private var stageRef:Stage;
private var _vx:Number = 3;
private var _vy:Number = 3;
private var fireTimer:Timer;
private var canFire:Boolean = true;
private var projectile:Projectile;
public var projectileList:Array = [];
public function Boss(stageRef:Stage, X:int, Y:int)
{
this.stageRef = stageRef;
this.x = X;
this.y = Y;
fireTimer = new Timer(300, 1);
fireTimer.addEventListener(TimerEvent.TIMER, fireTimerHandler, false, 0, true);
}
public function update():void
{
this.x += _vx;
if(this.x <= 100 || this.x >= 700)
{
_vx *= -1;
}
fireProjectile();
projectile.update();
}
public function fireProjectile():void
{
if(canFire)
{
projectile = new Projectile(stageRef, this.x / 200 + this._vx, this.y, 90);
addChild(projectile);
canFire = false;
fireTimer.start();
}
}
private function fireTimerHandler(event:TimerEvent) : void
{
canFire = true;
}
}
}
Edit: Current suggestions have been to do the following:
stage.addChild(projectile); and this.parent.addChild(projectile); both which have the projectile firing from the top left corner (0, 0) and not constantly firing from the current center of the Boss.
The other issue, which has been untouched, is the fast that the projectile stops moving after a certain point and remains on the screen.
Another Edit:
After commenting out the code with the timer I have found that the projectile stops moving entirely. The reason why it was stopping after a certain amount of time was due to the timer, when the timer elapsed the projectile stopped and another would fire.
So now I need the projectile to constantly fire and move until it hits the edge of the screen, any ideas?
The problem is you are 'addChild'ing your projectiles to your Boss as opposed the stage (or the same display level as your Boss). When your Boss moves, your projectiles will move relative to him (ie, when he moves sideways, so will they).
When your boss fires a projectile, use a custom event to trigger a fireProjectile method in the Class that is your Boss' display parent. Instantiate your projectiles there and addChild them to the same object to which you addChild your Boss (possibly the stage?).
Alternatively, if you don't want to use a custom event, in your current fireProjectile method change the addChild line to:
this.parent.addChild(projectile);
This will add projectiles to the parent object of your Boss. Although that line seems, slightly, like cheating to me.

Flash AS3 (shape class) CPU usage and optimization

I'm new to Flash Actionscript 3.0 and object programming in general. I'm trying to create a simple game, which is drawing a shape based on steering.
public class Player extends Shape
{
public var X,Y,v,vX,vY,size,a,r:Number;
public var k,counter,leftKey,rightKey,_color:uint;
public var line:Shape = new Shape();
public var dot:Shape = new Shape();
/*...*/
/*constructor, giving values to variables here, not important*/
/*...*/
public function Move():void
{
a=a+0.05*k;
//player controls k parameter k=0 by default
//k=1 when right key pressed
//k=-1 when left key pressed
vX=v*Math.cos(a);
vY=v*Math.sin(a);
X=X+vX;
Y=Y+vY;
dot.x=X+vX*size/(2*v);
dot.y=Y+vY*size/(2*v);
if (counter==0)
{
line.graphics.lineTo(X,Y);
if (Math.random()<0.008) counter=12;
} else
{
line.graphics.moveTo(X, Y);
counter--;
}
}
}
Function Move is in my Player class, which is called from inifinite TimerEvent function in my Main Class
public function mainLoop(TimerEvent:Event):void
{
for (var i:uint=0; i<players; i++) player[i].Move();
}
It seems to be working well at the beginning but after some time CPU usage raises dramatically and game becomes unplayble. I belivie it's caused by my shape (line) getting more and more complex.
Is there some reasonable way to optimize it? Can I somehow draw a line in less consuming way? I tried to convert it to bitmap but that looked ugly and didn't really help.
Thanks and cheers!
You're right in assuming that your slowdown in coming from your shape code - vector data is redrawn every frame in flash, so the more complex it is, the longer it takes to draw. Some solutions, depending on what you're willing to do:
Your fidelity is way to high - you're calling your Move function every frame; you probably don't need it that high, as the difference in movement since the last frame is probably less than a pixel. Sample your position every X frames instead (where X is the level of fidelity your willing to go down to). This can be done with a simple counter in the enter frame
If you don't need to keep the entire history of the drawing, put all your points into an array/vector, culling the length as needed. Then every frame, do a line.graphics.clear() and just draw the points in the array
If you do need to keep the entire history, then keep a BitmapData under your line (e.g. the size of the stage). Every so often, draw the line to the BitmapData and call clear() on your graphics to get right of the vector data. You shouldn't notice any loss in quality (set smoothing to true when you're drawing)
I'd do the first point in any case, then choose between the second and third, depending on your use case
Expanding my comment, try something like this:
public class Player extends Shape
{
public var X,Y,v,vX,vY,size,a,r:Number;
public var k,counter,leftKey,rightKey,_color:uint;
public var line:Shape = new Shape();
public var dot:Shape = new Shape();
/*...*/
/*constructor, giving values to variables here, not important*/
/*...*/
public function Player(){
//draw shapes
graphics.lineStyle(1);
graphics.drawCircle(0,0,r);
graphics.lineTo(size,0);//can't test this now, but make sure the line is in the same direction as rotation 0 (guessing it's to the right)
//your other constructor code here
}
public function Move():void
{
a=a+0.05*k;
//player controls k parameter k=0 by default
//k=1 when right key pressed
//k=-1 when left key pressed
vX=v*Math.cos(a);
vY=v*Math.sin(a);
X=X+vX;
Y=Y+vY;
x=X+vX*size/(2*v);
y=Y+vY*size/(2*v);
rotation = a * 57.2957795;//quick'n'dirty radians to degrees
}
and if you want to draw the trails you can try something like this:
var canvas:Bitmap = new BitmapData(state.stageWidth,stage.stageHeight,true,0xFF000000);
var ct:ColorTransform = new ColorTransform(1,1,1,.1);
public function mainLoop(TimerEvent:Event):void
{
for (var i:uint=0; i<players; i++) {
player[i].Move();
canvas.draw(player[i],player[i].transform.concatenatedMatrix,ct);
}
}
Hope this makes sense.
Update
Here is a standalone code snippet to illustrate the idea above(which has untested syntax):
package {
import flash.display.Bitmap;
import flash.geom.ColorTransform;
import flash.display.BitmapData;
import flash.text.TextField;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.utils.Dictionary;
import flash.display.Sprite;
public class PlayerMoveTest extends Sprite {
private var keys:Dictionary = new Dictionary();
private var players:Vector.<Player> = new Vector.<Player>();
private var trails:BitmapData;
private var fade:ColorTransform = new ColorTransform(1,1,1,.1);
public function PlayerMoveTest() {
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event):void{
trails = new BitmapData(stage.stageWidth,stage.stageHeight,true,0x00FFFFFF);
addChild(new Bitmap(trails));
for(var i:int = 0 ; i < 2; i++){
var p:Player = addChild(new Player(10+i*10)) as Player;
p.x = stage.stageWidth * .5;
p.y = stage.stageHeight * .5;
players.push(p);
}
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onKeyUp);
stage.addEventListener(Event.ENTER_FRAME,update);
}
private function onKeyDown(e:KeyboardEvent):void{
keys[e.keyCode] = true;
}
private function onKeyUp(e:KeyboardEvent):void{
keys[e.keyCode] = null;
}
private function update(e:Event):void{
if(keys[Keyboard.LEFT] != undefined) {players[0].a -= .05;players[1].a += .05;}
if(keys[Keyboard.RIGHT] != undefined) {players[0].a += .05;players[1].a -= .05;}
if(keys[Keyboard.UP] != undefined) {players[0].s += .15;players[1].s -= .15;}
if(keys[Keyboard.DOWN] != undefined) {players[0].s -= .15;players[0].s += .15;}
for(var i:int = 0 ; i < players.length; i++) {
players[i].move();
trails.draw(players[i],players[i].transform.concatenatedMatrix,fade);
}
}
}
}
import flash.display.*;
class Player extends Shape{
public var vx:Number,vy:Number,a:Number,size:Number,r:Number,s:Number;
public function Player(size:Number){
init(size);
}
private function init(size:Number):void{
vx = vy = a = s = 0;
this.size = size;
this.r = size * .25;
graphics.lineStyle(1);
graphics.drawCircle(0,0,r);
graphics.lineTo(size,0);
}
public function move():void{
rotation = a * 57.2957795;
vx = Math.cos(a) * s;
vy = Math.sin(a) * s;
x += vx;
y += vy;
if(x < 0) x = 0;
if(y < 0) y = 0;
if(x > stage.stageWidth) x = stage.stageWidth-width;
if(y > stage.stageHeight) y = stage.stageHeight-height;
}
}
You can test this code here and here's a preview:
Use the arrow keys to drive(up arrow accelerates, left/right steer).
The first player is the smaller one, having the correct controls, the other is simply mirroring the previous controls)

Falling object and repeating in a loop ( Action Script 3.0)

I am trying to make a symbol (made a special class for it) to fall continuously until a timer reaches 0. Also I would like this rock to repeat and show in random places on the stage. I can't figure out how to code that. Pretty much I am still a newbie to action script 3.0.
This is what I have so far:
The Main
package {
import flash.display.Sprite;
import Game_Objects.TinyBird;
import Game_Objects.Rock;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Main extends Sprite {
private var userbird:TinyBird;
private var obstacle:Rock;
//containers.
private var obstacleContainer:Sprite = new Sprite();
//timers.
private var enemySpawn:Timer;
public function Main() {
// The main code of the game
// The Bird has to avoid rocks by moving left and right
// Obstacles = rocks
// The Birdie will be controlled by the keyboard
// As long as Birdie alive=1 the loop will continue until alive=0 (where 1=true and 0=false) or timer reaches 0
// if the bird will hit an object it will die (collision detection)
this.userbird = new TinyBird(stage.stageWidth/2, stage.stageHeight-20);
this.obstacle = new Rock;
obstacleContainer.addChild(obstacle);
addChild(userbird);
stage.addEventListener(Event.ENTER_FRAME, startpulse)
stage.addEventListener(KeyboardEvent.KEY_DOWN, keymove);
// event to count the passed rocks in order to set score.
stage.addEventListener(obstacle.KILLED, deadEnemy);
}
private function startpulse(evt:Event):void {
// makes the bird pulsate
this.userbird.pulse_animation();
}
private function keymove(evt:KeyboardEvent):void {
// the keyboard movements for the bird
// if leftArrow = pressed -> tiny bird will move left. Else if rightArrow = pressed -> tiny bird will move right
if (evt.keyCode == Keyboard.LEFT) {
this.userbird.left();
} else if (evt.keyCode == Keyboard.RIGHT) {
this.userbird.right();
}
}
// The obstacle objects are going to fall randomly
private function spawn(e:TimerEvent):void {
// calculate a random starting position
var xPos:Number = Math.floor(Math.random()*stage.stageWidth);
// calculate a random speed between 2 and 6
var speed:Number = Math.floor(Math.random()*4+2) ;
// create the new rock
var enemy:Rock = new Rock(xPos, 42, speed, stage.stageWidth, stage.stageHeight);
// add it to the container
this.obstacleContainer.addChild(enemy);
enemy.name = "Rock " + Rock.createdCount;
}
private function deadEnemy(e:Event) {
var obj:Rock = (e.object as Rock);
this.objectContainer.removeChild(obj)
}
}
}
And this is the rock symbol:
package Game_Objects {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.utils.Timer ;
import flash.events.TimerEvent ;
public class Rock extends Sprite {
// The Rock is the obstacle that, if colided with the bird, the game is over.
// public function properties
static public var _createdCount:int = 0;
// private function properties
private var speed:Number;
private var _score:Number = 4;
private var scoreCounter:Number = 0;
// Classes methods
public static function get createdCount():int {
return _createdCount;
}
// instance methods
// Initialization
public function Rock(x:Number, y:Number, s:Number, maxX:Number = 0, maxY:Number = 0) {
// set the speed
this.speed = s;
// If the rock goes off the stage, then
if (x < this.width/2) {
// Put on at left
this.x = this.width/2;
// else if x would put the rocks beyond right side of the stage then
} else if (x > maxX - this.width/2) {
// Position the rock on the stage.
this.x = maxX-this.width/2;
} else {
// Otherwise position at x
this.x = x;
}
// same for Y
if (y < this.height/2) {
this.y = this.height/2;
} else if (y > maxY - this.height/2) {
this.y = maxY-this.height/2;
} else {
this.y = y;
}
// Creating the animation loop in order to repeat the falling motion of the rocks.
configUI();
this.addEventListener(Event.ENTER_FRAME, drop);
// adding a boolean type of loop, taken from
// http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001283.html#374074
this.cacheAsBitmap = true;
// Add 1 to the public var in order to keep track of the rocks
_createdCount++;
}
// protected function
protected function configUI():void {
}
// private function
private function drop(e:Event) {
// in order to show the dropping effect
// The falling of the rocks
this.y += this.speed;
// if at bottom of stage then
if (this.y-this.height >= stage.stageHeight) {
// Set score to +1 as reward for not hitting the rock.
this._score++;
// Kill the rock that has reached the bottom of the stage
}
}
}
}

Bullets will only fire to the right?

I'm making a flash game for my course at college, I have been following a tutorial but been spinning it off for my own sake. One wall I hit is that when I fire a bullet, it will only fire to the right, with a little movement up or down, I have been trying to fix it for a while but nothing is happening and nothing works.
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Wizard extends MovieClip {
private var dx:Number;
private var dy:Number;
private var Bulletspeed:int;
public var Angle:Number;
public var newAngle:Number;
var shotCoolDown:int;
const MAX_COOLDOWN=20;
public function Wizard() {
//constructor
//Shot cool down
shotCoolDown=MAX_COOLDOWN;
addEventListener(Event.ENTER_FRAME, update);
//set up an event listener for when the turret is added to stage
addEventListener(Event.ADDED_TO_STAGE, initialise);
}
function initialise(e:Event) {
//reduce shot cool down by one
shotCoolDown=shotCoolDown-1;
//add a click listener to the stage
stage.addEventListener(MouseEvent.CLICK, fire);
}
function fire(m:MouseEvent) {
//Able to shoot
if (shotCoolDown<=0) {
//resets cool down
shotCoolDown=MAX_COOLDOWN;
//spawn bullet
var B = new Bullet();
//set position and rotation of the bullet
B.rotation=rotation;
B.x=x;
B.y=y;
//add the bullet the the wizard
parent.addChild(B);
}
}
function update():void {
//Shot cool down
shotCoolDown--;
//Make the Wizard face the mouse
if (parent!=null) {
dx=stage.mouseX-this.x;
dy=stage.mouseY-this.y;
Math.abs(dx);
Math.abs(dy);
var Angle=Math.atan2(dy,dx);
var newAngle = Angle * (180 / Math.PI);
if ((0 < newAngle) && (newAngle <= 90)) {
gotoAndPlay("Right");
} else if ((90 < newAngle) && (newAngle <= 180)) {
gotoAndPlay("Down");
} else if ((-180 < newAngle) && (newAngle <= -90)) {
gotoAndPlay("Left");
} else if ((-90 < newAngle) && (newAngle <= 0)) {
gotoAndPlay("Up");
}
this.rotation=Angle;
}
}
}
}
That's the code for my player class, with things such as bullets firing and what not. I think I know the problem, I need to link it to the rest of the Wizard update. But I don't know how, here is my bullet class if needed.
package {
import flash.display.Sprite;
import flash.events.Event;
public class Bullet extends Sprite {
private var speed:int;
private var myCharacter:Wizard;
public function Bullet() {
//constructor
speed = 10;
addEventListener(Event.ENTER_FRAME, update);
}
function update (e:Event) {
//Move in the direction the bullet is facing
x=x+Math.cos(rotation/180*Math.PI)*speed;
y=y+Math.sin(rotation/180*Math.PI)*speed;
//Clears bullet once it leaves the stage
if (x<0 || x>500 || y<0 || y>500) {
//removes the update listner
removeEventListener(Event.ENTER_FRAME, update);
parent.removeChild(this);
}
}
}
}
You're setting the Wizard's rotation to Angle, which is in radians; the rotation is then passed on to the Bullet, which expects its rotation to be in degrees. It's probably better to set this.rotation=newAngle; at the end of update(), as the UIComponent class expects that value in degrees and uses it for rotating its drawing.

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