[haXe] Animation performace issues
Thomas Reilly
treilly at adobe.com
Sat Aug 25 00:35:27 CEST 2007
This probably won't help you but there's a profiling API built into the
new Debugger player. Flex Builder has a nice UI built on it. If
anyones interested in using the (soon to be documented) API to build a
profiler I'd be the one to talk to. The architecture would allow it to
be implemented entirely in haXe believe it or not.
-----Original Message-----
From: haxe-bounces at lists.motion-twin.com
[mailto:haxe-bounces at lists.motion-twin.com] On Behalf Of Jaevla Faenskap
Sent: Friday, August 24, 2007 1:31 PM
To: haxe at lists.motion-twin.com
Subject: [haXe] Animation performace issues
Hi all,
I'm totally new to flash and actionscript development, so I might be way
off here.. However I was hoping you could help me a bit with a few
issues I'm having.
This might be a little more general actionscript than haxe specifically,
I'm not sure - I've only used haxe so far (and I think it's a great
project!).
It might be a little long, but I decided to include all my code (it's
(almost) a small game). Let me know if I should have posted it some
other way. I am targeting Flash9 (AS3).
Anyway, on to the questions.. The problems I am having is with
animation. All the games I have seen have really smooth movement. Mine
not so. I'm using a timer for updating positions (so it will run at the
same speed independent of framerate), and I use an updateafterevent().
But still when I move my player-controlled clip I see a lot of
stuttering - no matter what framerate I run it on. What's the magic
trick I am missing?
Also, if I let the "game" run, it just keeps on slowing down. I guess
that this is because of my shots not beeing properly deleted somehow
when they move out of the screen - even tough I set them to null. I've
also tried Reflect.deleteField() - to no avail (though I couldn't find
any documentation on what the string was supposed to be?).
I hope I'm not asking too much, and that someone with the knowledge and
kindness will step up?
Cheers
--- CODE FOLLOWS ---
import flash.display.StageScaleMode;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.geom.ColorTransform;
import flash.geom.Rectangle;
import flash.Lib;
import flash.net.ObjectEncoding;
import flash.ui.ContextMenu;
import flash.utils.Timer;
import flash.display.BlendMode;
import haxe.Timer;
class Mob extends MovieClip
{
public var direction:String;
public function new()
{
super();
this.graphics.beginFill(0x555555);
this.graphics.drawCircle(32,32,32);
this.graphics.endFill();
direction = "RIGHT";
}
}
class Shot extends MovieClip
{
public var speed:UInt;
public function new()
{
super();
this.graphics.beginFill(0xff0000);
this.graphics.drawCircle(8,8,8);
this.graphics.endFill();
this.speed = 4;
}
}
class MobShot extends MovieClip
{
public var speed:UInt;
public function new()
{
super();
this.graphics.beginFill(0xff0000);
this.graphics.drawRect(0,0,3,6);
this.graphics.endFill();
this.speed = 2;
}
}
class Spaceship extends MovieClip
{
public var moveleft:Bool;
public var moveright:Bool;
public var speed:UInt;
public function new()
{
super();
this.graphics.beginFill(0x000000);
this.graphics.moveTo(31,0);
this.graphics.lineTo(33,0);
this.graphics.lineTo(33,10);
this.graphics.lineTo(64,64);
this.graphics.lineTo(0,64);
this.graphics.lineTo(31,10);
this.graphics.lineTo(31,0);
this.graphics.endFill();
this.moveleft = false;
this.moveright = false;
this.speed = 3;
}
}
class App
{
var player:Spaceship;
var shots:Array<Shot>;
var mobs:Array<Mob>;
var mobshots:Array<MobShot>;
var updatetimer:Timer;
var canvas:Sprite;
var shottimer:UInt;
public function new(w:Int, h:Int)
{
// Set up the board
canvas = new Sprite();
canvas.graphics.beginFill( 0xffffffff, 0x0 );
canvas.graphics.drawRect( 0, 0, w, h );
canvas.graphics.endFill();
Lib.current.addChild(canvas);
// Set up the pieces on the board
player = new Spaceship();
player.x = ( w / 2 ) - ( player.width / 2);
player.y = h - player.height - ( h / 20 );
shots = new Array<Shot>();
shottimer = 0;
mobs = new Array<Mob>();
mobshots = new Array<MobShot>();
var mob1 = new Mob();
mobs.push(mob1);
canvas.addChild(player);
for ( i in mobs )
{
canvas.addChild( i );
}
// Handlers
updatetimer = new Timer( 10, 0 ); // T=10ms => f=
updatetimer.addEventListener(TimerEvent.TIMER, update);
updatetimer.stop();
Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN,
keyhandler);
Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP,
keyhandler);
}
public function start()
{
updatetimer.start();
}
public function stop()
{
updatetimer.stop();
}
public function pause()
{
if ( updatetimer.running == true ) updatetimer.stop();
else updatetimer.start();
}
private function keyhandler(evt:KeyboardEvent)
{
switch( evt.keyCode )
{
case 37:
// left
if ( evt.type == KeyboardEvent.KEY_DOWN ) player.moveleft =
true;
else if ( evt.type == KeyboardEvent.KEY_UP ) player.moveleft =
false;
case 39:
// right
if ( evt.type == KeyboardEvent.KEY_DOWN ) player.moveright =
true;
else if ( evt.type == KeyboardEvent.KEY_UP ) player.moveright =
false;
case 32:
// space, shoot
if ( evt.type == KeyboardEvent.KEY_DOWN && shottimer == 0)
{
shottimer = 30;
var newshot = new Shot();
newshot.x = ( player.x + ( player.width / 2) ) - (
newshot.width / 2);
newshot.y = player.y - 1;
this.canvas.addChild( newshot );
this.shots.push( newshot );
}
}
}
private function update(evt:TimerEvent)
{
// Move player
if ( player.moveleft == true )
{
player.x -= player.speed;
if ( player.x < 0 ) player.x = 0;
}
if ( player.moveright == true )
{
var xmax = canvas.width - player.width;
var newx = player.x + player.speed;
if ( newx > xmax ) player.x = xmax;
else player.x = newx;
}
// Move shots
if ( shottimer >= 1 ) shottimer--;
for ( s in this.shots )
{
s.y -= s.speed;
if ( s.y < (0-s.height) )
{
this.canvas.removeChild( s );
this.shots.remove( s );
s = null;
Reflect.deleteField(s, "");
}
}
// Move mobs
for ( i in this.mobs )
{
// Shoot?
if ( Math.random() < 0.02 )
{
var ms = new MobShot();
ms.x = i.x + ( i.width / 2 ) - ( ms.width / 2 );
ms.y = i.y + i.height + 1;
this.mobshots.push( ms );
this.canvas.addChild( ms );
}
// Movement
switch( i.direction )
{
case "LEFT":
i.x--;
if ( i.x <= 0 )
{
i.x = 0;
i.direction = "RIGHT";
}
case "RIGHT":
i.x++;
var xmax = canvas.width - i.width;
if ( i.x >= xmax )
{
i.x = xmax;
i.direction = "LEFT";
}
default:
}
}
// Move mobshots
for ( msh in this.mobshots )
{
msh.y += msh.speed;
if ( msh.y > canvas.height + msh.height )
{
this.canvas.removeChild( msh );
this.mobshots.remove( msh );
msh = null;
Reflect.deleteField(msh, "");
}
}
// Check for collisions
// Playershot - Mob
for ( sh in this.shots )
{
for ( mo in this.mobs )
{
var col = this.checkForCollision( sh, mo, 0 );
//if ( col != null ) trace("HIT!");
}
}
// Mobshot - Player
for ( msho in this.mobshots )
{
var col = this.checkForCollision( msho, player, 0);
//if ( col != null ) trace ("BANG, YOU'RE DEAD!");
}
// Update
evt.updateAfterEvent();
}
private function checkForCollision( p1:MovieClip, p2:MovieClip,
alphatolerance:Int ) : Rectangle
{
var bounds1 = p1.getBounds( Lib.current );
var bounds2 = p2.getBounds( Lib.current );
if ( ( ( bounds1.right < bounds2.left ) || ( bounds2.right <
bounds1.left ) ) || ( ( bounds1.bottom < bounds2.top) || (
bounds2.bottom < bounds1.top ) ) )
{
return null;
}
var bounds = new Rectangle();
bounds.left = Math.max( bounds1.left, bounds2.left );
bounds.right = Math.min( bounds1.right, bounds2.right );
bounds.top = Math.max( bounds1.top, bounds2.top );
bounds.bottom = Math.min( bounds1.bottom, bounds2.bottom );
var img:BitmapData = new BitmapData( cast( bounds.width,Int ), cast(
bounds.height,Int ), false );
var mat = p1.transform.concatenatedMatrix;
mat.tx -= bounds.left;
mat.ty -= bounds.top;
img.draw( p1, mat, new ColorTransform( 1, 1, 1, 1, 255, -255, -255,
alphatolerance ) );
mat = p2.transform.concatenatedMatrix;
mat.tx -= bounds.left;
mat.ty -= bounds.top;
img.draw( p2, mat, new ColorTransform( 1, 1, 1, 1, 255, 255, 255,
alphatolerance ), BlendMode.DIFFERENCE );
var intersection:Rectangle = img.getColorBoundsRect( 0xFFFFFFFF,
0xFF00FFFF );
if ( intersection.width == 0 ) { return null; }
intersection.x += bounds.left;
intersection.y += bounds.top;
return intersection;
}
}
class Main
{
public function new()
{
Lib.current.addEventListener( Event.ENTER_FRAME, firstframe );
}
static function main()
{
Lib.current.stage.scaleMode = StageScaleMode.NO_SCALE;
var self = new Main();
}
public function firstframe(evt:Event)
{
Lib.current.removeEventListener( Event.ENTER_FRAME, firstframe );
var app = new App( Lib.current.stage.stageWidth,
Lib.current.stage.stageHeight );
app.start();
}
}
--
We've Got Your Name at http://www.mail.com !
Get a FREE E-mail Account Today - Choose From 100+ Domains
--
haXe - an open source web programming language
http://haxe.org
More information about the Haxe
mailing list