manabk
manabk

Reputation: 55

Actionscript 3 smooth Sprite movement

I move a Sprite across the screen using the keyboard, at a rate of 10 pixels/ENTER_FRAME event fire. The issue is that, when it moves, you can see it being "redrawn" every 10 pixels, which makes it hard to look at. I haven't seen this in other Flash games.

If you look closely, you can also see this here (although at a much lower scale): http://kirill-poletaev.blogspot.com/2010/07/smooth-character-movement-using-as3.html

I want to get rid of that effect, any ideas?


If the player is at a distance of ... from the screen edge, it stops moving (by moving in the opposite direction), and the BG starts scrolling (the same visual effect can be seen). Music in playing in the background, a minimap is updated with the player's position.


    private function updater(e:Event):void
        {
            if(up && GlobalVars.vars.upPossible)
            {
                cont.y-=unit;
                setu(); // Player graphics state
            }
            else if(down && GlobalVars.vars.downPossible)
                 {
                     cont.y+=unit;
                     setd(); // Player graphics state
                 }
            else if(left && GlobalVars.vars.leftPossible)
                 {
                    cont.x-=unit;
                    setl(); // Player graphics state
                 }
            else if(right && GlobalVars.vars.rightPossible)
                 {
                     cont.x+=unit;
                     setr(); // Player graphics state
                 }
            else
                 {
                     ups.visible=false; downs.visible=false; rights.visible=false;
                     lefts.visible=false; normals.visible=true; // Player graphics state
                     GlobalVars.vars.scXr=0; GlobalVars.vars.scYu=0; GlobalVars.vars.scXl=0;
                     GlobalVars.vars.scYd=0; cont.x=int(cont.x); cont.y=int(cont.y); //Someone from the Kongregate.com forums suggested this, no visible effect 
                 }
            if((cont.x=GlobalVars.vars.maxX))
            {
                if(cont.x=GlobalVars.vars.maxX && right && GlobalVars.vars.canScrollR) GlobalVars.vars.scXr=1, cont.x-=unit, setr();
            }
            else GlobalVars.vars.scXl=0, GlobalVars.vars.scXr=0; //BG Scrolling
            if((cont.y=stage.stageHeight*7.3/10))
            {
                if(cont.y=stage.stageHeight*7.3/10 && down && GlobalVars.vars.canScrollD) GlobalVars.vars.scYd=1, cont.y-=unit, setd();
            }
            else GlobalVars.vars.scYu=0, GlobalVars.vars.scYd=0; //BG Scrolling
            if(cont.y>=stage.stageHeight*7.3/10 && cont.x>=GlobalVars.vars.maxX)  GlobalVars.vars.minimapTr=1;
            else  GlobalVars.vars.minimapTr=0;
            if(cont.y-unitGlobalVars.vars.sH-cont.height-3.1) GlobalVars.vars.downPossible=false;
            else GlobalVars.vars.downPossible=true;
            if(cont.x-unitGlobalVars.vars.sW-cont.width-3.5) GlobalVars.vars.rightPossible=false;
            else GlobalVars.vars.rightPossible=true;
            GlobalVars.vars.plX=cont.x; //for minimap
            GlobalVars.vars.plY=cont.y;

Also, key listener functions:



stage.addEventListener(KeyboardEvent.KEY_DOWN, keyD, false, 0, true);
stage.addEventListener(KeyboardEvent.KEY_UP, keyU, false, 0, true);

private function keyD(e:KeyboardEvent):void
    {
        if(e.keyCode==37 || e.keyCode==65) left=true;
        if(e.keyCode==38 || e.keyCode==87) up=true;
        if(e.keyCode==39 || e.keyCode==68) right=true;
        if(e.keyCode==40 || e.keyCode==83) down=true;
    }
private function keyU(e:KeyboardEvent):void
    {
        if(e.keyCode==37 || e.keyCode==65) left=false;
        if(e.keyCode==38 || e.keyCode==87) up=false;
        if(e.keyCode==39 || e.keyCode==68) right=false;
        if(e.keyCode==40 || e.keyCode==83) down=false;
    }

I've encountered some improvement by increasing the FPS to 120, and decreasing the step to 4, but it's still there. I'm fairly sure it's not a performance issue, but, rather, a movement method fault.

Upvotes: 1

Views: 2631

Answers (3)

ido
ido

Reputation: 811

I love Tweenlite, it's great for pre-defined effects. It isn't for the core of your game though so I'd use Tweenlite for UI effects but barely for ingame movements responding to user controls.

I think around 24-30 fps for games is great, that's how I set all my games. I think abit you're picky, but perhaps what you're missing is a bit of edge: a smooth start and end for the movement. In most platformers I have a similar mechanic:

You want the start of the movement to start slow, reach the normal (max) speed you define and when the player lets go of a button, it slows down back to 0. This means you need to check the speed on enter frame regardless of the button triggers (they increment the speed but aren't the only condition to change speed and move the object)

enterframe loop:
  //check for each direction:
  if up, y_speed++
  else if down, y_speed--
  else if right, x_speed++
  else if left, x_speed--
  else // perform a decrease:
    y_speed *= .8
    x_speed *= .8
  // make sure we aren't past the max speed
  if x_speed>max_x_speed
    x_speed = max_x_speed
  etc. else other direction and y_speed
  // now apply the movement
  object.x += x_speed
  object.y += y_speed
  // remove the enterframe for better performance
  if math.abs(x_speed)<.1 && math.abs(y_speed)<.1
    // remove enterframe for movement here, add it again next time we know we have movement (button downs related to the movement, etc.)

I would implement this in your code but your code is too crowded. Anyway otherwise, most games with these simple controls are working just like your application does.

Upvotes: 0

Manish
Manish

Reputation: 3522

A couple of suggestions:

  1. Increase the frame rate
  2. Use a tween library (e.g. GTween) with some easing effect.

Basically, if you want the object to jump 10px to the right, don't just move it right away, let it animate to its new position with some easing effect. Additionally, if the object is still moving and the key is pressed again, you probably want to accelerate the movement a bit (but only up to a point!).

Upvotes: 2

Jacksonkr
Jacksonkr

Reputation: 32247

I think you're asking how to make it more smooth. Well:

If you change the movement 2px per frame, then you'll have a much smoother experience. However, the movement will see very slow. To combat this, you just increase the frame rate of your swf. I believe the maximum is 120 frames, but that should be more than enough.

Upvotes: 0

Related Questions