diff -r 31570b766315 -r ed5a6478e710 hedgewars/uLandObjects.pas --- a/hedgewars/uLandObjects.pas Tue Nov 10 18:16:35 2015 +0100 +++ b/hedgewars/uLandObjects.pas Tue Nov 10 20:43:13 2015 +0100 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2013 Andrey Korotaev + * Copyright (c) 2004-2015 Andrey Korotaev * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *) {$INCLUDE "options.inc"} @@ -26,7 +26,8 @@ procedure FreeLandObjects(); procedure LoadThemeConfig; procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline; -procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline; +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean); procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); procedure AddOnLandObjects(Surface: PSDL_Surface); procedure SetLand(var LandWord: Word; Pixel: LongWord); inline; @@ -92,12 +93,17 @@ procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline; begin - BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0); + BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0, false); end; - -procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); + +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline; +begin + BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, LandFlags, false); +end; + +procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean); var p: PLongwordArray; - x, y: Longword; + px, x, y: Longword; bpp: LongInt; begin WriteToConsole('Generating collision info... '); @@ -115,22 +121,30 @@ for y:= 0 to Pred(Image^.h) do begin for x:= 0 to Pred(Width) do - if (p^[x] and AMask) <> 0 then + begin + // map image pixels per line backwards if in flip mode + if Flip then + px:= Pred(Image^.w) - x + else + px:= x; + + if (p^[px] and AMask) <> 0 then begin if (cReducedQuality and rqBlurryLand) = 0 then begin if (LandPixels[cpY + y, cpX + x] = 0) - or (((p^[x] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then - LandPixels[cpY + y, cpX + x]:= p^[x]; + or (((p^[px] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then + LandPixels[cpY + y, cpX + x]:= p^[px]; end else - if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then - LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x]; + if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then + LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[px]; - if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[x] and AMask) <> 0) then + if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[px] and AMask) <> 0) then Land[cpY + y, cpX + x]:= lfObject or LandFlags end; - p:= @(p^[Image^.pitch shr 2]) + end; + p:= PLongwordArray(@(p^[Image^.pitch shr 2])) end; if SDL_MustLock(Image) then @@ -164,14 +178,14 @@ LandPixels[cpY + y, cpX + x]:= p^[x]; end else - if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then + if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x]; if (Land[cpY + y, cpX + x] <= lfAllObjMask) or (Land[cpY + y, cpX + x] and lfObject <> 0) then SetLand(Land[cpY + y, cpX + x], mp^[x]); end; - p:= @(p^[Image^.pitch shr 2]); - mp:= @(mp^[Mask^.pitch shr 2]) + p:= PLongwordArray(@(p^[Image^.pitch shr 2])); + mp:= PLongwordArray(@(mp^[Mask^.pitch shr 2])) end; if SDL_MustLock(Image) then @@ -219,50 +233,54 @@ end; -function CountNonZeroz(x, y: LongInt): Longword; +function CountNonZeroz(x, y, h: LongInt): Longword; var i: LongInt; lRes: Longword; begin lRes:= 0; - for i:= y to y + 15 do + for i:= y to Pred(y + h) do if Land[i, x] <> 0 then inc(lRes); CountNonZeroz:= lRes; end; -function AddGirder(gX: LongInt): boolean; -var tmpsurf: PSDL_Surface; - x1, x2, y, k, i: LongInt; +function AddGirder(gX: LongInt; var girSurf: PSDL_Surface): boolean; +var x1, x2, y, k, i, girderHeight: LongInt; rr: TSDL_Rect; bRes: boolean; begin +if girSurf = nil then + girSurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifTransparent or ifIgnoreCaps); + +girderHeight:= girSurf^.h; + y:= topY+150; repeat inc(y, 24); x1:= gX; x2:= gX; - while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y) = 0) do + while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y, girderHeight) = 0) do dec(x1, 2); i:= x1 - 12; repeat - dec(x1, 2); - k:= CountNonZeroz(x1, y) - until (x1 < Longint(leftX)+150) or (k = 0) or (k = 16) or (x1 < i); + k:= CountNonZeroz(x1, y, girderHeight); + dec(x1, 2) + until (x1 < Longint(leftX) + 100) or (k = 0) or (k = girderHeight) or (x1 < i); inc(x1, 2); - if k = 16 then + if k = girderHeight then begin - while (x2 < (rightX-150)) and (CountNonZeroz(x2, y) = 0) do + while (x2 < (LongInt(rightX) - 100)) and (CountNonZeroz(x2, y, girderHeight) = 0) do inc(x2, 2); i:= x2 + 12; repeat inc(x2, 2); - k:= CountNonZeroz(x2, y) - until (x2 >= (rightX-150)) or (k = 0) or (k = 16) or (x2 > i) or (x2 - x1 >= 768); - - if (x2 < (rightX - 150)) and (k = 16) and (x2 - x1 > 250) and (x2 - x1 < 768) + k:= CountNonZeroz(x2, y, girderHeight) + until (x2 >= (LongInt(rightX)-150)) or (k = 0) or (k = girderHeight) or (x2 > i) or (x2 - x1 >= 900); + + if (x2 < (LongInt(rightX) - 100)) and (k = girderHeight) and (x2 - x1 > 200) and (x2 - x1 < 900) and (not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144)) then break; end; @@ -272,18 +290,16 @@ if x1 > 0 then begin bRes:= true; - tmpsurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifTransparent or ifIgnoreCaps); rr.x:= x1; while rr.x < x2 do begin - if cIce then - BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf, lfIce) + if cIce then + BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, girSurf^.w), girSurf, lfIce) else - BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, tmpsurf^.w), tmpsurf); - inc(rr.x, tmpsurf^.w); + BlitImageAndGenerateCollisionInfo(rr.x, y, min(x2 - rr.x, girSurf^.w), girSurf); + inc(rr.x, girSurf^.w); end; - SDL_FreeSurface(tmpsurf); AddRect(x1 - 8, y - 32, x2 - x1 + 16, 80); end @@ -372,8 +388,8 @@ ar[cnt].y:= y; if cnt >= MaxPointsIndex then // buffer is full, do not check the rest land begin - y:= $FF000000; - x:= $FF000000; + y:= LAND_HEIGHT; + x:= LAND_WIDTH; end else inc(cnt); end; @@ -455,9 +471,9 @@ procedure CheckRect(Width, Height, x, y, w, h: LongWord); begin - if (x + w > Width) then + if (x + w > Width) then OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true); - if (y + h > Height) then + if (y + h > Height) then OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true); end; @@ -473,7 +489,7 @@ // Set default water greyscale values if GrayScale then begin - for i:= 0 to 3 do + for i:= Low(SDWaterColorArray) to High(SDWaterColorArray) do begin t:= round(SDWaterColorArray[i].r * RGB_LUMINANCE_RED + SDWaterColorArray[i].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[i].b * RGB_LUMINANCE_BLUE); if t > 255 then @@ -482,7 +498,7 @@ SDWaterColorArray[i].g:= t; SDWaterColorArray[i].b:= t end; - for i:= 0 to 1 do + for i:= Low(WaterColorArray) to High(WaterColorArray) do begin t:= round(WaterColorArray[i].r * RGB_LUMINANCE_RED + WaterColorArray[i].g * RGB_LUMINANCE_GREEN + WaterColorArray[i].b * RGB_LUMINANCE_BLUE); if t > 255 then @@ -555,11 +571,39 @@ c2.g:= t; c2.b:= t end; - ExplosionBorderColor:= (c2.r shl RShift) or (c2.g shl GShift) or (c2.b shl BShift) or AMask; + ExplosionBorderColorR:= c2.r; + ExplosionBorderColorG:= c2.g; + ExplosionBorderColorB:= c2.b; + ExplosionBorderColorNoA:= + (c2.r shl RShift) or (c2.g shl GShift) or (c2.b shl BShift); + ExplosionBorderColor:= ExplosionBorderColorNoA or AMask; end else if key = 'water-top' then begin i:= Pos(',', s); + WaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + i:= Pos(',', s); + WaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + WaterColorArray[1].b:= StrToInt(Trim(s)); + WaterColorArray[1].a := 255; + if GrayScale then + begin + t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE); + if t > 255 then + t:= 255; + WaterColorArray[1].r:= t; + WaterColorArray[1].g:= t; + WaterColorArray[1].b:= t + end; + WaterColorArray[3]:= WaterColorArray[1]; + WaterColorArray[5]:= WaterColorArray[1]; + WaterColorArray[7]:= WaterColorArray[1]; + end + else if key = 'water-bottom' then + begin + i:= Pos(',', s); WaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); Delete(s, 1, i); i:= Pos(',', s); @@ -569,35 +613,16 @@ WaterColorArray[0].a := 255; if GrayScale then begin - t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE); + t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE); if t > 255 then t:= 255; WaterColorArray[0].r:= t; WaterColorArray[0].g:= t; WaterColorArray[0].b:= t end; - WaterColorArray[1]:= WaterColorArray[0]; - end - else if key = 'water-bottom' then - begin - i:= Pos(',', s); - WaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - i:= Pos(',', s); - WaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - WaterColorArray[2].b:= StrToInt(Trim(s)); - WaterColorArray[2].a := 255; - if GrayScale then - begin - t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE); - if t > 255 then - t:= 255; - WaterColorArray[2].r:= t; - WaterColorArray[2].g:= t; - WaterColorArray[2].b:= t - end; - WaterColorArray[3]:= WaterColorArray[2]; + WaterColorArray[2]:= WaterColorArray[0]; + WaterColorArray[4]:= WaterColorArray[0]; + WaterColorArray[6]:= WaterColorArray[0]; end else if key = 'water-opacity' then begin @@ -605,7 +630,9 @@ SDWaterOpacity:= WaterOpacity end else if key = 'music' then - SetMusicName(Trim(s)) + MusicFN:= Trim(s) + else if key = 'sd-music' then + SDMusicFN:= Trim(s) else if key = 'clouds' then begin cCloudsNumber:= Word(StrToInt(Trim(s))) * cScreenSpace div 4096; @@ -713,6 +740,29 @@ else if key = 'sd-water-top' then begin i:= Pos(',', s); + SDWaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + i:= Pos(',', s); + SDWaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); + Delete(s, 1, i); + SDWaterColorArray[1].b:= StrToInt(Trim(s)); + SDWaterColorArray[1].a := 255; + if GrayScale then + begin + t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE); + if t > 255 then + t:= 255; + SDWaterColorArray[1].r:= t; + SDWaterColorArray[1].g:= t; + SDWaterColorArray[1].b:= t + end; + SDWaterColorArray[3]:= SDWaterColorArray[1]; + SDWaterColorArray[5]:= SDWaterColorArray[1]; + SDWaterColorArray[7]:= SDWaterColorArray[1]; + end + else if key = 'sd-water-bottom' then + begin + i:= Pos(',', s); SDWaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); Delete(s, 1, i); i:= Pos(',', s); @@ -722,35 +772,16 @@ SDWaterColorArray[0].a := 255; if GrayScale then begin - t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE); + t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE); if t > 255 then t:= 255; SDWaterColorArray[0].r:= t; SDWaterColorArray[0].g:= t; SDWaterColorArray[0].b:= t end; - SDWaterColorArray[1]:= SDWaterColorArray[0]; - end - else if key = 'sd-water-bottom' then - begin - i:= Pos(',', s); - SDWaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - i:= Pos(',', s); - SDWaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i)))); - Delete(s, 1, i); - SDWaterColorArray[2].b:= StrToInt(Trim(s)); - SDWaterColorArray[2].a := 255; - if GrayScale then - begin - t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE); - if t > 255 then - t:= 255; - SDWaterColorArray[2].r:= t; - SDWaterColorArray[2].g:= t; - SDWaterColorArray[2].b:= t - end; - SDWaterColorArray[3]:= SDWaterColorArray[2]; + SDWaterColorArray[2]:= SDWaterColorArray[0]; + SDWaterColorArray[4]:= SDWaterColorArray[0]; + SDWaterColorArray[6]:= SDWaterColorArray[0]; end else if key = 'sd-water-opacity' then SDWaterOpacity:= StrToInt(Trim(s)) @@ -856,17 +887,25 @@ end; procedure AddObjects(); -var i, g: Longword; +var girSurf: PSDL_Surface; + i, g: Longword; begin InitRects; if hasGirders then begin g:= max(playWidth div 8, 256); i:= leftX + g; + girSurf:= nil; repeat - AddGirder(i); + AddGirder(i, girSurf); i:=i + g; until (i > rightX - g); + // free girder surface + if girSurf <> nil then + begin + SDL_FreeSurface(girSurf); + girSurf:= nil; + end; end; if (GameFlags and gfDisableLandObjects) = 0 then AddThemeObjects(ThemeObjects);