21 unit uLandGraphics; |
21 unit uLandGraphics; |
22 interface |
22 interface |
23 uses uFloat, uConsts, uTypes, Math, uRenderUtils; |
23 uses uFloat, uConsts, uTypes, Math, uRenderUtils; |
24 |
24 |
25 type |
25 type |
26 fillType = (nullPixel, backgroundPixel, ebcPixel, icePixel, setNotCurrentMask, changePixelSetNotCurrent, setCurrentHog, changePixelNotSetNotCurrent); |
26 fillType = (nullPixel, backgroundPixel, ebcPixel, icePixel, addNotHHObj, removeNotHHObj, addHH, removeHH, setCurrentHog, removeCurrentHog); |
27 |
27 |
28 type TRangeArray = array[0..31] of record |
28 type TRangeArray = array[0..31] of record |
29 Left, Right: LongInt; |
29 Left, Right: LongInt; |
30 end; |
30 end; |
31 PRangeArray = ^TRangeArray; |
31 PRangeArray = ^TRangeArray; |
39 function DrawExplosion(X, Y, Radius: LongInt): Longword; |
39 function DrawExplosion(X, Y, Radius: LongInt): Longword; |
40 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte); |
40 procedure DrawHLinesExplosions(ar: PRangeArray; Radius: LongInt; y, dY: LongInt; Count: Byte); |
41 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt); |
41 procedure DrawTunnel(X, Y, dX, dY: hwFloat; ticks, HalfWidth: LongInt); |
42 function FillRoundInLand(X, Y, Radius: LongInt; Value: Longword): Longword; |
42 function FillRoundInLand(X, Y, Radius: LongInt; Value: Longword): Longword; |
43 function FillRoundInLandFT(X, Y, Radius: LongInt; fill: fillType): Longword; |
43 function FillRoundInLandFT(X, Y, Radius: LongInt; fill: fillType): Longword; |
44 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean); |
44 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent, isHH: boolean); |
45 function LandBackPixel(x, y: LongInt): LongWord; |
45 function LandBackPixel(x, y: LongInt): LongWord; |
46 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword); |
46 procedure DrawLine(X1, Y1, X2, Y2: LongInt; Color: Longword); |
47 function DrawThickLine(X1, Y1, X2, Y2, radius: LongInt; color: Longword): Longword; |
47 function DrawThickLine(X1, Y1, X2, Y2, radius: LongInt; color: Longword): Longword; |
48 procedure DumpLandToLog(x, y, r: LongInt); |
48 procedure DumpLandToLog(x, y, r: LongInt); |
49 procedure DrawIceBreak(x, y, iceRadius, iceHeight: Longint); |
49 procedure DrawIceBreak(x, y, iceRadius, iceHeight: Longint); |
207 for i:= fromPix to toPix do |
207 for i:= fromPix to toPix do |
208 begin |
208 begin |
209 calculatePixelsCoordinates(i, y, px, py); |
209 calculatePixelsCoordinates(i, y, px, py); |
210 DrawPixelIce(i, y, px, py); |
210 DrawPixelIce(i, y, px, py); |
211 end; |
211 end; |
212 setNotCurrentMask: |
212 addNotHHObj: |
213 for i:= fromPix to toPix do |
213 for i:= fromPix to toPix do |
214 begin |
214 begin |
215 Land[y, i]:= Land[y, i] and lfNotCurrentMask; |
215 if Land[y, i] and lfNotHHObjMask shr lfNotHHObjShift < lfNotHHObjSize then |
216 end; |
216 Land[y, i]:= (Land[y, i] and (not lfNotHHObjMask)) or ((Land[y, i] and lfNotHHObjMask shr lfNotHHObjShift + 1) shl lfNotHHObjShift); |
217 changePixelSetNotCurrent: |
217 end; |
|
218 removeNotHHObj: |
218 for i:= fromPix to toPix do |
219 for i:= fromPix to toPix do |
219 begin |
220 begin |
220 if Land[y, i] and lfObjMask > 0 then |
221 if Land[y, i] and lfNotHHObjMask <> 0 then |
|
222 Land[y, i]:= (Land[y, i] and (not lfNotHHObjMask)) or ((Land[y, i] and lfNotHHObjMask shr lfNotHHObjShift - 1) shl lfNotHHObjShift); |
|
223 end; |
|
224 addHH: |
|
225 for i:= fromPix to toPix do |
|
226 begin |
|
227 if Land[y, i] and lfHHMask < lfHHMask then |
|
228 Land[y, i]:= Land[y, i] + 1 |
|
229 end; |
|
230 removeHH: |
|
231 for i:= fromPix to toPix do |
|
232 begin |
|
233 if Land[y, i] and lfHHMask > 0 then |
221 Land[y, i]:= Land[y, i] - 1; |
234 Land[y, i]:= Land[y, i] - 1; |
222 end; |
235 end; |
223 setCurrentHog: |
236 setCurrentHog: |
224 for i:= fromPix to toPix do |
237 for i:= fromPix to toPix do |
225 begin |
238 begin |
226 Land[y, i]:= Land[y, i] or lfCurrentHog |
239 Land[y, i]:= Land[y, i] or lfCurrentHog |
227 end; |
240 end; |
228 changePixelNotSetNotCurrent: |
241 removeCurrentHog: |
229 for i:= fromPix to toPix do |
242 for i:= fromPix to toPix do |
230 begin |
243 begin |
231 if Land[y, i] and lfObjMask < lfObjMask then |
244 Land[y, i]:= Land[y, i] and lfNotCurrentMask; |
232 Land[y, i]:= Land[y, i] + 1 |
|
233 end; |
245 end; |
234 end; |
246 end; |
235 end; |
247 end; |
236 |
248 |
237 function FillLandCircleSegmentFT(x, y, dx, dy: LongInt; fill : fillType): Longword; inline; |
249 function FillLandCircleSegmentFT(x, y, dx, dy: LongInt; fill : fillType): Longword; inline; |
358 end; |
370 end; |
359 if (dx = dy) then |
371 if (dx = dy) then |
360 inc(FillRoundInLand, FillCircleLines(x, y, dx, dy, Value)); |
372 inc(FillRoundInLand, FillCircleLines(x, y, dx, dy, Value)); |
361 end; |
373 end; |
362 |
374 |
363 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent: boolean); |
375 procedure ChangeRoundInLand(X, Y, Radius: LongInt; doSet, isCurrent, isHH: boolean); |
364 begin |
376 begin |
365 if not doSet and isCurrent then |
377 if not doSet and isCurrent then |
366 FillRoundInLandFT(X, Y, Radius, setNotCurrentMask) |
378 FillRoundInLandFT(X, Y, Radius, removeCurrentHog) |
367 else if not doSet and (not IsCurrent) then |
379 else if (not doSet) and (not IsCurrent) and isHH then |
368 FillRoundInLandFT(X, Y, Radius, changePixelSetNotCurrent) |
380 FillRoundInLandFT(X, Y, Radius, removeHH) |
|
381 else if (not doSet) and (not IsCurrent) and (not isHH) then |
|
382 FillRoundInLandFT(X, Y, Radius, removeNotHHObj) |
369 else if doSet and IsCurrent then |
383 else if doSet and IsCurrent then |
370 FillRoundInLandFT(X, Y, Radius, setCurrentHog) |
384 FillRoundInLandFT(X, Y, Radius, setCurrentHog) |
371 else if doSet and (not IsCurrent) then |
385 else if doSet and (not IsCurrent) and isHH then |
372 FillRoundInLandFT(X, Y, Radius, changePixelNotSetNotCurrent); |
386 FillRoundInLandFT(X, Y, Radius, addHH) |
|
387 else if doSet and (not IsCurrent) and (not isHH) then |
|
388 FillRoundInLandFT(X, Y, Radius, addNotHHObj); |
373 end; |
389 end; |
374 |
390 |
375 procedure DrawIceBreak(x, y, iceRadius, iceHeight: Longint); |
391 procedure DrawIceBreak(x, y, iceRadius, iceHeight: Longint); |
376 var |
392 var |
377 i, j, iceL, iceR, IceT, iceB: LongInt; |
393 i, j, iceL, iceR, IceT, iceB: LongInt; |
691 |
707 |
692 function ForcePlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; Tint: LongWord; Behind, flipHoriz, flipVert: boolean): boolean; inline; |
708 function ForcePlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; LandFlags: Word; Tint: LongWord; Behind, flipHoriz, flipVert: boolean): boolean; inline; |
693 begin |
709 begin |
694 ForcePlaceOnLand:= TryPlaceOnLand(cpX, cpY, Obj, Frame, true, false, true, behind, flipHoriz, flipVert, LandFlags, Tint) |
710 ForcePlaceOnLand:= TryPlaceOnLand(cpX, cpY, Obj, Frame, true, false, true, behind, flipHoriz, flipVert, LandFlags, Tint) |
695 end; |
711 end; |
696 |
|
697 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, outOfMap, force, behind, flipHoriz, flipVert: boolean; LandFlags: Word; Tint: LongWord): boolean; |
712 function TryPlaceOnLand(cpX, cpY: LongInt; Obj: TSprite; Frame: LongInt; doPlace, outOfMap, force, behind, flipHoriz, flipVert: boolean; LandFlags: Word; Tint: LongWord): boolean; |
698 var X, Y, bpp, h, w, row, col, gx, gy, numFramesFirstCol: LongInt; |
713 var X, Y, bpp, h, w, row, col, gx, gy, numFramesFirstCol: LongInt; |
699 p: PByteArray; |
714 p: PByteArray; |
700 Image: PSDL_Surface; |
715 Image: PSDL_Surface; |
701 pixel: LongWord; |
716 pixel: LongWord; |
763 case bpp of |
778 case bpp of |
764 4: for y:= 0 to Pred(h) do |
779 4: for y:= 0 to Pred(h) do |
765 begin |
780 begin |
766 for x:= 0 to Pred(w) do |
781 for x:= 0 to Pred(w) do |
767 if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then |
782 if ((PLongword(@(p^[x * 4]))^) and AMask) <> 0 then |
768 begin |
783 begin |
769 if (cReducedQuality and rqBlurryLand) = 0 then |
784 if (cReducedQuality and rqBlurryLand) = 0 then |
770 begin |
785 begin |
771 gX:= cpX + x; |
786 gX:= cpX + x; |
772 gY:= cpY + y; |
787 gY:= cpY + y; |
773 end |
788 end |
774 else |
789 else |
775 begin |
790 begin |
776 gX:= (cpX + x) div 2; |
791 gX:= (cpX + x) div 2; |
777 gY:= (cpY + y) div 2; |
792 gY:= (cpY + y) div 2; |
778 end; |
793 end; |
779 if not behind or (Land[cpY + y, cpX + x] and lfLandMask = 0) then |
794 if (not behind) or (Land[cpY + y, cpX + x] and lfLandMask = 0) then |
780 begin |
795 begin |
781 if (LandFlags and lfBasic <> 0) or |
796 if (LandFlags and lfBasic <> 0) or |
782 (((LandPixels[gY, gX] and AMask) shr AShift = 255) and // This test assumes lfBasic and lfObject differ only graphically |
797 ((LandPixels[gY, gX] and AMask shr AShift > 128) and // This test assumes lfBasic and lfObject differ only graphically |
783 (LandFlags or lfObject = 0)) then |
798 (LandFlags and lfObject = 0)) then |
784 Land[cpY + y, cpX + x]:= lfBasic or LandFlags |
799 Land[cpY + y, cpX + x]:= lfBasic or LandFlags |
785 else Land[cpY + y, cpX + x]:= lfObject or LandFlags |
800 else Land[cpY + y, cpX + x]:= lfObject or LandFlags |
786 end; |
801 end; |
787 if not behind or (LandPixels[gY, gX] = 0) then |
802 if (not behind) or (LandPixels[gY, gX] = 0) then |
788 begin |
803 begin |
789 if tint = $FFFFFFFF then |
804 if tint = $FFFFFFFF then |
790 LandPixels[gY, gX]:= PLongword(@(p^[x * 4]))^ |
805 LandPixels[gY, gX]:= PLongword(@(p^[x * 4]))^ |
791 else |
806 else |
792 begin |
807 begin |