summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d25ad51)
raw | patch | inline | side by side (parent: d25ad51)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sat, 2 Sep 2017 17:15:00 +0000 (20:15 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sat, 2 Sep 2017 19:36:15 +0000 (22:36 +0300) |
src/game/g_gfx.pas | patch | blob | history |
diff --git a/src/game/g_gfx.pas b/src/game/g_gfx.pas
index 6a994723c44807e0f329321e8c95daf5c820e8a8..8e257f8e33e71068a24b88c543297ebdbd905fbc 100644 (file)
--- a/src/game/g_gfx.pas
+++ b/src/game/g_gfx.pas
procedure g_GFX_Init ();
procedure g_GFX_Free ();
-procedure g_GFX_Blood (fX, fY: Integer; Count: Word; vx, vy: Integer;
- DevX, DevY: Word; CR, CG, CB: Byte; Kind: Byte = BLOOD_NORMAL);
-procedure g_GFX_Spark (fX, fY: Integer; Count: Word; Angle: SmallInt; DevX, DevY: Byte);
-procedure g_GFX_Water (fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DevX, DevY, Color: Byte);
-procedure g_GFX_SimpleWater (fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DefColor, CR, CG, CB: Byte);
-procedure g_GFX_Bubbles (fX, fY: Integer; Count: Word; DevX, DevY: Byte);
-
-procedure g_GFX_SetMax (Count: Integer);
+procedure g_GFX_Blood (fX, fY: Integer; count: Word; vx, vy: Integer;
+ devX, devY: Word; cr, cg, cb: Byte; kind: Byte=BLOOD_NORMAL);
+procedure g_GFX_Spark (fX, fY: Integer; count: Word; angle: SmallInt; devX, devY: Byte);
+procedure g_GFX_Water (fX, fY: Integer; count: Word; fVelX, fVelY: Single; devX, devY, Color: Byte);
+procedure g_GFX_SimpleWater (fX, fY: Integer; count: Word; fVelX, fVelY: Single; defColor, cr, cg, cb: Byte);
+procedure g_GFX_Bubbles (fX, fY: Integer; count: Word; devX, devY: Byte);
+
+procedure g_GFX_SetMax (count: Integer);
function g_GFX_GetMax (): Integer;
procedure g_GFX_OnceAnim (X, Y: Integer; Anim: TAnimation; AnimType: Byte = 0);
// Wall: floorY is just before floor
// LiquidIn: floorY is liquid *start* (i.e. just in a liquid)
// LiquidOut: floorY is liquid *end* (i.e. just out of a liquid)
+ TEnvType = (EAir, ELiquid, EWall); // where particle is now
+ // note: this MUST be record, so we can keep it in
+ // dynamic array and has sequential memory access pattern
PParticle = ^TParticle;
TParticle = record
x, y: Integer;
justSticked: Boolean; // not used
floorY: Integer; // actually, floor-1; `Unknown`: unknown
floorType: TFloorType;
+ env: TEnvType; // where particle is now
ceilingY: Integer; // actually, ceiling+1; `Unknown`: unknown
- wallEndY: Integer; // if we stuck to a wall, this is where wall ends; will never be > floorY
+ wallEndY: Integer; // if we stuck to a wall, this is where wall ends
// for all
onGround: Boolean;
awaken: Boolean;
procedure findFloor (force: Boolean=false); // this updates `floorY` if forced or Unknown
procedure findCeiling (force: Boolean=false); // this updates `ceilingY` if forced or Unknown
+ procedure freeze (); inline; // remove velocities and acceleration
+ procedure sleep (); inline; // switch to sleep mode
+
function isSleeping (): Boolean; inline;
procedure awake (); inline;
end;
+// remove velocities and acceleration
+procedure TParticle.freeze (); inline;
+begin
+ // stop right there, you criminal scum!
+ velX := 0;
+ velY := 0;
+ accelX := 0;
+ accelY := 0;
+end;
+
+
+// switch to sleep mode
+procedure TParticle.sleep (); inline;
+begin
+ state := TPartState.Sleeping;
+ freeze();
+end;
+
+
procedure TParticle.findFloor (force: Boolean=false);
var
ex: Integer;
pan: TPanel;
begin
if (not force) and (floorY <> Unknown) then exit;
- // are we in a liquid?
- pan := g_Map_PanelAtPoint(x, y, (GridTagObstacle or GridTagLiquid));
- if (pan <> nil) then
+ // stuck in the wall? rescan, 'cause it can be mplat
+ if (env = TEnvType.EWall) then
begin
- // either in a wall, or in a liquid
- if ((pan.tag and GridTagObstacle) <> 0) then
+ pan := g_Map_PanelAtPoint(x, y, (GridTagObstacle or GridTagLiquid));
+ if (pan <> nil) then
begin
- // we are in the wall, wtf?!
- floorY := y;
- floorType := TFloorType.Wall;
- state := TPartState.Sleeping; // anyway
- exit;
+ // either in a wall, or in a liquid
+ if ((pan.tag and GridTagObstacle) <> 0) then
+ begin
+ // we are in the wall, wtf?!
+ floorY := y;
+ env := TEnvType.EWall;
+ floorType := TFloorType.Wall;
+ state := TPartState.Sleeping; // anyway
+ exit;
+ end;
+ // we are in liquid, trace to liquid end
+ env := TEnvType.ELiquid;
end;
- // we are in liquid, trace to liquid end
- floorType := TFloorType.LiquidOut; // exiting liquid
+ end;
+ // are we in a liquid?
+ if (env = TEnvType.ELiquid) then
+ begin
+ // trace out of the liquid
+ //env := TEnvType.ELiquid;
+ floorType := TFloorType.LiquidOut;
//e_LogWritefln('tracing out of a liquid; floorY=%s; y=%s', [floorY, y]);
mapGrid.traceOrthoRayWhileIn(ex, floorY, x, y, x, g_Map_MaxY, GridTagLiquid);
floorY += 1; // so `floorY` is just out of a liquid
end
else
begin
- // not in a wall
+ // in the air
+ assert(env = TEnvType.EAir);
+ //env := TEnvType.EAir;
pan := g_Map_traceToNearest(x, y, x, g_Map_MaxY, (GridTagObstacle or GridTagLiquid), @ex, @floorY);
if (pan <> nil) then
begin
end;
-// ////////////////////////////////////////////////////////////////////////// //
-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_OPENDOOR 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;
-
-
-// ////////////////////////////////////////////////////////////////////////// //
-// st: set mark
-// t: mark type
-// currently unused
-procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean=true);
-var
- cx, ex, ey: Integer;
- ts: Integer;
-begin
- if (Width < 1) or (Height < 1) then exit;
- // make some border, so we'll hit particles lying around the panel
- x -= 1; Width += 2;
- y -= 1; Height += 2;
- ex := x+Width;
- ey := y+Height;
- ts := mapGrid.tileSize;
- while (y < ey) do
- begin
- cx := x;
- while (cx < ex) do
- begin
- awmSet(cx, y);
- Inc(cx, ts);
- end;
- Inc(y, ts);
- end;
-end;
-
-
-// ////////////////////////////////////////////////////////////////////////// //
-{$IF DEFINED(HAS_COLLIDE_BITMAP)}
-procedure CreateCollideMap();
-var
- a: Integer;
-begin
- //g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 1/6', 0, False);
- //SetLength(gCollideMap, gMapInfo.Height+1);
- //for a := 0 to High(gCollideMap) do SetLength(gCollideMap[a], gMapInfo.Width+1);
-end;
-{$ENDIF}
-
-
-procedure g_GFX_Init();
-begin
- //CreateCollideMap();
- awmSetup();
-{$IFDEF HEADLESS}
- gpart_dbg_enabled := False;
-{$ENDIF}
-end;
-
-
-procedure g_GFX_Free();
-var
- a: Integer;
-begin
- Particles := nil;
- SetLength(Particles, MaxParticles);
- for a := 0 to High(Particles) do Particles[a].die();
- CurrentParticle := 0;
-
- if (OnceAnims <> nil) then
- begin
- for a := 0 to High(OnceAnims) do OnceAnims[a].Animation.Free();
- OnceAnims := nil;
- end;
-
- awakeMap := nil;
- // why not?
- awakeMapH := -1;
- awakeMapW := -1;
-end;
-
-
// ////////////////////////////////////////////////////////////////////////// //
procedure TParticle.thinkerBlood ();
procedure stickToCeiling ();
begin
state := TPartState.Stuck;
stickDX := 0;
- // stop right there, you criminal scum!
- velX := 0;
- velY := 0;
- accelX := 0;
- accelY := 0;
+ freeze();
ceilingY := y; // yep
end;
begin
state := TPartState.Stuck;
if (dX > 0) then stickDX := 1 else stickDX := -1;
- // stop right there, you criminal scum!
- velX := 0;
- velY := 0;
- accelX := 0;
- accelY := 0;
+ freeze();
// find next floor transition
findFloor();
// find `wallEndY`
procedure hitAFloor ();
begin
state := TPartState.Sleeping; // we aren't moving anymore
- // stop right there, you criminal scum!
- velX := 0;
- velY := 0;
- accelX := 0;
- accelY := 0;
+ freeze();
floorY := y; // yep
floorType := TFloorType.Wall; // yep
end;
end;
end;
- // switch to sleep mode
- procedure sleep ();
- begin
- state := TPartState.Sleeping;
- // stop right there, you criminal scum!
- velX := 0;
- velY := 0;
- accelX := 0;
- accelY := 0;
- end;
-
// switch to freefall mode
procedure freefall ();
begin
if gAdvBlood then
begin
// still check for air streams when sleeping
- if (state = TPartState.Sleeping) and not checkAirStreams() then exit;
+ if (state = TPartState.Sleeping) then begin checkAirStreams(); goto _done; end; // so blood will dissolve
// process stuck particles
if (state = TPartState.Stuck) then
// stuck to a ceiling?
if (stickDX = 0) then
begin
+ // yeah, stuck to a ceiling
assert(ceilingY <> Unknown);
// dropped from a ceiling?
if (y > ceilingY) then
end;
end;
- // horizontal movement
+ // trace movement
if (dX <> 0) then
begin
- pan := g_Map_traceToNearest(x, y, x+dX, y, (GridTagWall or GridTagDoor or GridTagStep), @ex, @ey);
+ // has some horizontal velocity
+ pan := g_Map_traceToNearest(x, y, x+dX, y+dY, GridTagObstacle, @ex, @ey);
if (x <> ex) then begin floorY := Unknown; ceilingY := Unknown; end; // dunno yet
x := ex;
+ y := ey;
if (x < g_Map_MinX) or (x > g_Map_MaxX) then begin die(); exit; end;
- if (pan <> nil) then stickToWall(dX); // nope, we stuck
- end;
-
- // vertical movement
- if (dY < 0) then
- begin
- // flying up
- if (ceilingY = Unknown) then findCeiling(); // need to do this anyway
- y += dY;
- if (y <= ceilingY) then begin y := ceilingY; stickToCeiling(); end; // oops, hit a ceiling
+ if (pan <> nil) then
+ begin
+ // we stuck
+ // the only case when we can have both ceiling and wall is corner; stick to wall in this case
+ // check environment (air/liquid)
+ if (g_Map_PanelAtPoint(x, y, GridTagLiquid) <> nil) then env := TEnvType.ELiquid else env := TEnvType.EAir;
+ // check if we stuck to a wall
+ if (dX < 0) then dX := -1 else dX := 1;
+ if (g_Map_PanelAtPoint(x+dX, y, GridTagObstacle) <> nil) then
+ begin
+ // stuck to a wall
+ stickToWall(dX);
+ end
+ else
+ begin
+ // stuck to a ceiling
+ stickToCeiling();
+ end;
+ end;
end
- else
+ else if (dY <> 0) then
begin
- while (dY > 0) do
+ // has only vertical velocity
+ if (dY < 0) then
begin
- // falling down
- if (floorY = Unknown) then findFloor(); // need to do this anyway
+ // flying up
+ if (ceilingY = Unknown) then findCeiling(); // need to do this anyway
y += dY;
- //e_LogWritefln('floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
- if (y >= floorY) then
+ if (y <= ceilingY) then begin y := ceilingY; stickToCeiling(); end; // oops, hit a ceiling
+ // environmend didn't changed
+ end
+ else
+ begin
+ while (dY > 0) do
begin
- // floor transition
- dY := y-floorY;
- y := floorY;
- //e_LogWritefln(' HIT FLOORY: floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
- case floorType of
- TFloorType.Wall: // hit the ground
- begin
- hitAFloor();
- break; // done with vertical movement
- end;
- TFloorType.LiquidIn: // entering the liquid
- begin
- // rescan, so we'll know when we'll exit the liquid
- findFloor(true); // force rescan
- end;
- TFloorType.LiquidOut: // exiting the liquid
- begin
- // rescan, so we'll know when we'll enter something interesting
- findFloor(true); // force rescan
- if (floorType = TFloorType.Wall) and (floorY = y) then
+ // falling down
+ if (floorY = Unknown) then findFloor(); // need to do this anyway
+ y += dY;
+ //e_LogWritefln('floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
+ if (y >= floorY) then
+ begin
+ // floor transition
+ dY := y-floorY;
+ y := floorY;
+ //e_LogWritefln(' HIT FLOORY: floorY=%s; newy=%s; dY=%s; floorType=%s', [floorY, y, dY, floorType]);
+ case floorType of
+ TFloorType.Wall: // hit the ground
begin
+ // environmend didn't changed
hitAFloor();
break; // done with vertical movement
end;
- end;
+ TFloorType.LiquidIn: // entering the liquid
+ begin
+ // we're entered the liquid
+ env := TEnvType.ELiquid;
+ // rescan, so we'll know when we'll exit the liquid
+ findFloor(true); // force rescan
+ end;
+ TFloorType.LiquidOut: // exiting the liquid
+ begin
+ // we're exited the liquid
+ env := TEnvType.EAir;
+ // rescan, so we'll know when we'll enter something interesting
+ findFloor(true); // force rescan
+ if (floorType = TFloorType.Wall) and (floorY = y) then
+ begin
+ hitAFloor();
+ break; // done with vertical movement
+ end;
+ end;
+ end;
+ end
+ else
+ begin
+ break; // done with vertical movement
end;
- end
- else
- begin
- break; // done with vertical movement
end;
end;
end;
- if (y < g_Map_MinY) or (y > g_Map_MaxY) then begin die(); exit; end;
end // if gAdvBlood
else
begin
// simple blood
dX := Round(velX);
dY := Round(velY);
- if (x+dX > g_Map_MaxX) or (y+dY > g_Map_MaxY) or (x+dX < g_Map_MinX) or (y+dY < g_Map_MinY) or isBlockedAt(x+dX, y+dY) then
- begin
- // Ñòåíà/äâåðü/ãðàíèöà
- die();
- exit;
- end
- else
- begin
- y += dY;
- x += dX;
- end;
+ y += dY;
+ x += dX;
+ if (x > g_Map_MaxX) or (y > g_Map_MaxY) or (x < g_Map_MinX) or (y < g_Map_MinY) then begin die(); exit; end;
+ if (g_Map_PanelAtPoint(x, y, GridTagObstacle) <> nil) then begin die(); exit; end;
end;
_done:
velY += accelY;
// blood will dissolve in other liquids
- if (floorType = TFloorType.LiquidOut) then
- begin
- time += 1;
- alpha := 255-trunc((255.0*time)/liveTime);
- end;
- (*
- // Êðîâü ðàñòâîðÿåòñÿ â æèäêîñòè
- if isLiquidAt(x, y) {ByteBool(gCollideMap[Y, X] and MARK_LIQUID)} then
+ if (env = TEnvType.ELiquid) then
begin
time += 1;
- alpha := 255-trunc((255.0*time)/liveTime);
+ ex := 255-trunc((255.0*time)/liveTime);
+ if (ex >= 255) then begin die(); exit; end;
+ if (ex < 0) then ex := 0;
+ alpha := Byte(ex);
end;
- *)
end;
-procedure g_GFX_SparkVel (fX, fY: Integer; Count: Word; VX, VY: Integer; DevX, DevY: Byte); forward;
+procedure g_GFX_SparkVel (fX, fY: Integer; count: Word; VX, VY: Integer; devX, devY: Byte); forward;
+
+procedure g_GFX_Blood (fX, fY: Integer; count: Word; vx, vy: Integer;
+ devX, devY: Word; cr, cg, cb: Byte; kind: Byte = BLOOD_NORMAL);
+
+ function genColor (cbase, crnd: Integer; def: Byte=0): Byte;
+ begin
+ if (cbase > 0) then
+ begin
+ cbase += crnd;
+ if (cbase < 0) then result := 0
+ else if (cbase > 255) then result := 255
+ else result := Byte(cbase);
+ end
+ else
+ begin
+ result := def;
+ 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
a: Integer;
- DevX1, DevX2, DevY1, DevY2: Word;
+ devX1, devX2, devY1, devY2: Word;
l: Integer;
- CRnd: Byte;
- CC: SmallInt;
+ crnd: Integer;
+ pan: TPanel;
begin
if not gpart_dbg_enabled then Exit;
- if (Kind = BLOOD_SPARKS) then
+ if (kind = BLOOD_SPARKS) then
begin
- g_GFX_SparkVel(fX, fY, 2+Random(2), -VX div 2, -VY div 2, DevX, DevY);
+ g_GFX_SparkVel(fX, fY, 2+Random(2), -VX div 2, -VY div 2, devX, devY);
exit;
end;
l := Length(Particles);
if (l = 0) then exit;
- if (Count > l) then Count := l;
+ if (count > l) then count := l;
- DevX1 := DevX div 2;
- DevX2 := DevX+1;
- DevY1 := DevY div 2;
- DevY2 := DevY+1;
+ devX1 := devX div 2;
+ devX2 := devX+1;
+ devY1 := devY div 2;
+ devY2 := devY+1;
- for a := 1 to Count do
+ for a := 1 to count do
begin
with Particles[CurrentParticle] do
begin
- x := fX-DevX1+Random(DevX2);
- y := fY-DevY1+Random(DevY2);
+ 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;
+ // check for level bounds
+ if (x < g_Map_MinX) or (y < g_Map_MinY) or (x > g_Map_MaxX) or (y > g_Map_MaxY) then continue;
+
+ // in what environment we are starting in?
+ pan := g_Map_PanelAtPoint(x, y, (GridTagObstacle or GridTagLiquid));
+ if (pan <> nil) then
+ begin
+ // either in a wall, or in a liquid
+ if ((pan.tag and GridTagObstacle) <> 0) then continue; // don't spawn in walls
+ env := TEnvType.ELiquid;
+ end
+ else
+ begin
+ env := TEnvType.EAir;
+ end;
velX := vx+(Random-Random)*3;
velY := vy+(Random-Random)*3;
accelX := -sign(velX)*Random/100;
accelY := 0.8;
- CRnd := 20*Random(6);
- if (CR > 0) then
- begin
- CC := CR+CRnd-50;
- if (CC < 0) then CC := 0
- else if (CC > 255) then CC := 255;
- red := CC;
- end
- else
- begin
- red := 0;
- end;
- if CG > 0 then
- begin
- CC := CG+CRnd-50;
- if (CC < 0) then CC := 0
- else if (CC > 255) then CC := 255;
- green := CC;
- end
- else
- begin
- green := 0;
- end;
- if (CB > 0) then
- begin
- CC := CB+CRnd-50;
- if (CC < 0) then CC := 0
- else if (CC > 255) then CC := 255;
- blue := CC;
- end
- else
- begin
- blue := 0;
- end;
+ crnd := 20*Random(6)-50;
+ red := genColor(cr, CRnd, 0);
+ green := genColor(cg, CRnd, 0);
+ blue := genColor(cb, CRnd, 0);
alpha := 255;
+ particleType := TPartType.Blood;
state := TPartState.Normal;
time := 0;
liveTime := 120+Random(40);
- particleType := TPartType.Blood;
- //justSticked := false;
- //onGround := (velY >= 0) and g_Map_HasAnyPanelAtPoint(x, y+1, (PANEL_WALL or PANEL_CLOSEDOOR or PANEL_STEP));
- //awaken := false;
- //stickEY := 0;
floorY := Unknown;
ceilingY := Unknown;
end;
- if CurrentParticle >= MaxParticles-1 then
- CurrentParticle := 0
- else
- CurrentParticle := CurrentParticle+1;
+ if (CurrentParticle >= MaxParticles-1) then CurrentParticle := 0 else CurrentParticle += 1;
end;
end;
+// ////////////////////////////////////////////////////////////////////////// //
+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_OPENDOOR 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 TParticle.thinkerWater ();
var
// ////////////////////////////////////////////////////////////////////////// //
-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,
- DevY1, DevY2: Byte;
+ devX1, devX2,
+ devY1, devY2: Byte;
l: Integer;
begin
exit;
if not gpart_dbg_enabled then Exit;
l := Length(Particles);
if l = 0 then exit;
- if Count > l then Count := l;
+ if count > l then count := l;
- DevX1 := DevX div 2;
- DevX2 := DevX + 1;
- DevY1 := DevY div 2;
- DevY2 := DevY + 1;
+ devX1 := devX div 2;
+ devX2 := devX + 1;
+ devY1 := devY div 2;
+ devY2 := devY + 1;
- for a := 1 to Count do
+ for a := 1 to count do
begin
with Particles[CurrentParticle] do
begin
- x := fX-DevX1+Random(DevX2);
- y := fY-DevY1+Random(DevY2);
+ x := fX-devX1+Random(devX2);
+ y := fY-devY1+Random(devY2);
velX := VX + (Random-Random)*3;
velY := VY + (Random-Random)*3;
end;
-procedure g_GFX_Spark(fX, fY: Integer; Count: Word; Angle: SmallInt; DevX, DevY: Byte);
+procedure g_GFX_Spark(fX, fY: Integer; count: Word; angle: SmallInt; devX, devY: Byte);
var
a: Integer;
b: Single;
- DevX1, DevX2,
- DevY1, DevY2: Byte;
+ devX1, devX2,
+ devY1, devY2: Byte;
BaseVelX, BaseVelY: Single;
l: Integer;
begin
l := Length(Particles);
if l = 0 then
Exit;
- if Count > l then
- Count := l;
+ if count > l then
+ count := l;
- Angle := 360 - Angle;
+ angle := 360 - angle;
- DevX1 := DevX div 2;
- DevX2 := DevX + 1;
- DevY1 := DevY div 2;
- DevY2 := DevY + 1;
+ devX1 := devX div 2;
+ devX2 := devX + 1;
+ devY1 := devY div 2;
+ devY2 := devY + 1;
- b := DegToRad(Angle);
+ b := DegToRad(angle);
BaseVelX := cos(b);
BaseVelY := 1.6*sin(b);
if Abs(BaseVelX) < 0.01 then
BaseVelX := 0.0;
if Abs(BaseVelY) < 0.01 then
BaseVelY := 0.0;
- for a := 1 to Count do
+ for a := 1 to count do
begin
with Particles[CurrentParticle] do
begin
- x := fX-DevX1+Random(DevX2);
- y := fY-DevY1+Random(DevY2);
+ x := fX-devX1+Random(devX2);
+ y := fY-devY1+Random(devY2);
velX := BaseVelX*Random;
velY := BaseVelY-Random;
end;
-procedure g_GFX_Water(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DevX, DevY, Color: Byte);
+procedure g_GFX_Water(fX, fY: Integer; count: Word; fVelX, fVelY: Single; devX, devY, Color: Byte);
var
a: Integer;
- DevX1, DevX2,
- DevY1, DevY2: Byte;
+ devX1, devX2,
+ devY1, devY2: Byte;
l: Integer;
begin
exit;
l := Length(Particles);
if l = 0 then
Exit;
- if Count > l then
- Count := l;
+ if count > l then
+ count := l;
if Abs(fVelX) < 3.0 then
fVelX := 3.0 - 6.0*Random;
- DevX1 := DevX div 2;
- DevX2 := DevX + 1;
- DevY1 := DevY div 2;
- DevY2 := DevY + 1;
+ devX1 := devX div 2;
+ devX2 := devX + 1;
+ devY1 := devY div 2;
+ devY2 := devY + 1;
- for a := 1 to Count do
+ for a := 1 to count do
begin
with Particles[CurrentParticle] do
begin
- x := fX-DevX1+Random(DevX2);
- y := fY-DevY1+Random(DevY2);
+ x := fX-devX1+Random(devX2);
+ y := fY-devY1+Random(devY2);
if Abs(fVelX) < 0.5 then
velX := 1.0 - 2.0*Random
end;
-procedure g_GFX_SimpleWater(fX, fY: Integer; Count: Word; fVelX, fVelY: Single; DefColor, CR, CG, CB: Byte);
+procedure g_GFX_SimpleWater(fX, fY: Integer; count: Word; fVelX, fVelY: Single; defColor, cr, cg, cb: Byte);
var
a: Integer;
l: Integer;
l := Length(Particles);
if l = 0 then
Exit;
- if Count > l then
- Count := l;
+ if count > l then
+ count := l;
- for a := 1 to Count do
+ for a := 1 to count do
begin
with Particles[CurrentParticle] do
begin
accelX := 0.0;
accelY := 0.8;
- case DefColor of
+ case defColor of
1: // Êðàñíûé
begin
red := 155 + Random(9)*10;
red := 20 + Random(19)*10;
green := red;
blue := red;
- red := Min(red + CR, 255);
- green := Min(green + CG, 255);
- blue := Min(blue + CB, 255);
+ red := Min(red + cr, 255);
+ green := Min(green + cg, 255);
+ blue := Min(blue + cb, 255);
end;
5: // Ñâîé öâåò, òåìíåå
begin
red := 20 + Random(19)*10;
green := red;
blue := red;
- red := Max(CR - red, 0);
- green := Max(CG - green, 0);
- blue := Max(CB - blue, 0);
+ red := Max(cr - red, 0);
+ green := Max(cg - green, 0);
+ blue := Max(cb - blue, 0);
end;
else // Ñåðûé
begin
{.$DEFINE D2F_DEBUG_BUBBLES}
-procedure g_GFX_Bubbles(fX, fY: Integer; Count: Word; DevX, DevY: Byte);
+procedure g_GFX_Bubbles(fX, fY: Integer; count: Word; devX, devY: Byte);
var
a: Integer;
- DevX1, DevX2,
- DevY1, DevY2: Byte;
+ devX1, devX2,
+ devY1, devY2: Byte;
l, liquidx: Integer;
{$IF DEFINED(D2F_DEBUG_BUBBLES)}
stt: UInt64;
l := Length(Particles);
if l = 0 then
Exit;
- if Count > l then
- Count := l;
+ if count > l then
+ count := l;
- DevX1 := DevX div 2;
- DevX2 := DevX + 1;
- DevY1 := DevY div 2;
- DevY2 := DevY + 1;
+ devX1 := devX div 2;
+ devX2 := devX + 1;
+ devY1 := devY div 2;
+ devY2 := devY + 1;
- for a := 1 to Count do
+ for a := 1 to count do
begin
with Particles[CurrentParticle] do
begin
- x := fX-DevX1+Random(DevX2);
- y := fY-DevY1+Random(DevY2);
+ x := fX-devX1+Random(devX2);
+ y := fY-devY1+Random(devY2);
if (x >= gMapInfo.Width) or (x <= 0) or
(y >= gMapInfo.Height) or (y <= 0) then
// ////////////////////////////////////////////////////////////////////////// //
-procedure g_GFX_SetMax(Count: Integer);
+procedure g_GFX_SetMax(count: Integer);
var
a: Integer;
begin
- if Count > 50000 then Count := 50000;
- if (Count < 1) then Count := 1;
+ if count > 50000 then count := 50000;
+ if (count < 1) then count := 1;
- SetLength(Particles, Count);
+ SetLength(Particles, count);
for a := 0 to High(Particles) do Particles[a].die();
- MaxParticles := Count;
+ MaxParticles := count;
//if CurrentParticle >= Count then
CurrentParticle := 0;
end;
end;
+// ////////////////////////////////////////////////////////////////////////// //
+// st: set mark
+// t: mark type
+// currently unused
+procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean=true);
+var
+ cx, ex, ey: Integer;
+ ts: Integer;
+begin
+ if (Width < 1) or (Height < 1) then exit;
+ // make some border, so we'll hit particles lying around the panel
+ x -= 1; Width += 2;
+ y -= 1; Height += 2;
+ ex := x+Width;
+ ey := y+Height;
+ ts := mapGrid.tileSize;
+ while (y < ey) do
+ begin
+ cx := x;
+ while (cx < ex) do
+ begin
+ awmSet(cx, y);
+ Inc(cx, ts);
+ end;
+ Inc(y, ts);
+ end;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+{$IF DEFINED(HAS_COLLIDE_BITMAP)}
+procedure CreateCollideMap();
+var
+ a: Integer;
+begin
+ //g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 1/6', 0, False);
+ //SetLength(gCollideMap, gMapInfo.Height+1);
+ //for a := 0 to High(gCollideMap) do SetLength(gCollideMap[a], gMapInfo.Width+1);
+end;
+{$ENDIF}
+
+
+procedure g_GFX_Init();
+begin
+ //CreateCollideMap();
+ awmSetup();
+{$IFDEF HEADLESS}
+ gpart_dbg_enabled := False;
+{$ENDIF}
+end;
+
+
+procedure g_GFX_Free();
+var
+ a: Integer;
+begin
+ Particles := nil;
+ SetLength(Particles, MaxParticles);
+ for a := 0 to High(Particles) do Particles[a].die();
+ CurrentParticle := 0;
+
+ if (OnceAnims <> nil) then
+ begin
+ for a := 0 to High(OnceAnims) do OnceAnims[a].Animation.Free();
+ OnceAnims := nil;
+ end;
+
+ awakeMap := nil;
+ // why not?
+ awakeMapH := -1;
+ awakeMapW := -1;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
procedure g_GFX_Update ();
var
a: Integer;