hedgewars/uLandObjects.pas
branchsdl2transition
changeset 11362 ed5a6478e710
parent 9798 f2b18754742f
parent 11046 47a8c19ecb60
child 11507 bd9a2f1b0080
equal deleted inserted replaced
11361:31570b766315 11362:ed5a6478e710
     1 (*
     1 (*
     2  * Hedgewars, a free turn based strategy game
     2  * Hedgewars, a free turn based strategy game
     3  * Copyright (c) 2004-2013 Andrey Korotaev <unC0Rr@gmail.com>
     3  * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
     4  *
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; version 2 of the License
     7  * the Free Software Foundation; version 2 of the License
     8  *
     8  *
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    12  * GNU General Public License for more details.
    13  *
    13  *
    14  * You should have received a copy of the GNU General Public License
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    17  *)
    17  *)
    18 
    18 
    19 {$INCLUDE "options.inc"}
    19 {$INCLUDE "options.inc"}
    20 
    20 
    21 unit uLandObjects;
    21 unit uLandObjects;
    24 
    24 
    25 procedure AddObjects();
    25 procedure AddObjects();
    26 procedure FreeLandObjects();
    26 procedure FreeLandObjects();
    27 procedure LoadThemeConfig;
    27 procedure LoadThemeConfig;
    28 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
    28 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
    29 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word);
    29 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline;
       
    30 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean);
    30 procedure BlitImageUsingMask(cpX, cpY: Longword;  Image, Mask: PSDL_Surface);
    31 procedure BlitImageUsingMask(cpX, cpY: Longword;  Image, Mask: PSDL_Surface);
    31 procedure AddOnLandObjects(Surface: PSDL_Surface);
    32 procedure AddOnLandObjects(Surface: PSDL_Surface);
    32 procedure SetLand(var LandWord: Word; Pixel: LongWord); inline;
    33 procedure SetLand(var LandWord: Word; Pixel: LongWord); inline;
    33 
    34 
    34 implementation
    35 implementation
    90         LandWord:= lfObject or lfBouncy
    91         LandWord:= lfObject or lfBouncy
    91 end;
    92 end;
    92 
    93 
    93 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
    94 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline;
    94 begin
    95 begin
    95     BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0);
    96     BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0, false);
    96 end;
    97 end;
    97     
    98 
    98 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word);
    99 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline;
       
   100 begin
       
   101     BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, LandFlags, false);
       
   102 end;
       
   103 
       
   104 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean);
    99 var p: PLongwordArray;
   105 var p: PLongwordArray;
   100     x, y: Longword;
   106     px, x, y: Longword;
   101     bpp: LongInt;
   107     bpp: LongInt;
   102 begin
   108 begin
   103 WriteToConsole('Generating collision info... ');
   109 WriteToConsole('Generating collision info... ');
   104 
   110 
   105 if SDL_MustLock(Image) then
   111 if SDL_MustLock(Image) then
   113 
   119 
   114 p:= Image^.pixels;
   120 p:= Image^.pixels;
   115 for y:= 0 to Pred(Image^.h) do
   121 for y:= 0 to Pred(Image^.h) do
   116     begin
   122     begin
   117     for x:= 0 to Pred(Width) do
   123     for x:= 0 to Pred(Width) do
   118         if (p^[x] and AMask) <> 0 then
   124         begin
       
   125         // map image pixels per line backwards if in flip mode
       
   126         if Flip then
       
   127             px:= Pred(Image^.w) - x
       
   128         else
       
   129             px:= x;
       
   130 
       
   131         if (p^[px] and AMask) <> 0 then
   119             begin
   132             begin
   120             if (cReducedQuality and rqBlurryLand) = 0 then
   133             if (cReducedQuality and rqBlurryLand) = 0 then
   121                 begin
   134                 begin
   122                 if (LandPixels[cpY + y, cpX + x] = 0)
   135                 if (LandPixels[cpY + y, cpX + x] = 0)
   123                 or (((p^[x] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then
   136                 or (((p^[px] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then
   124                     LandPixels[cpY + y, cpX + x]:= p^[x];
   137                     LandPixels[cpY + y, cpX + x]:= p^[px];
   125                 end
   138                 end
   126             else
   139             else
   127                 if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then 
   140                 if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then
   128                     LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x];
   141                     LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[px];
   129 
   142 
   130             if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[x] and AMask) <> 0) then
   143             if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[px] and AMask) <> 0) then
   131                 Land[cpY + y, cpX + x]:= lfObject or LandFlags
   144                 Land[cpY + y, cpX + x]:= lfObject or LandFlags
   132             end;
   145             end;
   133     p:= @(p^[Image^.pitch shr 2])
   146         end;
       
   147     p:= PLongwordArray(@(p^[Image^.pitch shr 2]))
   134     end;
   148     end;
   135 
   149 
   136 if SDL_MustLock(Image) then
   150 if SDL_MustLock(Image) then
   137     SDL_UnlockSurface(Image);
   151     SDL_UnlockSurface(Image);
   138 WriteLnToConsole(msgOK)
   152 WriteLnToConsole(msgOK)
   162             if (LandPixels[cpY + y, cpX + x] = 0)
   176             if (LandPixels[cpY + y, cpX + x] = 0)
   163             or (((p^[x] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then
   177             or (((p^[x] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then
   164                 LandPixels[cpY + y, cpX + x]:= p^[x];
   178                 LandPixels[cpY + y, cpX + x]:= p^[x];
   165             end
   179             end
   166         else
   180         else
   167             if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then 
   181             if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then
   168                 LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x];
   182                 LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x];
   169 
   183 
   170         if (Land[cpY + y, cpX + x] <= lfAllObjMask) or (Land[cpY + y, cpX + x] and lfObject <> 0)  then
   184         if (Land[cpY + y, cpX + x] <= lfAllObjMask) or (Land[cpY + y, cpX + x] and lfObject <> 0)  then
   171             SetLand(Land[cpY + y, cpX + x], mp^[x]);
   185             SetLand(Land[cpY + y, cpX + x], mp^[x]);
   172         end;
   186         end;
   173     p:= @(p^[Image^.pitch shr 2]);
   187     p:= PLongwordArray(@(p^[Image^.pitch shr 2]));
   174     mp:= @(mp^[Mask^.pitch shr 2])
   188     mp:= PLongwordArray(@(mp^[Mask^.pitch shr 2]))
   175     end;
   189     end;
   176 
   190 
   177 if SDL_MustLock(Image) then
   191 if SDL_MustLock(Image) then
   178     SDL_UnlockSurface(Image);
   192     SDL_UnlockSurface(Image);
   179 WriteLnToConsole(msgOK)
   193 WriteLnToConsole(msgOK)
   217     until (i = RectCount) or (res);
   231     until (i = RectCount) or (res);
   218 CheckIntersect:= res;
   232 CheckIntersect:= res;
   219 end;
   233 end;
   220 
   234 
   221 
   235 
   222 function CountNonZeroz(x, y: LongInt): Longword;
   236 function CountNonZeroz(x, y, h: LongInt): Longword;
   223 var i: LongInt;
   237 var i: LongInt;
   224     lRes: Longword;
   238     lRes: Longword;
   225 begin
   239 begin
   226     lRes:= 0;
   240     lRes:= 0;
   227     for i:= y to y + 15 do
   241     for i:= y to Pred(y + h) do
   228         if Land[i, x] <> 0 then
   242         if Land[i, x] <> 0 then
   229             inc(lRes);
   243             inc(lRes);
   230     CountNonZeroz:= lRes;
   244     CountNonZeroz:= lRes;
   231 end;
   245 end;
   232 
   246 
   233 function AddGirder(gX: LongInt): boolean;
   247 function AddGirder(gX: LongInt; var girSurf: PSDL_Surface): boolean;
   234 var tmpsurf: PSDL_Surface;
   248 var x1, x2, y, k, i, girderHeight: LongInt;
   235     x1, x2, y, k, i: LongInt;
       
   236     rr: TSDL_Rect;
   249     rr: TSDL_Rect;
   237     bRes: boolean;
   250     bRes: boolean;
   238 begin
   251 begin
       
   252 if girSurf = nil then
       
   253     girSurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifTransparent or ifIgnoreCaps);
       
   254 
       
   255 girderHeight:= girSurf^.h;
       
   256 
   239 y:= topY+150;
   257 y:= topY+150;
   240 repeat
   258 repeat
   241     inc(y, 24);
   259     inc(y, 24);
   242     x1:= gX;
   260     x1:= gX;
   243     x2:= gX;
   261     x2:= gX;
   244 
   262 
   245     while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y) = 0) do
   263     while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y, girderHeight) = 0) do
   246         dec(x1, 2);
   264         dec(x1, 2);
   247 
   265 
   248     i:= x1 - 12;
   266     i:= x1 - 12;
   249     repeat
   267     repeat
   250         dec(x1, 2);
   268         k:= CountNonZeroz(x1, y, girderHeight);
   251         k:= CountNonZeroz(x1, y)
   269         dec(x1, 2)
   252     until (x1 < Longint(leftX)+150) or (k = 0) or (k = 16) or (x1 < i);
   270     until (x1 < Longint(leftX) + 100) or (k = 0) or (k = girderHeight) or (x1 < i);
   253 
   271 
   254     inc(x1, 2);
   272     inc(x1, 2);
   255     if k = 16 then
   273     if k = girderHeight then
   256         begin
   274         begin
   257         while (x2 < (rightX-150)) and (CountNonZeroz(x2, y) = 0) do
   275         while (x2 < (LongInt(rightX) - 100)) and (CountNonZeroz(x2, y, girderHeight) = 0) do
   258             inc(x2, 2);
   276             inc(x2, 2);
   259         i:= x2 + 12;
   277         i:= x2 + 12;
   260         repeat
   278         repeat
   261         inc(x2, 2);
   279         inc(x2, 2);
   262         k:= CountNonZeroz(x2, y)
   280         k:= CountNonZeroz(x2, y, girderHeight)
   263         until (x2 >= (rightX-150)) or (k = 0) or (k = 16) or (x2 > i) or (x2 - x1 >= 768);
   281         until (x2 >= (LongInt(rightX)-150)) or (k = 0) or (k = girderHeight) or (x2 > i) or (x2 - x1 >= 900);
   264         
   282 
   265         if (x2 < (rightX - 150)) and (k = 16) and (x2 - x1 > 250) and (x2 - x1 < 768)
   283         if (x2 < (LongInt(rightX) - 100)) and (k = girderHeight) and (x2 - x1 > 200) and (x2 - x1 < 900)
   266         and (not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144)) then
   284         and (not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144)) then
   267                 break;
   285                 break;
   268         end;
   286         end;
   269 x1:= 0;
   287 x1:= 0;
   270 until y > (LAND_HEIGHT-125);
   288 until y > (LAND_HEIGHT-125);
   271 
   289 
   272 if x1 > 0 then
   290 if x1 > 0 then
   273 begin
   291 begin
   274     bRes:= true;
   292     bRes:= true;
   275     tmpsurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifTransparent or ifIgnoreCaps);
       
   276 
   293 
   277     rr.x:= x1;
   294     rr.x:= x1;
   278     while rr.x < x2 do
   295     while rr.x < x2 do
   279         begin
   296         begin
   280         if cIce then 
   297         if cIce then
   281             BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf, lfIce)
   298             BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, girSurf^.w), girSurf, lfIce)
   282         else
   299         else
   283             BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf);
   300             BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, girSurf^.w), girSurf);
   284         inc(rr.x, tmpsurf^.w);
   301         inc(rr.x, girSurf^.w);
   285         end;
   302         end;
   286     SDL_FreeSurface(tmpsurf);
       
   287 
   303 
   288     AddRect(x1 - 8, y - 32, x2 - x1 + 16, 80);
   304     AddRect(x1 - 8, y - 32, x2 - x1 + 16, 80);
   289 end
   305 end
   290 else bRes:= false;
   306 else bRes:= false;
   291 
   307 
   370                 begin
   386                 begin
   371                 ar[cnt].x:= x;
   387                 ar[cnt].x:= x;
   372                 ar[cnt].y:= y;
   388                 ar[cnt].y:= y;
   373                 if cnt >= MaxPointsIndex then // buffer is full, do not check the rest land
   389                 if cnt >= MaxPointsIndex then // buffer is full, do not check the rest land
   374                     begin
   390                     begin
   375                     y:= $FF000000;
   391                     y:= LAND_HEIGHT;
   376                     x:= $FF000000;
   392                     x:= LAND_WIDTH;
   377                     end
   393                     end
   378                     else inc(cnt);
   394                     else inc(cnt);
   379                 end;
   395                 end;
   380             inc(y, 3);
   396             inc(y, 3);
   381         until y >= LAND_HEIGHT - Height;
   397         until y >= LAND_HEIGHT - Height;
   453 end;
   469 end;
   454 
   470 
   455 
   471 
   456 procedure CheckRect(Width, Height, x, y, w, h: LongWord);
   472 procedure CheckRect(Width, Height, x, y, w, h: LongWord);
   457 begin
   473 begin
   458     if (x + w > Width) then 
   474     if (x + w > Width) then
   459         OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
   475         OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true);
   460     if (y + h > Height) then 
   476     if (y + h > Height) then
   461         OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
   477         OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true);
   462 end;
   478 end;
   463 
   479 
   464 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
   480 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects);
   465 var s, key: shortstring;
   481 var s, key: shortstring;
   471 
   487 
   472 AddProgress;
   488 AddProgress;
   473 // Set default water greyscale values
   489 // Set default water greyscale values
   474 if GrayScale then
   490 if GrayScale then
   475     begin
   491     begin
   476     for i:= 0 to 3 do
   492     for i:= Low(SDWaterColorArray) to High(SDWaterColorArray) do
   477         begin
   493         begin
   478         t:= round(SDWaterColorArray[i].r * RGB_LUMINANCE_RED + SDWaterColorArray[i].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[i].b * RGB_LUMINANCE_BLUE);
   494         t:= round(SDWaterColorArray[i].r * RGB_LUMINANCE_RED + SDWaterColorArray[i].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[i].b * RGB_LUMINANCE_BLUE);
   479         if t > 255 then
   495         if t > 255 then
   480             t:= 255;
   496             t:= 255;
   481         SDWaterColorArray[i].r:= t;
   497         SDWaterColorArray[i].r:= t;
   482         SDWaterColorArray[i].g:= t;
   498         SDWaterColorArray[i].g:= t;
   483         SDWaterColorArray[i].b:= t
   499         SDWaterColorArray[i].b:= t
   484         end;
   500         end;
   485     for i:= 0 to 1 do
   501     for i:= Low(WaterColorArray) to High(WaterColorArray) do
   486         begin
   502         begin
   487         t:= round(WaterColorArray[i].r * RGB_LUMINANCE_RED + WaterColorArray[i].g * RGB_LUMINANCE_GREEN + WaterColorArray[i].b * RGB_LUMINANCE_BLUE);
   503         t:= round(WaterColorArray[i].r * RGB_LUMINANCE_RED + WaterColorArray[i].g * RGB_LUMINANCE_GREEN + WaterColorArray[i].b * RGB_LUMINANCE_BLUE);
   488         if t > 255 then
   504         if t > 255 then
   489             t:= 255;
   505             t:= 255;
   490         WaterColorArray[i].r:= t;
   506         WaterColorArray[i].r:= t;
   553                 t:= 255;
   569                 t:= 255;
   554             c2.r:= t;
   570             c2.r:= t;
   555             c2.g:= t;
   571             c2.g:= t;
   556             c2.b:= t
   572             c2.b:= t
   557             end;
   573             end;
   558         ExplosionBorderColor:= (c2.r shl RShift) or (c2.g shl GShift) or (c2.b shl BShift) or AMask; 
   574         ExplosionBorderColorR:= c2.r;
       
   575         ExplosionBorderColorG:= c2.g;
       
   576         ExplosionBorderColorB:= c2.b;
       
   577         ExplosionBorderColorNoA:=
       
   578             (c2.r shl RShift) or (c2.g shl GShift) or (c2.b shl BShift);
       
   579         ExplosionBorderColor:= ExplosionBorderColorNoA or AMask;
   559         end
   580         end
   560     else if key = 'water-top' then
   581     else if key = 'water-top' then
       
   582         begin
       
   583         i:= Pos(',', s);
       
   584         WaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   585         Delete(s, 1, i);
       
   586         i:= Pos(',', s);
       
   587         WaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   588         Delete(s, 1, i);
       
   589         WaterColorArray[1].b:= StrToInt(Trim(s));
       
   590         WaterColorArray[1].a := 255;
       
   591         if GrayScale then
       
   592             begin
       
   593             t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE);
       
   594             if t > 255 then
       
   595                 t:= 255;
       
   596             WaterColorArray[1].r:= t;
       
   597             WaterColorArray[1].g:= t;
       
   598             WaterColorArray[1].b:= t
       
   599             end;
       
   600         WaterColorArray[3]:= WaterColorArray[1];
       
   601         WaterColorArray[5]:= WaterColorArray[1];
       
   602         WaterColorArray[7]:= WaterColorArray[1];
       
   603         end
       
   604     else if key = 'water-bottom' then
   561         begin
   605         begin
   562         i:= Pos(',', s);
   606         i:= Pos(',', s);
   563         WaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   607         WaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   564         Delete(s, 1, i);
   608         Delete(s, 1, i);
   565         i:= Pos(',', s);
   609         i:= Pos(',', s);
   567         Delete(s, 1, i);
   611         Delete(s, 1, i);
   568         WaterColorArray[0].b:= StrToInt(Trim(s));
   612         WaterColorArray[0].b:= StrToInt(Trim(s));
   569         WaterColorArray[0].a := 255;
   613         WaterColorArray[0].a := 255;
   570         if GrayScale then
   614         if GrayScale then
   571             begin
   615             begin
   572             t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE);
   616             t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE);
   573             if t > 255 then
   617             if t > 255 then
   574                 t:= 255;
   618                 t:= 255;
   575             WaterColorArray[0].r:= t;
   619             WaterColorArray[0].r:= t;
   576             WaterColorArray[0].g:= t;
   620             WaterColorArray[0].g:= t;
   577             WaterColorArray[0].b:= t
   621             WaterColorArray[0].b:= t
   578             end;
   622             end;
   579         WaterColorArray[1]:= WaterColorArray[0];
   623         WaterColorArray[2]:= WaterColorArray[0];
   580         end
   624         WaterColorArray[4]:= WaterColorArray[0];
   581     else if key = 'water-bottom' then
   625         WaterColorArray[6]:= WaterColorArray[0];
   582         begin
       
   583         i:= Pos(',', s);
       
   584         WaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   585         Delete(s, 1, i);
       
   586         i:= Pos(',', s);
       
   587         WaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   588         Delete(s, 1, i);
       
   589         WaterColorArray[2].b:= StrToInt(Trim(s));
       
   590         WaterColorArray[2].a := 255;
       
   591         if GrayScale then
       
   592             begin
       
   593             t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE);
       
   594             if t > 255 then
       
   595                 t:= 255;
       
   596             WaterColorArray[2].r:= t;
       
   597             WaterColorArray[2].g:= t;
       
   598             WaterColorArray[2].b:= t
       
   599             end;
       
   600         WaterColorArray[3]:= WaterColorArray[2];
       
   601         end
   626         end
   602     else if key = 'water-opacity' then
   627     else if key = 'water-opacity' then
   603         begin
   628         begin
   604         WaterOpacity:= StrToInt(Trim(s));
   629         WaterOpacity:= StrToInt(Trim(s));
   605         SDWaterOpacity:= WaterOpacity
   630         SDWaterOpacity:= WaterOpacity
   606         end
   631         end
   607     else if key = 'music' then
   632     else if key = 'music' then
   608         SetMusicName(Trim(s))
   633         MusicFN:= Trim(s)
       
   634     else if key = 'sd-music' then
       
   635         SDMusicFN:= Trim(s)
   609     else if key = 'clouds' then
   636     else if key = 'clouds' then
   610         begin
   637         begin
   611         cCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096;
   638         cCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096;
   612         cSDCloudsNumber:= cCloudsNumber
   639         cSDCloudsNumber:= cCloudsNumber
   613         end
   640         end
   711     else if key = 'snow' then
   738     else if key = 'snow' then
   712         cSnow:= true
   739         cSnow:= true
   713     else if key = 'sd-water-top' then
   740     else if key = 'sd-water-top' then
   714         begin
   741         begin
   715         i:= Pos(',', s);
   742         i:= Pos(',', s);
       
   743         SDWaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   744         Delete(s, 1, i);
       
   745         i:= Pos(',', s);
       
   746         SDWaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   747         Delete(s, 1, i);
       
   748         SDWaterColorArray[1].b:= StrToInt(Trim(s));
       
   749         SDWaterColorArray[1].a := 255;
       
   750         if GrayScale then
       
   751             begin
       
   752             t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE);
       
   753             if t > 255 then
       
   754                 t:= 255;
       
   755             SDWaterColorArray[1].r:= t;
       
   756             SDWaterColorArray[1].g:= t;
       
   757             SDWaterColorArray[1].b:= t
       
   758             end;
       
   759         SDWaterColorArray[3]:= SDWaterColorArray[1];
       
   760         SDWaterColorArray[5]:= SDWaterColorArray[1];
       
   761         SDWaterColorArray[7]:= SDWaterColorArray[1];
       
   762         end
       
   763     else if key = 'sd-water-bottom' then
       
   764         begin
       
   765         i:= Pos(',', s);
   716         SDWaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   766         SDWaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   717         Delete(s, 1, i);
   767         Delete(s, 1, i);
   718         i:= Pos(',', s);
   768         i:= Pos(',', s);
   719         SDWaterColorArray[0].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   769         SDWaterColorArray[0].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
   720         Delete(s, 1, i);
   770         Delete(s, 1, i);
   721         SDWaterColorArray[0].b:= StrToInt(Trim(s));
   771         SDWaterColorArray[0].b:= StrToInt(Trim(s));
   722         SDWaterColorArray[0].a := 255;
   772         SDWaterColorArray[0].a := 255;
   723         if GrayScale then
   773         if GrayScale then
   724             begin
   774             begin
   725             t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE);
   775             t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE);
   726             if t > 255 then
   776             if t > 255 then
   727                 t:= 255;
   777                 t:= 255;
   728             SDWaterColorArray[0].r:= t;
   778             SDWaterColorArray[0].r:= t;
   729             SDWaterColorArray[0].g:= t;
   779             SDWaterColorArray[0].g:= t;
   730             SDWaterColorArray[0].b:= t
   780             SDWaterColorArray[0].b:= t
   731             end;
   781             end;
   732         SDWaterColorArray[1]:= SDWaterColorArray[0];
   782         SDWaterColorArray[2]:= SDWaterColorArray[0];
   733         end
   783         SDWaterColorArray[4]:= SDWaterColorArray[0];
   734     else if key = 'sd-water-bottom' then
   784         SDWaterColorArray[6]:= SDWaterColorArray[0];
   735         begin
       
   736         i:= Pos(',', s);
       
   737         SDWaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   738         Delete(s, 1, i);
       
   739         i:= Pos(',', s);
       
   740         SDWaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
       
   741         Delete(s, 1, i);
       
   742         SDWaterColorArray[2].b:= StrToInt(Trim(s));
       
   743         SDWaterColorArray[2].a := 255;
       
   744         if GrayScale then
       
   745             begin
       
   746             t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE);
       
   747             if t > 255 then
       
   748                 t:= 255;
       
   749             SDWaterColorArray[2].r:= t;
       
   750             SDWaterColorArray[2].g:= t;
       
   751             SDWaterColorArray[2].b:= t
       
   752             end;
       
   753         SDWaterColorArray[3]:= SDWaterColorArray[2];
       
   754         end
   785         end
   755     else if key = 'sd-water-opacity' then
   786     else if key = 'sd-water-opacity' then
   756         SDWaterOpacity:= StrToInt(Trim(s))
   787         SDWaterOpacity:= StrToInt(Trim(s))
   757     else if key = 'sd-clouds' then
   788     else if key = 'sd-clouds' then
   758         cSDCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096
   789         cSDCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096
   854             end;
   885             end;
   855     until not b;
   886     until not b;
   856 end;
   887 end;
   857 
   888 
   858 procedure AddObjects();
   889 procedure AddObjects();
   859 var i, g: Longword;
   890 var girSurf: PSDL_Surface;
       
   891     i, g: Longword;
   860 begin
   892 begin
   861 InitRects;
   893 InitRects;
   862 if hasGirders then
   894 if hasGirders then
   863     begin
   895     begin
   864     g:= max(playWidth div 8, 256);
   896     g:= max(playWidth div 8, 256);
   865     i:= leftX + g;
   897     i:= leftX + g;
       
   898     girSurf:= nil;
   866     repeat
   899     repeat
   867         AddGirder(i);
   900         AddGirder(i, girSurf);
   868         i:=i + g;
   901         i:=i + g;
   869     until (i > rightX - g);
   902     until (i > rightX - g);
       
   903     // free girder surface
       
   904     if girSurf <> nil then
       
   905         begin
       
   906         SDL_FreeSurface(girSurf);
       
   907         girSurf:= nil;
       
   908         end;
   870     end;
   909     end;
   871 if (GameFlags and gfDisableLandObjects) = 0 then
   910 if (GameFlags and gfDisableLandObjects) = 0 then
   872     AddThemeObjects(ThemeObjects);
   911     AddThemeObjects(ThemeObjects);
   873 AddProgress();
   912 AddProgress();
   874 FreeRects();
   913 FreeRects();