--- 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 <unC0Rr@gmail.com>
+ * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
*
* 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);