hedgewars/uLandGraphics.pas
changeset 2647 0e1208e92dfe
parent 2646 6a1185633872
child 2648 415a75d45693
equal deleted inserted replaced
2646:6a1185633872 2647:0e1208e92dfe
    28                                    end;
    28                                    end;
    29 
    29 
    30 function SweepDirty: boolean;
    30 function SweepDirty: boolean;
    31 function Despeckle(X, Y: LongInt): boolean;
    31 function Despeckle(X, Y: LongInt): boolean;
    32 function CheckLandValue(X, Y: LongInt; Color: Word): boolean;
    32 function CheckLandValue(X, Y: LongInt; Color: Word): boolean;
    33 procedure Despeckle2(X, Y, Threesold: LongInt);
       
    34 procedure DrawExplosion(X, Y, Radius: LongInt);
    33 procedure DrawExplosion(X, Y, Radius: LongInt);
    35 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
    34 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
    36 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
    35 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
    37 procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword);
    36 procedure FillRoundInLand(X, Y, Radius: LongInt; Value: Longword);
    38 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet: boolean);
    37 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet: boolean);
    39 
    38 
    40 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean): boolean;
    39 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace: boolean): boolean;
    41 
    40 
    42 implementation
    41 implementation
    43 uses SDLh, uMisc, uLand, uLandTexture;
    42 uses SDLh, uMisc, uLand, uLandTexture;
    44 
       
    45 procedure Despeckle2(X, Y, Threesold: LongInt);
       
    46 var
       
    47 	i, j: LongInt;
       
    48 	x0, x1, y0, y1: LongInt;        
       
    49 	c: byte;
       
    50 begin
       
    51 	// If the pixel has less than Threesold neightbours, it gets erased
       
    52 	// Erasing is outwards recursive
       
    53 	c := 0;
       
    54 
       
    55 	x0 := max(X-1, 0);
       
    56 	x1 := min(X+1, LAND_WIDTH - 1);
       
    57 	y0 := max(Y-1, 0);
       
    58 	y1 := min(Y+1, LAND_HEIGHT - 1);
       
    59 
       
    60 	for i:=x0 to x1 do begin
       
    61 		for j:=y0 to y1 do begin
       
    62 			if Land[j, i]<>0 then begin
       
    63 				c := c+1;
       
    64 			end;
       
    65 		end;
       
    66 	end;
       
    67 	
       
    68 	if c<Threesold then begin
       
    69 		Land[Y, X] := 0;
       
    70 		LandPixels[Y, X] := 0;
       
    71 		for i:=x0 to x1 do begin
       
    72 			for j:=y0 to y1 do begin
       
    73 				if Land[j, i]<>0 then begin
       
    74 					LandPixels[j, i] := cExplosionBorderColor;
       
    75 					Despeckle2(i, j, 5);
       
    76 				end;
       
    77 			end;
       
    78 		end;
       
    79 	end;
       
    80     UpdateLandTexture(x0, x1-x0, y0, y1-y0);
       
    81 end;
       
    82 
    43 
    83 procedure FillCircleLines(x, y, dx, dy: LongInt; Value: Longword);
    44 procedure FillCircleLines(x, y, dx, dy: LongInt; Value: Longword);
    84 var i: LongInt;
    45 var i: LongInt;
    85 begin
    46 begin
    86 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
    47 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
   182 procedure FillLandCircleLines0(x, y, dx, dy: LongInt);
   143 procedure FillLandCircleLines0(x, y, dx, dy: LongInt);
   183 var i: LongInt;
   144 var i: LongInt;
   184 begin
   145 begin
   185 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
   146 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
   186     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   147     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   187         if Land[y + dy, i] = COLOR_LAND then
   148         if (Land[y + dy, i] <> COLOR_INDESTRUCTIBLE) then
   188             LandPixels[y + dy, i]:= 0;
   149             LandPixels[y + dy, i]:= 0;
   189 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
   150 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
   190     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   151     for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   191         if Land[y - dy, i] = COLOR_LAND then
   152         if (Land[y - dy, i] <> COLOR_INDESTRUCTIBLE) then
   192              LandPixels[y - dy, i]:= 0;
   153              LandPixels[y - dy, i]:= 0;
   193 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
   154 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
   194     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   155     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   195         if Land[y + dx, i] = COLOR_LAND then
   156         if (Land[y + dx, i] <> COLOR_INDESTRUCTIBLE) then
   196             LandPixels[y + dx, i]:= 0;
   157             LandPixels[y + dx, i]:= 0;
   197 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
   158 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
   198     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   159     for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   199         if Land[y - dx, i] = COLOR_LAND then
   160         if (Land[y - dx, i] <> COLOR_INDESTRUCTIBLE) then
   200              LandPixels[y - dx, i]:= 0;
   161              LandPixels[y - dx, i]:= 0;
       
   162 end;
       
   163 
       
   164 procedure FillLandCircleLinesBG(x, y, dx, dy: LongInt);
       
   165 var i: LongInt;
       
   166 begin
       
   167 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
       
   168    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
       
   169        if (Land[y + dy, i] = COLOR_LAND) then
       
   170           LandPixels[y + dy, i]:= LandBackPixel(i, y + dy)
       
   171        else
       
   172           if (Land[y + dy, i] = COLOR_OBJECT) then LandPixels[y + dy, i]:= 0;
       
   173 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
       
   174    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
       
   175        if (Land[y - dy, i] = COLOR_LAND) then
       
   176           LandPixels[y - dy, i]:= LandBackPixel(i, y - dy)
       
   177        else
       
   178           if (Land[y - dy, i] = COLOR_OBJECT) then LandPixels[y - dy, i]:= 0;
       
   179 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
       
   180    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
       
   181        if (Land[y + dx, i] = COLOR_LAND) then
       
   182            LandPixels[y + dx, i]:= LandBackPixel(i, y + dx)
       
   183        else
       
   184           if (Land[y + dx, i] = COLOR_OBJECT) then LandPixels[y + dx, i]:= 0;
       
   185 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
       
   186    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
       
   187        if (Land[y - dx, i] = COLOR_LAND) then
       
   188           LandPixels[y - dx, i]:= LandBackPixel(i, y - dx)
       
   189        else
       
   190           if (Land[y - dx, i] = COLOR_OBJECT) then LandPixels[y - dx, i]:= 0;
   201 end;
   191 end;
   202 
   192 
   203 procedure FillLandCircleLinesEBC(x, y, dx, dy: LongInt);
   193 procedure FillLandCircleLinesEBC(x, y, dx, dy: LongInt);
   204 var i: LongInt;
   194 var i: LongInt;
   205 begin
   195 begin
   206 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
   196 if ((y + dy) and LAND_HEIGHT_MASK) = 0 then
   207    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   197    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   208        if Land[y + dy, i] = COLOR_LAND then
   198        if (Land[y + dy, i] = COLOR_LAND) or (Land[y + dy, i] = COLOR_OBJECT) then
   209           begin
   199           begin
   210           LandPixels[y + dy, i]:= cExplosionBorderColor;
   200           LandPixels[y + dy, i]:= cExplosionBorderColor;
   211           Despeckle2(i, y + dy, 6);
   201           Despeckle(i, y + dy);
   212           LandDirty[(y + dy) div 32, i div 32]:= 1;
   202           LandDirty[(y + dy) div 32, i div 32]:= 1;
   213           end;
   203           end;
   214 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
   204 if ((y - dy) and LAND_HEIGHT_MASK) = 0 then
   215    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   205    for i:= max(x - dx, 0) to min(x + dx, LAND_WIDTH - 1) do
   216        if Land[y - dy, i] = COLOR_LAND then
   206        if (Land[y - dy, i] = COLOR_LAND) or (Land[y - dy, i] = COLOR_OBJECT) then
   217           begin
   207           begin
   218           LandPixels[y - dy, i]:= cExplosionBorderColor;
   208           LandPixels[y - dy, i]:= cExplosionBorderColor;
   219           Despeckle2(i, y - dy, 6);
   209           Despeckle(i, y - dy);
   220           LandDirty[(y - dy) div 32, i div 32]:= 1;
   210           LandDirty[(y - dy) div 32, i div 32]:= 1;
   221           end;
   211           end;
   222 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
   212 if ((y + dx) and LAND_HEIGHT_MASK) = 0 then
   223    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   213    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   224        if Land[y + dx, i] = COLOR_LAND then
   214        if (Land[y + dx, i] = COLOR_LAND) or (Land[y + dx, i] = COLOR_OBJECT) then
   225            begin
   215            begin
   226            LandPixels[y + dx, i]:= cExplosionBorderColor;
   216            LandPixels[y + dx, i]:= cExplosionBorderColor;
   227            Despeckle2(i, y + dx, 6);
   217            Despeckle(i, y + dx);
   228            LandDirty[(y + dx) div 32, i div 32]:= 1;
   218            LandDirty[(y + dx) div 32, i div 32]:= 1;
   229            end;
   219            end;
   230 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
   220 if ((y - dx) and LAND_HEIGHT_MASK) = 0 then
   231    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   221    for i:= max(x - dy, 0) to min(x + dy, LAND_WIDTH - 1) do
   232        if Land[y - dx, i] = COLOR_LAND then
   222        if (Land[y - dx, i] = COLOR_LAND) or (Land[y - dx, i] = COLOR_OBJECT) then
   233           begin
   223           begin
   234           LandPixels[y - dx, i]:= cExplosionBorderColor;
   224           LandPixels[y - dx, i]:= cExplosionBorderColor;
   235           Despeckle2(i, y - dy, 6);
   225           Despeckle(i, y - dy);
   236           LandDirty[(y - dx) div 32, i div 32]:= 1;
   226           LandDirty[(y - dx) div 32, i div 32]:= 1;
   237           end;
   227           end;
   238 end;
   228 end;
   239 
   229 
   240 procedure DrawExplosion(X, Y, Radius: LongInt);
   230 procedure DrawExplosion(X, Y, Radius: LongInt);
   241 var dx, dy, ty, tx, d: LongInt;
   231 var dx, dy, ty, tx, d: LongInt;
   242 begin
   232 begin
   243   dx:= 0;
   233 
   244   dy:= Radius;
   234 // draw background land texture
   245   d:= 3 - 2 * Radius;
   235 	begin
   246   while (dx < dy) do
   236 	dx:= 0;
   247      begin
   237 	dy:= Radius;
   248      FillLandCircleLines0(x, y, dx, dy);
   238 	d:= 3 - 2 * Radius;
   249      if (d < 0)
   239 
   250      then d:= d + 4 * dx + 6
   240 	while (dx < dy) do
   251      else begin
   241 		begin
   252           d:= d + 4 * (dx - dy) + 10;
   242 		FillLandCircleLinesBG(x, y, dx, dy);
   253           dec(dy)
   243 		if (d < 0)
   254           end;
   244 		then d:= d + 4 * dx + 6
   255      inc(dx)
   245 		else begin
   256      end;
   246 			d:= d + 4 * (dx - dy) + 10;
   257   if (dx = dy) then FillLandCircleLines0(x, y, dx, dy);
   247 			dec(dy)
       
   248 			end;
       
   249 		inc(dx)
       
   250 		end;
       
   251 	if (dx = dy) then FillLandCircleLinesBG(x, y, dx, dy);
       
   252 	end;
       
   253 
       
   254 // draw a hole in land
       
   255 if Radius > 25 then
       
   256 	begin
       
   257 	dx:= 0;
       
   258 	dy:= Radius - 25;
       
   259 	d:= 3 - 2 * dy;
       
   260 
       
   261 	while (dx < dy) do
       
   262 		begin
       
   263 		FillLandCircleLines0(x, y, dx, dy);
       
   264 		if (d < 0)
       
   265 		then d:= d + 4 * dx + 6
       
   266 		else begin
       
   267 			d:= d + 4 * (dx - dy) + 10;
       
   268 			dec(dy)
       
   269 			end;
       
   270 		inc(dx)
       
   271 		end;
       
   272 	if (dx = dy) then FillLandCircleLines0(x, y, dx, dy);
       
   273 	end;
       
   274 
   258   // FillRoundInLand after erasing land pixels to allow Land 0 check for mask.png to function
   275   // FillRoundInLand after erasing land pixels to allow Land 0 check for mask.png to function
   259   FillRoundInLand(X, Y, Radius, 0);
   276 	FillRoundInLand(X, Y, Radius, 0);
   260   inc(Radius, 4);
   277 
   261   dx:= 0;
   278 // draw explosion border
   262   dy:= Radius;
   279 	begin
   263   d:= 3 - 2 * Radius;
   280 	inc(Radius, 4);
   264   while (dx < dy) do
   281 	dx:= 0;
   265      begin
   282 	dy:= Radius;
   266      FillLandCircleLinesEBC(x, y, dx, dy);
   283 	d:= 3 - 2 * Radius;
   267      if (d < 0)
   284 	while (dx < dy) do
   268      then d:= d + 4 * dx + 6
   285 		begin
   269      else begin
   286 		FillLandCircleLinesEBC(x, y, dx, dy);
   270           d:= d + 4 * (dx - dy) + 10;
   287 		if (d < 0)
   271           dec(dy)
   288 		then d:= d + 4 * dx + 6
   272           end;
   289 		else begin
   273      inc(dx)
   290 			d:= d + 4 * (dx - dy) + 10;
   274      end;
   291 			dec(dy)
   275   if (dx = dy) then FillLandCircleLinesEBC(x, y, dx, dy);
   292 			end;
       
   293 		inc(dx)
       
   294 		end;
       
   295 	if (dx = dy) then FillLandCircleLinesEBC(x, y, dx, dy);
       
   296 	end;
   276 
   297 
   277 tx:= max(X - Radius - 1, 0);
   298 tx:= max(X - Radius - 1, 0);
   278 dx:= min(X + Radius + 1, LAND_WIDTH) - tx;
   299 dx:= min(X + Radius + 1, LAND_WIDTH) - tx;
   279 ty:= max(Y - Radius - 1, 0);
   300 ty:= max(Y - Radius - 1, 0);
   280 dy:= min(Y + Radius + 1, LAND_HEIGHT) - ty;
   301 dy:= min(Y + Radius + 1, LAND_HEIGHT) - ty;
   283 
   304 
   284 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
   305 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
   285 var tx, ty, i: LongInt;
   306 var tx, ty, i: LongInt;
   286 begin
   307 begin
   287 for i:= 0 to Pred(Count) do
   308 for i:= 0 to Pred(Count) do
   288     begin
   309 	begin
   289     for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
   310 	for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
   290         for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
   311 		for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
   291             if Land[ty, tx] = COLOR_LAND then
   312 			if Land[ty, tx] = COLOR_LAND then
   292                 LandPixels[ty, tx]:= 0;
   313 				LandPixels[ty, tx]:= LandBackPixel(tx, ty)
   293     inc(y, dY)
   314 			else if Land[ty, tx] = COLOR_OBJECT then
   294     end;
   315 				LandPixels[ty, tx]:= 0;
       
   316 	inc(y, dY)
       
   317 	end;
   295 
   318 
   296 inc(Radius, 4);
   319 inc(Radius, 4);
   297 dec(y, Count * dY);
   320 dec(y, Count * dY);
   298 
   321 
   299 for i:= 0 to Pred(Count) do
   322 for i:= 0 to Pred(Count) do
   300     begin
   323     begin
   301     for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
   324     for ty:= max(y - Radius, 0) to min(y + Radius, LAND_HEIGHT) do
   302         for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
   325         for tx:= max(0, ar^[i].Left - Radius) to min(LAND_WIDTH, ar^[i].Right + Radius) do
   303             if Land[ty, tx] = COLOR_LAND then
   326             if (Land[ty, tx] = COLOR_LAND) or (Land[ty, tx] = COLOR_OBJECT) then
   304                 begin
   327                 begin
   305                 LandPixels[ty, tx]:= cExplosionBorderColor;
   328                 LandPixels[ty, tx]:= cExplosionBorderColor;
   306                 LandDirty[trunc((y + dy)/32), trunc(i/32)]:= 1;
   329                 LandDirty[(y + dy) shr 5, i shr 5]:= 1;
   307                 end;
   330                 end;
   308     inc(y, dY)
   331     inc(y, dY)
   309     end;
   332     end;
   310 
   333 
   311 
   334 
   350         X:= X + dX;
   373         X:= X + dX;
   351         Y:= Y + dY;
   374         Y:= Y + dY;
   352         tx:= hwRound(X);
   375         tx:= hwRound(X);
   353         ty:= hwRound(Y);
   376         ty:= hwRound(Y);
   354         if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) then
   377         if ((ty and LAND_HEIGHT_MASK) = 0) and ((tx and LAND_WIDTH_MASK) = 0) then
   355          if Land[ty, tx] = COLOR_LAND then
   378             begin
   356            begin
   379             if Land[ty, tx] = COLOR_LAND then
   357            Land[ty, tx]:= 0;
   380                 LandPixels[ty, tx]:= LandBackPixel(tx, ty)
   358            LandPixels[ty, tx]:= 0;
   381             else if Land[ty, tx] = COLOR_OBJECT then
   359            end
   382                 LandPixels[ty, tx]:= 0;
       
   383             Land[ty, tx]:= 0;
       
   384             end
   360         end;
   385         end;
   361     for t:= 0 to 7 do
   386     for t:= 0 to 7 do
   362         {$INCLUDE "tunsetborder.inc"}
   387         {$INCLUDE "tunsetborder.inc"}
   363     nx:= nx - dY;
   388     nx:= nx - dY;
   364     ny:= ny + dX;
   389     ny:= ny + dX;
   436      4: for y:= 0 to Pred(h) do
   461      4: for y:= 0 to Pred(h) do
   437             begin
   462             begin
   438             for x:= 0 to Pred(w) do
   463             for x:= 0 to Pred(w) do
   439                 if PLongword(@(p^[x * 4]))^ <> 0 then
   464                 if PLongword(@(p^[x * 4]))^ <> 0 then
   440                    begin
   465                    begin
   441                    Land[cpY + y, cpX + x]:= COLOR_LAND;
   466                    Land[cpY + y, cpX + x]:= COLOR_OBJECT;
   442                    LandPixels[cpY + y, cpX + x]:= PLongword(@(p^[x * 4]))^
   467                    LandPixels[cpY + y, cpX + x]:= PLongword(@(p^[x * 4]))^
   443                    end;
   468                    end;
   444             p:= @(p^[Image^.pitch]);
   469             p:= @(p^[Image^.pitch]);
   445             end;
   470             end;
   446      end;
   471      end;
   472 						inc(c);
   497 						inc(c);
   473 				end;
   498 				end;
   474 
   499 
   475 	if c < 4 then // 0-3 neighbours
   500 	if c < 4 then // 0-3 neighbours
   476 		begin
   501 		begin
   477 		LandPixels[Y, X]:= 0;
   502         LandPixels[Y, X]:= ToggleLongInt(Land[Y, X] = COLOR_LAND, LandBackPixel(X, Y), 0);
   478 		Land[Y, X]:= 0;
   503 		Land[Y, X]:= 0;
   479 		exit(true);
   504 		exit(true);
   480 		end;
   505 		end;
   481 	end;
   506 	end;
   482 Despeckle:= false
   507 Despeckle:= false