From: Ketmar Dark Date: Wed, 30 Aug 2017 14:29:36 +0000 (+0300) Subject: smoother camera on stairs/slopes X-Git-Url: http://deadsoftware.ru/gitweb?a=commitdiff_plain;h=c7ee5fde8d382144cfd01bf9432031a827490e1b;p=d2df-sdl.git smoother camera on stairs/slopes --- diff --git a/src/game/g_game.pas b/src/game/g_game.pas index 1cf4808..66a589b 100644 --- a/src/game/g_game.pas +++ b/src/game/g_game.pas @@ -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; diff --git a/src/game/g_grid.pas b/src/game/g_grid.pas index 0679075..2d5d632 100644 --- a/src/game/g_grid.pas +++ b/src/game/g_grid.pas @@ -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 diff --git a/src/game/g_phys.pas b/src/game/g_phys.pas index 498bd75..a88ca21 100644 --- a/src/game/g_phys.pas +++ b/src/game/g_phys.pas @@ -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. diff --git a/src/game/g_player.pas b/src/game/g_player.pas index 488cee9..2d53dc5 100644 --- a/src/game/g_player.pas +++ b/src/game/g_player.pas @@ -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 diff --git a/src/shared/utils.pas b/src/shared/utils.pas index fd57312..49f7ef1 100644 --- a/src/shared/utils.pas +++ b/src/shared/utils.pas @@ -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 = 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';