X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_gfx.pas;h=c84ba47eda80a1e2c6097a134a78d5ba0929a212;hb=b79ddd98d923ee15f4bfd1db5111e669fc19964a;hp=87b60c17c8b1bd7374069158cbe9d7b577ff6f8b;hpb=ac201b02f10ef558087d50f6b03b4519ab567558;p=d2df-sdl.git diff --git a/src/game/g_gfx.pas b/src/game/g_gfx.pas index 87b60c1..c84ba47 100644 --- a/src/game/g_gfx.pas +++ b/src/game/g_gfx.pas @@ -1,10 +1,25 @@ -{$MODE DELPHI} +(* 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, either version 3 of the License, or + * (at your option) any later version. + * + * 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_gfx; interface uses - g_textures; + e_log, g_textures; const BLOOD_NORMAL = 0; @@ -43,8 +58,11 @@ procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean); procedure g_GFX_Update(); procedure g_GFX_Draw(); + var - gCollideMap: Array of Array of Byte; + gpart_dbg_enabled: Boolean = true; + gpart_dbg_phys_enabled: Boolean = true; + implementation @@ -54,6 +72,7 @@ uses g_game, g_language, g_net; type + PParticle = ^TParticle; TParticle = record X, Y: Integer; VelX, VelY: Single; @@ -64,6 +83,8 @@ type State: Byte; ParticleType: Byte; offsetX, offsetY: ShortInt; + // for bubbles + liquidTopY: Integer; // don't float higher than this end; TOnceAnim = record @@ -82,12 +103,67 @@ const STATE_STICK = 2; var - Particles: Array of TParticle; - OnceAnims: Array of TOnceAnim; + Particles: array of TParticle; + OnceAnims: array of TOnceAnim; MaxParticles: Integer; CurrentParticle: Integer; + +function isBlockedAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP)); +end; + +// ??? +function isWallAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WALL or PANEL_STEP)); +end; + +function isLiftUpAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTUP); +end; + +function isLiftDownAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTDOWN); +end; + +function isLiftLeftAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTLEFT); +end; + +function isLiftRightAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, PANEL_LIFTRIGHT); +end; + +function isLiquidAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WATER or PANEL_ACID1 or PANEL_ACID2)); +end; + +function isAnythingAt (x, y: Integer): Boolean; inline; +begin + if not gpart_dbg_phys_enabled then begin result := false; exit; end; + result := g_Map_HasAnyPanelAtPoint(x, y, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_OPENDOOR or PANEL_WATER or PANEL_ACID1 or PANEL_ACID2 or PANEL_STEP or PANEL_LIFTUP or PANEL_LIFTDOWN or PANEL_LIFTLEFT or PANEL_LIFTRIGHT)); +end; + + procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean); +{$IF not DEFINED(HAS_COLLIDE_BITMAP)} +begin +end; +{$ELSE} var yy, y2, xx, x2: Integer; begin @@ -136,7 +212,10 @@ begin gCollideMap[yy][xx] := gCollideMap[yy][xx] and t; end; end; +{$ENDIF} + +{$IF DEFINED(HAS_COLLIDE_BITMAP)} procedure CreateCollideMap(); var a: Integer; @@ -211,18 +290,22 @@ begin end; end; end; +{$ENDIF} + procedure g_GFX_Init(); begin - CreateCollideMap(); + //CreateCollideMap(); end; + procedure g_GFX_Free(); var a: Integer; begin Particles := nil; SetLength(Particles, MaxParticles); + for a := 0 to High(Particles) do Particles[a].State := STATE_FREE; CurrentParticle := 0; if OnceAnims <> nil then @@ -232,31 +315,26 @@ begin OnceAnims := nil; end; - - gCollideMap := nil; end; -procedure CorrectOffsets(id: Integer); -begin - with Particles[id] do - begin - if (X >= 0) and (Y > 0) and - (Y < Length(gCollideMap)) and (X < Length(gCollideMap[0])) and - (ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) then - offsetY := 1 // Ñòåíà ñâåðõó - else - offsetY := 0; - if (X > 0) and (Y >= 0) and - (Y < Length(gCollideMap)) and (X < Length(gCollideMap[0])) and - (ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)) then - offsetX := 1 // Ñòåíà ñëåâà - else - offsetX := 0; - end; +{ +procedure CorrectOffsets(id: Integer); inline; +var + part: PParticle; +begin + part := @Particles[id]; + part.offsetX := 0; + part.offsetY := 0; + // check for upper wall + if isBlockedAt(part.X, part.Y-1) then part.offsetY := 1; + // check for left wall + if isBlockedAt(part.X-1, part.Y) then part.offsetX := 1; end; +} + -procedure g_GFX_SparkVel(fX, fY: Integer; Count: Word; VX, VY: Integer; DevX, DevY: Byte); +procedure g_GFX_SparkVel (fX, fY: Integer; Count: Word; VX, VY: Integer; DevX, DevY: Byte); var a: Integer; DevX1, DevX2, @@ -264,10 +342,8 @@ var l: Integer; begin l := Length(Particles); - if l = 0 then - Exit; - if Count > l then - Count := l; + if l = 0 then exit; + if Count > l then Count := l; DevX1 := DevX div 2; DevX2 := DevX + 1; @@ -303,7 +379,7 @@ begin LiveTime := 30+Random(60); ParticleType := PARTICLE_SPARK; - CorrectOffsets(CurrentParticle); + {CorrectOffsets(CurrentParticle);} end; if CurrentParticle+2 > MaxParticles then @@ -313,6 +389,7 @@ begin end; end; + procedure g_GFX_Blood(fX, fY: Integer; Count: Word; vx, vy: Integer; DevX, DevY: Word; CR, CG, CB: Byte; Kind: Byte = BLOOD_NORMAL); var @@ -346,10 +423,13 @@ begin X := fX - DevX1 + Random(DevX2); Y := fY - DevY1 + Random(DevY2); + { if (X < 0) or (X > gMapInfo.Width-1) or (Y < 0) or (Y > gMapInfo.Height-1) or ByteBool(gCollideMap[Y, X] and MARK_WALL) then Continue; + } + if isWallAt(X, Y) then continue; VelX := vx + (Random-Random)*3; VelY := vy + (Random-Random)*3; @@ -396,7 +476,7 @@ begin LiveTime := 120+Random(40); ParticleType := PARTICLE_BLOOD; - CorrectOffsets(CurrentParticle); + {CorrectOffsets(CurrentParticle);} end; if CurrentParticle >= MaxParticles-1 then @@ -406,6 +486,7 @@ begin end; end; + procedure g_GFX_Spark(fX, fY: Integer; Count: Word; Angle: SmallInt; DevX, DevY: Byte); var a: Integer; @@ -457,7 +538,7 @@ begin LiveTime := 30+Random(60); ParticleType := PARTICLE_SPARK; - CorrectOffsets(CurrentParticle); + {CorrectOffsets(CurrentParticle);} end; if CurrentParticle+2 > MaxParticles then @@ -539,7 +620,7 @@ begin LiveTime := 60+Random(60); ParticleType := PARTICLE_WATER; - CorrectOffsets(CurrentParticle); + {CorrectOffsets(CurrentParticle);} end; if CurrentParticle+2 > MaxParticles then @@ -624,7 +705,7 @@ begin LiveTime := 60+Random(60); ParticleType := PARTICLE_WATER; - CorrectOffsets(CurrentParticle); + {CorrectOffsets(CurrentParticle);} end; if CurrentParticle+2 > MaxParticles then @@ -634,12 +715,13 @@ begin end; end; + procedure g_GFX_Bubbles(fX, fY: Integer; Count: Word; DevX, DevY: Byte); var a: Integer; DevX1, DevX2, DevY1, DevY2: Byte; - l: Integer; + l, liquidx: Integer; begin l := Length(Particles); if l = 0 then @@ -663,8 +745,15 @@ begin (Y >= gMapInfo.Height) or (Y <= 0) then Continue; - if not ByteBool(gCollideMap[Y, X] and MARK_LIQUID) then + (* + // don't spawn bubbles outside of the liquid + if not isLiquidAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then Continue; + *) + + // trace liquid, so we'll know where it ends; do it in 8px steps for speed + // tracer will return `false` if we started outside of the liquid + if not g_Map_TraceLiquid(X, Y, 0, -8, liquidx, liquidTopY) then continue; VelX := 0; VelY := -1-Random; @@ -681,7 +770,7 @@ begin LiveTime := 65535; ParticleType := PARTICLE_BUBBLES; - CorrectOffsets(CurrentParticle); + {CorrectOffsets(CurrentParticle);} end; if CurrentParticle+2 > MaxParticles then @@ -692,13 +781,16 @@ begin end; procedure g_GFX_SetMax(Count: Integer); +var + a: Integer; begin - if Count > 50000 then - Count := 50000; + if Count > 50000 then Count := 50000; + if (Count < 1) then Count := 1; SetLength(Particles, Count); + for a := 0 to High(Particles) do Particles[a].State := STATE_FREE; MaxParticles := Count; - if CurrentParticle >= Count then + //if CurrentParticle >= Count then CurrentParticle := 0; end; @@ -755,8 +847,9 @@ var dX, dY: SmallInt; b, len: Integer; s: ShortInt; - c: Byte; + //c: Byte; begin + if not gpart_dbg_enabled then exit; if Particles <> nil then begin w := gMapInfo.Width; @@ -765,15 +858,15 @@ begin len := High(Particles); for a := 0 to len do - if Particles[a].State <> 0 then + begin + if Particles[a].State <> STATE_FREE then + begin with Particles[a] do begin - if Time = LiveTime then - State := STATE_FREE; - if (X+1 >= w) or (Y+1 >= h) or (X <= 0) or (Y <= 0) then - State := STATE_FREE; - if State = STATE_FREE then - Continue; + if Time = LiveTime then State := STATE_FREE; + if (X+1 >= w) or (Y+1 >= h) or (X <= 0) or (Y <= 0) then State := STATE_FREE; + if State = STATE_FREE then Continue; + //e_WriteLog(Format('particle #%d: %d', [State, ParticleType]), MSG_NOTIFY); case ParticleType of PARTICLE_BLOOD: @@ -781,10 +874,18 @@ begin if gAdvBlood then begin if (State = STATE_STICK) then + { if (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) and (not ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED)) then + (not ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED)) + then + } + if (not isBlockedAt(X, Y-1)) and + (not isBlockedAt(X, Y+1)) and + (not isBlockedAt(X-1, Y)) and + (not isBlockedAt(X+1, Y)) + then begin // Îòëèïëà - êàïàåò VelY := 0.5; AccelY := 0.15; @@ -798,9 +899,9 @@ begin Continue; end; - if not ByteBool(gCollideMap[Y, X] and MARK_BLOCKED) then + if not isBlockedAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)} then begin - if ByteBool(gCollideMap[Y, X] and MARK_LIFTUP) then + if isLiftUpAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIFTUP)} then begin // Ëèôò ââåðõ if VelY > -4-Random(3) then VelY := VelY - 0.8; @@ -809,13 +910,13 @@ begin VelX := VelX + (Random-Random)*0.2; AccelY := 0.15; end; - if ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT) then + if isLiftLeftAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT)} then begin // Ïîòîê âëåâî if VelX > -8-Random(3) then VelX := VelX - 0.8; AccelY := 0.15; end; - if ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT) then + if isLiftRightAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT)} then begin // Ïîòîê âïðàâî if VelX < 8+Random(3) then VelX := VelX + 0.8; @@ -828,9 +929,9 @@ begin if (Abs(VelX) < 0.1) and (Abs(VelY) < 0.1) then if (State <> STATE_STICK) and - (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) then + (not isBlockedAt(X, Y-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and + (not isBlockedAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and + (not isBlockedAt(X, Y+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then begin // Âèñèò â âîçäóõå - êàïàåò VelY := 0.8; AccelY := 0.5; @@ -854,9 +955,9 @@ begin Break; end; - c := gCollideMap[Y, X+s]; + //c := gCollideMap[Y, X+s]; - if ByteBool(c and MARK_BLOCKED) then + if isBlockedAt(X+s, Y) {ByteBool(c and MARK_BLOCKED)} then begin // Ñòåíà/äâåðü VelX := 0; VelY := 0; @@ -887,9 +988,9 @@ begin Break; end; - c := gCollideMap[Y+s, X]; + //c := gCollideMap[Y+s, X]; - if ByteBool(c and MARK_BLOCKED) then + if isBlockedAt(X, Y+s) {ByteBool(c and MARK_BLOCKED)} then begin // Ñòåíà/äâåðü VelX := 0; VelY := 0; @@ -913,7 +1014,7 @@ begin if (X+dX >= w) or (Y+dY >= h) or (X+dX <= 0) or (Y+dY <= 0) or - ByteBool(gCollideMap[Y+dY, X+dX] and MARK_BLOCKED) then + isBlockedAt(X+dX, Y+dY) {ByteBool(gCollideMap[Y+dY, X+dX] and MARK_BLOCKED)} then begin // Ñòåíà/äâåðü/ãðàíèöà State := STATE_FREE; VelX := 0; @@ -930,7 +1031,7 @@ begin VelY := VelY + AccelY; // Êðîâü ðàñòâîðÿåòñÿ â æèäêîñòè: - if ByteBool(gCollideMap[Y, X] and MARK_LIQUID) then + if isLiquidAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then begin Inc(Time); @@ -944,9 +1045,9 @@ begin dY := Round(VelY); if (Abs(VelX) < 0.1) and (Abs(VelY) < 0.1) and - (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) then + (not isBlockedAt(X, Y-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and + (not isBlockedAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and + (not isBlockedAt(X, Y+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then begin // Âèñèò â âîçäóõå VelY := 0.8; AccelY := 0.5; @@ -969,16 +1070,16 @@ begin Break; end; - c := gCollideMap[Y, X+s]; + //c := gCollideMap[Y, X+s]; - if ByteBool(c and MARK_BLOCKED) then + if isBlockedAt(X+s, Y) {ByteBool(c and MARK_BLOCKED)} then begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî VelX := 0; AccelX := 0; Break; end else // Ïóñòî: - if c = MARK_FREE then + if not isAnythingAt(X+s, Y) {c = MARK_FREE} then X := X + s else // Îñòàëüíîå: begin @@ -1005,9 +1106,9 @@ begin Break; end; - c := gCollideMap[Y+s, X]; + //c := gCollideMap[Y+s, X]; - if ByteBool(c and MARK_BLOCKED) then + if isBlockedAt(X, Y+s) {ByteBool(c and MARK_BLOCKED)} then begin // Ñòåíà/äâåðü - ïàäàåò âåðòèêàëüíî if s < 0 then begin @@ -1025,7 +1126,7 @@ begin Break; end else // Ïóñòî: - if c = MARK_FREE then + if not isAnythingAt(X, Y+s) {c = MARK_FREE} then Y := Y + s else // Îñàëüíîå: begin @@ -1053,15 +1154,15 @@ begin begin // Ñòåêàåò/îòëèïàåò VelY := 0.5; AccelY := 0.15; - if (not ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED)) then + if (not isBlockedAt(X-1, Y) {ByteBool(gCollideMap[Y, X-1] and MARK_BLOCKED)}) and + (not isBlockedAt(X+1, Y) {ByteBool(gCollideMap[Y, X+1] and MARK_BLOCKED)}) then State := STATE_NORMAL; Continue; end; - if not ByteBool(gCollideMap[Y, X] and MARK_BLOCKED) then + if not isBlockedAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)} then begin - if ByteBool(gCollideMap[Y, X] and MARK_LIFTUP) then + if isLiftUpAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIFTUP)} then begin // Ëèôò ââåðõ if VelY > -4-Random(3) then VelY := VelY - 0.8; @@ -1070,13 +1171,13 @@ begin VelX := VelX + (Random-Random)*0.2; AccelY := 0.15; end; - if ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT) then + if isLiftLeftAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIFTLEFT)} then begin // Ïîòîê âëåâî if VelX > -8-Random(3) then VelX := VelX - 0.8; AccelY := 0.15; end; - if ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT) then + if isLiftRightAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_LIFTRIGHT)} then begin // Ïîòîê âïðàâî if VelX < 8+Random(3) then VelX := VelX + 0.8; @@ -1089,9 +1190,9 @@ begin if (Abs(VelX) < 0.1) and (Abs(VelY) < 0.1) then if (State <> STATE_STICK) and - (not ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)) and - (not ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)) then + (not isBlockedAt(X, Y-1) {ByteBool(gCollideMap[Y-1, X] and MARK_BLOCKED)}) and + (not isBlockedAt(X, Y) {ByteBool(gCollideMap[Y, X] and MARK_BLOCKED)}) and + (not isBlockedAt(X, Y+1) {ByteBool(gCollideMap[Y+1, X] and MARK_BLOCKED)}) then begin // Âèñèò â âîçäóõå - êàïàåò VelY := 0.8; AccelY := 0.5; @@ -1113,15 +1214,15 @@ begin Break; end; - c := gCollideMap[Y, X+s]; + //c := gCollideMap[Y, X+s]; - if ByteBool(c and MARK_LIQUID) and (dY > 0) then + if isLiquidAt(X+s, Y) {ByteBool(c and MARK_LIQUID)} and (dY > 0) then begin // Ñáîêó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò State := STATE_FREE; Break; end; - if ByteBool(c and MARK_BLOCKED) then + if isBlockedAt(X+s, Y) {ByteBool(c and MARK_BLOCKED)} then begin // Ñòåíà/äâåðü VelX := 0; VelY := 0; @@ -1150,15 +1251,15 @@ begin Break; end; - c := gCollideMap[Y+s, X]; + //c := gCollideMap[Y+s, X]; - if ByteBool(c and MARK_LIQUID) and (dY > 0) then + if isLiquidAt(X, Y+s) {ByteBool(c and MARK_LIQUID)} and (dY > 0) then begin // Ñíèçó æèäêîñòü, à ÷àñòèöà óæå ïàäàåò State := STATE_FREE; Break; end; - if ByteBool(c and MARK_BLOCKED) then + if isBlockedAt(X, Y+s) {ByteBool(c and MARK_BLOCKED)} then begin // Ñòåíà/äâåðü VelX := 0; VelY := 0; @@ -1200,7 +1301,7 @@ begin Break; end; - if not ByteBool(gCollideMap[Y+s, X] and MARK_LIQUID) then + if not isLiquidAt(X, Y+s) {ByteBool(gCollideMap[Y+s, X] and MARK_LIQUID)} then begin // Óæå íå æèäêîñòü State := STATE_FREE; Break; @@ -1217,8 +1318,10 @@ begin end; end; // case - CorrectOffsets(a); - end; + {CorrectOffsets(a);} + end; // with + end; // if + end; // for end; // Particles <> nil if OnceAnims <> nil then