Enforce camera limits regardless of zoom level
Previously, when you zoomed out, you could move the camera further out to the left, right and up.
--- a/hedgewars/uConsts.pas Mon Jun 29 00:15:37 2020 +0300
+++ b/hedgewars/uConsts.pas Mon Jun 29 13:14:18 2020 +0200
@@ -233,6 +233,12 @@
// do not change this value
cDefaultZoomLevel = 2.0; // 100% zoom
+ // Maximum camera positions, values are "pixels outside the mainland"
+ cCamLimitX = 0; // X (left/right) camera limit, no border. Note: Influences sndFlyAway
+ cCamLimitY = 2048; // Top Y camera limit, no border
+ cCamLimitBorderX = 2048; // X (left/right) camera limit, with border
+ cCamLimitBorderY = 2048; // Top Y camera limit, with border
+
// game flags
gfAny = $FFFFFFFF; // mask for all possible gameflags
gfOneClanMode = $00000001; // Game does not end if there's only one clan in play. For missions
--- a/hedgewars/uGearsHedgehog.pas Mon Jun 29 00:15:37 2020 +0300
+++ b/hedgewars/uGearsHedgehog.pas Mon Jun 29 13:14:18 2020 +0200
@@ -1281,7 +1281,7 @@
uStats.hedgehogFlight(Gear, Gear^.FlightTime);
Gear^.FlightTime:= 0;
end;
-if (WorldEdge = weNone) and (not Gear^.Hedgehog^.FlownOffMap) and (not isZero(Gear^.dX)) and (not isUnderwater) and ((Gear^.State and gstHHDriven) = 0) and (hwRound(Gear^.Y) < cWaterLine-300) and ((hwRound(Gear^.X) < leftX-2048) or (hwRound(Gear^.X) > rightX+2048)) then
+if (WorldEdge = weNone) and (not hasBorder) and (not Gear^.Hedgehog^.FlownOffMap) and (not isZero(Gear^.dX)) and (not isUnderwater) and ((Gear^.State and gstHHDriven) = 0) and (hwRound(Gear^.Y) < cWaterLine-300) and ((hwRound(Gear^.X) < -cCamLimitX) or (hwRound(Gear^.X) > LAND_WIDTH+cCamLimitX)) then
begin
PlaySoundV(sndFlyAway, Gear^.Hedgehog^.Team^.voicepack);
Gear^.Hedgehog^.FlownOffMap:= true;
--- a/hedgewars/uWorld.pas Mon Jun 29 00:15:37 2020 +0300
+++ b/hedgewars/uWorld.pas Mon Jun 29 13:14:18 2020 +0200
@@ -877,12 +877,42 @@
end
end;
-// Force the lower camera boundary to never be lower than a few pixels below the water line
-function LowerCameraBound: LongInt;
+// Force camera to stay within a certain area
+procedure CameraBounds;
+var lowBound: LongInt;
begin
-LowerCameraBound:= trunc(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - cWaterLine - (cVisibleWater + trunc(CinematicBarH / (cScaleFactor / 2.0)));
-if WorldDy < LowerCameraBound then
- WorldDy:= LowerCameraBound;
+if (not hasBorder) then
+ begin
+ if WorldDy > (-(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - TopY + cCamLimitY) then
+ WorldDy:= (-trunc(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - TopY + cCamLimitY);
+ if (RightX - LeftX + cCamLimitX * 2) div 2 < cScreenWidth / cScaleFactor then
+ WorldDx:= -((LeftX + RightX) div 2)
+ else
+ begin
+ if WorldDx < -LAND_WIDTH - cCamLimitX + (cScreenWidth / cScaleFactor) then
+ WorldDx:= -LAND_WIDTH - cCamLimitX + trunc(cScreenWidth / cScaleFactor);
+ if WorldDx > cCamLimitX - (cScreenWidth / cScaleFactor) then
+ WorldDx:= cCamLimitX - trunc(cScreenWidth / cScaleFactor);
+ end;
+ end
+else
+ begin
+ if WorldDy > (-(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - TopY + cCamLimitBorderY) then
+ WorldDy:= (-trunc(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - TopY + cCamLimitBorderY);
+ if (RightX - LeftX + cCamLimitBorderX * 2) div 2 < cScreenWidth / cScaleFactor then
+ WorldDx:= -((LeftX + RightX) div 2)
+ else
+ begin
+ if WorldDx > -LeftX + cCamLimitBorderX - (cScreenWidth / cScaleFactor) then
+ WorldDx:= -LeftX + cCamLimitBorderX - trunc(cScreenWidth / cScaleFactor);
+ if WorldDx < -RightX - cCamLimitBorderX + (cScreenWidth / cScaleFactor) then
+ WorldDx:= -RightX - cCamLimitBorderX + trunc(cScreenWidth / cScaleFactor);
+ end;
+ end;
+
+lowBound:= trunc(cScreenHeight / cScaleFactor) + cScreenHeight div 2 - cWaterLine - (cVisibleWater + trunc(CinematicBarH / (cScaleFactor / 2.0)));
+if WorldDy < lowBound then
+ WorldDy:= lowBound;
end;
procedure DrawWorld(Lag: LongInt);
@@ -906,7 +936,7 @@
if (not isPaused) and (not isAFK) and (GameType <> gmtRecord) then
MoveCamera
else if (isPaused) then
- LowerCameraBound;
+ CameraBounds;
if cStereoMode = smNone then
begin
@@ -1902,7 +1932,7 @@
var PrevSentPointTime: LongWord = 0;
procedure MoveCamera;
-var EdgesDist, wdy, shs,z, dstX: LongInt;
+var EdgesDist, shs,z, dstX: LongInt;
inbtwnTrgtAttks: Boolean;
begin
{$IFNDEF MOBILE}
@@ -1950,10 +1980,11 @@
WorldDx:= WorldDx + rightX - leftX;
end;
-wdy:= LowerCameraBound;
-
if ((CursorPoint.X = prevPoint.X) and (CursorPoint.Y = prevpoint.Y)) then
+ begin
+ CameraBounds;
exit;
+ end;
if (AMState = AMShowingUp) or (AMState = AMShowing) then
begin
@@ -1966,6 +1997,7 @@
if CursorPoint.Y < cScreenHeight - (AmmoRect.y + AmmoRect.h - AMSlotSize - 5) then//check bottom
CursorPoint.Y:= cScreenHeight - (AmmoRect.y + AmmoRect.h - AMSlotSize - 5);
prevPoint:= CursorPoint;
+ CameraBounds;
exit
end;
@@ -2021,14 +2053,10 @@
// this moves the camera according to CursorPoint X and Y
prevPoint:= CursorPoint;
-if WorldDy > LAND_HEIGHT + 1024 then
- WorldDy:= LAND_HEIGHT + 1024;
-if WorldDy < wdy then
- WorldDy:= wdy;
-if WorldDx < - LAND_WIDTH - 1024 then
- WorldDx:= - LAND_WIDTH - 1024;
-if WorldDx > 1024 then
- WorldDx:= 1024;
+
+// enforce camera bounds
+CameraBounds();
+
end;
procedure ShowMission(caption, subcaption, text: ansistring; icon, time : LongInt);