Expanding circle animation in AS3 - actionscript-3

I am using an array to create an expanding circle animation in Action Script 3. Drawing a new circle element and deleting the previous one, all led by a timer. The code, at present, is drawing the new circle element but not deleting the previous one. The output, at present,is a bunch of 30 circles. Please help.
The following is the class for creating the circles:
package
{
import flash.display.Sprite;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.Shape;
public class SoundWave2 extends Sprite
{
public function SoundWave2()
{
var wavearray:Array = new Array();
var waveTimer:Timer = new Timer(1000, 30);
var i:int = new int(0);
waveTimer.addEventListener(TimerEvent.TIMER, init);
waveTimer.start();
function init():void
{
if (i == 0)
{
wavearray[i] = graphics.lineStyle(1, 0x0000FF);
wavearray[i] = graphics.drawCircle(0, 0, 30);
i += 1;
trace(i);
}
else
{
wavearray[i] = graphics.lineStyle(1, 0x0000FF);
wavearray[i] = graphics.drawCircle(0, 0, 30 + i);
wavearray.removeAt(i-1);
i += 1;
trace(i);
}
}
}
}
}

waveArray.removeAt...
That may or may not remove it from the array but doesn't remove it from the stage
Instead of using an array of circles, just use the same circle and redraw it being sure to call the clear function first.
myCircle.graphics.clear();
myCircle.graphics.beginFill...
...drawCircle(...);
That's just some pseudo code but you get the idea.
edit
As you asked for additional info on removing all array elements from the stage:
private function destroyArray(arr:Array):void{
for (var i:int = 0; i < arr.length; i++){
arr[i].parent.removeChild[arr[i]];
}
}
Then for any array you want to take off the stage, do
destroyArray(yourArray);
but use your desired array in place of "yourArray", obviously.

Related

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

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)

ActionScript 3, handling MOUSE_UP outside stage

I'm new to ActionScript 3.0. I tried a tutorial at http://www.senocular.com/flash/tutorials/as3withmxmlc/ . The demo program animates a ball and allows it to be dragged.
There was a problem with the program as written. When you drag the mouse outside the stage and release the mouse button, the ball wouldn't get the MOUSE_UP event. The code, therefore would never call stopDrag(). I searched stackoverflow for suggestions, and one suggestion was to listen to MOUSE_UP with the stage as well as the ball and add some logic for dealing with it.
I added some code to do this. I also refactored the program as written because it was pretty disorganized. Here's what I have now:
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
public class BallToss extends Sprite {
private var ball:TossableBall;
// mouse position at last call to trackMouseMvt()
private var lastMousePos:Point = new Point();
// delta mouse movement from frame L-1 to frame L, where L is last frame
private var lastDeltaMouse:Point = new Point();
public function BallToss() {
var stageBounds:Rectangle = new Rectangle(0, 0, stage.stageWidth,
stage.stageHeight);
ball = new TossableBall(50, stageBounds);
ball.x = stageBounds.width/2;
ball.y = stageBounds.height/2;
addChild(ball);
ball.addEventListener(MouseEvent.MOUSE_DOWN, grabBall);
// however I order the next two calls to addEventListener(), it seems
// that the ball's MOUSE_UP gets handled before the stage's MOUSE_UP
stage.addEventListener(MouseEvent.MOUSE_UP, handleStageMouseUp);
ball.addEventListener(MouseEvent.MOUSE_UP, releaseBall);
// initialize 'lastMousePos' and set up 'trackMouseMvt' to be called on
// every frame
lastMousePos = new Point(mouseX, mouseY);
ball.addEventListener(Event.ENTER_FRAME, trackMouseMvt);
}
private function grabBall(evt:MouseEvent):void {
trace("in grabBall");
// set ball 'glideVector' to (0,0) so it will stop moving
ball.setGlideVector(new Point(0,0));
ball.startDrag();
}
private function releaseBall(evt:MouseEvent):void {
trace("in releaseBall");
ball.stopDrag();
// set up the ball to glide at the rate of 'lastDeltaMouse'
ball.setGlideVector(lastDeltaMouse);
}
private function trackMouseMvt(evt:Event):void {
var currMouse:Point = new Point(mouseX, mouseY);
lastDeltaMouse = currMouse.subtract(lastMousePos);
lastMousePos = currMouse;
}
private function handleStageMouseUp(evt:Event):void {
trace("in handleStageMouseUp");
ball.stopDrag();
var stageBounds:Rectangle = new Rectangle(0, 0, stage.stageWidth,
stage.stageHeight);
if (ball.x > stageBounds.right - 0.5)
ball.x = stageBounds.right - 0.5;
else if (ball.x < 0)
ball.x = 0;
if (ball.y > stageBounds.bottom - 0.5)
ball.y = stageBounds.bottom - 0.5;
else if (ball.y < 0)
ball.y = 0;
}
}
}
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
class TossableBall extends Sprite {
private var stageBounds:Rectangle;
private var glideVector:Point = new Point();
private var friction:Number = .95;
public function TossableBall(size:Number, stageBoundsIn:Rectangle) {
stageBounds = stageBoundsIn;
graphics.lineStyle(1);
graphics.beginFill(0xFF8000);
graphics.drawCircle(0, 0, size/2);
addEventListener(Event.ENTER_FRAME, glide);
}
public function setGlideVector(glideVectorIn:Point):void {
glideVector = glideVectorIn;
}
private function glide(evt:Event):void {
x += glideVector.x;
y += glideVector.y;
var shapeBounds:Rectangle = getBounds(parent);
if (shapeBounds.left < stageBounds.left) {
glideVector.x = Math.abs(glideVector.x);
} else if (shapeBounds.right > stageBounds.right) {
glideVector.x = -Math.abs(glideVector.x);
}
if (shapeBounds.top < stageBounds.top) {
glideVector.y = Math.abs(glideVector.y);
} else if (shapeBounds.bottom > stageBounds.bottom) {
glideVector.y = -Math.abs(glideVector.y);
}
glideVector.x *= friction;
glideVector.y *= friction;
}
}
I don't like this code very much. The problem comes down to not being able to detect all the cases in one place. I would like to write something like this:
if (..ball and stage both got MOUSE_UP..) {
..handle it..;
else if (..only stage got MOUSE_UP..) {
..handle it..;
}
This logic would let me write more foolproof, simpler case handling and clearer logic. As things stand, there is a lot of complex behavior that emerges from this way of organizing the code.
The event listening model doesn't seem to make this possible. The response to events must happen individually, or must it? Is there a way to detect events that are "in the queue"?
Alternatively, I could avoid using startDrag(), i.e. avoid making the ball Sprite draggable, and have only the stage listen to MOUSE_UP, then handle all the drag logic myself. That would also let me better handle questions like where I want the ball to be positioned when the user drags outside the stage. I wonder if that is better overall.
To track object being dragged this works good for me:
ball.addEventListener(MouseEvent.MOUSE_DOWN, onBallMouseDown)
var _stage:Stage;
private function onBallMouseDown(e:MouseEvent):void
{
_stage = stage;
stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp)
stage.addEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove)
ball.startDrag();
}
private function onStageMouseMove(e:MouseEvent):void
{
// track ball coordinates
}
private function onStageMouseUp(e:MouseEvent):void
{
ball.stopDrag();
_stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp)
_stage.removeEventListener(MouseEvent.MOUSE_MOVE, onStageMouseMove)
}
What about that, after years of Flash programming only now have I discovered the joys of MouseEvent.RELEASE_OUTSIDE. No more ugly hacks needed.

Relative coordinate issue in AS3

I've edited the following code in order to let those green rectangles to follow my cursor which is customized by a small rectangle. But I've encountered several problems:
Although I haven't defined any coordinate in the separate class, but the size is abviously wrong in the stage when publish with only half size for the cursor coordinate.
The reset button cannot be activated, although I've tested well in the other code.
Here is the work I've published: http://neowudesign.com/hwu_ex04.html
The code on timeline
//hw//Creating a new cursor
newcursor.startDrag ("true");
Mouse.hide();
//hw//Creating a holder to hold the butterfly objects
var mothHolder = new Sprite();
addChild(mothHolder);
//hw//Creating seven moths at the beginning
makeMoths(7);
//hw//creating a function which can generate limited numbers of moths.
function makeMoths(MothsNumber:Number)
{
for (var i = 0; i < MothsNumber; i++)
{
newMoth = new Moth();
mothHolder.addChild(newMoth);
}
}
//hw//Set the reset button at the top for clicking, but it's failed to work;
//hw//Set the cursor back to the default one, and remove the custom one when hovering;
mothHolder.setChildIndex(reset,mothHolder.numChildren);
reset.addEventListener(MouseEvent.MOUSE_OVER, cursorchange);
function cursorchange(event:MouseEvent):void
{
Mouse.show();
newcursor.visible = false;
trace("alert!!");
}
//hw//creating a function of reset
reset.addEventListener(MouseEvent.CLICK, resetClick, false, 0, true);
function resetClick(evt:MouseEvent):void
{
removeChild(mothHolder);
mothHolder = new MovieClip();
addChild(mothHolder);
var numMoths:Number = Math.round(Math.random() * 6) + 1;
trace("Moths Numeber: "+ numMoths);
makeButterflies(numButterflies);
}
//hw//when the cursor leave the reset region, it turns back to the customized one
reset.addEventListener(MouseEvent.MOUSE_OUT, fl_MouseOutHandler);
function fl_MouseOutHandler(event:MouseEvent):void
{
removeEventListener(MouseEvent.MOUSE_OVER, cursorchange);
Mouse.hide();
newcursor.visible = true;
}
And the code for class "Moth" separately named "angle.as"
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
public class angle extends MovieClip {
var speed:Number = 8;
function angle() {
//letting every moth follow the moving of the cursor
addEventListener(Event.ENTER_FRAME,mothMove);
function mothMove(myEvent:Event) {
trace(mouseX);
trace(mouseY);
var angle:Number = Math.atan2(mouseY - y, mouseX - x);
x += Math.cos( angle ) * speed;
y += Math.sin( angle ) * speed;
}
}
}
}

How many images I need to have more fluently animation(Actionscript);

I have an onEnterFrame event:
package {
import flash.display.MovieClip;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.errors.IOError;
public class Ball extends MovieClip {
private var images:Array;
private var frames:Array;
var i:int = 0;
public function Ball(images:Array) {
this.images = images
frames = new Array();
images.forEach(function(current){
trace(current);
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadCompleted);
loader.load(new URLRequest(current));
});
}
private function onLoadCompleted(e:Event):void{
frames.push(e.currentTarget.content);
i++;
if(i == images.length)
{
ready();
}
}
private function ready():void{
i = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e:Event):void{
graphics.clear();
var bitmapData:BitmapData = frames[i].bitmapData;
graphics.beginBitmapFill(bitmapData, new Matrix(), false, true);
graphics.drawRect(0, 0, 100, 100);
graphics.endFill();
i++;
if(i == frames.length)
{
i = 0;
}
}
}
}
this class is getting an array of images and then animates it, and this is my main class:
public class Test extends MovieClip {
private var ball:Ball;
public function Test()
{
var images:Array = new Array();
for(var i:int = 1; i < 21; i++)
{
images.push('ball' + i.toString(10) + '.png');
}
ball = new Ball(images);
addChild(ball);
}
}
so as you see I am passing an array of 20 images, so the question is how many images I need to make a good animation, not roughly, but smoothly, creating every time a new image like ball1.png, ball2.png, ball3.png, ball4.png - I need to move the ball pixel by pixed to make a good animation? or is there a better way to do this?
It depends upon your perception and device and what you want to visualize from your content.
Please refer to this site:
http://www.mathworks.com/help/toolbox/mupad/plot/INTRO_FramesAndTimeRange.html
First thing I would consider is the framerate. There is no point in having more images as your framerate.
Basically for a smooth animation 30 fps should be ok. Also if you consider this for mobile devices I think you should not go higher than 30fps in order to have a good performance.
Regarding the number of images and how to animate them, I suggest you have a look into this game tutorial (Hungry Hero)
http://www.hsharma.com/tutorials/starting-with-starling-ep-3-sprite-sheets/
http://www.hsharma.com/tutorials/starting-with-starling-ep-5-parallax-background/