hedgewars/uLandGraphics.pas
changeset 54 839fd258ae6f
child 57 e1a77ae57065
equal deleted inserted replaced
53:0e27949850e3 54:839fd258ae6f
       
     1 unit uLandGraphics;
       
     2 interface
       
     3 
       
     4 type PRangeArray = ^TRangeArray;
       
     5      TRangeArray = array[0..31] of record
       
     6                                    Left, Right: integer;
       
     7                                    end;
       
     8 
       
     9 procedure DrawExplosion(X, Y, Radius: integer);
       
    10 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: Longword; y, dY: integer; Count: Byte);
       
    11 procedure DrawTunnel(X, Y, dX, dY: real; ticks, HalfWidth: integer);
       
    12 procedure FillRoundInLand(X, Y, Radius: integer; Value: Longword);
       
    13 
       
    14 implementation
       
    15 uses SDLh, uStore, uMisc, uLand;
       
    16 
       
    17 procedure FillCircleLines(x, y, dx, dy: integer; Value: Longword);
       
    18 var i: integer;
       
    19 begin
       
    20 if ((y + dy) and $FFFFFC00) = 0 then
       
    21    for i:= max(x - dx, 0) to min(x + dx, 2047) do Land[y + dy, i]:= Value;
       
    22 if ((y - dy) and $FFFFFC00) = 0 then
       
    23    for i:= max(x - dx, 0) to min(x + dx, 2047) do Land[y - dy, i]:= Value;
       
    24 if ((y + dx) and $FFFFFC00) = 0 then
       
    25    for i:= max(x - dy, 0) to min(x + dy, 2047) do Land[y + dx, i]:= Value;
       
    26 if ((y - dx) and $FFFFFC00) = 0 then
       
    27    for i:= max(x - dy, 0) to min(x + dy, 2047) do Land[y - dx, i]:= Value;
       
    28 end;
       
    29 
       
    30 procedure FillRoundInLand(X, Y, Radius: integer; Value: Longword);
       
    31 var dx, dy, d: integer;
       
    32 begin
       
    33   dx:= 0;
       
    34   dy:= Radius;
       
    35   d:= 3 - 2 * Radius;
       
    36   while (dx < dy) do
       
    37      begin
       
    38      FillCircleLines(x, y, dx, dy, Value);
       
    39      if (d < 0)
       
    40      then d:= d + 4 * dx + 6
       
    41      else begin
       
    42           d:= d + 4 * (dx - dy) + 10;
       
    43           dec(dy)
       
    44           end;
       
    45      inc(dx)
       
    46      end;
       
    47   if (dx = dy) then FillCircleLines(x, y, dx, dy, Value);
       
    48 end;
       
    49 
       
    50 procedure DrawExplosion(X, Y, Radius: integer);
       
    51 var ty, tx, p: integer;
       
    52 begin
       
    53 FillRoundInLand(X, Y, Radius, 0);
       
    54 
       
    55 if SDL_MustLock(LandSurface) then
       
    56    SDLTry(SDL_LockSurface(LandSurface) >= 0, true);
       
    57 
       
    58 p:= integer(LandSurface.pixels);
       
    59 case LandSurface.format.BytesPerPixel of
       
    60      1: ;// not supported
       
    61      2: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
    62             for tx:= max(0, round(x-radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(x+radius*sqrt(1-sqr(ty/radius)))) do
       
    63                 PWord(p + LandSurface.pitch*(y + ty) + tx * 2)^:= 0;
       
    64      3: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
    65             for tx:= max(0, round(x-radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(x+radius*sqrt(1-sqr(ty/radius)))) do
       
    66                 begin
       
    67                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 0)^:= 0;
       
    68                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 1)^:= 0;
       
    69                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 2)^:= 0;
       
    70                 end;
       
    71      4: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
    72             for tx:= max(0, round(x-radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(x+radius*sqrt(1-sqr(ty/radius)))) do
       
    73                 PLongword(p + LandSurface.pitch*(y + ty) + tx * 4)^:= 0;
       
    74      end;
       
    75 
       
    76 inc(Radius, 4);
       
    77 
       
    78 case LandSurface.format.BytesPerPixel of
       
    79      1: ;// not supported
       
    80      2: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
    81             for tx:= max(0, round(x-radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(x+radius*sqrt(1-sqr(ty/radius)))) do
       
    82                if Land[y + ty, tx] = $FFFFFF then
       
    83                   PWord(p + LandSurface.pitch*(y + ty) + tx * 2)^:= cExplosionBorderColor;
       
    84      3: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
    85             for tx:= max(0, round(x-radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(x+radius*sqrt(1-sqr(ty/radius)))) do
       
    86                if Land[y + ty, tx] = $FFFFFF then
       
    87                 begin
       
    88                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 0)^:= cExplosionBorderColor and $FF;
       
    89                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 1)^:= (cExplosionBorderColor shr 8) and $FF;
       
    90                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 2)^:= (cExplosionBorderColor shr 16);
       
    91                 end;
       
    92      4: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
    93             for tx:= max(0, round(x-radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(x+radius*sqrt(1-sqr(ty/radius)))) do
       
    94                if Land[y + ty, tx] = $FFFFFF then
       
    95                    PLongword(p + LandSurface.pitch*(y + ty) + tx * 4)^:= cExplosionBorderColor;
       
    96      end;
       
    97 
       
    98 if SDL_MustLock(LandSurface) then
       
    99    SDL_UnlockSurface(LandSurface);
       
   100 
       
   101 SDL_UpdateRect(LandSurface, X - Radius, Y - Radius, Radius * 2, Radius * 2)
       
   102 end;
       
   103 
       
   104 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: Longword; y, dY: integer; Count: Byte);
       
   105 var tx, ty, i, p: integer;
       
   106 begin
       
   107 if SDL_MustLock(LandSurface) then
       
   108    SDL_LockSurface(LandSurface);
       
   109 
       
   110 p:= integer(LandSurface.pixels);
       
   111 for i:= 0 to Pred(Count) do
       
   112     begin
       
   113     case LandSurface.format.BytesPerPixel of
       
   114      1: ;
       
   115      2: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
   116             for tx:= max(0, round(ar[i].Left - radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(ar[i].Right + radius*sqrt(1-sqr(ty/radius)))) do
       
   117                 PWord(p + LandSurface.pitch*(y + ty) + tx * 2)^:= 0;
       
   118      3: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
   119             for tx:= max(0, round(ar[i].Left - radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(ar[i].Right + radius*sqrt(1-sqr(ty/radius)))) do
       
   120                 begin
       
   121                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 0)^:= 0;
       
   122                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 1)^:= 0;
       
   123                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 2)^:= 0;
       
   124                 end;
       
   125      4: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
   126             for tx:= max(0, round(ar[i].Left - radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(ar[i].Right + radius*sqrt(1-sqr(ty/radius)))) do
       
   127                 PLongword(p + LandSurface.pitch*(y + ty) + tx * 4)^:= 0;
       
   128      end;
       
   129     inc(y, dY)
       
   130     end;
       
   131 
       
   132 inc(Radius, 4);
       
   133 dec(y, Count*dY);
       
   134 
       
   135 for i:= 0 to Pred(Count) do
       
   136     begin
       
   137     case LandSurface.format.BytesPerPixel of
       
   138      1: ;
       
   139      2: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
   140             for tx:= max(0, round(ar[i].Left - radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(ar[i].Right + radius*sqrt(1-sqr(ty/radius)))) do
       
   141                if Land[y + ty, tx] = $FFFFFF then
       
   142                   PWord(p + LandSurface.pitch*(y + ty) + tx * 2)^:= cExplosionBorderColor;
       
   143      3: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
   144             for tx:= max(0, round(ar[i].Left - radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(ar[i].Right + radius*sqrt(1-sqr(ty/radius)))) do
       
   145                if Land[y + ty, tx] = $FFFFFF then
       
   146                 begin
       
   147                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 0)^:= cExplosionBorderColor and $FF;
       
   148                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 1)^:= (cExplosionBorderColor shr 8) and $FF;
       
   149                 PByte(p + LandSurface.pitch*(y + ty) + tx * 3 + 2)^:= (cExplosionBorderColor shr 16);
       
   150                 end;
       
   151      4: for ty:= max(-Radius, -y) to min(Radius, 1023 - y) do
       
   152             for tx:= max(0, round(ar[i].Left - radius*sqrt(1-sqr(ty/radius)))) to min(2047, round(ar[i].Right + radius*sqrt(1-sqr(ty/radius)))) do
       
   153                if Land[y + ty, tx] = $FFFFFF then
       
   154                    PLongword(p + LandSurface.pitch*(y + ty) + tx * 4)^:= cExplosionBorderColor;
       
   155      end;
       
   156     inc(y, dY)
       
   157     end;
       
   158 
       
   159 if SDL_MustLock(LandSurface) then
       
   160    SDL_UnlockSurface(LandSurface);
       
   161 end;
       
   162 
       
   163 //
       
   164 //  - (dX, dY) - direction, vector of length = 0.5
       
   165 //
       
   166 procedure DrawTunnel(X, Y, dX, dY: real; ticks, HalfWidth: integer);
       
   167 var nx, ny: real;
       
   168     i, t, tx, ty, p: integer;
       
   169 begin  // (-dY, dX) is (dX, dY) turned by PI/2
       
   170 if SDL_MustLock(LandSurface) then
       
   171    SDL_LockSurface(LandSurface);
       
   172 
       
   173 nx:= X + dY * (HalfWidth + 8);
       
   174 ny:= Y - dX * (HalfWidth + 8);
       
   175 p:= integer(LandSurface.pixels);
       
   176 
       
   177 for i:= 0 to 7 do
       
   178     begin
       
   179     X:= nx - 8 * dX;
       
   180     Y:= ny - 8 * dY;
       
   181     for t:= -8 to ticks + 8 do
       
   182         {$include tunsetborder.inc}
       
   183     nx:= nx - dY;
       
   184     ny:= ny + dX;
       
   185     end;
       
   186 
       
   187 for i:= -HalfWidth to HalfWidth do
       
   188     begin
       
   189     X:= nx - dX * 8;
       
   190     Y:= ny - dY * 8;
       
   191     for t:= 0 to 7 do
       
   192         {$include tunsetborder.inc}
       
   193     X:= nx;
       
   194     Y:= ny;
       
   195     for t:= 0 to ticks do
       
   196         begin
       
   197         X:= X + dX;
       
   198         Y:= Y + dY;
       
   199         tx:= round(X);
       
   200         ty:= round(Y);
       
   201         if ((ty and $FFFFFC00) = 0) and ((tx and $FFFFF800) = 0) then
       
   202            begin
       
   203            Land[ty, tx]:= 0;
       
   204            case LandSurface.format.BytesPerPixel of
       
   205                 1: ;
       
   206                 2: PWord(p + LandSurface.pitch * ty + tx * 2)^:= 0;
       
   207                 3: begin
       
   208                    PByte(p + LandSurface.pitch * ty + tx * 3 + 0)^:= 0;
       
   209                    PByte(p + LandSurface.pitch * ty + tx * 3 + 1)^:= 0;
       
   210                    PByte(p + LandSurface.pitch * ty + tx * 3 + 2)^:= 0;
       
   211                    end;
       
   212                 4: PLongword(p + LandSurface.pitch * ty + tx * 4)^:= 0;
       
   213                 end
       
   214            end
       
   215         end;
       
   216     for t:= 0 to 7 do
       
   217         {$include tunsetborder.inc}
       
   218     nx:= nx - dY;
       
   219     ny:= ny + dX;
       
   220     end;
       
   221 
       
   222 for i:= 0 to 7 do
       
   223     begin
       
   224     X:= nx - 8 * dX;
       
   225     Y:= ny - 8 * dY;
       
   226     for t:= -8 to ticks + 8 do
       
   227         {$include tunsetborder.inc}
       
   228     nx:= nx - dY;
       
   229     ny:= ny + dX;
       
   230     end;
       
   231 
       
   232 if SDL_MustLock(LandSurface) then
       
   233    SDL_UnlockSurface(LandSurface)
       
   234 end;
       
   235 
       
   236 
       
   237 end.