diff -r bde641cf53c8 -r e350500c4edb hedgewars/uLandObjects.pas --- a/hedgewars/uLandObjects.pas Thu Apr 04 14:37:19 2013 +0200 +++ b/hedgewars/uLandObjects.pas Tue Jun 04 22:28:12 2013 +0200 @@ -1,6 +1,6 @@ (* * Hedgewars, a free turn based strategy game - * Copyright (c) 2004-2012 Andrey Korotaev + * Copyright (c) 2004-2013 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 @@ -27,7 +27,9 @@ procedure LoadThemeConfig; procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline; procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; extraFlags: Word); +procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); procedure AddOnLandObjects(Surface: PSDL_Surface); +procedure SetLand(var LandWord: Word; Pixel: LongWord); inline; implementation uses uStore, uConsts, uConsole, uRandom, uSound, GLunit @@ -42,7 +44,7 @@ type TRectsArray = array[0..MaxRects] of TSDL_Rect; PRectArray = ^TRectsArray; TThemeObject = record - Surf: PSDL_Surface; + Surf, Mask: PSDL_Surface; inland: TSDL_Rect; outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect; rectcnt: Longword; @@ -68,7 +70,25 @@ ThemeObjects: TThemeObjects; SprayObjects: TSprayObjects; - +procedure SetLand(var LandWord: Word; Pixel: LongWord); inline; +begin + // this an if instead of masking colours to avoid confusing map creators + if ((AMask and Pixel) = 0) then + LandWord:= 0 + else if Pixel = $FFFFFFFF then // white + LandWord:= lfObject + else if Pixel = AMask then // black + begin + LandWord:= lfBasic; + disableLandBack:= false + end + else if Pixel = (AMask or RMask) then // red + LandWord:= lfIndestructible + else if Pixel = (AMask or BMask) then // blue + LandWord:= lfObject or lfIce + else if Pixel = (AMask or GMask) then // green + LandWord:= lfObject or lfBouncy +end; procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface); inline; begin @@ -121,6 +141,47 @@ WriteLnToConsole(msgOK) end; +procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); +var p, mp: PLongwordArray; + x, y: Longword; + bpp: LongInt; +begin +WriteToConsole('Generating collision info... '); + +if SDL_MustLock(Image) then + SDLTry(SDL_LockSurface(Image) >= 0, true); + +bpp:= Image^.format^.BytesPerPixel; +TryDo(bpp = 4, 'Land object should be 32bit', true); + +p:= Image^.pixels; +mp:= Mask^.pixels; +for y:= 0 to Pred(Image^.h) do + begin + for x:= 0 to Pred(Image^.w) do + 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]; + 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 (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]) + end; + +if SDL_MustLock(Image) then + SDL_UnlockSurface(Image); +WriteLnToConsole(msgOK) +end; + procedure AddRect(x1, y1, w1, h1: LongInt); begin with Rects^[RectCount] do @@ -328,7 +389,9 @@ if bRes then begin i:= getrandom(cnt); - BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf); + if Obj.Mask <> nil then + BlitImageUsingMask(ar[i].x, ar[i].y, Obj.Surf, Obj.Mask) + else BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf); AddRect(ar[i].x, ar[i].y, Width, Height); dec(Maxcnt) end @@ -557,9 +620,10 @@ with ThemeObjects.objs[Pred(ThemeObjects.Count)] do begin i:= Pos(',', s); - Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps); + Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifTransparent or ifIgnoreCaps or ifCritical); Width:= Surf^.w; Height:= Surf^.h; + Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifTransparent or ifIgnoreCaps); Delete(s, 1, i); i:= Pos(',', s); Maxcnt:= StrToInt(Trim(Copy(s, 1, Pred(i))));