DEADSOFTWARE

anim: add static variant of TAnimationState
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Wed, 2 Feb 2022 19:42:01 +0000 (22:42 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 9 Jun 2023 08:23:22 +0000 (11:23 +0300)
src/game/g_textures.pas

index dcfbd1a045f2179aee421ad6b6c25ffeb96cf680..fbbbf9270f4cbb82dfc64726ec1b948a434f496d 100644 (file)
@@ -72,6 +72,47 @@ type
     property length: Integer read mLength;
   end;
 
+  TAnimState = record
+  private
+    mCounter: Byte; // Ñ÷åò÷èê îæèäàíèÿ ìåæäó êàäðàìè
+    mSpeed: Byte; // Âðåìÿ îæèäàíèÿ ìåæäó êàäðàìè
+    mCurrentFrame: Integer; // Òåêóùèé êàäð (íà÷èíàÿ ñ 0)
+    mLoop: Boolean; // Ïåðåõîäèòü íà ïåðâûé êàäð ïîñëå ïîñëåäíåãî?
+    mEnabled: Boolean; // Ðàáîòà ðàçðåøåíà?
+    mPlayed: Boolean; // Ïðîèãðàíà âñÿ õîòÿ áû ðàç?
+    mMinLength: Byte; // Îæèäàíèå ïîñëå ïðîèãðûâàíèÿ
+    mRevert: Boolean; // Ñìåíà êàäðîâ îáðàòíàÿ?
+
+    mLength: Integer;
+
+  public
+    constructor Create (aloop: Boolean; aspeed: Byte; len: Integer);
+    procedure Destroy;
+
+    procedure reset ();
+    procedure update ();
+    procedure enable ();
+    procedure disable ();
+    procedure revert (r: Boolean);
+
+    procedure saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
+    procedure loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
+
+    function totalFrames (): Integer; inline;
+
+  public
+    property played: Boolean read mPlayed;
+    property enabled: Boolean read mEnabled;
+    property isReverse: Boolean read mRevert;
+    property loop: Boolean read mLoop write mLoop;
+    property speed: Byte read mSpeed write mSpeed;
+    property minLength: Byte read mMinLength write mMinLength;
+    property currentFrame: Integer read mCurrentFrame write mCurrentFrame;
+    property currentCounter: Byte read mCounter write mCounter;
+    property counter: Byte read mCounter;
+    property length: Integer read mLength;
+  end;
+
 implementation
 
 uses
@@ -239,4 +280,142 @@ begin
   mRevert := utils.readBool(st);
 end;
 
+
+(* ------------- *)
+
+constructor TAnimState.Create (aloop: Boolean; aspeed: Byte; len: Integer);
+begin
+  assert(len >= 0);
+  mLength := len;
+
+  mMinLength := 0;
+  mLoop := aloop;
+  mSpeed := aspeed;
+  mEnabled := true;
+  mCurrentFrame := 0;
+  mPlayed := false;
+end;
+
+procedure TAnimState.Destroy;
+begin
+  Self := Default(TAnimState);
+end;
+
+procedure TAnimState.update;
+begin
+  if (not mEnabled) then exit;
+
+  mCounter += 1;
+
+  if (mCounter >= mSpeed) then
+  begin
+    if mRevert then
+    begin
+      if (mCurrentFrame = 0) then
+      begin
+        if (mLength * mSpeed + mCounter < mMinLength) then exit;
+      end;
+
+      mCurrentFrame -= 1;
+      mPlayed := (mCurrentFrame < 0);
+
+      if mPlayed then
+      begin
+        if mLoop then
+          mCurrentFrame := mLength - 1
+        else
+          mCurrentFrame += 1
+      end;
+
+      mCounter := 0;
+    end
+    else
+    begin
+      if (mCurrentFrame = mLength - 1) then
+      begin
+        if (mLength * mSpeed + mCounter < mMinLength) then exit;
+      end;
+
+      mCurrentFrame += 1;
+      mPlayed := (mCurrentFrame > mLength - 1);
+
+      if mPlayed then
+      begin
+        if mLoop then mCurrentFrame := 0 else mCurrentFrame -= 1;
+      end;
+
+      mCounter := 0;
+    end;
+  end;
+end;
+
+procedure TAnimState.reset;
+begin
+  if mRevert then
+    mCurrentFrame := mLength - 1
+  else
+    mCurrentFrame := 0;
+  mCounter := 0;
+  mPlayed := false
+end;
+
+procedure TAnimState.disable;
+begin
+  mEnabled := false
+end;
+
+procedure TAnimState.enable;
+begin
+  mEnabled := true
+end;
+
+procedure TAnimState.revert (r: Boolean);
+begin
+  mRevert := r;
+  reset
+end;
+
+function TAnimState.totalFrames (): Integer; inline;
+begin
+  result := mLength
+end;
+
+procedure TAnimState.saveState (st: TStream; mAlpha: Byte; mBlending: Boolean);
+begin
+  if (st = nil) then exit;
+
+  utils.writeSign(st, 'ANIM');
+  utils.writeInt(st, Byte(0)); // version
+  utils.writeInt(st, Byte(mCounter));
+  utils.writeInt(st, LongInt(mCurrentFrame));
+  utils.writeBool(st, mPlayed);
+  utils.writeInt(st, Byte(mAlpha));
+  utils.writeInt(st, Byte(mBlending));
+  utils.writeInt(st, Byte(mSpeed));
+  utils.writeBool(st, mLoop);
+  utils.writeBool(st, mEnabled);
+  utils.writeInt(st, Byte(mMinLength));
+  utils.writeBool(st, mRevert);
+end;
+
+
+procedure TAnimState.loadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean);
+begin
+  if (st = nil) then exit;
+
+  if not utils.checkSign(st, 'ANIM') then raise XStreamError.Create('animation chunk expected');
+  if (utils.readByte(st) <> 0) then raise XStreamError.Create('invalid animation chunk version');
+  mCounter := utils.readByte(st);
+  mCurrentFrame := utils.readLongInt(st);
+  mPlayed := utils.readBool(st);
+  mAlpha := utils.readByte(st);
+  mBlending := utils.readBool(st);
+  mSpeed := utils.readByte(st);
+  mLoop := utils.readBool(st);
+  mEnabled := utils.readBool(st);
+  mMinLength := utils.readByte(st);
+  mRevert := utils.readBool(st);
+end;
+
+
 end.