From df1f12c26369a0d5e9e996583b30c9879570fe99 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Mon, 13 Jun 2022 19:03:33 +0300 Subject: [PATCH] gl: use TAnimInfo for animations calculated by render --- src/game/Doom2DF.lpr | 2 +- src/game/g_animations.pas | 290 ++++++++++++++++++++++++++ src/game/g_console.pas | 2 +- src/game/g_corpses.pas | 2 +- src/game/g_gfx.pas | 3 +- src/game/g_map.pas | 2 +- src/game/g_monsters.pas | 2 +- src/game/g_netmsg.pas | 2 +- src/game/g_panel.pas | 10 +- src/game/g_player.pas | 2 +- src/game/g_playermodel.pas | 10 +- src/game/g_saveload.pas | 2 +- src/game/g_textures.pas | 230 --------------------- src/game/g_weapons.pas | 2 +- src/game/opengl/r_animations.pas | 2 +- src/game/opengl/r_gfx.pas | 2 +- src/game/opengl/r_items.pas | 2 +- src/game/opengl/r_map.pas | 2 +- src/game/opengl/r_playermodel.pas | 2 +- src/game/renders/opengl/r_draw.pas | 2 +- src/game/renders/opengl/r_map.pas | 292 +++++++++++++-------------- src/game/renders/opengl/r_render.pas | 1 + 22 files changed, 465 insertions(+), 401 deletions(-) create mode 100644 src/game/g_animations.pas delete mode 100644 src/game/g_textures.pas diff --git a/src/game/Doom2DF.lpr b/src/game/Doom2DF.lpr index d5e4376..98c39b5 100644 --- a/src/game/Doom2DF.lpr +++ b/src/game/Doom2DF.lpr @@ -144,7 +144,7 @@ uses g_playermodel in 'g_playermodel.pas', g_saveload in 'g_saveload.pas', g_sound in 'g_sound.pas', - g_textures in 'g_textures.pas', + g_animations in 'g_animations.pas', g_triggers in 'g_triggers.pas', g_weapons in 'g_weapons.pas', g_window in 'g_window.pas', diff --git a/src/game/g_animations.pas b/src/game/g_animations.pas new file mode 100644 index 0000000..1e9078e --- /dev/null +++ b/src/game/g_animations.pas @@ -0,0 +1,290 @@ +(* Copyright (C) Doom 2D: Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License ONLY. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../shared/a_modes.inc} +unit g_animations; + +interface + + uses Classes; + + type + TAnimState = record + private + mCounter: Byte; // delay counter (normally [0..mSpeed]) + mSpeed: Byte; // delay between frames + mCurrentFrame: Integer; // current frame (normally [0..mLength - 1]) + mLoop: Boolean; // looped animation + mEnabled: Boolean; // allow update state + mPlayed: Boolean; // anmation played at least once + mMinLength: Byte; // delay at animation end + mRevert: Boolean; // reverse play + mLength: Integer; // total frames (normally mLength > 0) + + public + constructor Create (aloop: Boolean; aspeed: Byte; len: Integer); + procedure Invalidate; + + 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; + function IsInvalid (): Boolean; inline; + function IsValid (): Boolean; 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; + + type + TAnimInfo = record + loop: Boolean; (* loop animation normalization *) + delay: Byte; (* delay between frames [1..255] *) + frames: Word; (* number of frames in animation stream [1..65535] *) + back: Boolean; (* back animation normalization *) + end; + + function g_Anim_GetTotalFrames (const a: TAnimInfo): LongWord; + function g_Anim_GetTotalTime (const a: TAnimInfo): LongWord; + function g_Anim_GetCountByTime (const a: TAnimInfo; time: LongWord): LongInt; + procedure g_Anim_GetFrameByTime (const a: TAnimInfo; time: LongWord; out count, frame: LongInt); + procedure g_Anim_GetState (const anim: TAnimInfo; time: LongWord; out state: TAnimState); + +implementation + + uses Math, utils, xstreams; + + constructor TAnimState.Create (aloop: Boolean; aspeed: Byte; len: Integer); + begin + ASSERT(len >= 0); + + self := Default(TAnimState); + self.mLength := len; + self.mMinLength := 0; + self.mLoop := aloop; + self.mSpeed := aspeed; + self.mEnabled := true; + self.mCurrentFrame := 0; + self.mPlayed := false; + end; + + procedure TAnimState.Invalidate; + begin + self := Default(TAnimState); + end; + + procedure TAnimState.Update; + begin + ASSERT(self.IsValid()); + if self.mEnabled then + begin + INC(self.mCounter); + if self.mCounter >= self.mSpeed then + begin + if self.mRevert then + begin + if (self.mCurrentFrame <> 0) or (mLength * mSpeed + mCounter >= mMinLength) then + begin + DEC(self.mCurrentFrame); + self.mPlayed := self.mCurrentFrame < 0; + if self.mPlayed then + begin + if self.mLoop then self.mCurrentFrame := self.mLength - 1 else INC(self.mCurrentFrame); + end; + self.mCounter := 0; + end; + end + else + begin + if (self.mCurrentFrame <> self.mLength - 1) or (mLength * mSpeed + mCounter >= mMinLength) then + begin + INC(self.mCurrentFrame); + self.mPlayed := self.mCurrentFrame > self.mLength - 1; + if self.mPlayed then + begin + if self.mLoop then self.mCurrentFrame := 0 else DEC(self.mCurrentFrame); + end; + self.mCounter := 0; + end; + end; + end; + end; + end; + + procedure TAnimState.Reset; + begin + ASSERT(self.IsValid()); + if self.mRevert then self.mCurrentFrame := self.mLength - 1 else self.mCurrentFrame := 0; + self.mCounter := 0; + self.mPlayed := false; + end; + + procedure TAnimState.Disable; + begin + ASSERT(self.IsValid()); + self.mEnabled := false; + end; + + procedure TAnimState.Enable; + begin + ASSERT(self.IsValid()); + self.mEnabled := true; + end; + + procedure TAnimState.revert (r: Boolean); + begin + ASSERT(self.IsValid()); + self.mRevert := r; + self.Reset; + end; + + function TAnimState.TotalFrames (): Integer; + begin + ASSERT(self.IsValid()); + result := self.mLength; + end; + + function TAnimState.IsInvalid (): Boolean; + begin + result := self.mLength <= 0 + end; + + function TAnimState.IsValid (): Boolean; + begin + result := self.mLength > 0; + end; + + procedure TAnimState.SaveState (st: TStream; mAlpha: Byte; mBlending: Boolean); + begin + if st <> nil then + begin + 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; + end; + + procedure TAnimState.LoadState (st: TStream; out mAlpha: Byte; out mBlending: Boolean); + begin + if st <> nil then + begin + if utils.checkSign(st, 'ANIM') = false 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; + + function g_Anim_GetTotalFrames (const a: TAnimInfo): LongWord; + begin + ASSERT(a.frames > 0); + ASSERT(a.delay > 0); + if a.back then result := MAX(1, a.frames * 2 - 2) else result := a.frames; + end; + + function g_Anim_GetTotalTime (const a: TAnimInfo): LongWord; + begin + ASSERT(a.frames > 0); + ASSERT(a.delay > 0); + result := g_Anim_GetTotalFrames(a) * a.delay; + end; + + function g_Anim_GetCountByTime (const a: TAnimInfo; time: LongWord): LongInt; + var n, f, t: LongWord; + begin + ASSERT(a.frames > 0); + ASSERT(a.delay > 0); + n := g_Anim_GetTotalFrames(a); + t := g_Anim_GetTotalTime(a); + f := n * time div t; + if a.loop then result := f div n + else if f >= n then result := 1 + else result := 0; + end; + + procedure g_Anim_GetFrameByTime (const a: TAnimInfo; time: LongWord; out count, frame: LongInt); + var n, f, t: LongWord; + begin + ASSERT(a.frames > 0); + ASSERT(a.delay > 0); + (* 1. Get total number frames for one animation cycle *) + n := g_Anim_GetTotalFrames(a); + (* 2. Get time for one animation cycle *) + t := g_Anim_GetTotalTime(a); + (* 3. Get frame for specified time *) + f := n * time div t; + (* 4. Get how many times is played *) + if a.loop then count := f div n + else if f >= n then count := 1 + else count := 0; + (* 5. Normalize loop animation *) + if a.loop then f := f mod n else f := MIN(f, n - 1); + (* 6. Normalize back animation *) + if a.back and (f >= a.frames) then f := n - f; + frame := f; + end; + + procedure g_Anim_GetState (const anim: TAnimInfo; time: LongWord; out state: TAnimState); + var count, frame: LongInt; a: TAnimInfo; + begin + ASSERT(anim.frames > 0); + ASSERT(anim.delay > 0); + a := anim; + if a.back then + begin + a.frames := MAX(1, a.frames * 2 - 2); + a.back := false; + end; + g_Anim_GetFrameByTime(a, time, count, frame); + state := TAnimState.Create(a.loop, a.delay, a.frames); + state.mCounter := time MOD a.delay; + state.mCurrentFrame := frame; + state.mPlayed := count >= 1; + end; + +end. diff --git a/src/game/g_console.pas b/src/game/g_console.pas index c9cc11e..3005340 100644 --- a/src/game/g_console.pas +++ b/src/game/g_console.pas @@ -120,7 +120,7 @@ uses {$IFDEF ENABLE_CORPSES} g_corpses, {$ENDIF} - g_textures, e_input, g_game, g_player, g_items, + e_input, g_game, g_player, g_items, SysUtils, g_basic, g_options, Math, e_res, g_language, g_net, g_netmsg, e_log, conbuf, g_weapons, Keyboard; diff --git a/src/game/g_corpses.pas b/src/game/g_corpses.pas index 8869e8a..b606a5b 100644 --- a/src/game/g_corpses.pas +++ b/src/game/g_corpses.pas @@ -85,7 +85,7 @@ implementation {$ENDIF} Math, utils, g_saveload, xstreams, - g_game, g_textures, g_map + g_game, g_animations, g_map ; var diff --git a/src/game/g_gfx.pas b/src/game/g_gfx.pas index 9cc665c..0be98e3 100644 --- a/src/game/g_gfx.pas +++ b/src/game/g_gfx.pas @@ -19,8 +19,7 @@ unit g_gfx; interface -uses - e_log, g_textures; +uses e_log; const BLOOD_NORMAL = 0; diff --git a/src/game/g_map.pas b/src/game/g_map.pas index b7b3d45..03c029f 100644 --- a/src/game/g_map.pas +++ b/src/game/g_map.pas @@ -20,7 +20,7 @@ interface uses SysUtils, Classes, mempool, - g_base, g_basic, MAPDEF, g_textures, + g_base, g_basic, MAPDEF, g_phys, utils, g_panel, g_grid, md5, binheap, xprofiler, xparser, xdynrec; type diff --git a/src/game/g_monsters.pas b/src/game/g_monsters.pas index d6d65d3..718921b 100644 --- a/src/game/g_monsters.pas +++ b/src/game/g_monsters.pas @@ -23,7 +23,7 @@ uses SysUtils, Classes, mempool, MAPDEF, - g_base, g_basic, g_phys, g_textures, g_grid, + g_base, g_basic, g_phys, g_animations, g_grid, g_saveload, g_panel, xprofiler; const diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas index 85ff270..08fd9df 100644 --- a/src/game/g_netmsg.pas +++ b/src/game/g_netmsg.pas @@ -300,7 +300,7 @@ implementation g_corpses, {$ENDIF} Math, ENet, e_input, e_log, g_base, g_basic, - g_textures, g_sound, g_console, g_options, + g_sound, g_console, g_options, g_game, g_player, g_map, g_panel, g_items, g_weapons, g_phys, g_language, g_monsters, g_netmaster, utils, wadreader, MAPDEF ; diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index 07bd4ec..58e7477 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -20,9 +20,17 @@ interface uses SysUtils, Classes, - MAPDEF, g_textures, xdynrec; + MAPDEF, g_animations, xdynrec; type + TLevelTexture = record + TextureName: AnsiString; // as stored in wad + FullName: AnsiString; // full path to texture // !!! merge it with TextureName + framesCount, speed: Byte; + end; + + TLevelTextureArray = array of TLevelTexture; + TAddTextureArray = array of record Texture: Cardinal; // Textures[Texture] end; diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 312f186..b3c8fec 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -21,7 +21,7 @@ interface uses SysUtils, Classes, {$IFDEF USE_MEMPOOL}mempool,{$ENDIF} - g_base, g_playermodel, g_basic, g_textures, + g_base, g_playermodel, g_basic, g_animations, g_weapons, g_phys, g_sound, g_saveload, MAPDEF, g_panel; diff --git a/src/game/g_playermodel.pas b/src/game/g_playermodel.pas index 4f4d709..7a55bf7 100644 --- a/src/game/g_playermodel.pas +++ b/src/game/g_playermodel.pas @@ -18,7 +18,7 @@ unit g_playermodel; interface - uses MAPDEF, g_textures, g_base, g_basic, g_weapons, utils; + uses MAPDEF, g_animations, g_base, g_basic, g_weapons, utils; const A_STAND = 0; @@ -67,8 +67,6 @@ const type TWeaponPoints = Array [WP_FIRST + 1..WP_LAST, A_STAND..A_LAST, TDirection.D_LEFT..TDirection.D_RIGHT] of Array of TDFPoint; - TModelMatrix = Array [TDirection.D_LEFT..TDirection.D_RIGHT, A_STAND..A_LAST] of TAnimState; - TModelTextures = Array [TDirection.D_LEFT..TDirection.D_RIGHT, A_STAND..A_LAST] of record Resource: String; Mask: String; @@ -661,16 +659,16 @@ end; { TPlayerModel } procedure TPlayerModel.ChangeAnimation (Animation: Byte; Force: Boolean = False); - var once: Boolean; speed, count: Integer; + var loop: Boolean; speed, count: Integer; begin if not Force then if FCurrentAnimation = Animation then Exit; FCurrentAnimation := Animation; - once := FCurrentAnimation in [A_STAND, A_WALK]; + loop := FCurrentAnimation in [A_STAND, A_WALK]; speed := PlayerModelsArray[FID].ModelSpeed[FCurrentAnimation]; count := PlayerModelsArray[FID].Anim[FDirection, FCurrentAnimation].Frames; - FAnimState := TAnimState.Create(once, speed, count); + FAnimState := TAnimState.Create(loop, speed, count); end; destructor TPlayerModel.Destroy(); diff --git a/src/game/g_saveload.pas b/src/game/g_saveload.pas index 6c101a6..f513f3a 100644 --- a/src/game/g_saveload.pas +++ b/src/game/g_saveload.pas @@ -18,7 +18,7 @@ unit g_saveload; interface uses - SysUtils, Classes, g_phys, g_textures; + SysUtils, Classes, g_phys; function g_GetSaveName (n: Integer; out valid: Boolean): AnsiString; diff --git a/src/game/g_textures.pas b/src/game/g_textures.pas deleted file mode 100644 index 8a215c0..0000000 --- a/src/game/g_textures.pas +++ /dev/null @@ -1,230 +0,0 @@ -(* Copyright (C) Doom 2D: Forever Developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 3 of the License ONLY. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *) -{$INCLUDE ../shared/a_modes.inc} -unit g_textures; - -interface - -uses - SysUtils, Classes, - {$IFDEF USE_MEMPOOL}mempool,{$ENDIF} - g_base, MAPDEF; - -type - TLevelTexture = record - TextureName: AnsiString; // as stored in wad - FullName: AnsiString; // full path to texture // !!! merge it with TextureName - framesCount, speed: Byte; - end; - - TLevelTextureArray = array of TLevelTexture; - - 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 Invalidate; - - 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; - function IsInvalid (): Boolean; - function IsValid (): Boolean; - - 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 - g_game, e_log, g_basic, g_console, wadreader, - g_language, utils, xstreams; - -constructor TAnimState.Create (aloop: Boolean; aspeed: Byte; len: Integer); -begin - Self := Default(TAnimState); - - assert(len >= 0); - mLength := len; - - mMinLength := 0; - mLoop := aloop; - mSpeed := aspeed; - mEnabled := true; - mCurrentFrame := 0; - mPlayed := false; -end; - -procedure TAnimState.Invalidate; -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; - -function TAnimState.IsInvalid (): Boolean; -begin - result := mLength <= 0 -end; - -function TAnimState.IsValid (): Boolean; -begin - result := mLength > 0 -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. diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas index 3653963..2b38de3 100644 --- a/src/game/g_weapons.pas +++ b/src/game/g_weapons.pas @@ -20,7 +20,7 @@ interface uses SysUtils, Classes, mempool, - g_textures, g_basic, g_phys, xprofiler; + g_animations, g_basic, g_phys, xprofiler; type diff --git a/src/game/opengl/r_animations.pas b/src/game/opengl/r_animations.pas index 26d15c7..76426d5 100644 --- a/src/game/opengl/r_animations.pas +++ b/src/game/opengl/r_animations.pas @@ -17,7 +17,7 @@ unit r_animations; interface - uses g_base, g_textures, MAPDEF, Imaging; // TMirrorType, TAnimationState, TDFPoint, TDynImageDataArray + uses g_base, g_animations, MAPDEF, Imaging; // TMirrorType, TAnimationState, TDFPoint, TDynImageDataArray procedure r_AnimState_Draw (FID: DWORD; const t: TAnimState; x, y: Integer; alpha: Byte; mirror: TMirrorType; blending: Boolean); procedure r_AnimState_DrawEx (FID: DWORD; const t: TAnimState; x, y: Integer; alpha: Byte; mirror: TMirrorType; blending: Boolean; rpoint: TDFPoint; angle: SmallInt); diff --git a/src/game/opengl/r_gfx.pas b/src/game/opengl/r_gfx.pas index afdadd9..1800c78 100644 --- a/src/game/opengl/r_gfx.pas +++ b/src/game/opengl/r_gfx.pas @@ -39,7 +39,7 @@ implementation SysUtils, Classes, Math, utils, g_base, r_graphics, g_options, r_animations, - g_game, g_textures, + g_game, g_animations, g_gfx ; diff --git a/src/game/opengl/r_items.pas b/src/game/opengl/r_items.pas index 168d740..d29ccc2 100644 --- a/src/game/opengl/r_items.pas +++ b/src/game/opengl/r_items.pas @@ -30,7 +30,7 @@ implementation uses SysUtils, Classes, Math, r_graphics, r_animations, r_textures, - g_base, g_basic, g_game, g_options, g_textures, + g_base, g_basic, g_game, g_options, g_animations, g_items ; diff --git a/src/game/opengl/r_map.pas b/src/game/opengl/r_map.pas index 9a6235c..a35980d 100644 --- a/src/game/opengl/r_map.pas +++ b/src/game/opengl/r_map.pas @@ -54,7 +54,7 @@ implementation uses {$INCLUDE ../nogl/noGLuses.inc} SysUtils, Classes, Math, e_log, wadreader, CONFIG, utils, g_language, - r_graphics, r_animations, r_textures, g_textures, + r_graphics, r_animations, r_textures, g_animations, g_base, g_basic, g_game, g_options, g_map ; diff --git a/src/game/opengl/r_playermodel.pas b/src/game/opengl/r_playermodel.pas index 5ab33e9..aefbabb 100644 --- a/src/game/opengl/r_playermodel.pas +++ b/src/game/opengl/r_playermodel.pas @@ -41,7 +41,7 @@ implementation MAPDEF, utils, e_log, wadreader, ImagingTypes, Imaging, ImagingUtility, r_graphics, g_options, r_animations, r_textures, - g_basic, g_map, g_weapons, g_textures, g_player, g_phys, g_game + g_basic, g_map, g_weapons, g_animations, g_player, g_phys, g_game ; const diff --git a/src/game/renders/opengl/r_draw.pas b/src/game/renders/opengl/r_draw.pas index bdd6071..fbdae7e 100644 --- a/src/game/renders/opengl/r_draw.pas +++ b/src/game/renders/opengl/r_draw.pas @@ -18,7 +18,7 @@ unit r_draw; interface uses - g_textures, + g_animations, r_textures ; diff --git a/src/game/renders/opengl/r_map.pas b/src/game/renders/opengl/r_map.pas index 4f0621d..4ffd6e1 100644 --- a/src/game/renders/opengl/r_map.pas +++ b/src/game/renders/opengl/r_map.pas @@ -38,7 +38,6 @@ interface procedure r_Map_DrawPlayerModel (pm: TPlayerModel; x, y: Integer; alpha: Byte); {$ENDIF} - procedure r_Map_Update; procedure r_Map_Draw (x, y, w, h, camx, camy: Integer; player: TPlayer); @@ -54,7 +53,7 @@ implementation {$ENDIF} e_log, binheap, MAPDEF, utils, - g_options, g_textures, g_basic, g_phys, + g_options, g_animations, g_basic, g_phys, g_game, g_map, g_panel, g_items, g_monsters, g_weapons, {$IFDEF ENABLE_CORPSES} g_corpses, @@ -103,79 +102,75 @@ implementation ItemAnim: array [0..ITEM_LAST] of record name: AnsiString; w, h: Integer; - d: Integer; // delay - n: Integer; // count - b: Boolean; // backanim + anim: TAnimInfo; end = ( - (name: ''; w: 0; h: 0; d: 0; n: 0; b: False), - (name: 'MED1'; w: 16; h: 16; d: 0; n: 1; b: False), - (name: 'MED2'; w: 32; h: 32; d: 0; n: 1; b: False), - (name: 'BMED'; w: 32; h: 32; d: 0; n: 1; b: False), - (name: 'ARMORGREEN'; w: 32; h: 16; d: 20; n: 3; b: True), - (name: 'ARMORBLUE'; w: 32; h: 16; d: 20; n: 3; b: True), - (name: 'SBLUE'; w: 32; h: 32; d: 15; n: 4; b: True), - (name: 'SWHITE'; w: 32; h: 32; d: 20; n: 4; b: True), - (name: 'SUIT'; w: 32; h: 64; d: 0; n: 1; b: False), - (name: 'OXYGEN'; w: 16; h: 32; d: 0; n: 1; b: False), - (name: 'INVUL'; w: 32; h: 32; d: 20; n: 4; b: True), - (name: 'SAW'; w: 64; h: 32; d: 0; n: 1; b: False), - (name: 'SHOTGUN1'; w: 64; h: 16; d: 0; n: 1; b: False), - (name: 'SHOTGUN2'; w: 64; h: 16; d: 0; n: 1; b: False), - (name: 'MGUN'; w: 64; h: 16; d: 0; n: 1; b: False), - (name: 'RLAUNCHER'; w: 64; h: 16; d: 0; n: 1; b: False), - (name: 'PGUN'; w: 64; h: 16; d: 0; n: 1; b: False), - (name: 'BFG'; w: 64; h: 64; d: 0; n: 1; b: False), - (name: 'SPULEMET'; w: 64; h: 16; d: 0; n: 1; b: False), - (name: 'CLIP'; w: 16; h: 16; d: 0; n: 1; b: False), - (name: 'AMMO'; w: 32; h: 16; d: 0; n: 1; b: False), - (name: 'SHELL1'; w: 16; h: 8; d: 0; n: 1; b: False), - (name: 'SHELL2'; w: 32; h: 16; d: 0; n: 1; b: False), - (name: 'ROCKET'; w: 16; h: 32; d: 0; n: 1; b: False), - (name: 'ROCKETS'; w: 64; h: 32; d: 0; n: 1; b: False), - (name: 'CELL'; w: 16; h: 16; d: 0; n: 1; b: False), - (name: 'CELL2'; w: 32; h: 32; d: 0; n: 1; b: False), - (name: 'BPACK'; w: 32; h: 32; d: 0; n: 1; b: False), - (name: 'KEYR'; w: 16; h: 16; d: 0; n: 1; b: False), - (name: 'KEYG'; w: 16; h: 16; d: 0; n: 1; b: False), - (name: 'KEYB'; w: 16; h: 16; d: 0; n: 1; b: False), - (name: 'KASTET'; w: 64; h: 32; d: 0; n: 1; b: False), - (name: 'PISTOL'; w: 64; h: 16; d: 0; n: 1; b: False), - (name: 'BOTTLE'; w: 16; h: 32; d: 20; n: 4; b: True), - (name: 'HELMET'; w: 16; h: 16; d: 20; n: 4; b: True), - (name: 'JETPACK'; w: 32; h: 32; d: 15; n: 3; b: True), - (name: 'INVIS'; w: 32; h: 32; d: 20; n: 4; b: True), - (name: 'FLAMETHROWER'; w: 64; h: 32; d: 0; n: 1; b: False), - (name: 'FUELCAN'; w: 16; h: 32; d: 0; n: 1; b: False) + (name: 'NOTEXTURE'; w: 16; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'MED1'; w: 16; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'MED2'; w: 32; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'BMED'; w: 32; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'ARMORGREEN'; w: 32; h: 16; anim: (loop: true; delay: 20; frames: 3; back: true)), + (name: 'ARMORBLUE'; w: 32; h: 16; anim: (loop: true; delay: 20; frames: 3; back: true)), + (name: 'SBLUE'; w: 32; h: 32; anim: (loop: true; delay: 15; frames: 4; back: true)), + (name: 'SWHITE'; w: 32; h: 32; anim: (loop: true; delay: 20; frames: 4; back: true)), + (name: 'SUIT'; w: 32; h: 64; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'OXYGEN'; w: 16; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'INVUL'; w: 32; h: 32; anim: (loop: true; delay: 20; frames: 4; back: true)), + (name: 'SAW'; w: 64; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'SHOTGUN1'; w: 64; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'SHOTGUN2'; w: 64; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'MGUN'; w: 64; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'RLAUNCHER'; w: 64; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'PGUN'; w: 64; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'BFG'; w: 64; h: 64; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'SPULEMET'; w: 64; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'CLIP'; w: 16; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'AMMO'; w: 32; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'SHELL1'; w: 16; h: 8; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'SHELL2'; w: 32; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'ROCKET'; w: 16; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'ROCKETS'; w: 64; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'CELL'; w: 16; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'CELL2'; w: 32; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'BPACK'; w: 32; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'KEYR'; w: 16; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'KEYG'; w: 16; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'KEYB'; w: 16; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'KASTET'; w: 64; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'PISTOL'; w: 64; h: 16; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'BOTTLE'; w: 16; h: 32; anim: (loop: true; delay: 20; frames: 4; back: true)), + (name: 'HELMET'; w: 16; h: 16; anim: (loop: true; delay: 20; frames: 4; back: true)), + (name: 'JETPACK'; w: 32; h: 32; anim: (loop: true; delay: 15; frames: 3; back: true)), + (name: 'INVIS'; w: 32; h: 32; anim: (loop: true; delay: 20; frames: 4; back: true)), + (name: 'FLAMETHROWER'; w: 64; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)), + (name: 'FUELCAN'; w: 16; h: 32; anim: (loop: true; delay: 1; frames: 1; back: false)) ); {$IFDEF ENABLE_GFX} GFXAnim: array [0..R_GFX_LAST] of record name: AnsiString; w, h: Integer; - count: Integer; - back: Boolean; - speed: Integer; - rspeed: Integer; + anim: TAnimInfo; + rdelay: Integer; alpha: Integer; end = ( - (name: ''; w: 0; h: 0; count: 0; back: false; speed: 0; rspeed: 0; alpha: 0), - (name: 'TELEPORT'; w: 64; h: 64; count: 10; back: false; speed: 6; rspeed: 0; alpha: 0), - (name: 'FLAME'; w: 32; h: 32; count: 11; back: false; speed: 3; rspeed: 0; alpha: 0), - (name: 'EROCKET'; w: 128; h: 128; count: 6; back: false; speed: 6; rspeed: 0; alpha: 0), - (name: 'EBFG'; w: 128; h: 128; count: 6; back: false; speed: 6; rspeed: 0; alpha: 0), - (name: 'BFGHIT'; w: 64; h: 64; count: 4; back: false; speed: 4; rspeed: 0; alpha: 0), - (name: 'FIRE'; w: 64; h: 128; count: 8; back: false; speed: 4; rspeed: 2; alpha: 0), - (name: 'ITEMRESPAWN'; w: 32; h: 32; count: 5; back: true; speed: 4; rspeed: 0; alpha: 0), - (name: 'SMOKE'; w: 32; h: 32; count: 10; back: false; speed: 3; rspeed: 0; alpha: 0), - (name: 'ESKELFIRE'; w: 64; h: 64; count: 3; back: false; speed: 8; rspeed: 0; alpha: 0), - (name: 'EPLASMA'; w: 32; h: 32; count: 4; back: true; speed: 3; rspeed: 0; alpha: 0), - (name: 'EBSPFIRE'; w: 32; h: 32; count: 5; back: false; speed: 3; rspeed: 0; alpha: 0), - (name: 'EIMPFIRE'; w: 64; h: 64; count: 3; back: false; speed: 6; rspeed: 0; alpha: 0), - (name: 'ECACOFIRE'; w: 64; h: 64; count: 3; back: false; speed: 6; rspeed: 0; alpha: 0), - (name: 'EBARONFIRE'; w: 64; h: 64; count: 3; back: false; speed: 6; rspeed: 0; alpha: 0), - (name: 'TELEPORT'; w: 64; h: 64; count: 10; back: false; speed: 3; rspeed: 0; alpha: 0), // fast - (name: 'SMOKE'; w: 32; h: 32; count: 10; back: false; speed: 3; rspeed: 0; alpha: 150), // transparent - (name: 'FLAME'; w: 32; h: 32; count: 11; back: false; speed: 3; rspeed: 2; alpha: 0) // random + (name: ''; w: 0; h: 0; anim: (loop: false; delay: 0; frames: 0; back: false); rdelay: 0; alpha: 0), + (name: 'TELEPORT'; w: 64; h: 64; anim: (loop: false; delay: 6; frames: 10; back: false); rdelay: 0; alpha: 0), + (name: 'FLAME'; w: 32; h: 32; anim: (loop: false; delay: 3; frames: 11; back: false); rdelay: 0; alpha: 0), + (name: 'EROCKET'; w: 128; h: 128; anim: (loop: false; delay: 6; frames: 6; back: false); rdelay: 0; alpha: 0), + (name: 'EBFG'; w: 128; h: 128; anim: (loop: false; delay: 6; frames: 6; back: false); rdelay: 0; alpha: 0), + (name: 'BFGHIT'; w: 64; h: 64; anim: (loop: false; delay: 4; frames: 4; back: false); rdelay: 0; alpha: 0), + (name: 'FIRE'; w: 64; h: 128; anim: (loop: false; delay: 4; frames: 8; back: false); rdelay: 2; alpha: 0), + (name: 'ITEMRESPAWN'; w: 32; h: 32; anim: (loop: false; delay: 4; frames: 5; back: true); rdelay: 0; alpha: 0), + (name: 'SMOKE'; w: 32; h: 32; anim: (loop: false; delay: 3; frames: 10; back: false); rdelay: 0; alpha: 0), + (name: 'ESKELFIRE'; w: 64; h: 64; anim: (loop: false; delay: 8; frames: 3; back: false); rdelay: 0; alpha: 0), + (name: 'EPLASMA'; w: 32; h: 32; anim: (loop: false; delay: 3; frames: 4; back: true); rdelay: 0; alpha: 0), + (name: 'EBSPFIRE'; w: 32; h: 32; anim: (loop: false; delay: 3; frames: 5; back: false); rdelay: 0; alpha: 0), + (name: 'EIMPFIRE'; w: 64; h: 64; anim: (loop: false; delay: 6; frames: 3; back: false); rdelay: 0; alpha: 0), + (name: 'ECACOFIRE'; w: 64; h: 64; anim: (loop: false; delay: 6; frames: 3; back: false); rdelay: 0; alpha: 0), + (name: 'EBARONFIRE'; w: 64; h: 64; anim: (loop: false; delay: 6; frames: 3; back: false); rdelay: 0; alpha: 0), + (name: 'TELEPORT'; w: 64; h: 64; anim: (loop: false; delay: 3; frames: 10; back: false); rdelay: 0; alpha: 0), // fast + (name: 'SMOKE'; w: 32; h: 32; anim: (loop: false; delay: 3; frames: 10; back: false); rdelay: 0; alpha: 150), // transparent + (name: 'FLAME'; w: 32; h: 32; anim: (loop: false; delay: 3; frames: 11; back: false); rdelay: 2; alpha: 0) // random ); {$ENDIF} @@ -224,6 +219,8 @@ implementation ); {$ENDIF} + FlagAnim: TAnimInfo = (loop: true; delay: 8; frames: 5; back: false); + type TBinHeapPanelDrawCmp = class public @@ -242,7 +239,7 @@ implementation end; Items: array [0..ITEM_LAST] of record tex: TGLMultiTexture; - anim: TAnimState; + frame: Integer; end; MonTextures: array [0..MONSTER_MAN] of TMonsterAnims; WeapTextures: array [0..WP_LAST, 0..W_POS_LAST, 0..W_ACT_LAST] of TGLTexture; @@ -264,7 +261,7 @@ implementation end; StubShotAnim: TAnimState; // TODO remove this hack - FlagAnim: TAnimState; + FlagFrame: LongInt; {$IFDEF ENABLE_SHELLS} ShellTextures: array [0..SHELL_LAST] of TGLTexture; @@ -273,10 +270,11 @@ implementation GFXTextures: array [0..R_GFX_LAST] of TGLMultiTexture; gfxlist: array of record typ: Byte; - alpha: Byte; x, y: Integer; oldX, oldY: Integer; - anim: TAnimState; + anim: TAnimInfo; + time: LongWord; + frame: LongInt; end = nil; {$ENDIF} @@ -292,13 +290,14 @@ implementation procedure r_Map_Initialize; begin StubShotAnim := TAnimState.Create(true, 1, 1); - FlagAnim := TAnimState.Create(true, 8, 5); + FlagFrame := 0; plist := TBinHeapPanelDraw.Create(); end; procedure r_Map_Finalize; begin plist.Free; + FlagFrame := 0; StubShotAnim.Invalidate; end; @@ -412,19 +411,15 @@ implementation // --------- items --------- // for i := 0 to ITEM_LAST do begin - if ItemAnim[i].n > 0 then - begin - Items[i].tex := r_Textures_LoadMultiFromFileAndInfo( - GameWAD + ':TEXTURES/' + ItemAnim[i].name, - ItemAnim[i].w, - ItemAnim[i].h, - ItemAnim[i].n, - ItemAnim[i].b, - false - ); - k := IfThen(ItemAnim[i].b, ItemAnim[i].n * 2 - 2, ItemAnim[i].n); - Items[i].anim := TAnimState.Create(True, ItemAnim[i].d, k); - end; + Items[i].tex := r_Textures_LoadMultiFromFileAndInfo( + GameWAD + ':TEXTURES/' + ItemAnim[i].name, + ItemAnim[i].w, + ItemAnim[i].h, + ItemAnim[i].anim.frames, + ItemAnim[i].anim.back, + false + ); + Items[i].frame := 0; end; // --------- monsters --------- // for i := MONSTER_DEMON to MONSTER_MAN do @@ -447,8 +442,8 @@ implementation // --------- gfx animations --------- // {$IFDEF ENABLE_GFX} for i := 1 to R_GFX_LAST do - if GFXAnim[i].count > 0 then - GFXTextures[i] := r_Textures_LoadMultiFromFileAndInfo(GameWad + ':TEXTURES/' + GFXAnim[i].name, GFXAnim[i].w, GFXAnim[i].h, GFXAnim[i].count, GFXAnim[i].back); + if GFXAnim[i].anim.frames > 0 then + GFXTextures[i] := r_Textures_LoadMultiFromFileAndInfo(GameWad + ':TEXTURES/' + GFXAnim[i].name, GFXAnim[i].w, GFXAnim[i].h, GFXAnim[i].anim.frames, GFXAnim[i].anim.back); {$ENDIF} // --------- shots --------- // for i := 0 to WEAPON_LAST do @@ -548,11 +543,8 @@ implementation for i := 0 to ITEM_LAST do begin if Items[i].tex <> nil then - begin Items[i].tex.Free; - Items[i].tex := nil; - end; - Items[i].anim.Invalidate; + Items[i].tex := nil; end; end; @@ -644,7 +636,7 @@ implementation end; procedure r_Map_DrawItems (x, y, w, h: Integer; drop: Boolean); - var i, fX, fY: Integer; it: PItem; t: TGLMultiTexture; + var i, fX, fY: Integer; it: PItem; t: TGLMultiTexture; tex: TGLTexture; begin if ggItems <> nil then begin @@ -657,7 +649,8 @@ implementation if g_Collide(it.obj.x, it.obj.y, t.width, t.height, x, y, w, h) then begin it.obj.Lerp(gLerpFactor, fX, fY); - r_Draw_MultiTextureRepeat(t, Items[it.ItemType].anim, fX, fY, t.width, t.height, false, 255, 255, 255, 255, false); + tex := t.GetTexture(Items[it.ItemType].frame); + r_Draw_TextureRepeat(tex, fX, fY, tex.width, tex.height, false, 255, 255, 255, 255, false); end; end; end; @@ -767,13 +760,13 @@ implementation angle := PlayerModelsArray[pm.id].FlagAngle; xx := PlayerModelsArray[pm.id].FlagPoint.X; yy := PlayerModelsArray[pm.id].FlagPoint.Y; - r_Draw_MultiTextureRepeatRotate( - t, - FlagAnim, + tex := t.GetTexture(FlagFrame); + r_Draw_TextureRepeatRotate( + tex, x + IfThen(flip, 2 * FLAG_BASEPOINT.X - xx + 1, xx - 1) - FLAG_BASEPOINT.X, y + yy - FLAG_BASEPOINT.Y + 1, - t.width, - t.height, + tex.width, + tex.height, flip, 255, 255, 255, 255, false, IfThen(flip, 64 - FLAG_BASEPOINT.X, FLAG_BASEPOINT.X), @@ -961,7 +954,7 @@ implementation i := 0; if gfxlist <> nil then begin - while (i < Length(gfxlist)) and gfxlist[i].anim.IsValid() do + while (i < Length(gfxlist)) and (gfxlist[i].typ > 0) do Inc(i); if i >= Length(gfxlist) then SetLength(gfxlist, Length(gfxlist) + 1) @@ -969,7 +962,6 @@ implementation else SetLength(gfxlist, 1); gfxlist[i].typ := R_GFX_NONE; - gfxlist[i].anim.Invalidate; result := i end; @@ -986,37 +978,63 @@ implementation gfxlist[i].y := y; gfxlist[i].oldX := x; gfxlist[i].oldY := y; - gfxlist[i].anim := TAnimState.Create(false, GFXAnim[typ].speed + Random(GFXAnim[typ].rspeed), GFXAnim[typ].count); - gfxlist[i].anim.Reset(); - gfxlist[i].anim.Enable(); + gfxlist[i].anim := GFXAnim[typ].anim; + gfxlist[i].time := gTime DIV GAME_TICK; + gfxlist[i].frame := 0; + INC(gfxlist[i].anim.delay, Random(GFXAnim[typ].rdelay)); end; end; end; - procedure r_Map_UpdateGFX; - var i: Integer; + procedure r_Map_UpdateGFX (tick: LongWord); + var i: Integer; count: LongInt; begin if gfxlist <> nil then begin for i := 0 to High(gfxlist) do begin - if gfxlist[i].anim.IsValid() then + if (gfxlist[i].typ > 0) and (tick >= gfxlist[i].time) then begin - gfxlist[i].oldX := gfxlist[i].x; - gfxlist[i].oldY := gfxlist[i].y; - case gfxlist[i].typ of - R_GFX_FLAME, R_GFX_SMOKE: - begin - if Random(3) = 0 then - gfxlist[i].x := gfxlist[i].x - 1 + Random(3); - if Random(2) = 0 then - gfxlist[i].y := gfxlist[i].y - Random(2); + g_Anim_GetFrameByTime(gfxlist[i].anim, tick - gfxlist[i].time, count, gfxlist[i].frame); + if count < 1 then + begin + gfxlist[i].oldX := gfxlist[i].x; + gfxlist[i].oldY := gfxlist[i].y; + case gfxlist[i].typ of + R_GFX_FLAME, R_GFX_SMOKE: + begin + if Random(3) = 0 then + gfxlist[i].x := gfxlist[i].x - 1 + Random(3); + if Random(2) = 0 then + gfxlist[i].y := gfxlist[i].y - Random(2); + end; end; - end; - if gfxlist[i].anim.played then - gfxlist[i].anim.Invalidate + end else - gfxlist[i].anim.Update + gfxlist[i].typ := R_GFX_NONE; + end; + end; + end; + end; + + procedure r_Map_DrawGFX (x, y, w, h: Integer); + var i, fx, fy, typ: Integer; t: TGLMultiTexture; tex: TGLTexture; + begin + if gfxlist <> nil then + begin + for i := 0 to High(gfxlist) do + begin + if gfxlist[i].typ > 0 then + begin + typ := gfxlist[i].typ; + t := GFXTextures[typ]; + if t <> nil then + begin + fx := nlerp(gfxlist[i].oldX, gfxlist[i].x, gLerpFactor); + fy := nlerp(gfxlist[i].oldY, gfxlist[i].y, gLerpFactor); + tex := t.GetTexture(gfxlist[i].frame); + r_Draw_TextureRepeat(tex, fx, fy, tex.width, tex.height, false, 255, 255, 255, 255 - GFXAnim[typ].alpha, false); + end; end; end; end; @@ -1054,28 +1072,6 @@ implementation glDisable(GL_BLEND); end; end; - - procedure r_Map_DrawGFX (x, y, w, h: Integer); - var i, fx, fy, typ: Integer; tex: TGLMultiTexture; - begin - if gfxlist <> nil then - begin - for i := 0 to High(gfxlist) do - begin - if gfxlist[i].anim.IsValid() then - begin - typ := gfxlist[i].typ; - tex := GFXTextures[typ]; - if tex <> nil then - begin - fx := nlerp(gfxlist[i].oldX, gfxlist[i].x, gLerpFactor); - fy := nlerp(gfxlist[i].oldY, gfxlist[i].y, gLerpFactor); - r_Draw_MultiTextureRepeat(tex, gfxlist[i].anim, fx, fy, tex.width, tex.height, false, 255, 255, 255, 255 - GFXAnim[typ].alpha, false); - end; - end; - end; - end; - end; {$ENDIF} procedure r_Map_DrawShots (x, y, w, h: Integer); @@ -1110,7 +1106,7 @@ implementation end; procedure r_Map_DrawFlags (x, y, w, h: Integer); - var i, dx, fx, fy: Integer; flip: Boolean; tex: TGLMultiTexture; + var i, dx, fx, fy: Integer; flip: Boolean; t: TGLMultiTexture; tex: TGLTexture; begin if gGameSettings.GameMode = GM_CTF then begin @@ -1121,8 +1117,9 @@ implementation gFlags[i].Obj.Lerp(gLerpFactor, fx, fy); flip := gFlags[i].Direction = TDirection.D_LEFT; if flip then dx := -1 else dx := +1; - tex := FlagTextures[i]; - r_Draw_MultiTextureRepeat(tex, FlagAnim, fx + dx, fy + 1, tex.width, tex.height, flip, 255, 255, 255, 255, false) + t := FlagTextures[i]; + tex := t.GetTexture(FlagFrame); + r_Draw_TextureRepeat(tex, fx + dx, fy + 1, tex.width, tex.height, flip, 255, 255, 255, 255, false) end; end; end; @@ -1325,12 +1322,13 @@ implementation end; procedure r_Map_Update; - var i: Integer; + var i, count, tick: LongInt; begin + tick := gTime div GAME_TICK; for i := 0 to ITEM_LAST do - Items[i].anim.Update; - r_Map_UpdateGFX; - FlagAnim.Update; + g_Anim_GetFrameByTime(ItemAnim[i].anim, tick, count, Items[i].frame); + r_Map_UpdateGFX(tick); + g_Anim_GetFrameByTime(FlagAnim, tick, count, FlagFrame); end; end. diff --git a/src/game/renders/opengl/r_render.pas b/src/game/renders/opengl/r_render.pas index fb65ab5..135141e 100644 --- a/src/game/renders/opengl/r_render.pas +++ b/src/game/renders/opengl/r_render.pas @@ -488,6 +488,7 @@ implementation procedure r_Render_DrawLoading (force: Boolean); begin + // TODO draw loading screen end; end. -- 2.29.2