hedgewars/uLandGraphics.pas
branchqmlfrontend
changeset 11606 99966b4a6e1e
parent 11590 8d1cfedfaf1f
child 13405 4c813650fe17
equal deleted inserted replaced
11544:b69f5f22a3ba 11606:99966b4a6e1e
    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
   996     begin
  1011     begin
   997         xx:= X div 2;
  1012         xx:= X div 2;
   998         yy:= Y div 2;
  1013         yy:= Y div 2;
   999     end;
  1014     end;
  1000 
  1015 
  1001     pixelsweep:= (Land[Y, X] <= lfAllObjMask) and ((LandPixels[yy, xx] and AMASK) <> 0);
  1016     pixelsweep:= (Land[Y, X] <= lfAllObjMask) and ((LandPixels[yy, xx] and AMask) <> 0);
  1002     if (((Land[Y, X] and lfDamaged) <> 0) and ((Land[Y, X] and lfIndestructible) = 0)) or pixelsweep then
  1017     if (((Land[Y, X] and lfDamaged) <> 0) and ((Land[Y, X] and lfIndestructible) = 0)) or pixelsweep then
  1003     begin
  1018     begin
  1004         c:= 0;
  1019         c:= 0;
  1005         for i:= -1 to 1 do
  1020         for i:= -1 to 1 do
  1006             for j:= -1 to 1 do
  1021             for j:= -1 to 1 do