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); inline; |
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 BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean); |
|
31 procedure BlitOverlayAndGenerateCollisionInfo(cpX, cpY: Longword; Image: PSDL_Surface); |
31 procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); |
32 procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); |
32 procedure AddOnLandObjects(Surface: PSDL_Surface); |
33 procedure AddOnLandObjects(Surface: PSDL_Surface); |
33 procedure SetLand(var LandWord: Word; Pixel: LongWord); inline; |
34 procedure SetLand(var LandWord: Word; Pixel: LongWord); inline; |
34 |
35 |
35 implementation |
36 implementation |
40 const MaxRects = 512; |
41 const MaxRects = 512; |
41 MAXOBJECTRECTS = 16; |
42 MAXOBJECTRECTS = 16; |
42 MAXTHEMEOBJECTS = 32; |
43 MAXTHEMEOBJECTS = 32; |
43 cThemeCFGFilename = 'theme.cfg'; |
44 cThemeCFGFilename = 'theme.cfg'; |
44 |
45 |
45 type TRectsArray = array[0..MaxRects] of TSDL_Rect; |
46 type PLongWord = ^LongWord; |
|
47 TRectsArray = array[0..MaxRects] of TSDL_Rect; |
46 PRectArray = ^TRectsArray; |
48 PRectArray = ^TRectsArray; |
|
49 TThemeObjectOverlay = record |
|
50 Position: TPoint; |
|
51 Surf: PSDL_Surface; |
|
52 Width, Height: LongWord; |
|
53 end; |
47 TThemeObject = record |
54 TThemeObject = record |
|
55 Name: ShortString; |
48 Surf, Mask: PSDL_Surface; |
56 Surf, Mask: PSDL_Surface; |
49 inland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect; |
57 inland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect; |
50 outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect; |
58 outland: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect; |
51 inrectcnt: Longword; |
59 anchors: array[0..Pred(MAXOBJECTRECTS)] of TSDL_Rect; |
52 outrectcnt: Longword; |
60 overlays: array[0..Pred(MAXOBJECTRECTS)] of TThemeObjectOverlay; |
|
61 inrectcnt: LongInt; |
|
62 outrectcnt: LongInt; |
|
63 anchorcnt: LongInt; |
|
64 overlaycnt: LongInt; |
53 Width, Height: Longword; |
65 Width, Height: Longword; |
54 Maxcnt: Longword; |
66 Maxcnt: Longword; |
55 end; |
67 end; |
56 TThemeObjects = record |
68 TThemeObjects = record |
57 Count: LongInt; |
69 Count: LongInt; |
100 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline; |
112 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word); inline; |
101 begin |
113 begin |
102 BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, LandFlags, false); |
114 BlitImageAndGenerateCollisionInfo(cpX, cpY, Width, Image, LandFlags, false); |
103 end; |
115 end; |
104 |
116 |
|
117 function LerpByte(src, dst: Byte; l: LongWord): LongWord; inline; |
|
118 begin |
|
119 LerpByte:= ((255 - l) * src + l * dst) div 255; |
|
120 end; |
|
121 |
105 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean); |
122 procedure BlitImageAndGenerateCollisionInfo(cpX, cpY, Width: Longword; Image: PSDL_Surface; LandFlags: Word; Flip: boolean); |
106 var p: PLongwordArray; |
123 var p: PLongwordArray; |
107 px, x, y: Longword; |
124 pLandColor: PLongWord; |
|
125 alpha, color, landColor, x, y: LongWord; |
108 bpp: LongInt; |
126 bpp: LongInt; |
109 begin |
127 begin |
110 WriteToConsole('Generating collision info... '); |
128 WriteToConsole('Generating collision info... '); |
111 |
129 |
112 if SDL_MustLock(Image) then |
130 if SDL_MustLock(Image) then |
121 |
139 |
122 if Width = 0 then |
140 if Width = 0 then |
123 Width:= Image^.w; |
141 Width:= Image^.w; |
124 |
142 |
125 p:= Image^.pixels; |
143 p:= Image^.pixels; |
|
144 |
126 for y:= 0 to Pred(Image^.h) do |
145 for y:= 0 to Pred(Image^.h) do |
127 begin |
146 begin |
128 for x:= 0 to Pred(Width) do |
147 for x:= 0 to Pred(Width) do |
129 begin |
148 begin |
130 // map image pixels per line backwards if in flip mode |
149 // map image pixels per line backwards if in flip mode |
131 if Flip then |
150 if Flip then |
132 px:= Pred(Image^.w) - x |
151 color:= p^[Pred(Image^.w) - x] |
133 else |
152 else |
134 px:= x; |
153 color:= p^[x]; |
135 |
154 |
136 if (p^[px] and AMask) <> 0 then |
155 if (cReducedQuality and rqBlurryLand) = 0 then |
137 begin |
156 pLandColor:= @LandPixels[cpY + y, cpX + x] |
138 if (cReducedQuality and rqBlurryLand) = 0 then |
157 else |
139 begin |
158 pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2]; |
140 if (LandPixels[cpY + y, cpX + x] = 0) |
159 |
141 or (((p^[px] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then |
160 landColor:= pLandColor^; |
142 LandPixels[cpY + y, cpX + x]:= p^[px]; |
161 alpha:= (landColor and AMask) shr AShift; |
143 end |
162 |
|
163 if ((color and AMask) <> 0) and (alpha <> 255) then |
|
164 begin |
|
165 if alpha = 0 then |
|
166 pLandColor^:= color |
144 else |
167 else |
145 if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then |
168 pLandColor^:= |
146 LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[px]; |
169 (LerpByte((color and RMask) shr RShift, (landColor and RMask) shr RShift, alpha) shl RShift) |
147 |
170 or (LerpByte((color and GMask) shr GShift, (landColor and GMask) shr GShift, alpha) shl GShift) |
148 if (Land[cpY + y, cpX + x] <= lfAllObjMask) and ((p^[px] and AMask) <> 0) then |
171 or (LerpByte((color and BMask) shr BShift, (landColor and BMask) shr BShift, alpha) shl BShift) |
149 Land[cpY + y, cpX + x]:= lfObject or LandFlags |
172 or (LerpByte(alpha, 255, (color and AMask) shr AShift) shl AShift); |
150 end; |
173 |
|
174 end; |
|
175 |
|
176 if ((color and AMask) <> 0) and (Land[cpY + y, cpX + x] <= lfAllObjMask) then |
|
177 Land[cpY + y, cpX + x]:= lfObject or LandFlags |
151 end; |
178 end; |
152 p:= PLongwordArray(@(p^[Image^.pitch shr 2])) |
179 p:= PLongwordArray(@(p^[Image^.pitch shr 2])) |
153 end; |
180 end; |
154 |
181 |
155 if SDL_MustLock(Image) then |
182 if SDL_MustLock(Image) then |
156 SDL_UnlockSurface(Image); |
183 SDL_UnlockSurface(Image); |
157 WriteLnToConsole(msgOK) |
184 WriteLnToConsole(msgOK) |
158 end; |
185 end; |
159 |
186 |
|
187 procedure BlitOverlayAndGenerateCollisionInfo(cpX, cpY: Longword; Image: PSDL_Surface); |
|
188 var p: PLongwordArray; |
|
189 pLandColor: PLongWord; |
|
190 x, y, alpha, color, landColor: LongWord; |
|
191 begin |
|
192 WriteToConsole('Generating overlay collision info... '); |
|
193 |
|
194 if SDL_MustLock(Image) then |
|
195 if SDLCheck(SDL_LockSurface(Image) >= 0, 'SDL_LockSurface', true) then exit; |
|
196 |
|
197 if checkFails(Image^.format^.BytesPerPixel = 4, 'Land object overlay should be 32bit', true) |
|
198 and SDL_MustLock(Image) then |
|
199 SDL_UnlockSurface(Image); |
|
200 |
|
201 p:= Image^.pixels; |
|
202 |
|
203 for y:= 0 to Pred(Image^.h) do |
|
204 begin |
|
205 for x:= 0 to Pred(Image^.w) do |
|
206 begin |
|
207 color:= p^[x]; |
|
208 if (color and AMask) <> 0 then |
|
209 begin |
|
210 if (cReducedQuality and rqBlurryLand) = 0 then |
|
211 pLandColor:= @LandPixels[cpY + y, cpX + x] |
|
212 else |
|
213 pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2]; |
|
214 |
|
215 alpha:= (color and AMask) shr AShift; |
|
216 if ((alpha <> $FF) and ((pLandColor^) <> 0)) then |
|
217 begin |
|
218 landColor:= pLandColor^; |
|
219 color:= |
|
220 (LerpByte((landColor and RMask) shr RShift, (color and RMask) shr RShift, alpha) shl RShift) |
|
221 or (LerpByte((landColor and GMask) shr GShift, (color and GMask) shr GShift, alpha) shl GShift) |
|
222 or (LerpByte((landColor and BMask) shr BShift, (color and BMask) shr BShift, alpha) shl BShift) |
|
223 or (LerpByte(alpha, 255, (landColor and AMask) shr AShift) shl AShift) |
|
224 end; |
|
225 pLandColor^:= color; |
|
226 |
|
227 if Land[cpY + y, cpX + x] <= lfAllObjMask then |
|
228 Land[cpY + y, cpX + x]:= lfObject |
|
229 end; |
|
230 end; |
|
231 p:= PLongwordArray(@(p^[Image^.pitch shr 2])) |
|
232 end; |
|
233 |
|
234 if SDL_MustLock(Image) then |
|
235 SDL_UnlockSurface(Image); |
|
236 WriteLnToConsole(msgOK) |
|
237 end; |
|
238 |
160 procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); |
239 procedure BlitImageUsingMask(cpX, cpY: Longword; Image, Mask: PSDL_Surface); |
161 var p, mp: PLongwordArray; |
240 var p, mp: PLongwordArray; |
162 x, y: Longword; |
241 pLandColor: PLongWord; |
|
242 alpha, color, landColor, x, y: Longword; |
163 bpp: LongInt; |
243 bpp: LongInt; |
164 begin |
244 begin |
165 WriteToConsole('Generating collision info... '); |
245 WriteToConsole('Generating collision info... '); |
166 |
246 |
167 if SDL_MustLock(Image) then |
247 if SDL_MustLock(Image) then |
178 mp:= Mask^.pixels; |
258 mp:= Mask^.pixels; |
179 for y:= 0 to Pred(Image^.h) do |
259 for y:= 0 to Pred(Image^.h) do |
180 begin |
260 begin |
181 for x:= 0 to Pred(Image^.w) do |
261 for x:= 0 to Pred(Image^.w) do |
182 begin |
262 begin |
|
263 color:= p^[x]; |
|
264 |
183 if (cReducedQuality and rqBlurryLand) = 0 then |
265 if (cReducedQuality and rqBlurryLand) = 0 then |
184 begin |
266 pLandColor:= @LandPixels[cpY + y, cpX + x] |
185 if (LandPixels[cpY + y, cpX + x] = 0) |
|
186 or (((p^[x] and AMask) <> 0) and (((LandPixels[cpY + y, cpX + x] and AMask) shr AShift) < 255)) then |
|
187 LandPixels[cpY + y, cpX + x]:= p^[x]; |
|
188 end |
|
189 else |
267 else |
190 if LandPixels[(cpY + y) div 2, (cpX + x) div 2] = 0 then |
268 pLandColor:= @LandPixels[(cpY + y) div 2, (cpX + x) div 2]; |
191 LandPixels[(cpY + y) div 2, (cpX + x) div 2]:= p^[x]; |
269 |
|
270 landColor:= pLandColor^; |
|
271 alpha:= (landColor and AMask) shr AShift; |
|
272 |
|
273 if ((color and AMask) <> 0) and (alpha <> 255) then |
|
274 begin |
|
275 if alpha = 0 then |
|
276 pLandColor^:= color |
|
277 else |
|
278 pLandColor^:= |
|
279 (LerpByte((color and RMask) shr RShift, (landColor and RMask) shr RShift, alpha) shl RShift) |
|
280 or (LerpByte((color and GMask) shr GShift, (landColor and GMask) shr GShift, alpha) shl GShift) |
|
281 or (LerpByte((color and BMask) shr BShift, (landColor and BMask) shr BShift, alpha) shl BShift) |
|
282 or (LerpByte(alpha, 255, (color and AMask) shr AShift) shl AShift); |
|
283 end; |
192 |
284 |
193 if (Land[cpY + y, cpX + x] <= lfAllObjMask) or (Land[cpY + y, cpX + x] and lfObject <> 0) then |
285 if (Land[cpY + y, cpX + x] <= lfAllObjMask) or (Land[cpY + y, cpX + x] and lfObject <> 0) then |
194 SetLand(Land[cpY + y, cpX + x], mp^[x]); |
286 SetLand(Land[cpY + y, cpX + x], mp^[x]); |
195 end; |
287 end; |
|
288 |
196 p:= PLongwordArray(@(p^[Image^.pitch shr 2])); |
289 p:= PLongwordArray(@(p^[Image^.pitch shr 2])); |
197 mp:= PLongwordArray(@(mp^[Mask^.pitch shr 2])) |
290 mp:= PLongwordArray(@(mp^[Mask^.pitch shr 2])) |
198 end; |
291 end; |
199 |
292 |
200 if SDL_MustLock(Image) then |
293 if SDL_MustLock(Image) then |
251 if Land[i, x] <> 0 then |
344 if Land[i, x] <> 0 then |
252 inc(lRes); |
345 inc(lRes); |
253 CountNonZeroz:= lRes; |
346 CountNonZeroz:= lRes; |
254 end; |
347 end; |
255 |
348 |
|
349 procedure ChecksumLandObjectImage(Image: PSDL_Surface); |
|
350 var y: LongInt; |
|
351 begin |
|
352 if Image = nil then exit; |
|
353 |
|
354 if SDL_MustLock(Image) then |
|
355 SDL_LockSurface(Image); |
|
356 |
|
357 if checkFails(Image^.format^.BytesPerPixel = 4, 'Land object image should be 32bit', true) then |
|
358 begin |
|
359 if SDL_MustLock(Image) then |
|
360 SDL_UnlockSurface(Image); |
|
361 exit |
|
362 end; |
|
363 |
|
364 for y := 0 to Image^.h-1 do |
|
365 syncedPixelDigest:= Adler32Update(syncedPixelDigest, @PByteArray(Image^.pixels)^[y*Image^.pitch], Image^.w*4); |
|
366 |
|
367 if SDL_MustLock(Image) then |
|
368 SDL_UnlockSurface(Image); |
|
369 end; |
|
370 |
256 function AddGirder(gX: LongInt; var girSurf: PSDL_Surface): boolean; |
371 function AddGirder(gX: LongInt; var girSurf: PSDL_Surface): boolean; |
257 var x1, x2, y, k, i, girderHeight: LongInt; |
372 var x1, x2, y, k, i, girderHeight: LongInt; |
258 rr: TSDL_Rect; |
373 rr: TSDL_Rect; |
259 bRes: boolean; |
374 bRes: boolean; |
260 begin |
375 begin |
261 if girSurf = nil then |
376 if girSurf = nil then |
262 girSurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifColorKey or ifIgnoreCaps); |
377 girSurf:= LoadDataImageAltPath(ptCurrTheme, ptGraphics, 'Girder', ifCritical or ifColorKey or ifIgnoreCaps); |
263 |
378 |
264 for y := 0 to girsurf^.h-1 do |
379 ChecksumLandObjectImage(girsurf); |
265 syncedPixelDigest:= Adler32Update(syncedPixelDigest, @PByteArray(girsurf^.pixels)^[y*girsurf^.pitch], girsurf^.w*4); |
|
266 |
380 |
267 girderHeight:= girSurf^.h; |
381 girderHeight:= girSurf^.h; |
268 |
382 |
269 y:= topY+150; |
383 y:= topY+150; |
270 repeat |
384 repeat |
271 inc(y, 24); |
385 inc(y, 24); |
272 x1:= gX; |
386 x1:= gX; |
273 x2:= gX; |
387 x2:= gX; |
274 |
388 |
275 while (x1 > Longint(leftX)+150) and (CountNonZeroz(x1, y, girderHeight) = 0) do |
389 while (x1 > leftX+150) and (CountNonZeroz(x1, y, girderHeight) = 0) do |
276 dec(x1, 2); |
390 dec(x1, 2); |
277 |
391 |
278 i:= x1 - 12; |
392 i:= x1 - 12; |
279 repeat |
393 repeat |
280 k:= CountNonZeroz(x1, y, girderHeight); |
394 k:= CountNonZeroz(x1, y, girderHeight); |
281 dec(x1, 2) |
395 dec(x1, 2) |
282 until (x1 < Longint(leftX) + 100) or (k = 0) or (k = girderHeight) or (x1 < i); |
396 until (x1 < leftX + 100) or (k = 0) or (k = girderHeight) or (x1 < i); |
283 |
397 |
284 inc(x1, 2); |
398 inc(x1, 2); |
285 if k = girderHeight then |
399 if k = girderHeight then |
286 begin |
400 begin |
287 while (x2 < (LongInt(rightX) - 100)) and (CountNonZeroz(x2, y, girderHeight) = 0) do |
401 while (x2 < (rightX - 100)) and (CountNonZeroz(x2, y, girderHeight) = 0) do |
288 inc(x2, 2); |
402 inc(x2, 2); |
289 i:= x2 + 12; |
403 i:= x2 + 12; |
290 repeat |
404 repeat |
291 inc(x2, 2); |
405 inc(x2, 2); |
292 k:= CountNonZeroz(x2, y, girderHeight) |
406 k:= CountNonZeroz(x2, y, girderHeight) |
293 until (x2 >= (LongInt(rightX)-150)) or (k = 0) or (k = girderHeight) or (x2 > i) or (x2 - x1 >= 900); |
407 until (x2 >= (rightX-150)) or (k = 0) or (k = girderHeight) or (x2 > i) or (x2 - x1 >= 900); |
294 |
408 |
295 if (x2 < (LongInt(rightX) - 100)) and (k = girderHeight) and (x2 - x1 > 200) and (x2 - x1 < 900) |
409 if (x2 < (rightX - 100)) and (k = girderHeight) and (x2 - x1 > 200) and (x2 - x1 < 900) |
296 and (not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144)) then |
410 and (not CheckIntersect(x1 - 32, y - 64, x2 - x1 + 64, 144)) then |
297 break; |
411 break; |
298 end; |
412 end; |
299 x1:= 0; |
413 x1:= 0; |
300 until y > (LAND_HEIGHT-125); |
414 until y > (LAND_HEIGHT-125); |
353 end; |
467 end; |
354 {$WARNINGS ON} |
468 {$WARNINGS ON} |
355 CheckLand:= bRes; |
469 CheckLand:= bRes; |
356 end; |
470 end; |
357 |
471 |
|
472 function CheckLandAny(rect: TSDL_Rect; dX, dY, LandType: Longword): boolean; |
|
473 var tmpx, tmpy, bx, by: LongInt; |
|
474 begin |
|
475 inc(rect.x, dX); |
|
476 inc(rect.y, dY); |
|
477 bx:= rect.x + rect.w - 1; |
|
478 by:= rect.y + rect.h - 1; |
|
479 CheckLandAny:= false; |
|
480 |
|
481 if (((rect.x and LAND_WIDTH_MASK) or (bx and LAND_WIDTH_MASK) or |
|
482 (rect.y and LAND_HEIGHT_MASK) or (by and LAND_HEIGHT_MASK)) = 0) then |
|
483 begin |
|
484 for tmpx := rect.x to bx do |
|
485 begin |
|
486 if (((Land[rect.y, tmpx] and LandType) or (Land[by, tmpx] and LandType)) <> 0) then |
|
487 begin |
|
488 CheckLandAny := true; |
|
489 exit; |
|
490 end |
|
491 end; |
|
492 for tmpy := rect.y to by do |
|
493 begin |
|
494 if (((Land[tmpy, rect.x] and LandType) or (Land[tmpy, bx] and LandType)) <> 0) then |
|
495 begin |
|
496 CheckLandAny := true; |
|
497 exit; |
|
498 end |
|
499 end; |
|
500 end; |
|
501 end; |
|
502 |
358 function CheckCanPlace(x, y: Longword; var Obj: TThemeObject): boolean; |
503 function CheckCanPlace(x, y: Longword; var Obj: TThemeObject): boolean; |
359 var i: Longword; |
504 var i: Longword; |
360 bRes: boolean; |
505 bRes, anchored: boolean; |
|
506 overlayP1, overlayP2: TPoint; |
361 begin |
507 begin |
362 with Obj do begin |
508 with Obj do begin |
363 bRes:= true; |
509 bRes:= true; |
364 i:= 1; |
510 i:= 0; |
365 while bRes and (i <= inrectcnt) do |
511 while bRes and (i < overlaycnt) do |
|
512 begin |
|
513 overlayP1.x:= overlays[i].Position.x + x; |
|
514 overlayP1.y:= overlays[i].Position.y + y; |
|
515 overlayP2.x:= overlayP1.x + overlays[i].Width - 1; |
|
516 overlayP2.y:= overlayP1.y + overlays[i].Height - 1; |
|
517 bRes:= (((LAND_WIDTH_MASK and overlayP1.x) or (LAND_HEIGHT_MASK and overlayP1.y) or |
|
518 (LAND_WIDTH_MASK and overlayP2.x) or (LAND_HEIGHT_MASK and overlayP2.y)) = 0) |
|
519 and (not CheckIntersect(overlayP1.x, overlayP1.y, overlays[i].Width, overlays[i].Height)); |
|
520 inc(i) |
|
521 end; |
|
522 |
|
523 i:= 0; |
|
524 while bRes and (i < inrectcnt) do |
366 begin |
525 begin |
367 bRes:= CheckLand(inland[i], x, y, lfBasic); |
526 bRes:= CheckLand(inland[i], x, y, lfBasic); |
368 inc(i) |
527 inc(i) |
369 end; |
528 end; |
370 |
529 |
371 i:= 1; |
530 i:= 0; |
372 while bRes and (i <= outrectcnt) do |
531 while bRes and (i < outrectcnt) do |
373 begin |
532 begin |
374 bRes:= CheckLand(outland[i], x, y, 0); |
533 bRes:= CheckLand(outland[i], x, y, 0); |
375 inc(i) |
534 inc(i) |
|
535 end; |
|
536 |
|
537 if bRes then |
|
538 begin |
|
539 anchored:= anchorcnt = 0; |
|
540 i:= 0; |
|
541 while i < anchorcnt do |
|
542 begin |
|
543 anchored := CheckLandAny(anchors[i], x, y, lfLandMask); |
|
544 if anchored then break; |
|
545 inc(i); |
|
546 end; |
|
547 bRes:= anchored; |
376 end; |
548 end; |
377 |
549 |
378 if bRes then |
550 if bRes then |
379 bRes:= not CheckIntersect(x, y, Width, Height); |
551 bRes:= not CheckIntersect(x, y, Width, Height); |
380 |
552 |
415 else inc(cnt); |
587 else inc(cnt); |
416 end; |
588 end; |
417 inc(y, 3); |
589 inc(y, 3); |
418 until y >= LAND_HEIGHT - Height; |
590 until y >= LAND_HEIGHT - Height; |
419 inc(x, getrandom(6) + 3) |
591 inc(x, getrandom(6) + 3) |
420 until x >= LAND_WIDTH - Width; |
592 until x >= rightX - Width; |
421 bRes:= cnt <> 0; |
593 bRes:= cnt <> 0; |
422 if bRes then |
594 if bRes then |
423 begin |
595 begin |
424 i:= getrandom(cnt); |
596 i:= getrandom(cnt); |
425 if Obj.Mask <> nil then |
597 if Obj.Mask <> nil then |
426 BlitImageUsingMask(ar[i].x, ar[i].y, Obj.Surf, Obj.Mask) |
598 BlitImageUsingMask(ar[i].x, ar[i].y, Obj.Surf, Obj.Mask) |
427 else BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf); |
599 else BlitImageAndGenerateCollisionInfo(ar[i].x, ar[i].y, 0, Obj.Surf); |
428 AddRect(ar[i].x, ar[i].y, Width, Height); |
600 AddRect(ar[i].x, ar[i].y, Width, Height); |
|
601 |
|
602 ii:= 0; |
|
603 while ii < overlaycnt do |
|
604 begin |
|
605 BlitOverlayAndGenerateCollisionInfo( |
|
606 ar[i].x + overlays[ii].Position.X, |
|
607 ar[i].y + overlays[ii].Position.Y, overlays[ii].Surf); |
|
608 AddRect(ar[i].x + overlays[ii].Position.X, |
|
609 ar[i].y + overlays[ii].Position.Y, |
|
610 Width, Height); |
|
611 inc(ii); |
|
612 end; |
429 dec(Maxcnt) |
613 dec(Maxcnt) |
430 end |
614 end |
431 else Maxcnt:= 0 |
615 else Maxcnt:= 0 |
432 end; |
616 end; |
433 TryPut:= bRes; |
617 TryPut:= bRes; |
434 end; |
618 end; |
435 |
619 |
436 function TryPut2(var Obj: TSprayObject; Surface: PSDL_Surface): boolean; |
620 function TryPut2(var Obj: TSprayObject; Surface: PSDL_Surface): boolean; |
437 const MaxPointsIndex = 8095; |
621 const MaxPointsIndex = 8095; |
438 var x, y: Longword; |
622 var x, y, xStart, yStart: Longword; |
|
623 xWraps, yWraps: Byte; |
439 ar: array[0..MaxPointsIndex] of TPoint; |
624 ar: array[0..MaxPointsIndex] of TPoint; |
440 cnt, i: Longword; |
625 cnt, i: Longword; |
441 r: TSDL_Rect; |
626 r: TSDL_Rect; |
442 bRes: boolean; |
627 bRes: boolean; |
443 begin |
628 begin |
486 |
688 |
487 |
689 |
488 procedure CheckRect(Width, Height, x, y, w, h: LongWord); |
690 procedure CheckRect(Width, Height, x, y, w, h: LongWord); |
489 begin |
691 begin |
490 if (x + w > Width) then |
692 if (x + w > Width) then |
491 OutError('Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true); |
693 OutError('Broken theme. Object''s rectangle exceeds image: x + w (' + inttostr(x) + ' + ' + inttostr(w) + ') > Width (' + inttostr(Width) + ')', true); |
492 if (y + h > Height) then |
694 if (y + h > Height) then |
493 OutError('Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true); |
695 OutError('Broken theme. Object''s rectangle exceeds image: y + h (' + inttostr(y) + ' + ' + inttostr(h) + ') > Height (' + inttostr(Height) + ')', true); |
|
696 end; |
|
697 |
|
698 procedure ReadRect(var rect: TSDL_Rect; var s: ShortString); |
|
699 var i: LongInt; |
|
700 begin |
|
701 with rect do |
|
702 begin |
|
703 i:= Pos(',', s); |
|
704 x:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
705 Delete(s, 1, i); |
|
706 i:= Pos(',', s); |
|
707 y:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
708 Delete(s, 1, i); |
|
709 i:= Pos(',', s); |
|
710 w:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
711 Delete(s, 1, i); |
|
712 i:= Pos(',', s); |
|
713 if i = 0 then i:= Succ(Length(S)); |
|
714 h:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
715 Delete(s, 1, i); |
|
716 end; |
|
717 end; |
|
718 |
|
719 |
|
720 |
|
721 procedure ReadOverlay(var overlay: TThemeObjectOverlay; var s: ShortString); |
|
722 var i: LongInt; |
|
723 begin |
|
724 with overlay do |
|
725 begin |
|
726 i:= Pos(',', s); |
|
727 Position.X:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
728 Delete(s, 1, i); |
|
729 i:= Pos(',', s); |
|
730 Position.Y:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
731 Delete(s, 1, i); |
|
732 i:= Pos(',', s); |
|
733 if i = 0 then i:= Succ(Length(S)); |
|
734 Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifColorKey or ifIgnoreCaps or ifCritical); |
|
735 Width:= Surf^.w; |
|
736 Height:= Surf^.h; |
|
737 Delete(s, 1, i); |
|
738 ChecksumLandObjectImage(Surf); |
|
739 end; |
494 end; |
740 end; |
495 |
741 |
496 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects); |
742 procedure ReadThemeInfo(var ThemeObjects: TThemeObjects; var SprayObjects: TSprayObjects); |
497 var s, key: shortstring; |
743 var s, key, nameRef: shortstring; |
498 f: PFSFile; |
744 f: PFSFile; |
499 i, y: LongInt; |
745 i: LongInt; |
500 ii, t: Longword; |
746 ii, t: Longword; |
501 c2: TSDL_Color; |
747 c2: TSDL_Color; |
502 begin |
748 begin |
503 |
749 |
504 AddProgress; |
750 AddProgress; |
685 begin |
932 begin |
686 inc(ThemeObjects.Count); |
933 inc(ThemeObjects.Count); |
687 with ThemeObjects.objs[Pred(ThemeObjects.Count)] do |
934 with ThemeObjects.objs[Pred(ThemeObjects.Count)] do |
688 begin |
935 begin |
689 i:= Pos(',', s); |
936 i:= Pos(',', s); |
690 Surf:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i))), ifColorKey or ifIgnoreCaps or ifCritical); |
937 Name:= Trim(Copy(s, 1, Pred(i))); |
|
938 Surf:= LoadDataImage(ptCurrTheme, Name, ifColorKey or ifIgnoreCaps or ifCritical); |
691 Width:= Surf^.w; |
939 Width:= Surf^.w; |
692 Height:= Surf^.h; |
940 Height:= Surf^.h; |
693 Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifColorKey or ifIgnoreCaps); |
941 Mask:= LoadDataImage(ptCurrTheme, Trim(Copy(s, 1, Pred(i)))+'_mask', ifColorKey or ifIgnoreCaps); |
694 Delete(s, 1, i); |
942 Delete(s, 1, i); |
695 i:= Pos(',', s); |
943 i:= Pos(',', s); |
696 Maxcnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
944 Maxcnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
697 Delete(s, 1, i); |
945 Delete(s, 1, i); |
698 if (Maxcnt < 1) or (Maxcnt > MAXTHEMEOBJECTS) then |
946 if (Maxcnt < 1) or (Maxcnt > MAXTHEMEOBJECTS) then |
699 OutError('Object''s max count should be between 1 and '+ inttostr(MAXTHEMEOBJECTS) +' (it was '+ inttostr(Maxcnt) +').', true); |
947 OutError('Broken theme. Object''s max. count should be between 1 and '+ inttostr(MAXTHEMEOBJECTS) +' (it was '+ inttostr(Maxcnt) +').', true); |
700 for y := 0 to Surf^.h-1 do |
948 ChecksumLandObjectImage(Surf); |
701 syncedPixelDigest:= Adler32Update(syncedPixelDigest, @PByteArray(Surf^.pixels)^[y*Surf^.pitch], Surf^.w*4); |
949 ChecksumLandObjectImage(Mask); |
702 |
950 |
703 inrectcnt := 0; |
951 inrectcnt := 0; |
704 |
952 |
705 for ii := 1 to Length(S) do |
953 for ii := 1 to Length(S) do |
706 if S[ii] = ',' then |
954 if S[ii] = ',' then |
712 i:= Pos(',', s); |
960 i:= Pos(',', s); |
713 inrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
961 inrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
714 Delete(s, 1, i); |
962 Delete(s, 1, i); |
715 end; |
963 end; |
716 |
964 |
717 for ii:= 1 to inrectcnt do |
965 if inrectcnt > MAXOBJECTRECTS then |
718 with inland[ii] do |
966 OutError('Broken theme. Object''s inland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(inrectcnt) +').', true); |
719 begin |
967 |
720 i:= Pos(',', s); |
968 for ii:= 0 to Pred(inrectcnt) do |
721 x:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
969 ReadRect(inland[ii], s); |
722 Delete(s, 1, i); |
|
723 i:= Pos(',', s); |
|
724 y:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
725 Delete(s, 1, i); |
|
726 i:= Pos(',', s); |
|
727 w:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
728 Delete(s, 1, i); |
|
729 i:= Pos(',', s); |
|
730 h:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
731 Delete(s, 1, i); |
|
732 CheckRect(Width, Height, x, y, w, h) |
|
733 end; |
|
734 |
970 |
735 i:= Pos(',', s); |
971 i:= Pos(',', s); |
736 outrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
972 outrectcnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
737 Delete(s, 1, i); |
973 Delete(s, 1, i); |
738 for ii:= 1 to outrectcnt do |
974 |
739 with outland[ii] do |
975 if outrectcnt > MAXOBJECTRECTS then |
740 begin |
976 OutError('Broken theme. Object''s outland rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(outrectcnt) +').', true); |
741 i:= Pos(',', s); |
977 |
742 x:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
978 for ii:= 0 to Pred(outrectcnt) do |
743 Delete(s, 1, i); |
979 ReadRect(outland[ii], s); |
744 i:= Pos(',', s); |
980 end; |
745 y:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
981 end |
746 Delete(s, 1, i); |
982 else if key = 'anchors' then |
747 i:= Pos(',', s); |
983 begin |
748 w:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
984 i:= Pos(',', s); |
749 Delete(s, 1, i); |
985 nameRef:= Trim(Copy(s, 1, Pred(i))); |
750 if ii = outrectcnt then |
986 for ii:= 0 to Pred(ThemeObjects.Count) do |
751 h:= StrToInt(Trim(s)) |
987 if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do |
752 else |
988 begin |
753 begin |
989 if anchorcnt <> 0 then |
754 i:= Pos(',', s); |
990 OutError('Broken theme. Duplicate anchors declaration for object ' + nameRef, true); |
755 h:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
991 Delete(s, 1, i); |
756 Delete(s, 1, i) |
992 i:= Pos(',', s); |
757 end; |
993 anchorcnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
758 CheckRect(Width, Height, x, y, w, h) |
994 Delete(s, 1, i); |
759 end; |
995 if anchorcnt > MAXOBJECTRECTS then |
760 |
996 OutError('Broken theme. Object''s anchor rectangle count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(anchorcnt) +').', true); |
|
997 for t:= 0 to Pred(anchorcnt) do |
|
998 ReadRect(anchors[t], s); |
|
999 break |
|
1000 end; |
|
1001 end |
|
1002 else if key = 'overlays' then |
|
1003 begin |
|
1004 i:= Pos(',', s); |
|
1005 nameRef:= Trim(Copy(s, 1, Pred(i))); |
|
1006 for ii:= 0 to Pred(ThemeObjects.Count) do |
|
1007 if ThemeObjects.objs[ii].Name = nameRef then with ThemeObjects.objs[ii] do |
|
1008 begin |
|
1009 if overlaycnt <> 0 then |
|
1010 OutError('Broken theme. Duplicate overlays declaration for object ' + nameRef, true); |
|
1011 Delete(s, 1, i); |
|
1012 i:= Pos(',', s); |
|
1013 overlaycnt:= StrToInt(Trim(Copy(s, 1, Pred(i)))); |
|
1014 Delete(s, 1, i); |
|
1015 if overlaycnt > MAXOBJECTRECTS then |
|
1016 OutError('Broken theme. Object''s overlay count should be no more than '+ inttostr(MAXOBJECTRECTS) +' (it was '+ inttostr(overlaycnt) +').', true); |
|
1017 for t:= 0 to Pred(overlaycnt) do |
|
1018 ReadOverlay(overlays[t], s); |
|
1019 break |
761 end; |
1020 end; |
762 end |
1021 end |
763 else if key = 'spray' then |
1022 else if key = 'spray' then |
764 begin |
1023 begin |
765 inc(SprayObjects.Count); |
1024 inc(SprayObjects.Count); |
1007 begin |
1270 begin |
1008 ReadThemeInfo(ThemeObjects, SprayObjects) |
1271 ReadThemeInfo(ThemeObjects, SprayObjects) |
1009 end; |
1272 end; |
1010 |
1273 |
1011 procedure FreeLandObjects(); |
1274 procedure FreeLandObjects(); |
1012 var i: Longword; |
1275 var i, ii: Longword; |
1013 begin |
1276 begin |
1014 for i:= 0 to Pred(MAXTHEMEOBJECTS) do |
1277 for i:= 0 to Pred(MAXTHEMEOBJECTS) do |
1015 begin |
1278 begin |
1016 if ThemeObjects.objs[i].Surf <> nil then |
1279 if ThemeObjects.objs[i].Surf <> nil then |
1017 SDL_FreeSurface(ThemeObjects.objs[i].Surf); |
1280 SDL_FreeSurface(ThemeObjects.objs[i].Surf); |
1018 if SprayObjects.objs[i].Surf <> nil then |
1281 if SprayObjects.objs[i].Surf <> nil then |
1019 SDL_FreeSurface(SprayObjects.objs[i].Surf); |
1282 SDL_FreeSurface(SprayObjects.objs[i].Surf); |
1020 ThemeObjects.objs[i].Surf:= nil; |
1283 ThemeObjects.objs[i].Surf:= nil; |
1021 SprayObjects.objs[i].Surf:= nil; |
1284 SprayObjects.objs[i].Surf:= nil; |
|
1285 |
|
1286 ii:= 0; |
|
1287 while ii < ThemeObjects.objs[i].overlaycnt do |
|
1288 begin |
|
1289 if ThemeObjects.objs[i].overlays[ii].Surf <> nil then |
|
1290 begin |
|
1291 SDL_FreeSurface(ThemeObjects.objs[i].overlays[ii].Surf); |
|
1292 ThemeObjects.objs[i].overlays[ii].Surf:= nil; |
|
1293 end; |
|
1294 inc(ii); |
|
1295 end; |
1022 end; |
1296 end; |
1023 end; |
1297 end; |
1024 |
1298 |
1025 end. |
1299 end. |