hedgewars/uLandGraphics.pas
changeset 2647 0e1208e92dfe
parent 2646 6a1185633872
child 2648 415a75d45693
--- a/hedgewars/uLandGraphics.pas	Sun Nov 29 16:37:12 2009 +0000
+++ b/hedgewars/uLandGraphics.pas	Sun Nov 29 16:56:04 2009 +0000
@@ -30,7 +30,6 @@
 function SweepDirty: boolean;
 function Despeckle(X, Y: LongInt): boolean;
 function CheckLandValue(X, Y: LongInt; Color: Word): boolean;
-procedure Despeckle2(X, Y, Threesold: LongInt);
 procedure DrawExplosion(X, Y, Radius: LongInt);
 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
@@ -42,44 +41,6 @@
 implementation
 uses SDLh, uMisc, uLand, uLandTexture;
 
-procedure Despeckle2(X, Y, Threesold: LongInt);
-var
-	i, j: LongInt;
-	x0, x1, y0, y1: LongInt;        
-	c: byte;
-begin
-	// If the pixel has less than Threesold neightbours, it gets erased
-	// Erasing is outwards recursive
-	c := 0;
-
-	x0 := max(X-1, 0);
-	x1 := min(X+1, LAND_WIDTH - 1);
-	y0 := max(Y-1, 0);
-	y1 := min(Y+1, LAND_HEIGHT - 1);
-
-	for i:=x0 to x1 do begin
-		for j:=y0 to y1 do begin
-			if Land[j, i]<>0 then begin
-				c := c+1;
-			end;
-		end;
-	end;
-	
-	if c<Threesold then begin
-		Land[Y, X] := 0;
-		LandPixels[Y, X] := 0;
-		for i:=x0 to x1 do begin
-			for j:=y0 to y1 do begin
-				if Land[j, i]<>0 then begin
-					LandPixels[j, i] := cExplosionBorderColor;
-					Despeckle2(i, j, 5);
-				end;
-			end;
-		end;
-	end;
-    UpdateLandTexture(x0, x1-x0, y0, y1-y0);
-end;
-
 procedure FillCircleLines(x, y, dx, dy: LongInt; Value: Longword);
 var i: LongInt;
 begin
@@ -184,55 +145,84 @@
 begin
 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-        if Land[y + dy, i] = COLOR_LAND then
+        if (Land[y + dy, i] <> COLOR_INDESTRUCTIBLE) then
             LandPixels[y + dy, i]:= 0;
 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-        if Land[y - dy, i] = COLOR_LAND then
+        if (Land[y - dy, i] <> COLOR_INDESTRUCTIBLE) then
              LandPixels[y - dy, i]:= 0;
 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-        if Land[y + dx, i] = COLOR_LAND then
+        if (Land[y + dx, i] <> COLOR_INDESTRUCTIBLE) then
             LandPixels[y + dx, i]:= 0;
 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-        if Land[y - dx, i] = COLOR_LAND then
+        if (Land[y - dx, i] <> COLOR_INDESTRUCTIBLE) then
              LandPixels[y - dx, i]:= 0;
 end;
 
+procedure FillLandCircleLinesBG(x, y, dx, dy: LongInt);
+var i: LongInt;
+begin
+if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
+   for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
+       if (Land[y + dy, i] = COLOR_LAND) then
+          LandPixels[y + dy, i]:= LandBackPixel(i, y + dy)
+       else
+          if (Land[y + dy, i] = COLOR_OBJECT) then LandPixels[y + dy, i]:= 0;
+if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
+   for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
+       if (Land[y - dy, i] = COLOR_LAND) then
+          LandPixels[y - dy, i]:= LandBackPixel(i, y - dy)
+       else
+          if (Land[y - dy, i] = COLOR_OBJECT) then LandPixels[y - dy, i]:= 0;
+if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
+   for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
+       if (Land[y + dx, i] = COLOR_LAND) then
+           LandPixels[y + dx, i]:= LandBackPixel(i, y + dx)
+       else
+          if (Land[y + dx, i] = COLOR_OBJECT) then LandPixels[y + dx, i]:= 0;
+if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
+   for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
+       if (Land[y - dx, i] = COLOR_LAND) then
+          LandPixels[y - dx, i]:= LandBackPixel(i, y - dx)
+       else
+          if (Land[y - dx, i] = COLOR_OBJECT) then LandPixels[y - dx, i]:= 0;
+end;
+
 procedure FillLandCircleLinesEBC(x, y, dx, dy: LongInt);
 var i: LongInt;
 begin
 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-       if Land[y + dy, i] = COLOR_LAND then
+       if (Land[y + dy, i] = COLOR_LAND) or (Land[y + dy, i] = COLOR_OBJECT) then
           begin
           LandPixels[y + dy, i]:= cExplosionBorderColor;
-          Despeckle2(i, y + dy, 6);
+          Despeckle(i, y + dy);
           LandDirty[(y + dy) div 32, i div 32]:= 1;
           end;
 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
-       if Land[y - dy, i] = COLOR_LAND then
+       if (Land[y - dy, i] = COLOR_LAND) or (Land[y - dy, i] = COLOR_OBJECT) then
           begin
           LandPixels[y - dy, i]:= cExplosionBorderColor;
-          Despeckle2(i, y - dy, 6);
+          Despeckle(i, y - dy);
           LandDirty[(y - dy) div 32, i div 32]:= 1;
           end;
 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-       if Land[y + dx, i] = COLOR_LAND then
+       if (Land[y + dx, i] = COLOR_LAND) or (Land[y + dx, i] = COLOR_OBJECT) then
            begin
            LandPixels[y + dx, i]:= cExplosionBorderColor;
-           Despeckle2(i, y + dx, 6);
+           Despeckle(i, y + dx);
            LandDirty[(y + dx) div 32, i div 32]:= 1;
            end;
 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
-       if Land[y - dx, i] = COLOR_LAND then
+       if (Land[y - dx, i] = COLOR_LAND) or (Land[y - dx, i] = COLOR_OBJECT) then
           begin
           LandPixels[y - dx, i]:= cExplosionBorderColor;
-          Despeckle2(i, y - dy, 6);
+          Despeckle(i, y - dy);
           LandDirty[(y - dx) div 32, i div 32]:= 1;
           end;
 end;
@@ -240,39 +230,70 @@
 procedure DrawExplosion(X, Y, Radius: LongInt);
 var dx, dy, ty, tx, d: LongInt;
 begin
-  dx:= 0;
-  dy:= Radius;
-  d:= 3 - 2 * Radius;
-  while (dx < dy) do
-     begin
-     FillLandCircleLines0(x, y, dx, dy);
-     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 FillLandCircleLines0(x, y, dx, dy);
+
+// draw background land texture
+	begin
+	dx:= 0;
+	dy:= Radius;
+	d:= 3 - 2 * Radius;
+
+	while (dx < dy) do
+		begin
+		FillLandCircleLinesBG(x, y, dx, dy);
+		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 FillLandCircleLinesBG(x, y, dx, dy);
+	end;
+
+// draw a hole in land
+if Radius > 25 then
+	begin
+	dx:= 0;
+	dy:= Radius - 25;
+	d:= 3 - 2 * dy;
+
+	while (dx < dy) do
+		begin
+		FillLandCircleLines0(x, y, dx, dy);
+		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 FillLandCircleLines0(x, y, dx, dy);
+	end;
+
   // FillRoundInLand after erasing land pixels to allow Land 0 check for mask.png to function
-  FillRoundInLand(X, Y, Radius, 0);
-  inc(Radius, 4);
-  dx:= 0;
-  dy:= Radius;
-  d:= 3 - 2 * Radius;
-  while (dx < dy) do
-     begin
-     FillLandCircleLinesEBC(x, y, dx, dy);
-     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 FillLandCircleLinesEBC(x, y, dx, dy);
+	FillRoundInLand(X, Y, Radius, 0);
+
+// draw explosion border
+	begin
+	inc(Radius, 4);
+	dx:= 0;
+	dy:= Radius;
+	d:= 3 - 2 * Radius;
+	while (dx < dy) do
+		begin
+		FillLandCircleLinesEBC(x, y, dx, dy);
+		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 FillLandCircleLinesEBC(x, y, dx, dy);
+	end;
 
 tx:= max(X - Radius - 1, 0);
 dx:= min(X + Radius + 1, LAND_WIDTH) - tx;
@@ -285,13 +306,15 @@
 var tx, ty, i: LongInt;
 begin
 for i:= 0 to Pred(Count) do
-    begin
-    for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
-        for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
-            if Land[ty, tx] = COLOR_LAND then
-                LandPixels[ty, tx]:= 0;
-    inc(y, dY)
-    end;
+	begin
+	for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
+		for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
+			if Land[ty, tx] = COLOR_LAND then
+				LandPixels[ty, tx]:= LandBackPixel(tx, ty)
+			else if Land[ty, tx] = COLOR_OBJECT then
+				LandPixels[ty, tx]:= 0;
+	inc(y, dY)
+	end;
 
 inc(Radius, 4);
 dec(y, Count * dY);
@@ -300,10 +323,10 @@
     begin
     for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
         for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
-            if Land[ty, tx] = COLOR_LAND then
+            if (Land[ty, tx] = COLOR_LAND) or (Land[ty, tx] = COLOR_OBJECT) then
                 begin
                 LandPixels[ty, tx]:= cExplosionBorderColor;
-                LandDirty[trunc((y + dy)/32), trunc(i/32)]:= 1;
+                LandDirty[(y + dy) shr 5, i shr 5]:= 1;
                 end;
     inc(y, dY)
     end;
@@ -352,11 +375,13 @@
         tx:= hwRound(X);
         ty:= hwRound(Y);
         if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) then
-         if Land[ty, tx] = COLOR_LAND then
-           begin
-           Land[ty, tx]:= 0;
-           LandPixels[ty, tx]:= 0;
-           end
+            begin
+            if Land[ty, tx] = COLOR_LAND then
+                LandPixels[ty, tx]:= LandBackPixel(tx, ty)
+            else if Land[ty, tx] = COLOR_OBJECT then
+                LandPixels[ty, tx]:= 0;
+            Land[ty, tx]:= 0;
+            end
         end;
     for t:= 0 to 7 do
         {$INCLUDE "tunsetborder.inc"}
@@ -438,7 +463,7 @@
             for x:= 0 to Pred(w) do
                 if PLongword(@(p^[x * 4]))^ <> 0 then
                    begin
-                   Land[cpY + y, cpX + x]:= COLOR_LAND;
+                   Land[cpY + y, cpX + x]:= COLOR_OBJECT;
                    LandPixels[cpY + y, cpX + x]:= PLongword(@(p^[x * 4]))^
                    end;
             p:= @(p^[Image^.pitch]);
@@ -474,7 +499,7 @@
 
 	if c < 4 then // 0-3 neighbours
 		begin
-		LandPixels[Y, X]:= 0;
+        LandPixels[Y, X]:= ToggleLongInt(Land[Y, X] = COLOR_LAND, LandBackPixel(X, Y), 0);
 		Land[Y, X]:= 0;
 		exit(true);
 		end;