3
votes

I'm trying to make a basic game in Flash and Actionscript 3.

As of now, I've been working on a smooth game loop but ran into problems. I tried to implement a fixed time-stamp loop seen: http://gafferongames.com/game-physics/fix-your-timestep/ and in Flixel.

The main issue that I have right now is that moving a simple object across the screen produces noticeable stuttering. I am aiming for a smoother experience but can't seem to figure out what the issue is.

The main loop is called on an Event.ENTER_FRAME at 60 fps.

These variables are instantiated first:

public var total:uint = 0;
public var fixedDT:Number = 1000.0/60.0; //Shoot for 60 FPS in MS
public var accumulator:int = 0;
public var maxAccumulation:uint =  120;

This is the main loop on every ENTER_FRAME:

//Most times are in ms
var mark:uint = getTimer();
var elapsedMS:uint = mark-total;
total = mark;

accumulator += elapsedMS;
if(accumulator > maxAccumulation){
    accumulator = maxAccumulation;
}

while(accumulator > fixedDT){
    step();
    accumulator = accumulator - fixedDT;
}

//Convert from ms to secs. to interpolate graphics drawing (linear interpolation)
renderGameState(accumulator/fixedDT/1000.0);

step() is just updating every game-object with the fixed delta-time. The game object update function is simple and is as follows:

//First part is just updating the previous position for graphic interpolation
position.x += velocity.x*deltaTime;
position.y +=  velocity.y*deltaTime;

For rendering, I am just drawing bitmap.copyPixel. The graphical interpolation I mentioned is using a basic linear interpolation function that uses prev./curr. position and deltaTime to calculate the drawX/Y.

 public function render(bitmap:BitmapData, deltaTime:Number, xOff:Number, yOff:Number):void{
        this.x = lerp(prevPosition.x,position.x,deltaTime) + xOff;
        this.y = lerp(prevPosition.y,position.y,deltaTime) + yOff;

        bitmap.copyPixels(bitmapData, bitmapData.rect,new Point(this.x,this.y),null,null,true);
    }


 public function lerp(v0:Number, v1:Number, t:Number):Number {
     return (1-t)*v0 + t*v1;
 }

However, there is noticeable stuttering appearing. In the image below, I don't clear the bitmap before drawing to it. You should be able to see that there's a lot of variation between the spacing of circles rendered, and sometimes it's extremely noticeable.

http://i.stack.imgur.com/00c39.png

I would appreciate any help at all, thanks!

1
It's been awhile since I've programmed in AS3 but I was looking over your code and noticed renderGameState(accumulator/fixedDT/1000.0); is renderGameState(int/Number/Number), perhaps that has something to do with it. (int/Number/Number) might pass an int parameter rather than a NumberJonny Henly
I feel like AS3 will cast that input as a Number, but to make sure, I casted the accumulator to a Number as well. However, it still has noticeable stuttering. Thanks for your time though.user3591615
I'm not sure you've implemented correctly The final touch section. You should run debugger and check what's going on, as there's no magic way to tell you what it is :) I think the reason is that it's normal that sometimes there are more steps, because of the extra time left in the previous steps. Check if your linear interpolation works as expected - I think there's the problem.Andrey Popov

1 Answers

0
votes

I don't know if this helps but here's the code I use to fix my time step.

private var _pause          :Boolean;
private var _prevTimeMS     :int;
private var _simulationTime :Number;

override public function update():void 
{
    super.update();

    if (!_pause)
    {
        var curTimeMS:uint  = getTimer();
        if (curTimeMS == _prevTimeMS)
        {
            return;
        }
        var deltaTime:Number    = (curTimeMS - _prevTimeMS) / 1000;
        if (deltaTime > 0.05)
        {
            deltaTime = 0.05;
        }
        _prevTimeMS     = curTimeMS;
        _simulationTime += deltaTime;
        while (space.elapsedTime < _simulationTime)
        {
            // Your game step goes here.
            _space.step((stage.frameRate > 0) ? (1 / stage.frameRate) : (1 / 60));
        }
    }
}

(Originally taken from a Nape Physics sample)