diff -r 8cf1ed3bae45 -r e9ebd63f8a03 hedgewars/uLandObjects.pas --- a/hedgewars/uLandObjects.pas Thu Apr 04 10:44:03 2013 +0300 +++ b/hedgewars/uLandObjects.pas Thu Apr 04 08:10:59 2013 -0400 @@ -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,6 +70,26 @@ 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 BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, 0); @@ -119,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 @@ -326,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 @@ -555,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))));