hedgewars/uLandGraphics.pas
branchhedgeroid
changeset 5932 5164d17b6374
parent 5895 212d3b459658
child 6011 519f8a58c021
equal deleted inserted replaced
5828:667fb58d7f18 5932:5164d17b6374
    27                                    Left, Right: LongInt;
    27                                    Left, Right: LongInt;
    28                                    end;
    28                                    end;
    29 
    29 
    30 function  addBgColor(OldColor, NewColor: LongWord): LongWord;
    30 function  addBgColor(OldColor, NewColor: LongWord): LongWord;
    31 function  SweepDirty: boolean;
    31 function  SweepDirty: boolean;
    32 function  Despeckle(X, Y: LongInt; gfxOnly: boolean): LongWord;
    32 function  Despeckle(X, Y: LongInt): Boolean;
    33 procedure Smooth(X, Y: LongInt);
    33 procedure Smooth(X, Y: LongInt);
    34 function  CheckLandValue(X, Y: LongInt; LandFlag: Word): boolean;
    34 function  CheckLandValue(X, Y: LongInt; LandFlag: Word): boolean;
    35 function  DrawExplosion(X, Y, Radius: LongInt): Longword;
    35 function  DrawExplosion(X, Y, Radius: LongInt): Longword;
    36 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
    36 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte);
    37 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
    37 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt);
   526     if ((ty and LAND_HEIGHT_MASK) = 0) and
   526     if ((ty and LAND_HEIGHT_MASK) = 0) and
   527        ((tx and LAND_WIDTH_MASK) = 0) and
   527        ((tx and LAND_WIDTH_MASK) = 0) and
   528        (((Land[ty, tx] and lfBasic) <> 0) or
   528        (((Land[ty, tx] and lfBasic) <> 0) or
   529        ((Land[ty, tx] and lfObject) <> 0)) then
   529        ((Land[ty, tx] and lfObject) <> 0)) then
   530         begin
   530         begin
   531         Land[ty, tx]:= Land[ty, tx] or lfDamaged;
   531         if despeckle then 
   532         if despeckle then LandDirty[ty div 32, tx div 32]:= 1;
   532             begin
       
   533             Land[ty, tx]:= Land[ty, tx] or lfDamaged;
       
   534             LandDirty[ty div 32, tx div 32]:= 1
       
   535             end;
   533         if (cReducedQuality and rqBlurryLand) = 0 then
   536         if (cReducedQuality and rqBlurryLand) = 0 then
   534             LandPixels[ty, tx]:= cExplosionBorderColor
   537             LandPixels[ty, tx]:= cExplosionBorderColor
   535         else LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
   538         else LandPixels[ty div 2, tx div 2]:= cExplosionBorderColor
   536         end
   539         end
   537     end;
   540     end;
   719 y:= Max(cpY, topY);
   722 y:= Max(cpY, topY);
   720 h:= Min(cpY + Image^.h, LAND_HEIGHT) - y;
   723 h:= Min(cpY + Image^.h, LAND_HEIGHT) - y;
   721 UpdateLandTexture(x, w, y, h)
   724 UpdateLandTexture(x, w, y, h)
   722 end;
   725 end;
   723 
   726 
   724 // was experimenting with applying as damage occurred.
   727 function Despeckle(X, Y: LongInt): boolean;
   725 function Despeckle(X, Y: LongInt; gfxOnly: boolean): LongWord;
       
   726 var nx, ny, i, j, c, xx, yy: LongInt;
   728 var nx, ny, i, j, c, xx, yy: LongInt;
   727     pixelsweep: boolean;
   729     pixelsweep: boolean;
   728 begin
   730 begin
   729 if (cReducedQuality and rqBlurryLand) = 0 then
   731 if (cReducedQuality and rqBlurryLand) = 0 then
   730    begin
   732    begin
   735    begin
   737    begin
   736    xx:= X div 2;
   738    xx:= X div 2;
   737    yy:= Y div 2;
   739    yy:= Y div 2;
   738    end;
   740    end;
   739 pixelsweep:= ((Land[Y, X] and $FF00) = 0) and (LandPixels[yy, xx] <> 0);
   741 pixelsweep:= ((Land[Y, X] and $FF00) = 0) and (LandPixels[yy, xx] <> 0);
   740 if not pixelsweep and gfxOnly then exit(0);
   742 if (((Land[Y, X] and lfDamaged) <> 0) and ((Land[Y, X] and lfIndestructible) = 0)) or pixelsweep then
   741 if ((Land[Y, X] > 255) and ((Land[Y, X] and lfIndestructible) = 0)) or pixelsweep then
       
   742     begin
   743     begin
   743     c:= 0;
   744     c:= 0;
   744     for i:= -1 to 1 do
   745     for i:= -1 to 1 do
   745         for j:= -1 to 1 do
   746         for j:= -1 to 1 do
   746             if (i <> 0) or (j <> 0) then
   747             if (i <> 0) or (j <> 0) then
   759                         if LandPixels[ny, nx] <> 0 then inc(c);
   760                         if LandPixels[ny, nx] <> 0 then inc(c);
   760                         end
   761                         end
   761                     else if Land[ny, nx] > 255 then inc(c);
   762                     else if Land[ny, nx] > 255 then inc(c);
   762                     end
   763                     end
   763                 end;
   764                 end;
   764     if (c < 2) or
   765 
   765        ((c < 4) and (((Land[Y, X] and lfDamaged) <> 0) or pixelsweep)) then
   766     if c < 4 then // 0-3 neighbours
   766         begin
   767         begin
   767         if ((Land[Y, X] and lfBasic) <> 0) and not disableLandBack then
   768         if ((Land[Y, X] and lfBasic) <> 0) and not disableLandBack then
   768             LandPixels[yy, xx]:= LandBackPixel(X, Y)
   769             LandPixels[yy, xx]:= LandBackPixel(X, Y)
   769         else
   770         else
   770             LandPixels[yy, xx]:= 0;
   771             LandPixels[yy, xx]:= 0;
   771 
   772 
   772         Land[Y, X]:= 0;
   773         Land[Y, X]:= 0;
   773         if not pixelsweep then exit(1)
   774         if not pixelsweep then exit(true);
   774         else exit(2)
       
   775         end;
   775         end;
   776     end;
   776     end;
   777 Despeckle:= 0
   777 Despeckle:= false
   778 end;
   778 end;
   779 
   779 
   780 procedure Smooth(X, Y: LongInt);
   780 procedure Smooth(X, Y: LongInt);
   781 begin
   781 begin
   782 // a bit of AA for explosions
   782 // a bit of AA for explosions
   825         end
   825         end
   826     end
   826     end
   827 end;
   827 end;
   828 
   828 
   829 function SweepDirty: boolean;
   829 function SweepDirty: boolean;
   830 var x, y, xx, yy, ty, tx, d: LongInt;
   830 var x, y, xx, yy, ty, tx: LongInt;
   831     bRes, updateBlock, resweepCol, resweepGfx, gfxOnly, recheck, firstpass: boolean;
   831     bRes, updateBlock, resweep, recheck: boolean;
   832 begin
   832 begin
   833 bRes:= false;
   833 bRes:= false;
   834 reCheck:= true;
   834 reCheck:= true;
   835 
   835 
   836 while recheck do
   836 while recheck do
   838     recheck:= false;
   838     recheck:= false;
   839     for y:= 0 to LAND_HEIGHT div 32 - 1 do
   839     for y:= 0 to LAND_HEIGHT div 32 - 1 do
   840         begin
   840         begin
   841         for x:= 0 to LAND_WIDTH div 32 - 1 do
   841         for x:= 0 to LAND_WIDTH div 32 - 1 do
   842             begin
   842             begin
   843             if LandDirty[y, x] <> 0 then
   843             if LandDirty[y, x] = 1 then
   844                 begin
   844                 begin
   845                 updateBlock:= false;
   845                 updateBlock:= false;
   846                 resweepCol:= true;
   846                 resweep:= true;
   847                 resweepGfx:= true;
       
   848                 firstpass:= true;
       
   849                 ty:= y * 32;
   847                 ty:= y * 32;
   850                 tx:= x * 32;
   848                 tx:= x * 32;
   851                 while(resweepCol or resweepGfx) do
   849                 while(resweep) do
   852                     begin
   850                     begin
   853                     gfxOnly:= resweepGfx and not resweepCol;
   851                     resweep:= false;
   854                     resweepCol:= false;
       
   855                     resweepGfx:= false;
       
   856                     for yy:= ty to ty + 31 do
   852                     for yy:= ty to ty + 31 do
   857                         for xx:= tx to tx + 31 do
   853                         for xx:= tx to tx + 31 do
   858                             begin
   854                             if Despeckle(xx, yy) then
   859                             d:= Despeckle(xx, yy, gfxOnly);
       
   860                             if d <> 0 then
       
   861                                 begin
   855                                 begin
   862                                 bRes:= true;
   856                                 bRes:= true;
   863                                 updateBlock:= true;
   857                                 updateBlock:= true;
   864                                 if d = 1 then resweepCol:= true
   858                                 resweep:= true;
   865                                 else resweepGfx:= true;
   859                                 if (yy = ty) and (y > 0) then
   866                                 if d = 1 then
   860                                     begin
   867                                     if (yy = ty) and (y > 0) then
   861                                     LandDirty[y-1, x]:= 1;
   868                                         begin
   862                                     recheck:= true;
   869                                         LandDirty[y-1, x]:= 1;
   863                                     end
   870                                         recheck:= true;
   864                                 else if (yy = ty+31) and (y < LAND_HEIGHT div 32 - 1) then
   871                                         end
   865                                     begin
   872                                     else if (yy = ty+31) and (y < LAND_HEIGHT div 32 - 1) then
   866                                     LandDirty[y+1, x]:= 1;
   873                                         begin
   867                                     recheck:= true;
   874                                         LandDirty[y+1, x]:= 1;
   868                                     end;
   875                                         recheck:= true;
   869                                 if (xx = tx) and (x > 0) then
   876                                         end;
   870                                     begin
   877                                     if (xx = tx) and (x > 0) then
   871                                     LandDirty[y, x-1]:= 1;
   878                                         begin
   872                                     recheck:= true;
   879                                         LandDirty[y, x-1]:= 1;
   873                                     end
   880                                         recheck:= true;
   874                                 else if (xx = tx+31) and (x < LAND_WIDTH div 32 - 1) then
   881                                         end
   875                                     begin
   882                                     else if (xx = tx+31) and (x < LAND_WIDTH div 32 - 1) then
   876                                     LandDirty[y, x+1]:= 1;
   883                                         begin
   877                                     recheck:= true;
   884                                         LandDirty[y, x+1]:= 1;
   878                                     end
   885                                         recheck:= true;
       
   886                                         end
       
   887                                 end;
   879                                 end;
   888                             if firstpass then Smooth(xx,yy);
       
   889                             end;
       
   890                     firstpass:= false
       
   891                     end;
   880                     end;
   892                 if updateBlock then UpdateLandTexture(tx, 32, ty, 32);
   881                 if updateBlock then UpdateLandTexture(tx, 32, ty, 32);
   893                 LandDirty[y, x]:= 0;
   882                 LandDirty[y, x]:= 2;
   894                 end;
   883                 end;
   895             end;
   884             end;
   896         end;
   885         end;
   897      end;
   886      end;
   898 
   887 
       
   888 for y:= 0 to LAND_HEIGHT div 32 - 1 do
       
   889     for x:= 0 to LAND_WIDTH div 32 - 1 do
       
   890         if LandDirty[y, x] <> 0 then
       
   891             begin
       
   892             LandDirty[y, x]:= 0;
       
   893             ty:= y * 32;
       
   894             tx:= x * 32;
       
   895             for yy:= ty to ty + 31 do
       
   896                 for xx:= tx to tx + 31 do
       
   897                     Smooth(xx,yy)
       
   898             end;
       
   899 
   899 SweepDirty:= bRes;
   900 SweepDirty:= bRes;
   900 end;
   901 end;
       
   902 
   901 
   903 
   902 // Return true if outside of land or not the value tested, used right now for some X/Y movement that does not use normal hedgehog movement in GSHandlers.inc
   904 // Return true if outside of land or not the value tested, used right now for some X/Y movement that does not use normal hedgehog movement in GSHandlers.inc
   903 function CheckLandValue(X, Y: LongInt; LandFlag: Word): boolean;
   905 function CheckLandValue(X, Y: LongInt; LandFlag: Word): boolean;
   904 begin
   906 begin
   905      CheckLandValue:= ((X and LAND_WIDTH_MASK <> 0) or (Y and LAND_HEIGHT_MASK <> 0)) or ((Land[Y, X] and LandFlag) = 0)
   907      CheckLandValue:= ((X and LAND_WIDTH_MASK <> 0) or (Y and LAND_HEIGHT_MASK <> 0)) or ((Land[Y, X] and LandFlag) = 0)