我正在尝试在Flash和Actionscript 3中制作基本游戏。
截至目前,我一直在努力进行顺畅的游戏循环,但遇到了问题。我试图实现一个固定的时间戳循环:http://gafferongames.com/game-physics/fix-your-timestep/和Flixel。
我现在面临的主要问题是在屏幕上移动一个简单的物体会产生明显的口吃。我的目标是获得更顺畅的体验,但似乎无法弄清楚问题是什么。
主循环在Event.ENTER_FRAME上以60 fps调用。
首先实例化这些变量:
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;
这是每个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()只是用固定的delta时间更新每个游戏对象。游戏对象更新功能很简单,如下:
//First part is just updating the previous position for graphic interpolation
position.x += velocity.x*deltaTime;
position.y += velocity.y*deltaTime;
对于渲染,我只是绘制bitmap.copyPixel。我提到的图形插值使用的是使用prev./curr的基本线性插值函数。 position和deltaTime来计算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;
}
然而,出现明显的口吃。在下图中,我不会在绘制之前清除位图。您应该能够看到渲染的圆的间距之间有很多变化,有时它非常明显。
http://i.stack.imgur.com/00c39.png
感谢任何帮助,谢谢!
答案 0 :(得分:0)
我不知道这是否有帮助,但这是我用来修复时间步骤的代码。
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));
}
}
}
(最初取自Nape Physics样本)