[haXe] Animation performace issues

Jaevla Faenskap harikke at email.com
Fri Aug 24 22:30:39 CEST 2007


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




More information about the Haxe mailing list