Fix freeze ray not working through wrap world edge; add DrawLineWrapped
authorWuzzy <Wuzzy2@mail.ru>
Mon, 30 Jul 2018 13:20:01 +0200
changeset 13577 a71e6856ffab
parent 13576 fb81633f17fa
child 13578 e896ff1b1d96
Fix freeze ray not working through wrap world edge; add DrawLineWrapped
ChangeLog.txt
hedgewars/uGearsHandlersMess.pas
hedgewars/uGearsList.pas
hedgewars/uGearsRender.pas
hedgewars/uGearsUtils.pas
hedgewars/uRender.pas
--- a/ChangeLog.txt	Sun Jul 29 11:39:48 2018 -0400
+++ b/ChangeLog.txt	Mon Jul 30 13:20:01 2018 +0200
@@ -10,6 +10,8 @@
  * Functionality of controllers restored
  * Fix crash when 2 or more controllers were connected
  * Fix hammer and pickhammer not digging correctly at wrap world edge
+ * Fix freezer ray not working through wrap world edge
+ * Fix freezer ray going through bounce world edge
  * Fix extreme amounts of droplets when shooting with minigun into ocean world edge
  * Fix hog being unable to walk after using sniper rifle without firing both shots
  * Fix video recorder not working when game audio was disabled
--- a/hedgewars/uGearsHandlersMess.pas	Sun Jul 29 11:39:48 2018 -0400
+++ b/hedgewars/uGearsHandlersMess.pas	Mon Jul 30 13:20:01 2018 +0200
@@ -6227,6 +6227,9 @@
         exit
         end;
     updateFuel(Gear);
+    if WorldWrap(Gear) and (WorldEdge = weWrap) and (Gear^.Target.X = NoPointX) then
+        // Use FlightTime to count number of times the gear has world-wrapped
+        inc(Gear^.FlightTime);
 
     with Gear^ do
         begin
@@ -6240,6 +6243,7 @@
             begin
             updateTarget(Gear, ndX, ndY);
             Timer := iceWaitCollision;
+            FlightTime := 0;
             end
         else
             begin
--- a/hedgewars/uGearsList.pas	Sun Jul 29 11:39:48 2018 -0400
+++ b/hedgewars/uGearsList.pas	Mon Jul 30 13:20:01 2018 +0200
@@ -727,6 +727,7 @@
       gtIceGun: begin
                 gear^.Health:= 1000;
                 gear^.Radius:= 8;
+                gear^.Density:= _0;
                 end;
         gtDuck: begin
                 gear^.Pos:= 0;               // 0: in air, 1-4: on water, 5-8: underwater
--- a/hedgewars/uGearsRender.pas	Sun Jul 29 11:39:48 2018 -0400
+++ b/hedgewars/uGearsRender.pas	Mon Jul 30 13:20:01 2018 +0200
@@ -1568,11 +1568,11 @@
                                 i:= random(100)+100;
                                 if Gear^.Target.X <> NoPointX then
                                     begin
-                                    DrawLine(Gear^.Target.X, Gear^.Target.Y, hwRound(HHGear^.X), hwRound(HHGear^.Y), 4.0, i, i, $FF, $40);
+                                    DrawLineWrapped(hwRound(HHGear^.X), hwRound(HHGear^.Y), Gear^.Target.X, Gear^.Target.Y, 4.0, hwSign(HHGear^.dX) < 0, Gear^.FlightTime, i, i, $FF, $40);
                                     end
                                 else
                                     begin
-                                    DrawLine(hwRound(HHGear^.X), hwRound(HHGear^.Y), hwRound(Gear^.X), hwRound(Gear^.Y), 4.0, i, i, $FF, $40);
+                                    DrawLineWrapped(hwRound(HHGear^.X), hwRound(HHGear^.Y), hwRound(Gear^.X), hwRound(Gear^.Y), 4.0, hwSign(HHGear^.dX) < 0, Gear^.FlightTime, i, i, $FF, $40);
                                     end;
                                 end
                           end
--- a/hedgewars/uGearsUtils.pas	Sun Jul 29 11:39:48 2018 -0400
+++ b/hedgewars/uGearsUtils.pas	Mon Jul 30 13:20:01 2018 +0200
@@ -1723,6 +1723,8 @@
 procedure AddBounceEffectForGear(Gear: PGear);
 var boing: PVisualGear;
 begin
+    if Gear^.Density < _0_01 then
+        exit;
     boing:= AddVisualGear(hwRound(Gear^.X), hwRound(Gear^.Y), vgtStraightShot, 0, false, 1);
     if boing <> nil then
         with boing^ do
--- a/hedgewars/uRender.pas	Sun Jul 29 11:39:48 2018 -0400
+++ b/hedgewars/uRender.pas	Mon Jul 30 13:20:01 2018 +0200
@@ -53,6 +53,8 @@
 
 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
+procedure DrawLineWrapped       (X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; color: LongWord); inline;
+procedure DrawLineWrapped       (X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; r, g, b, a: Byte);
 procedure DrawLineOnScreen      (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
 procedure DrawRect              (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
@@ -1337,11 +1339,17 @@
         end;
 end;
 
+// Same as below, but with color as LongWord
 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
 begin
 DrawLine(X0, Y0, X1, Y1, Width, (color shr 24) and $FF, (color shr 16) and $FF, (color shr 8) and $FF, color and $FF)
 end;
 
+// Draw line between 2 points
+// X0, Y0: Start point
+// X0, Y1: End point
+// Width: Visual line width
+// r, g, b, a: Color
 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
 begin
     openglPushMatrix();
@@ -1356,6 +1364,106 @@
     UpdateModelviewProjection;
 end;
 
+// Same as below, but with color as a longword
+procedure DrawLineWrapped(X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; color: LongWord); inline;
+begin
+DrawLineWrapped(X0, Y0, X1, Y1, Width, goesLeft, Wraps, (color shr 24) and $FF, (color shr 16) and $FF, (color shr 8) and $FF, color and $FF);
+end;
+
+// Draw a line between 2 points, but it wraps around the
+// world edge for a given number of times.
+// goesLeft: true if the line direction from the start point is left
+// Wraps: Number of times the line intersects the wrapping world edge
+// r, g, b, a: color
+procedure DrawLineWrapped(X0, Y0, X1, Y1, Width: Single; goesLeft: boolean; Wraps: LongWord; r, g, b, a: Byte);
+var w: LongWord;
+    startX, startY, endX, endY: Single;
+    // total X and Y distance the line travels if you would unwrap it
+    // with this we know the slope of the line.
+    totalX, totalY: Single;
+    // x variable for the line formula
+    x: Single;
+begin
+    openglPushMatrix();
+    openglTranslatef(WorldDx, WorldDy, 0);
+
+    UpdateModelviewProjection;
+
+    startX:= X0;
+    startY:= Y0;
+    if (Wraps = 0) then
+        begin
+        // Wraps=0 is trivial: Just draw one direct connection
+        endX:= X1;
+        endY:= Y1;
+        DrawLineOnScreen(startX, startY, endX, endY, Width, r, g, b, a);
+        end
+    else
+        begin
+        // A wrapping line is drawn using multiple line segments
+        // which stop at the left and right border. We
+        // calculate the points at which the line intersects with the border.
+        // Then we draws all line segments.
+
+        // Calculate position of first wrap point
+        if goesLeft then
+            begin
+            endX:= LeftX;
+            totalX:= (RightX - X1) + (X0 - LeftX);
+            x:= X0 - LeftX;
+            end
+        else
+            begin
+            endX:= RightX;
+            totalX:= (RightX - X0) + (X1 - LeftX);
+            x:= RightX - X0;
+            end;
+        if (Wraps >= 2) then
+            totalX:= totalX + ((RightX - LeftX) * (Wraps-1));
+        totalY:= Y1 - Y0;
+        // Calculate Y of first wrap point using the line formula
+        endY:= Y0 + (totalY / totalX) * x;
+        // Draw line segment between starting point and first wrap point
+        DrawLineOnScreen(startX, startY, endX, endY, Width, r, g, b, a);
+
+        // Calculate and draw all remaining line segments
+        for w:=1 to Wraps do
+            begin
+            startY:= endY;
+            if goesLeft then
+                begin
+                startX:= RightX;
+                if w < Wraps then
+                    endX:= LeftX
+                else
+                    endX:= X1;
+                end
+            else
+                begin
+                startX:= LeftX;
+                if w < Wraps then
+                    endX:= RightX
+                else
+                    endX:= X1;
+                end;
+            if w < Wraps then
+                begin
+                x:= x + (RightX - LeftX);
+                endY:= Y0 + (totalY / totalX) * x;
+                end
+            else
+                endY:= Y1;
+
+            DrawLineOnScreen(startX, startY, endX, endY, Width, r, g, b, a);
+            end;
+
+        end;
+
+    openglPopMatrix();
+
+    UpdateModelviewProjection;
+end;
+
 procedure DrawLineOnScreen(X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
 begin
     glEnable(GL_LINE_SMOOTH);