index d12a9a24e4ba74789cfbe74fbaa0713e4b0c376f..02fe5aad01a60530c126232a0679d05d4d87b173 100644 (file)
--- a/src/game/g_textures.pas
+++ b/src/game/g_textures.pas
type
TLevelTexture = record
- textureName: AnsiString;
- width, height: Word;
- case anim: Boolean of
- false: (textureID: LongWord);
- true: (framesID: LongWord; framesCount: Byte; speed: Byte);
+ TextureName: AnsiString; // as stored in wad
+ FullName: AnsiString; // full path to texture // !!! merge it with TextureName
+ framesCount, speed: Byte;
end;
TLevelTextureArray = array of TLevelTexture;
+ TAnimationState = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
+ private
+ mAlpha: Byte;
+ mBlending: Boolean;
+ 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);
+ destructor Destroy (); override;
+
+ procedure reset ();
+ procedure update ();
+ procedure enable ();
+ procedure disable ();
+ procedure revert (r: Boolean);
+
+ procedure saveState (st: TStream);
+ procedure loadState (st: TStream);
+
+ 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 blending: Boolean read mBlending write mBlending;
+ property alpha: Byte read mAlpha write mAlpha;
+ end;
+
TAnimation = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
private
mId: LongWord;
g_game, e_log, g_basic, g_console, wadreader, r_animations,
g_language, utils, xstreams;
+
+
+
+constructor TAnimationState.Create (aloop: Boolean; aspeed: Byte; len: Integer);
+begin
+ assert(len >= 0);
+ mLength := len;
+
+ mMinLength := 0;
+ mLoop := aloop;
+ mSpeed := aspeed;
+ mEnabled := true;
+ mCurrentFrame := 0;
+ mAlpha := 0;
+ mPlayed := false;
+end;
+
+destructor TAnimationState.Destroy;
+begin
+ inherited;
+end;
+
+procedure TAnimationState.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 TAnimationState.reset;
+begin
+ if mRevert then
+ mCurrentFrame := mLength - 1
+ else
+ mCurrentFrame := 0;
+ mCounter := 0;
+ mPlayed := false
+end;
+
+procedure TAnimationState.disable;
+begin
+ mEnabled := false
+end;
+
+procedure TAnimationState.enable;
+begin
+ mEnabled := true
+end;
+
+procedure TAnimationState.revert (r: Boolean);
+begin
+ mRevert := r;
+ reset
+end;
+
+function TAnimationState.totalFrames (): Integer; inline;
+begin
+ result := mLength
+end;
+
+procedure TAnimationState.saveState (st: TStream);
+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);
+ // Alpha-êàíàë âñåé òåêñòóðû
+ 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 TAnimationState.loadState (st: TStream);
+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);
+ // Alpha-êàíàë âñåé òåêñòóðû
+ 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;
+
+
+
+
+
+
constructor TAnimation.Create (aframesID: LongWord; aloop: Boolean; aspeed: Byte);
begin
if (aframesID >= Length(framesArray)) then