DEADSOFTWARE

smoother camera on stairs/slopes
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Wed, 30 Aug 2017 14:29:36 +0000 (17:29 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Wed, 30 Aug 2017 14:29:55 +0000 (17:29 +0300)
src/game/g_game.pas
src/game/g_grid.pas
src/game/g_phys.pas
src/game/g_player.pas
src/shared/utils.pas

index 1cf480864080a2c4115db2cae221b07de7e16299..66a589b316a7f447f4eda273418a3a4c08b1cdec 100644 (file)
@@ -2857,7 +2857,6 @@ procedure DrawPlayer(p: TPlayer);
 var
   px, py, a, b, c, d: Integer;
   //R: TRect;
-
 begin
   if (p = nil) or (p.FDummy) then
   begin
@@ -2875,7 +2874,7 @@ begin
   glPushMatrix();
 
   px := p.GameX + PLAYER_RECT_CX;
-  py := p.GameY + PLAYER_RECT_CY;
+  py := p.GameY + PLAYER_RECT_CY+p.Obj.slopeUpLeft;
 
   if px > (gPlayerScreenSize.X div 2) then a := -px+(gPlayerScreenSize.X div 2) else a := 0;
   if py > (gPlayerScreenSize.Y div 2) then b := -py+(gPlayerScreenSize.Y div 2) else b := 0;
index 06790755698dfce7e15d73241fdabd65b4cbe689..2d5d6323f00f2f0ae41d6728d073ea66d3f865cc 100644 (file)
@@ -20,7 +20,7 @@
   {.$DEFINE D2F_DEBUG_XXQ}
   {.$DEFINE D2F_DEBUG_MOVER}
 {$ENDIF}
-{$DEFINE GRID_USE_ORTHO_ACCEL}
+{.$DEFINE GRID_USE_ORTHO_ACCEL}
 unit g_grid;
 
 interface
index 498bd7587489f9faf6e72ffca873c72e06de6702..a88ca21c9da246a2f61e2f76ff17160cc032681e 100644 (file)
@@ -28,6 +28,10 @@ type
     Rect:    TRectWH;
     Vel:     TPoint2i;
     Accel:   TPoint2i;
+    // going up the slope will set this, and renderer will adjust the position
+    // this is purely visual change, it won't affect anything else
+    slopeUpLeft: Integer; // left to go
+    slopeFramesLeft: Integer; // frames left to go
   end;
 
 const
@@ -59,8 +63,8 @@ function  g_Obj_StayOnStep(Obj: PObj): Boolean;
 procedure g_Obj_Push(Obj: PObj; VelX, VelY: Integer);
 procedure g_Obj_PushA(Obj: PObj; Vel: Integer; Angle: SmallInt);
 procedure g_Obj_SetSpeed(Obj: PObj; s: Integer);
-function  z_dec(a, b: Integer): Integer;
-function  z_fdec(a, b: Double): Double;
+function  z_dec(a, b: Integer): Integer; inline;
+function  z_fdec(a, b: Double): Double; inline;
 
 var
   gMon: Boolean = False;
@@ -69,7 +73,12 @@ implementation
 
 uses
   g_map, g_basic, Math, g_player, g_console, SysUtils,
-  g_sound, g_gfx, MAPDEF, g_monsters, g_game, BinEditor;
+  g_sound, g_gfx, MAPDEF, g_monsters, g_game, BinEditor, utils;
+
+
+const
+  SmoothSlopeFrames = 4;
+
 
 function g_Obj_StayOnStep(Obj: PObj): Boolean;
 begin
@@ -122,25 +131,26 @@ end;
 
 function CollidePlayers(_Obj: PObj; XInc, YInc: Integer): Boolean;
 var
-  a: Integer;
+  plr: TPlayer;
 begin
-  Result := False;
-
-  if gPlayers = nil then
-    Exit;
-
-  for a := 0 to High(gPlayers) do
-    if gPlayers[a] <> nil then
-      with gPlayers[a] do
-        if Live and
-           g_Collide(GameX+PLAYER_RECT.X, GameY+PLAYER_RECT.Y,
-                     PLAYER_RECT.Width, PLAYER_RECT.Height,
-                     _Obj^.X+_Obj^.Rect.X+XInc, _Obj^.Y+_Obj^.Rect.Y+YInc,
-                     _Obj^.Rect.Width, _Obj^.Rect.Height) then
-        begin
-          Result := True;
-          Exit;
-        end;
+  result := false;
+  if (gPlayers = nil) then exit;
+  for plr in gPlayers do
+  begin
+    if (plr = nil) then continue;
+    if not plr.Live then continue;
+    with plr do
+    begin
+      if g_Collide(GameX+PLAYER_RECT.X, GameY+PLAYER_RECT.Y,
+                   PLAYER_RECT.Width, PLAYER_RECT.Height,
+                   _Obj^.X+_Obj^.Rect.X+XInc, _Obj^.Y+_Obj^.Rect.Y+YInc,
+                   _Obj^.Rect.Width, _Obj^.Rect.Height) then
+      begin
+        result := true;
+        exit;
+      end;
+    end;
+  end;
 end;
 
 function Blocked(Obj: PObj; XInc, YInc: Integer): Boolean;
@@ -189,8 +199,9 @@ procedure g_Obj_Splash(Obj: PObj; Color: Byte);
 var
   MaxVel: Integer;
 begin
-  MaxVel := Max(Abs(Obj^.Vel.X), Abs(Obj^.Vel.Y));
-  if MaxVel > 4 then begin
+  MaxVel := nmax(abs(Obj^.Vel.X), abs(Obj^.Vel.Y));
+  if MaxVel > 4 then
+  begin
     if MaxVel < 10 then
       g_Sound_PlayExAt('SOUND_GAME_BULK1', Obj^.X, Obj^.Y)
     else
@@ -199,162 +210,170 @@ begin
 
   g_GFX_Water(Obj^.X+Obj^.Rect.X+(Obj^.Rect.Width div 2),
               Obj^.Y+Obj^.Rect.Y+(Obj^.Rect.Height div 2),
-              Min(5*(Abs(Obj^.Vel.X)+Abs(Obj^.Vel.Y)), 50),
+              Min(5*(abs(Obj^.Vel.X)+abs(Obj^.Vel.Y)), 50),
               -Obj^.Vel.X, -Obj^.Vel.Y,
               Obj^.Rect.Width, 16, Color);
 end;
 
-function move(Obj: PObj; dx, dy: Integer; ClimbSlopes: Boolean): Word;
+
+function move (Obj: PObj; dx, dy: Integer; ClimbSlopes: Boolean): Word;
 var
   i: Integer;
   sx, sy: ShortInt;
   st: Word;
 
-  procedure slope(s: Integer);
+  procedure slope (s: Integer);
   var
     i: Integer;
   begin
     i := 0;
     while g_Obj_CollideLevel(Obj, sx, 0) and (i < 4) do
     begin
-      Obj^.Y := Obj^.Y + s;
+      Obj^.Y += s;
       Inc(i);
     end;
-    Obj^.X := Obj^.X + sx;
+    Obj^.X += sx;
+    if (s < 0) then
+    begin
+      Obj.slopeUpLeft += i*(-s);
+      Obj.slopeFramesLeft := SmoothSlopeFrames;
+    end;
   end;
 
-  function movex(): Boolean;
+  function movex (): Boolean;
   begin
-    Result := False;
+    result := false;
 
-  // Åñëè ìîíñòðó øàãíóòü â ñòîðîíó, à òàì áëîêìîí:
-    if gMon and not WordBool(st and MOVE_BLOCK) then
-      if Blocked(Obj, sx, 0) then
-        st := st or MOVE_BLOCK;
+    // Åñëè ìîíñòðó øàãíóòü â ñòîðîíó, à òàì áëîêìîí
+    if gMon and ((st and MOVE_BLOCK) = 0) then
+    begin
+      if Blocked(Obj, sx, 0) then st := st or MOVE_BLOCK;
+    end;
 
-  // Åñëè øàãíóòü â ñòîðîíó, à òàì ñòåíà => øàãàòü íåëüçÿ:
+    // Åñëè øàãíóòü â ñòîðîíó, à òàì ñòåíà => øàãàòü íåëüçÿ
     if g_Obj_CollideLevel(Obj, sx, 0) then
+    begin
+      if ClimbSlopes and (abs(dy) < 2) then
       begin
-        if ClimbSlopes and (Abs(dy) < 2) then
-          begin
-            Result := True;
-            if (not g_Obj_CollideLevel(Obj, sx, -12)) // çàáèðàåìñÿ íà 12 ïèêñåëåé âëåâî/âïðàâî
-            and g_Obj_CollidePanel(Obj, 0, 1, PANEL_WALL or PANEL_STEP) // òîëüêî åñëè åñòü çåìëÿ ïîä íîãàìè
-            then
-              slope(-1)
-            else
-              begin
-                Result := False;
-                st := st or MOVE_HITWALL;
-              end;
-          end
-          else
-            st := st or MOVE_HITWALL;
+        result := true;
+        if (not g_Obj_CollideLevel(Obj, sx, -12)) and // çàáèðàåìñÿ íà 12 ïèêñåëåé âëåâî/âïðàâî
+           g_Obj_CollidePanel(Obj, 0, 1, PANEL_WALL or PANEL_STEP) then // òîëüêî åñëè åñòü çåìëÿ ïîä íîãàìè
+        begin
+          slope(-1);
+        end
+        else
+        begin
+          result := false;
+          st := st or MOVE_HITWALL;
+        end;
       end
+      else
+      begin
+        st := st or MOVE_HITWALL;
+      end;
+    end
     else // Òàì ñòåíû íåò
+    begin
+      if CollideLiquid(Obj, sx, 0) then
+      begin // Åñëè øàãíóòü â ñòîðîíó, à òàì òåïåðü æèäêîñòü
+        if ((st and MOVE_INWATER) = 0) then st := st or MOVE_HITWATER;
+      end
+      else // Åñëè øàãíóòü â ñòîðîíó, à òàì óæå íåò æèäêîñòè
       begin
-        if CollideLiquid(Obj, sx, 0) then
-          begin // Åñëè øàãíóòü â ñòîðîíó, à òàì òåïåðü æèäêîñòü
-            if not WordBool(st and MOVE_INWATER) then
-              st := st or MOVE_HITWATER;
-          end
-        else // Åñëè øàãíóòü â ñòîðîíó, à òàì óæå íåò æèäêîñòè
-          if WordBool(st and MOVE_INWATER) then
-            st := st or MOVE_HITAIR;
-
-      // Øàã:
-        Obj^.X := Obj^.X + sx;
-        Result := True;
+        if ((st and MOVE_INWATER) <> 0) then st := st or MOVE_HITAIR;
       end;
+
+      // Øàã
+      Obj^.X += sx;
+      result := true;
+    end;
   end;
 
-  function movey(): Boolean;
+  function movey (): Boolean;
   begin
-    Result := False;
+    result := false;
 
-  // Åñëè ìîíñòðó øàãíóòü ïî âåðòèêàëè, à òàì áëîêìîí:
-    if gMon and not WordBool(st and MOVE_BLOCK) then
-      if Blocked(Obj, 0, sy) then
-        st := st or MOVE_BLOCK;
+    // Åñëè ìîíñòðó øàãíóòü ïî âåðòèêàëè, à òàì áëîêìîí
+    if gMon and ((st and MOVE_BLOCK) = 0) then
+    begin
+      if Blocked(Obj, 0, sy) then st := st or MOVE_BLOCK;
+    end;
 
-  // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì ñòåíà => øàãàòü íåëüçÿ:
-  // Èëè åñëè øàãíóòü âíèç, à òàì ñòóïåíü => øàãàòü íåëüçÿ:
-    if g_Obj_CollideLevel(Obj, 0, sy) or
-       ((sy > 0) and g_Obj_StayOnStep(Obj)) then
-      begin
-        if sy > 0 then
-          st := st or MOVE_HITLAND
-        else
-          st := st or MOVE_HITCEIL;
-      end
+    // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì ñòåíà => øàãàòü íåëüçÿ
+    // Èëè åñëè øàãíóòü âíèç, à òàì ñòóïåíü => øàãàòü íåëüçÿ
+    if g_Obj_CollideLevel(Obj, 0, sy) or ((sy > 0) and g_Obj_StayOnStep(Obj)) then
+    begin
+      if sy > 0 then
+        st := st or MOVE_HITLAND
+      else
+        st := st or MOVE_HITCEIL;
+    end
     else // Òàì ñòåíû íåò. È ñòóïåíè ñíèçó òîæå íåò
+    begin
+      if CollideLiquid(Obj, 0, sy) then
+      begin // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì òåïåðü æèäêîñòü
+        if ((st and MOVE_INWATER) = 0) then st := st or MOVE_HITWATER;
+      end
+      else // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì óæå íåò æèäêîñòè
       begin
-        if CollideLiquid(Obj, 0, sy) then
-          begin // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì òåïåðü æèäêîñòü
-            if not WordBool(st and MOVE_INWATER) then
-              st := st or MOVE_HITWATER;
-          end
-        else // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì óæå íåò æèäêîñòè
-          if WordBool(st and MOVE_INWATER) then
-            st := st or MOVE_HITAIR;
-
-      // Øàã:
-        Obj^.Y := Obj^.Y + sy;
-
-        Result := True;
+        if ((st and MOVE_INWATER) <> 0) then st := st or MOVE_HITAIR;
       end;
+
+      // Øàã
+      Obj^.Y += sy;
+      result := true;
+    end;
   end;
 
 begin
   st := MOVE_NONE;
 
-// Îáúåêò â æèäêîñòè:
-  if CollideLiquid(Obj, 0, 0) then
-    st := st or MOVE_INWATER;
+  // Îáúåêò â æèäêîñòè?
+  if CollideLiquid(Obj, 0, 0) then st := st or MOVE_INWATER;
 
-// Ìîíñòð â áëîêìîíå:
+  // Ìîíñòð â áëîêìîíå?
   if gMon then
-    if Blocked(Obj, 0, 0) then
-      st := st or MOVE_BLOCK;
-
-// Äâèãàòüñÿ íå íàäî:
-  if (dx = 0) and (dy = 0) then
   begin
-    Result := st;
-    Exit;
+    if Blocked(Obj, 0, 0) then st := st or MOVE_BLOCK;
   end;
 
+  // Äâèãàòüñÿ íå íàäî?
+  if (dx = 0) and (dy = 0) then begin result := st; exit; end;
+
   sx := g_basic.Sign(dx);
   sy := g_basic.Sign(dy);
-  dx := Abs(dx);
-  dy := Abs(dy);
+  dx := abs(dx);
+  dy := abs(dy);
 
-  for i := 1 to dx do
-    if not movex() then
-      Break;
+  for i := 1 to dx do if not movex() then break;
+  for i := 1 to dy do if not movey() then break;
 
-  for i := 1 to dy do
-    if not movey() then
-      Break;
-
-  Result := st;
+  result := st;
 end;
 
-procedure g_Obj_Init(Obj: PObj);
+
+procedure g_Obj_Init (Obj: PObj);
 begin
   ZeroMemory(Obj, SizeOf(TObj));
 end;
 
-function g_Obj_Move(Obj: PObj; Fallable: Boolean; Splash: Boolean; ClimbSlopes: Boolean = False): Word;
+
+function g_Obj_Move (Obj: PObj; Fallable: Boolean; Splash: Boolean; ClimbSlopes: Boolean=False): Word;
 var
   xv, yv, dx, dy: Integer;
   inwater: Boolean;
   c: Boolean;
   wtx: DWORD;
+  slopeStep: Integer;
 label
   _move;
 begin
-// Ëèìèòû íà ñêîðîñòü è óñêîðåíèå
+  // Ëèìèòû íà ñêîðîñòü è óñêîðåíèå
+  Obj^.Vel.X := nclamp(Obj^.Vel.X, -LIMIT_VEL, LIMIT_VEL);
+  Obj^.Vel.Y := nclamp(Obj^.Vel.Y, -LIMIT_VEL, LIMIT_VEL);
+  Obj^.Accel.X := nclamp(Obj^.Accel.X, -LIMIT_ACCEL, LIMIT_ACCEL);
+  Obj^.Accel.Y := nclamp(Obj^.Accel.Y, -LIMIT_ACCEL, LIMIT_ACCEL);
+  {
   if      Obj^.Vel.X < -LIMIT_VEL then Obj^.Vel.X := -LIMIT_VEL
   else if Obj^.Vel.X >  LIMIT_VEL then Obj^.Vel.X :=  LIMIT_VEL;
   if      Obj^.Vel.Y < -LIMIT_VEL then Obj^.Vel.Y := -LIMIT_VEL
@@ -363,136 +382,138 @@ begin
   else if Obj^.Accel.X >  LIMIT_ACCEL then Obj^.Accel.X :=  LIMIT_ACCEL;
   if      Obj^.Accel.Y < -LIMIT_ACCEL then Obj^.Accel.Y := -LIMIT_ACCEL
   else if Obj^.Accel.Y >  LIMIT_ACCEL then Obj^.Accel.Y :=  LIMIT_ACCEL;
+  }
 
-// Âûëåòåë çà íèæíþþ ãðàíèöó êàðòû:
-  if Obj^.Y > gMapInfo.Height+128 then
+  // Âûëåòåë çà íèæíþþ ãðàíèöó êàðòû?
+  if (Obj^.Y > gMapInfo.Height+128) then begin result := MOVE_FALLOUT; Obj.slopeUpLeft := 0; Obj.slopeFramesLeft := 0; exit; end;
+
+  // Ìåíÿåì ñêîðîñòü è óñêîðåíèå òîëüêî ïî ÷åòíûì êàäðàì
+  c := (gTime mod (GAME_TICK*2) <> 0);
+
+  // smoothed slopes
+  if {not c and} (Obj.slopeUpLeft > 0) then
   begin
-    Result := MOVE_FALLOUT;
-    Exit;
+    if (Obj.slopeFramesLeft < 1) then
+    begin
+      //conwritefln('SLOPE DONE: slopeUpLeft=%s', [Obj.slopeUpLeft]);
+      Obj.slopeUpLeft := 0; // oops
+    end
+    else
+    begin
+      slopeStep := Obj.slopeUpLeft div Obj.slopeFramesLeft;
+      if (slopeStep < 1) then slopeStep := 1;
+      //conwritefln('SLOPE STEP: slopeUpLeft=%s; slopeFramesLeft=%s; slopeStep=%d', [Obj.slopeUpLeft, Obj.slopeFramesLeft, slopeStep]);
+      Dec(Obj.slopeFramesLeft);
+      Obj.slopeUpLeft -= slopeStep;
+      if (Obj.slopeUpLeft < 1) then
+      begin
+        Obj.slopeUpLeft := 0;
+        Obj.slopeFramesLeft := 0;
+      end;
+    end;
   end;
 
-// Ìåíÿåì ñêîðîñòü è óñêîðåíèå òîëüêî ïî ÷åòíûì êàäðàì:
-  c := gTime mod (GAME_TICK*2) <> 0;
-
-  if c then
-    goto _move;
+  if c then goto _move;
 
   case CollideLift(Obj, 0, 0) of
     -1: //up
       begin
-        Obj^.Vel.Y := Obj^.Vel.Y - 1; // Ëèôò ââåðõ
-        if Obj^.Vel.Y < -5 then
-          Obj^.Vel.Y := Obj^.Vel.Y + 1;
+        Obj^.Vel.Y -= 1; // Ëèôò ââåðõ
+        if (Obj^.Vel.Y < -5) then Obj^.Vel.Y += 1;
       end;
-
     1: //down
       begin
-        if Obj^.Vel.Y > 5 then
-          Obj^.Vel.Y := Obj^.Vel.Y - 1;
-        Obj^.Vel.Y := Obj^.Vel.Y + 1; // Ãðàâèòàöèÿ èëè ëèôò âíèç
+        if (Obj^.Vel.Y > 5) then Obj^.Vel.Y -= 1;
+        Obj^.Vel.Y += 1; // Ãðàâèòàöèÿ èëè ëèôò âíèç
       end;
-
-    0:
+    0: //???
       begin
-        if Fallable then
-          Obj^.Vel.Y := Obj^.Vel.Y + 1; // Ãðàâèòàöèÿ
-        if Obj^.Vel.Y > MAX_YV then
-          Obj^.Vel.Y := Obj^.Vel.Y - 1;
+        if Fallable then Obj^.Vel.Y += 1; // Ãðàâèòàöèÿ
+        if (Obj^.Vel.Y > MAX_YV) then Obj^.Vel.Y -= 1;
       end;
   end;
 
   case CollideHorLift(Obj, 0, 0) of
     -1: //left
       begin
-        Obj^.Vel.X := Obj^.Vel.X - 3; // Ëèôò ââåðõ
-        if Obj^.Vel.X < -9 then
-          Obj^.Vel.X := Obj^.Vel.X + 3;
+        Obj^.Vel.X -= 3;
+        if (Obj^.Vel.X < -9) then Obj^.Vel.X += 3;
       end;
-
     1: //right
       begin
-        Obj^.Vel.X := Obj^.Vel.X + 3;
-        if Obj^.Vel.X > 9 then
-          Obj^.Vel.X := Obj^.Vel.X - 3;
+        Obj^.Vel.X += 3;
+        if (Obj^.Vel.X > 9) then Obj^.Vel.X -= 3;
       end;
     // 0 is not needed here
   end;
 
+  // Â âîäå?
   inwater := CollideLiquid(Obj, 0, 0);
   if inwater then
   begin
-    xv := Abs(Obj^.Vel.X)+1;
-    if xv > 5 then
-      Obj^.Vel.X := z_dec(Obj^.Vel.X, (xv div 2)-2);
+    xv := abs(Obj^.Vel.X)+1;
+    if (xv > 5) then Obj^.Vel.X := z_dec(Obj^.Vel.X, (xv div 2)-2);
 
-    yv := Abs(Obj^.Vel.Y)+1;
-    if yv > 5 then
-      Obj^.Vel.Y := z_dec(Obj^.Vel.Y, (yv div 2)-2);
+    yv := abs(Obj^.Vel.Y)+1;
+    if (yv > 5) then Obj^.Vel.Y := z_dec(Obj^.Vel.Y, (yv div 2)-2);
 
-    xv := Abs(Obj^.Accel.X)+1;
-    if xv > 5 then
-      Obj^.Accel.X := z_dec(Obj^.Accel.X, (xv div 2)-2);
+    xv := abs(Obj^.Accel.X)+1;
+    if (xv > 5) then Obj^.Accel.X := z_dec(Obj^.Accel.X, (xv div 2)-2);
 
-    yv := Abs(Obj^.Accel.Y)+1;
-    if yv > 5 then
-      Obj^.Accel.Y := z_dec(Obj^.Accel.Y, (yv div 2)-2);
+    yv := abs(Obj^.Accel.Y)+1;
+    if (yv > 5) then Obj^.Accel.Y := z_dec(Obj^.Accel.Y, (yv div 2)-2);
   end;
 
-// Óìåíüøàåì ïðèáàâêó ê ñêîðîñòè:
+  // Óìåíüøàåì ïðèáàâêó ê ñêîðîñòè
   Obj^.Accel.X := z_dec(Obj^.Accel.X, 1);
   Obj^.Accel.Y := z_dec(Obj^.Accel.Y, 1);
 
 _move:
 
-  xv := Obj^.Vel.X + Obj^.Accel.X;
-  yv := Obj^.Vel.Y + Obj^.Accel.Y;
+  xv := Obj^.Vel.X+Obj^.Accel.X;
+  yv := Obj^.Vel.Y+Obj^.Accel.Y;
 
   dx := xv;
   dy := yv;
 
-  Result := move(Obj, dx, dy, ClimbSlopes);
+  result := move(Obj, dx, dy, ClimbSlopes);
 
-// Áðûçãè (åñëè íóæíû):
+  // Áðûçãè (åñëè íóæíû)
   if Splash then
+  begin
     if WordBool(Result and MOVE_HITWATER) then
     begin
-      wtx := g_Map_CollideLiquid_Texture(Obj^.X+Obj^.Rect.X,
-                                         Obj^.Y+Obj^.Rect.Y,
-                                         Obj^.Rect.Width,
-                                         Obj^.Rect.Height*2 div 3);
+      wtx := g_Map_CollideLiquid_Texture(Obj^.X+Obj^.Rect.X, Obj^.Y+Obj^.Rect.Y,
+                                         Obj^.Rect.Width, Obj^.Rect.Height*2 div 3);
       case wtx of
-        LongWord(TEXTURE_SPECIAL_WATER):
-          g_Obj_Splash(Obj, 3);
-        LongWord(TEXTURE_SPECIAL_ACID1):
-          g_Obj_Splash(Obj, 2);
-        LongWord(TEXTURE_SPECIAL_ACID2):
-          g_Obj_Splash(Obj, 1);
-        LongWord(TEXTURE_NONE):
-          ;
-        else
-          g_Obj_Splash(Obj, 0);
+        LongWord(TEXTURE_SPECIAL_WATER): g_Obj_Splash(Obj, 3);
+        LongWord(TEXTURE_SPECIAL_ACID1): g_Obj_Splash(Obj, 2);
+        LongWord(TEXTURE_SPECIAL_ACID2): g_Obj_Splash(Obj, 1);
+        LongWord(TEXTURE_NONE): begin end;
+        else g_Obj_Splash(Obj, 0);
       end;
     end;
+  end;
 
-// Ìåíÿåì ñêîðîñòü è óñêîðåíèå òîëüêî ïî ÷åòíûì êàäðàì:
-  if c then
-    Exit;
+  // Ìåíÿåì ñêîðîñòü è óñêîðåíèå òîëüêî ïî ÷åòíûì êàäðàì
+  if c then exit;
 
-// Âðåçàëèñü â ñòåíó - ñòîï:
-  if WordBool(Result and MOVE_HITWALL) then
+  // Âðåçàëèñü â ñòåíó - ñòîï
+  if ((Result and MOVE_HITWALL) <> 0) then
   begin
     Obj^.Vel.X := 0;
     Obj^.Accel.X := 0;
   end;
 
-// Âðåçàëèñü â ïîë èëè ïîòîëîê - ñòîï:
-  if WordBool(Result and (MOVE_HITCEIL or MOVE_HITLAND)) then
+  // Âðåçàëèñü â ïîë èëè ïîòîëîê - ñòîï
+  if ((Result and (MOVE_HITCEIL or MOVE_HITLAND)) <> 0) then
   begin
     Obj^.Vel.Y := 0;
     Obj^.Accel.Y := 0;
   end;
 end;
 
+
 function g_Obj_Collide(Obj1, Obj2: PObj): Boolean;
 begin
   Result := g_Collide(Obj1^.X+Obj1^.Rect.X, Obj1^.Y+Obj1^.Rect.Y,
@@ -539,7 +560,7 @@ begin
   vx := Obj^.Vel.X;
   vy := Obj^.Vel.Y;
 
-  m := Max(Abs(vx), Abs(vy));
+  m := Max(abs(vx), abs(vy));
   if m = 0 then
     m := 1;
 
@@ -547,34 +568,25 @@ begin
   Obj^.Vel.Y := (vy*s) div m;
 end;
 
-function z_dec(a, b: Integer): Integer;
-begin
+
 // Ïðèáëèæàåì a ê 0 íà b åäèíèö:
-  if Abs(a) < b then
-    Result := 0
-  else
-    if a > 0 then
-      Result := a - b
-    else
-      if a < 0 then
-        Result := a + b
-      else // a = 0
-        Result := 0;
+function z_dec (a, b: Integer): Integer; inline;
+begin
+       if (abs(a) < b) then result := 0
+  else if (a > 0) then result := a-b
+  else if (a < 0) then result := a+b
+  else result := 0; // a = 0
 end;
 
-function z_fdec(a, b: Double): Double;
-begin
+
 // Ïðèáëèæàåì a ê 0.0 íà b åäèíèö:
-  if Abs(a) < b then
-    Result := 0.0
-  else
-    if a > 0.0 then
-      Result := a - b
-    else
-      if a < 0.0 then
-        Result := a + b
-      else // a = 0.0
-        Result := 0.0;
+function z_fdec (a, b: Double): Double; inline;
+begin
+       if (abs(a) < b) then result := 0.0
+  else if (a > 0.0) then result := a-b
+  else if (a < 0.0) then result := a+b
+  else result := 0.0; // a = 0.0
 end;
 
+
 end.
index 488cee9edc6ce085a2c329f1f5d26f506bf4cb9e..2d53dc5b6c7c3f0f4c9c3eec7f54b65dcaabbc51 100644 (file)
@@ -2271,10 +2271,10 @@ begin
         e_GetTextureSize(ID, @w, @h);
         if FDirection = D_LEFT then
           e_Draw(ID, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-(w div 2)+4,
-                     FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7, 0, True, False)
+                     FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7+FObj.slopeUpLeft, 0, True, False)
         else
           e_Draw(ID, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-(w div 2)-2,
-                     FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7, 0, True, False);
+                     FObj.Y+FObj.Rect.Y+(FObj.Rect.Height div 2)-(h div 2)-7+FObj.slopeUpLeft, 0, True, False);
       end;
 
     if FMegaRulez[MR_INVIS] > gTime then
@@ -2287,15 +2287,15 @@ begin
         else
           dr := True;
         if dr then
-          FModel.Draw(FObj.X, FObj.Y, 200)
+          FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft, 200)
         else
-          FModel.Draw(FObj.X, FObj.Y);
+          FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft);
       end
       else
-        FModel.Draw(FObj.X, FObj.Y, 254);
+        FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft, 254);
     end
     else
-      FModel.Draw(FObj.X, FObj.Y);
+      FModel.Draw(FObj.X, FObj.Y+FObj.slopeUpLeft);
   end;
 
   if g_debug_Frames then
index fd57312b5481e117c5ea21ea1da89a4bbe9710d2..49f7ef1e4f1a9b2ec39be9cdd79760cb929ba538 100644 (file)
@@ -122,6 +122,43 @@ function readInt64BE (st: TStream): Int64;
 function readUInt64BE (st: TStream): UInt64;
 
 
+function nmin (a, b: Byte): Byte; inline; overload;
+function nmin (a, b: ShortInt): ShortInt; inline; overload;
+function nmin (a, b: Word): Word; inline; overload;
+function nmin (a, b: SmallInt): SmallInt; inline; overload;
+function nmin (a, b: LongWord): LongWord; inline; overload;
+function nmin (a, b: LongInt): LongInt; inline; overload;
+function nmin (a, b: Int64): Int64; inline; overload;
+function nmin (a, b: UInt64): UInt64; inline; overload;
+function nmin (a, b: Single): Single; inline; overload;
+function nmin (a, b: Double): Double; inline; overload;
+function nmin (a, b: Extended): Extended; inline; overload;
+
+function nmax (a, b: Byte): Byte; inline; overload;
+function nmax (a, b: ShortInt): ShortInt; inline; overload;
+function nmax (a, b: Word): Word; inline; overload;
+function nmax (a, b: SmallInt): SmallInt; inline; overload;
+function nmax (a, b: LongWord): LongWord; inline; overload;
+function nmax (a, b: LongInt): LongInt; inline; overload;
+function nmax (a, b: Int64): Int64; inline; overload;
+function nmax (a, b: UInt64): UInt64; inline; overload;
+function nmax (a, b: Single): Single; inline; overload;
+function nmax (a, b: Double): Double; inline; overload;
+function nmax (a, b: Extended): Extended; inline; overload;
+
+function nclamp (v, a, b: Byte): Byte; inline; overload;
+function nclamp (v, a, b: ShortInt): ShortInt; inline; overload;
+function nclamp (v, a, b: Word): Word; inline; overload;
+function nclamp (v, a, b: SmallInt): SmallInt; inline; overload;
+function nclamp (v, a, b: LongWord): LongWord; inline; overload;
+function nclamp (v, a, b: LongInt): LongInt; inline; overload;
+function nclamp (v, a, b: Int64): Int64; inline; overload;
+function nclamp (v, a, b: UInt64): UInt64; inline; overload;
+function nclamp (v, a, b: Single): Single; inline; overload;
+function nclamp (v, a, b: Double): Double; inline; overload;
+function nclamp (v, a, b: Extended): Extended; inline; overload;
+
+
 type
   TFormatStrFCallback = procedure (constref buf; len: SizeUInt);
 
@@ -143,7 +180,7 @@ function quoteStr (const s: AnsiString): AnsiString;
 type
   generic TSimpleList<ItemT> = class
   private
-    type PItemT = ^ItemT;
+    //type PItemT = ^ItemT;
     type TItemArr = array of ItemT;
 
   public
@@ -975,6 +1012,44 @@ function readInt64BE (st: TStream): Int64; begin readIntegerBE(st, @result, 8);
 function readUInt64BE (st: TStream): UInt64; begin readIntegerBE(st, @result, 8); end;
 
 
+// ////////////////////////////////////////////////////////////////////////// //
+function nmin (a, b: Byte): Byte; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: ShortInt): ShortInt; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: Word): Word; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: SmallInt): SmallInt; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: LongWord): LongWord; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: LongInt): LongInt; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: Int64): Int64; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: UInt64): UInt64; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: Single): Single; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: Double): Double; inline; overload; begin if (a < b) then result := a else result := b; end;
+function nmin (a, b: Extended): Extended; inline; overload; begin if (a < b) then result := a else result := b; end;
+
+function nmax (a, b: Byte): Byte; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: ShortInt): ShortInt; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: Word): Word; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: SmallInt): SmallInt; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: LongWord): LongWord; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: LongInt): LongInt; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: Int64): Int64; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: UInt64): UInt64; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: Single): Single; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: Double): Double; inline; overload; begin if (a > b) then result := a else result := b; end;
+function nmax (a, b: Extended): Extended; inline; overload; begin if (a > b) then result := a else result := b; end;
+
+function nclamp (v, a, b: Byte): Byte; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: ShortInt): ShortInt; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: Word): Word; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: SmallInt): SmallInt; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: LongWord): LongWord; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: LongInt): LongInt; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: Int64): Int64; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: UInt64): UInt64; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: Single): Single; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: Double): Double; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+function nclamp (v, a, b: Extended): Extended; inline; overload; begin if (v < a) then result := a else if (v > b) then result := b else result := v; end;
+
+
 // ////////////////////////////////////////////////////////////////////////// //
 {$IFDEF WINDOWS}
 function snprintf (buf: PAnsiChar; bufsize: SizeUInt; const fmt: PAnsiChar): SizeUInt; cdecl; varargs; external 'msvcrt.dll' name '_snprintf';