summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 6bd2d9e)
raw | patch | inline | side by side (parent: 6bd2d9e)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Fri, 1 Sep 2017 15:54:36 +0000 (18:54 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Fri, 1 Sep 2017 19:17:53 +0000 (22:17 +0300) |
src/game/g_gfx.pas | patch | blob | history | |
src/game/g_map.pas | patch | blob | history | |
src/game/g_panel.pas | patch | blob | history |
diff --git a/src/game/g_gfx.pas b/src/game/g_gfx.pas
index 7903e13b28ca2a8d139e29b42ab64c4c3f937911..b7e5ff73c2f21188708b7dec90b91b43b3789494 100644 (file)
--- a/src/game/g_gfx.pas
+++ b/src/game/g_gfx.pas
procedure g_GFX_OnceAnim(X, Y: Integer; Anim: TAnimation; AnimType: Byte = 0);
-procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean=true);
+procedure g_Mark (x, y, Width, Height: Integer; t: Byte; st: Boolean=true);
-procedure g_GFX_Update();
-procedure g_GFX_Draw();
+procedure g_GFX_Update ();
+procedure g_GFX_Draw ();
var
procedure thinkerBubble ();
procedure thinkerWater ();
+ function isSleeping (): Boolean; inline;
+ procedure awake (); inline;
+
function alive (): Boolean; inline;
procedure die (); inline;
procedure think (); inline;
OnceAnims: array of TOnceAnim;
MaxParticles: Integer;
CurrentParticle: Integer;
+ // awakeMap has one bit for each map grid cell; on g_Mark,
+ // corresponding bits will be set, and in `think()` all particles
+ // in marked cells will be awaken
+ awakeMap: packed array of LongWord = nil;
+ awakeMapH: Integer = -1;
+ awakeMapW: Integer = -1;
+ awakeMinX, awakeMinY: Integer;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+// HACK! using mapgrid
+procedure awmClear (); inline;
+begin
+ if (awakeMapW > 0) then FillDWord(awakeMap[0], Length(awakeMap), 0);
+end;
+
+
+procedure awmSetup ();
+begin
+ assert(mapGrid <> nil);
+ awakeMapW := (mapGrid.gridWidth+mapGrid.tileSize-1) div mapGrid.tileSize;
+ awakeMapW := (awakeMapW+31) div 32; // LongWord has 32 bits ;-)
+ awakeMapH := (mapGrid.gridHeight+mapGrid.tileSize-1) div mapGrid.tileSize;
+ awakeMinX := mapGrid.gridX0;
+ awakeMinY := mapGrid.gridY0;
+ SetLength(awakeMap, awakeMapW*awakeMapH);
+ {$IF DEFINED(D2F_DEBUG)}
+ e_LogWritefln('particle awake map: %sx%s (for grid of size %sx%s)', [awakeMapW, awakeMapH, mapGrid.gridWidth, mapGrid.gridHeight]);
+ {$ENDIF}
+ awmClear();
+end;
+
+
+function awmIsSet (x, y: Integer): Boolean; inline;
+begin
+ x := (x-awakeMinX) div mapGrid.tileSize;
+ y := (y-awakeMinY) div mapGrid.tileSize;
+ if (x >= 0) and (y >= 0) and (x div 32 < awakeMapW) and (y < awakeMapH) then
+ begin
+ {$IF DEFINED(D2F_DEBUG)}
+ assert(y*awakeMapW+x div 32 < Length(awakeMap));
+ {$ENDIF}
+ result := ((awakeMap[y*awakeMapW+x div 32] and (LongWord(1) shl (x mod 32))) <> 0);
+ end
+ else
+ begin
+ result := false;
+ end;
+end;
+
+
+procedure awmSet (x, y: Integer); inline;
+var
+ v: PLongWord;
+begin
+ x := (x-awakeMinX) div mapGrid.tileSize;
+ y := (y-awakeMinY) div mapGrid.tileSize;
+ if (x >= 0) and (y >= 0) and (x div 32 < awakeMapW) and (y < awakeMapH) then
+ begin
+ {$IF DEFINED(D2F_DEBUG)}
+ assert(y*awakeMapW+x div 32 < Length(awakeMap));
+ {$ENDIF}
+ v := @awakeMap[y*awakeMapW+x div 32];
+ v^ := v^ or (LongWord(1) shl (x mod 32));
+ end;
+end;
// ////////////////////////////////////////////////////////////////////////// //
function TParticle.alive (): Boolean; inline; begin result := (State <> STATE_FREE); end;
procedure TParticle.die (); inline; begin State := STATE_FREE; end;
+function TParticle.isSleeping (): Boolean; inline;
+begin
+ result := alive and (onGround or (not justSticked and (State = STATE_STICK)));
+end;
+
+procedure TParticle.awake (); inline;
+begin
+ if {alive and} (onGround or (not justSticked and (State = STATE_STICK))) then
+ begin
+ // wakeup this particle
+ {
+ if (part.ParticleType = PARTICLE_SPARK) then
+ begin
+ e_LogWritefln('waking up particle of type %s; justSticked=%s; onGround=%s; VelY=%s; AccelY=%s', [part.ParticleType, part.justSticked, part.onGround, part.VelY, part.AccelY]);
+ end;
+ }
+ justSticked := true; // so sticked state will be re-evaluated
+ if onGround then
+ begin
+ if (VelY = 0) then VelY := 0.1;
+ if (AccelY = 0) then AccelY := 0.5;
+ end;
+ onGround := false; // so onground state will be re-evaluated
+ awaken := true;
+ end;
+end;
+
+
procedure TParticle.think (); inline;
begin
+ // awake sleeping particle, if necessary
+ if isSleeping then
+ begin
+ if awmIsSet(X, Y) then awake();
+ end;
case ParticleType of
PARTICLE_BLOOD: thinkerBlood();
PARTICLE_SPARK: thinkerSpark();
end;
+// st: set mark
+// t: mark type
+// currently unused
procedure g_Mark(x, y, Width, Height: Integer; t: Byte; st: Boolean=true);
-{$IF not DEFINED(HAS_COLLIDE_BITMAP)}
var
- part: PParticle;
- f: Integer;
+ cx, ex, ey: Integer;
+ ts: Integer;
begin
- for f := 0 to High(Particles) do
+ 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
- part := @Particles[f];
- if part.alive and (part.onGround or (not part.justSticked and (part.State = STATE_STICK))) and
- (part.X >= x-2) and (part.Y >= y-2) and (part.X < x+Width+4) and (part.Y < y+Height+4) then
+ cx := x;
+ while (cx < ex) do
begin
- // wakup this particle
- {
- if (part.ParticleType = PARTICLE_SPARK) then
- begin
- e_LogWritefln('waking up particle of type %s; justSticked=%s; onGround=%s; VelY=%s; AccelY=%s', [part.ParticleType, part.justSticked, part.onGround, part.VelY, part.AccelY]);
- end;
- }
- part.justSticked := true; // so sticked state will be re-evaluated
- if part.onGround then
- begin
- if (part.VelY = 0) then part.VelY := 0.1;
- if (part.AccelY = 0) then part.AccelY := 0.5;
- end;
- part.onGround := false; // so onground state will be re-evaluated
- part.awaken := true;
+ awmSet(cx, y);
+ Inc(cx, ts);
end;
+ Inc(y, ts);
end;
end;
-{$ELSE}
-var
- yy, y2, xx, x2: Integer;
-begin
- if x < 0 then
- begin
- Width := Width + x;
- x := 0;
- end;
-
- if Width < 0 then
- Exit;
-
- if y < 0 then
- begin
- Height := Height + y;
- y := 0;
- end;
-
- if Height < 0 then
- Exit;
-
- if x > gMapInfo.Width then
- Exit;
- if y > gMapInfo.Height then
- Exit;
-
- y2 := y + Height - 1;
- if y2 > gMapInfo.Height then
- y2 := gMapInfo.Height;
-
- x2 := x + Width - 1;
- if x2 > gMapInfo.Width then
- x2 := gMapInfo.Width;
-
- if st then
- begin // Óñòàíîâèòü ïðèçíàê
- for yy := y to y2 do
- for xx := x to x2 do
- gCollideMap[yy][xx] := gCollideMap[yy][xx] or t;
- end
- else
- begin // Óáðàòü ïðèçíàê
- t := not t;
- for yy := y to y2 do
- for xx := x to x2 do
- gCollideMap[yy][xx] := gCollideMap[yy][xx] and t;
- end;
-end;
-{$ENDIF}
{$IF DEFINED(HAS_COLLIDE_BITMAP)}
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);
-
- if gWater <> nil then
- begin
- g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 2/6', 0, True);
- for a := 0 to High(gWater) do
- with gWater[a] do
- g_Mark(X, Y, Width, Height, MARK_WATER, True);
- end;
-
- if gAcid1 <> nil then
- begin
- g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 3/6', 0, True);
- for a := 0 to High(gAcid1) do
- with gAcid1[a] do
- g_Mark(X, Y, Width, Height, MARK_ACID, True);
- end;
-
- if gAcid2 <> nil then
- begin
- g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 4/6', 0, True);
- for a := 0 to High(gAcid2) do
- with gAcid2[a] do
- g_Mark(X, Y, Width, Height, MARK_ACID, True);
- end;
-
- if gLifts <> nil then
- begin
- g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 5/6', 0, True);
- for a := 0 to High(gLifts) do
- with gLifts[a] do
- begin
- g_Mark(X, Y, Width, Height, MARK_LIFT, False);
-
- if LiftType = 0 then
- g_Mark(X, Y, Width, Height, MARK_LIFTUP, True)
- else if LiftType = 1 then
- g_Mark(X, Y, Width, Height, MARK_LIFTDOWN, True)
- else if LiftType = 2 then
- g_Mark(X, Y, Width, Height, MARK_LIFTLEFT, True)
- else if LiftType = 3 then
- g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT, True)
- end;
- end;
-
- if gWalls <> nil then
- begin
- g_Game_SetLoadingText(_lc[I_LOAD_COLLIDE_MAP]+' 6/6', 0, True);
- for a := 0 to High(gWalls) do
- begin
- if gWalls[a].Door then
- begin
- // Çàêðûòàÿ äâåðü:
- if gWalls[a].Enabled then
- with gWalls[a] do
- g_Mark(X, Y, Width, Height, MARK_DOOR, True)
- else // Îòêðûòàÿ äâåðü:
- if gWalls[a].Enabled then
- with gWalls[a] do
- g_Mark(X, Y, Width, Height, MARK_DOOR, False);
- end
- else // Ñòåíà
- with gWalls[a] do
- g_Mark(X, Y, Width, Height, MARK_WALL, True);
- end;
- end;
+ //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}
for a := 0 to High(Particles) do Particles[a].die();
CurrentParticle := 0;
- if OnceAnims <> nil then
+ if (OnceAnims <> nil) then
begin
- for a := 0 to High(OnceAnims) do
- OnceAnims[a].Animation.Free();
-
+ for a := 0 to High(OnceAnims) do OnceAnims[a].Animation.Free();
OnceAnims := nil;
end;
+
+ awakeMap := nil;
+ // why not?
+ awakeMapH := -1;
+ awakeMapW := -1;
end;
len: Integer;
begin
if not gpart_dbg_enabled then exit;
- if Particles <> nil then
+
+ if (Particles <> nil) then
begin
w := gMapInfo.Width;
h := gMapInfo.Height;
end; // for
end; // Particles <> nil
+ // clear awake map
+ awmClear();
+
if OnceAnims <> nil then
begin
for a := 0 to High(OnceAnims) do
diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 5c3a8a17ef5ef457e970dc450bc6ef9e03c4a321..ff6e7570c3b35863ce5ad0dd26127907ed12d8ce 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
begin
pan := gWalls[ID];
pan.Enabled := True;
- g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, True);
+ g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, true);
mapGrid.proxyEnabled[pan.proxyId] := true;
//if (pan.proxyId >= 0) then mapGrid.proxyEnabled[pan.proxyId] := true
begin
pan := gWalls[ID];
pan.Enabled := False;
- g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, False);
+ g_Mark(pan.X, pan.Y, pan.Width, pan.Height, MARK_DOOR, false);
mapGrid.proxyEnabled[pan.proxyId] := false;
//if (pan.proxyId >= 0) then begin mapGrid.removeBody(pan.proxyId); pan.proxyId := -1; end;
begin
LiftType := t;
- g_Mark(X, Y, Width, Height, MARK_LIFT, False);
+ g_Mark(X, Y, Width, Height, MARK_LIFT, false);
//TODO: make separate lift tags, and change tag here
- if LiftType = 0 then
- g_Mark(X, Y, Width, Height, MARK_LIFTUP, True)
- else if LiftType = 1 then
- g_Mark(X, Y, Width, Height, MARK_LIFTDOWN, True)
- else if LiftType = 2 then
- g_Mark(X, Y, Width, Height, MARK_LIFTLEFT, True)
- else if LiftType = 3 then
- g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT, True);
+ case LiftType of
+ 0: g_Mark(X, Y, Width, Height, MARK_LIFTUP);
+ 1: g_Mark(X, Y, Width, Height, MARK_LIFTDOWN);
+ 2: g_Mark(X, Y, Width, Height, MARK_LIFTLEFT);
+ 3: g_Mark(X, Y, Width, Height, MARK_LIFTRIGHT);
+ end;
if g_Game_IsServer and g_Game_IsNet then MH_SEND_PanelState(PanelType, ID);
end;
diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas
index 634e21bfca8bd5ca3672e461352666a32f7cadec..685c245ffe075590491851c94d6e95699296e8c1 100644 (file)
--- a/src/game/g_panel.pas
+++ b/src/game/g_panel.pas
implementation
uses
- SysUtils, g_basic, g_map, g_game, e_graphics,
+ SysUtils, g_basic, g_map, g_game, g_gfx, e_graphics,
g_console, g_language, g_monsters, g_player, e_log, GL;
const
monMoveListUsed := 0;
nx := X+mMovingSpeed.X;
ny := Y+mMovingSpeed.Y;
+ // move monsters on lifts
g_Mons_ForEachAt(X, Y-1, Width, 1, monMove);
+ // push monsters
g_Mons_ForEachAt(nx, ny, Width, Height, monPush);
+ // move and push players
for f := 0 to High(gPlayers) do plrMove(gPlayers[f]);
+ // reverse moving direction, if necessary
if (mMovingSpeed.X < 0) and (nx <= mMovingStart.X) then mMovingSpeed.X := -mMovingSpeed.X
else if (mMovingSpeed.X > 0) and (nx >= mMovingEnd.X) then mMovingSpeed.X := -mMovingSpeed.X;
if (mMovingSpeed.Y < 0) and (ny <= mMovingStart.Y) then mMovingSpeed.Y := -mMovingSpeed.Y
else if (mMovingSpeed.Y > 0) and (ny >= mMovingEnd.Y) then mMovingSpeed.Y := -mMovingSpeed.Y;
- //!!!g_Mark(X, Y, Width, Height, MARK_FREE);
+ // awake particles
+ g_Mark(X, Y, Width, Height, MARK_WALL, false);
X := nx;
Y := ny;
- //!!!g_Mark(X, Y, Width, Height, MARK_WALL);
+ g_Mark(nx, ny, Width, Height, MARK_WALL);
+ // fix grid
if (proxyId >= 0) then mapGrid.moveBody(proxyId, nx, ny);
+ // notify moved monsters about their movement
for f := 0 to monMoveListUsed-1 do monMoveList[f].positionChanged();
end;
end;
var
sig: DWORD;
anim: Boolean;
- ox, oy: Integer;
+ //ox, oy: Integer;
begin
if (Mem = nil) then exit;
//if not SaveIt then exit;
// Íîìåð òåêóùåé òåêñòóðû:
Mem.ReadInt(FCurTexture);
// Êîîðäû
- ox := FX;
- oy := FY;
+ //ox := FX;
+ //oy := FY;
Mem.ReadInt(FX);
Mem.ReadInt(FY);
//e_LogWritefln('panel %s(%s): old=(%s,%s); new=(%s,%s); delta=(%s,%s)', [arrIdx, proxyId, ox, oy, FX, FY, FX-ox, FY-oy]);