Draw ice on water
authorUrbertar@gmail.com
Wed, 27 Feb 2013 13:13:34 +0200
changeset 8592 bb724ef609db
parent 8590 c64b758e0412
child 8594 8946f98d09a0
Draw ice on water
hedgewars/GSHandlers.inc
hedgewars/uLandGraphics.pas
--- a/hedgewars/GSHandlers.inc	Tue Feb 26 20:39:18 2013 -0500
+++ b/hedgewars/GSHandlers.inc	Wed Feb 27 13:13:34 2013 +0200
@@ -5127,57 +5127,15 @@
         end;
 end;
 
-
-procedure drawIcePixel(x, y:Longint);
-var 
-    iceSurface: PSDL_Surface;
-    icePixels: PLongwordArray;
-    pictureX, pictureY: LongInt;
-    w, c: LongWord;
-begin
-    if Land[y, x] and lfIce <> 0 then exit;
-// So. 3 parameters here. Ice colour, Ice opacity, and a bias on the greyscaled pixel towards lightness
-    iceSurface:= SpritesData[sprIceTexture].Surface;
-    pictureX := x mod iceSurface^.w;
-    pictureY := y mod iceSurface^.h;
-    icePixels := iceSurface^.pixels;
-    w:= LandPixels[y, x];
-    w:= round(((w shr RShift and $FF) * RGB_LUMINANCE_RED +
-          (w shr BShift and $FF) * RGB_LUMINANCE_GREEN +
-          (w shr GShift and $FF) * RGB_LUMINANCE_BLUE));
-    if w < 128 then w:= w+128;
-    if w > 255 then w:= 255;
-    w:= (w shl RShift) or (w shl BShift) or (w shl GShift) or (LandPixels[y,x] and AMask);
-    //LandPixels[y, x]:= w;
-    LandPixels[y, x]:= addBgColor(w, IceColor);
-    LandPixels[y, x]:= addBgColor(LandPixels[y, x], icePixels^[iceSurface^.w * (y mod iceSurface^.h) + (x mod iceSurface^.w)]);
-
-    Land[y, x] := Land[y, x] or lfIce;
-end;
-
-procedure DrawIce(x, y: Longint); 
-    const iceRadius :Longint = 32;
-var
-    i, j: Longint;
-    weight: Longint;
-    landRect : TSDL_RECT;
-begin
-    FillRoundInLandWithIce(x, y, iceRadius);
-    SetAllHHToActive; 
-    landRect.x := min(max(x - iceRadius, 0), LAND_WIDTH - 1);
-    landRect.y := min(max(y - iceRadius, 0), LAND_HEIGHT - 1);
-    landRect.w := min(2*iceRadius, LAND_WIDTH - landRect.x - 1);
-    landRect.h := min(2*iceRadius, LAND_HEIGHT - landRect.y - 1);
-    UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true);
-end;
-
-
 procedure doStepIceGun(Gear: PGear);
 const iceWaitCollision:Longint = 0;
 const iceCollideWithGround:Longint = 1;
 const iceWaitNextTarget:Longint = 2;
 const iceCollideWithHog:Longint = 4;
+const iceCollideWithWater:Longint = 5;
 const groundFreezingTime:Longint = 1000;
+const waterFreezingTime:Longint = 500;
+const iceRadius:Longint = 32;
 var
     HHGear: PGear;
     ndX, ndY: hwFloat;
@@ -5229,6 +5187,9 @@
                         IceState := iceCollideWithGround;
                         IceTime := GameTicks;                    
                     end;
+                end else if (target.y >= cWaterLine) then
+                begin
+                    IceState := iceCollideWithWater;
                 end;
 
                 if (abs(gX-Target.X) < 2) and (abs(gY-Target.Y) < 2) then
@@ -5239,10 +5200,20 @@
 
                 if (IceState = iceCollideWithGround) and ((GameTicks - IceTime) > groundFreezingTime) then
                 begin 
-                    DrawIce(Target.X, Target.Y);                                        
+                    FillRoundInLandWithIce(Target.X, Target.Y, iceRadius);
+                    SetAllHHToActive; 
                     IceState := iceWaitNextTarget;
                 end;
 
+                if (IceState = iceCollideWithWater) and ((GameTicks - IceTime) > waterFreezingTime) then
+                begin 
+                    DrawSemiRound(Target.X, cWaterLine - 32, 16, iceRadius-5);
+                    FillRoundInLandWithIce(Target.X,  cWaterLine - 32, iceRadius);
+                    SetAllHHToActive; 
+                    IceState := iceWaitNextTarget;
+                end;
+
+
 // freeze nearby hogs
                 hogs := GearsNear(int2hwFloat(Target.X), int2hwFloat(Target.Y), gtHedgehog, Gear^.Radius*2);
                 if hogs.size > 0 then
@@ -5267,14 +5238,14 @@
                 X:= HHGear^.X;
                 Y:= HHGear^.Y
             end;
-            {if (gX > max(LAND_WIDTH,4096)*2) or
+            if (gX > max(LAND_WIDTH,4096)*2) or
                     (gX < -max(LAND_WIDTH,4096)) or
                     (gY < -max(LAND_HEIGHT,4096)) or
                     (gY > max(LAND_HEIGHT,4096)+512) then
             begin
                 X:= HHGear^.X;
                 Y:= HHGear^.Y
-            end}
+            end
         end
     end;
 end;
--- a/hedgewars/uLandGraphics.pas	Tue Feb 26 20:39:18 2013 -0500
+++ b/hedgewars/uLandGraphics.pas	Wed Feb 27 13:13:34 2013 +0200
@@ -37,6 +37,7 @@
 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
 procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword);
 procedure FillRoundInLandWithIce(X, Y, Radius: LongInt);
+procedure DrawSemiRound(x, y, height, radius:Longint); 
 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean);
 function  LandBackPixel(x, y: LongInt): LongWord;
 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword);
@@ -247,21 +248,6 @@
 end;
 
 
-function isLandscapeEdge(weight:Longint):boolean;
-begin
-    result := (weight < 8) and (weight >= 2);
-end;
-
-function isLandscape(weight:Longint):boolean;
-begin
-    result := weight < 2;
-end;
-
-function isEmptySpace(weight:Longint):boolean;
-begin
-    result := not isLandscape(weight) and not isLandscapeEdge(weight);
-end;
-
 function getPixelWeight(x, y:Longint): Longint;
 var
     i, j:Longint;
@@ -290,7 +276,7 @@
     weight: Longint;
 begin
     weight := getPixelWeight(x, y);
-    if isLandscape(weight) then
+    if weight < 2 then
         begin
         // So. 3 parameters here. Ice colour, Ice opacity, and a bias on the greyscaled pixel towards lightness
         iceSurface:= SpritesData[sprIceTexture].Surface;
@@ -307,12 +293,10 @@
         //LandPixels[y, x]:= w;
         LandPixels[y, x]:= addBgColor(w, IceColor);
         LandPixels[y, x]:= addBgColor(LandPixels[y, x], icePixels^[iceSurface^.w * (y mod iceSurface^.h) + (x mod iceSurface^.w)]);
-        Land[y, x] := land[y, x] or lfIce;
         end
-    else if (isLandscapeEdge(weight)) then
+    else if weight < 8 then
         begin
         LandPixels[y, x] := $FFB2AF8A;
-        if Land[y, x] > 255 then Land[y, x] := Land[y, x] or lfIce;
         end;
 
 end;
@@ -331,24 +315,31 @@
     getIncrementInquarter2 := directionX[quarter] * dx + directionY[quarter] * dy;
 end;
 
+
 procedure FillLandCircleLinesIce(x, y, dx, dy: LongInt);
 var q, i, t: LongInt;
 begin
 for q := 0 to 3 do
     begin
-        t:= y + getIncrementInquarter(dx, dy, q);
-        if (t and LAND_HEIGHT_MASK) = 0 then
-            for i:= Max(x - getIncrementInquarter2(dx, dy, q), 0) to Min(x + getIncrementInquarter2(dx, dy, q), LAND_WIDTH - 1) do
-                if (Land[t, i] and (lfIndestructible or lfIce) = 0) and (not disableLandBack or (Land[t, i] > 255))  then
+    t:= min(y + getIncrementInquarter(dx, dy, q), LAND_HEIGHT - 1);
+    if (t and LAND_HEIGHT_MASK) = 0 then
+        for i:= Max(x - getIncrementInquarter2(dx, dy, q), 0) to Min(x + getIncrementInquarter2(dx, dy, q), LAND_WIDTH - 1) do
+            begin
+            if (Land[t, i] and (lfIndestructible or lfIce) = 0) and (not disableLandBack or (Land[t, i] > 255))  then
+                begin
                     if (cReducedQuality and rqBlurryLand) = 0 then
                        drawIcePixel(t, i)
                     else
                        drawIcePixel(t div 2, i div 2) ;
+                    if Land[t, i] > 255 then Land[t, i] := Land[t, i] or lfIce;                                    
+                end;
+            end;
     end;
 end;
 
 procedure FillRoundInLandWithIce(X, Y, Radius: LongInt);
 var dx, dy, d: LongInt;
+    landRect: TSDL_Rect;
 begin
 dx:= 0;
 dy:= Radius;
@@ -367,9 +358,67 @@
         end;
     if (dx = dy) then
         FillLandCircleLinesIce(x, y, dx, dy);
+    landRect.x := min(max(x - Radius, 0), LAND_WIDTH - 1);
+    landRect.y := min(max(y - Radius, 0), LAND_HEIGHT - 1);
+    landRect.w := min(2*Radius, LAND_WIDTH - landRect.x - 1);
+    landRect.h := min(2*Radius, LAND_HEIGHT - landRect.y - 1);
+    UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true);        
 end;
 
 
+procedure FillLandCircleLinesColor(x, y, dx, dy, border: LongInt);
+var q, i, t: LongInt;
+begin
+for q := 0 to 3 do
+    begin
+        t:= y + getIncrementInquarter(dx, dy, q);
+        if (t and LAND_HEIGHT_MASK) = 0 then
+            for i:= Max(x - getIncrementInquarter2(dx, dy, q), 0) to Min(x + getIncrementInquarter2(dx, dy, q), LAND_WIDTH - 1) do
+            begin
+                if (Land[t, i] and (lfIndestructible or lfIce) = 0) and (not disableLandBack or (Land[t, i] > 255))  and (t > border) then
+                    begin
+                    if (cReducedQuality and rqBlurryLand) = 0 then
+                       LandPixels[t, i] := $FFFFFFFF
+                    else
+                       LandPixels[t div 2, i div 2] := $FFFFFFFF;
+                    Land[t, i] := lfBasic;                        
+                    end;
+            end;
+    end;
+end;
+
+
+procedure DrawSemiRound(x, y, height, radius:Longint);    
+var dx, dy, d: LongInt;
+    landRect: TSDL_Rect;
+begin
+dx:= 0;
+dy:= Radius;
+d:= 3 - 2 * Radius;
+    while (dx < dy) do
+        begin        
+            FillLandCircleLinesColor(x, y, dx, dy, y);
+        if (d < 0) then
+            d:= d + 4 * dx + 6
+        else
+            begin
+            d:= d + 4 * (dx - dy) + 10;
+            dec(dy)
+            end;
+        inc(dx)
+        end;
+    if (dx = dy) then
+           FillLandCircleLinesColor(x, y, dx, dy, y);
+    landRect.x := min(max(x - Radius, 0), LAND_WIDTH - 1);
+    landRect.y := min(max(y - Radius, 0), LAND_HEIGHT - 1);
+    landRect.w := min(2*Radius, LAND_WIDTH - landRect.x - 1);
+    landRect.h := min(2*Radius, LAND_HEIGHT - landRect.y - 1);
+    UpdateLandTexture(landRect.x, landRect.w, landRect.y, landRect.h, true);                
+end;
+
+
+
+
 function FillLandCircleLinesBG(x, y, dx, dy: LongInt): Longword;
 var i, t, by, bx: LongInt;
     cnt: Longword;