/// <summary>
/// 背景類
/// </summary>
TGameCycleBack = class(TLSGameAnimateSprite)
private
FSpeed, FPartX: TLSint;
FTick: Cardinal;
protected
procedure DoDraw; override;
procedure DoProcess(const MoveCount: TLSSingle); override;
public
constructor Create(const AParent: TLSGameSprite); override;
/// <summary>
/// 卷动速度
/// </summary>
property Speed: TLSint read FSpeed write FSpeed;
end;
在声明中 声明了
FSpeed 循环背景的移动速度
FPartX DoProcess中的移动距离
FTick 时间节点
procedure TGameCycleBack.DoDraw;
/// <summary>
/// 四舍五入
/// </summary>
function GameRound(AFloat: Single): TLSint;
begin
if AFloat - Trunc(AFloat) >= 0.5 then
Result := Trunc(AFloat) + 1
else
Result := Trunc(AFloat);
end;
var
bk: TLSGameTexture;
tick: Cardinal;
actualx: TLSint;
begin
{ (1000 div GameTimer.FPS) 一个DoPorcess所用的时间 }
tick := (GameTimer.GetTicks - FTick); //移动一次的时间间隔
actualx := FPartX + GameRound(FSpeed * Integer(tick) / (1000 div GameTimer.FPS)); //渲染时实际走的距离
if actualx >= GameDevice.WindowSize.X then
actualx := actualx - GameDevice.WindowSize.X;
bk := GameImages.Items[Self.PatternIndex];
if actualx > 0 then
begin
bk.BoundsRect := LSRect(GameDevice.WindowSize.X - actualx, 0, actualx, GameDevice.WindowSize.Y);
GameCanvas.UseTexture(bk);
GameCanvas.Draw2D(LSPoint(Self.X, Self.Y));
end;
bk.BoundsRect := LSRect(0, 0, GameDevice.WindowSize.X - actualx, GameDevice.WindowSize.Y);
GameCanvas.UseTexture(bk);
GameCanvas.Draw2D(LSPoint(actualx, Self.Y));
end;
因为DoDraw和DoProcess 的不同步所以 当DoDraw花费的时间长时。导致逻辑运算比绘画要多走, 这样就会出现画面卡。 为了让画面平滑滚动,在DoDraw中做时时的移动渲染, actualx 就是在时间渲染时真正走的距离。在每走一次DoDraw就计算一次,并绘画一次,比在DoProcess中处理移动在DoDraw处理渲染要显的更加平滑。
procedure TGameCycleBack.DoProcess(const MoveCount: TLSSingle);
begin
inherited;
FPartX := FPartX + FSpeed;
if FPartX >= GameDevice.WindowSize.X then
Dec(FPartX, GameDevice.WindowSize.X);
FTick := GameTimer.GetTicks;
end;