Archived

This topic is now archived and is closed to further replies.

madison

TImageSprite.PixelCheck - bug

Recommended Posts

Hi everybody ! I tried to fix that bug in DelphiX 2000.07.17a. After a looong night I came to the conclusion the hoped thing can be done It works for me, but I would like to know if it does in general, so check it out, any feedback is welcome! cya, madison (Replace this function in your DXSprite.pas)
function ImageCollisionTest(suf1, suf2: TDirectDrawSurface; const rect1, rect2: TRect;
  x1,y1,x2,y2: Integer; DoPixelCheck: Boolean): Boolean;

  function ClipRect(var DestRect: TRect; const DestRect2: TRect): Boolean;
  begin
    with DestRect do
    begin
		Left := Max(Left, DestRect2.Left);
		Right := Min(Right, DestRect2.Right);
		Top := Max(Top, DestRect2.Top);
      Bottom := Min(Bottom, DestRect2.Bottom);

      Result := (Left < Right) and (Top < Bottom);
    end;
  end;

type
  PRGB = ^TRGB;
  TRGB = packed record
	 R, G, B: Byte;
  end;
var
  ddsd1, ddsd2: TDDSurfaceDesc;
  r1, r2, r01, r02, rLock: TRect;
  tc1, tc2: DWORD;
  x, y, w, h, dx1, dx2, dy1, dy2 : Integer;
  P1, P2: Pointer;
begin
  r1 := rect1;
  with rect2 do r2 := Bounds(x2-x1, y2-y1, Right-Left, Bottom-Top);

	{ the same rects in (0,0) }
  with rect1 do r01 := Bounds(0, 0, Right-Left, Bottom-Top);
  with rect2 do r02 := Bounds(0, 0, Right-Left, Bottom-Top);

	{ maybe r1 is not in the first pattern. r01 is the better choice }
  Result := OverlapRect(r01, r2);

  if (suf1=nil) or (suf2=nil) then Exit;

  if DoPixelCheck and Result then
  begin
	 {  Get Overlapping rectangle  }
	 with r1 do r1 := Bounds(Max(x2-x1, 0), Max(y2-y1, 0), Right-Left, Bottom-Top);
	 with r2 do r2 := Bounds(Max(x1-x2, 0), Max(y1-y2, 0), Right-Left, Bottom-Top);

	 ClipRect(r1, r01);
	 ClipRect(r2, r02);

	 w := Min(r1.Right-r1.Left, r2.Right-r2.Left);
	 h := Min(r1.Bottom-r1.Top, r2.Bottom-r2.Top);

	 ClipRect(r1, bounds(r1.Left, r1.Top, w, h));
	 ClipRect(r2, bounds(r2.Left, r2.Top, w, h));

		{ move r1,r2 back into original patternposition }
	 r1 := bounds(r1.Left+rect1.Left, r1.Top+rect1.Top, w, h);
	 r2 := bounds(r2.Left+rect2.Left, r2.Top+rect2.Top, w, h);

		{ we cannot lock two surfaces, but animated sprites could be in different
		  patterns, so we need one big rectangle for the lock that includes both,
		  and the distance between r1 and r2 for the pointer offsets }
	 if (suf1=suf2) then
	 begin
		rLock.Left := Min(r1.Left,r2.Left);
		rLock.Top := Min(r1.Top,r2.Top);
		rLock.Right := Max(r1.Right,r2.Right);
		rLock.Bottom := Max(r1.Bottom, r2.Bottom);
		dx1 := Max(r1.Left-r2.Left,0);
		dx2 := Max(r2.Left-r1.Left,0);
		dy1 := Max(r1.Top-r2.Top,0);
		dy2 := Max(r2.Top-r1.Top,0);
	 end
	 else
	 begin
		rLock := r1;
		dx1 := 0;
		dx2 := 0;
		dy1 := 0;
		dy2 := 0;
	 end;

	 {  Pixel check !!!  }
	 ddsd1.dwSize := SizeOf(ddsd1);
	 if suf1.Lock(rLock, ddsd1) then
	 begin
      try
        ddsd2.dwSize := SizeOf(ddsd2);
		  if (suf1=suf2) or suf2.Lock(r2, ddsd2) then
		  begin
			 try
				if suf1=suf2 then ddsd2 := ddsd1;
				if ddsd1.ddpfPixelFormat.dwRGBBitCount<>ddsd2.ddpfPixelFormat.dwRGBBitCount then Exit;

				{  Get transparent color  }
				tc1 := ddsd1.ddckCKSrcBlt.dwColorSpaceLowValue;
				tc2 := ddsd2.ddckCKSrcBlt.dwColorSpaceLowValue;

				case ddsd1.ddpfPixelFormat.dwRGBBitCount of
				  8 : begin
						  for y:=0 to h-1 do
						  begin
							 P1 := Pointer(Integer(ddsd1.lpSurface)+(y+dy1)*ddsd1.lPitch);
							 P2 := Pointer(Integer(ddsd2.lpSurface)+(y+dy2)*ddsd2.lPitch);
							 Inc(PByte(P1),dx1);
							 Inc(PByte(P2),dx2);
                      for x:=0 to w-1 do
                      begin
                        if (PByte(P1)^<>tc1) and (PByte(P2)^<>tc2) then Exit;
                        Inc(PByte(P1));
                        Inc(PByte(P2));
                      end;
                    end;
                  end;
              16: begin
						  for y:=0 to h-1 do
						  begin
							 P1 := Pointer(Integer(ddsd1.lpSurface)+(y+dy1)*ddsd1.lPitch);
							 P2 := Pointer(Integer(ddsd2.lpSurface)+(y+dy2)*ddsd2.lPitch);
							 Inc(PWord(P1),dx1);
							 Inc(PWord(P2),dx2);
							 for x:=0 to w-1 do
							 begin
								if (PWord(P1)^<>tc1) and (PWord(P2)^<>tc2) then Exit;
								Inc(PWord(P1));
								Inc(PWord(P2));
							 end;
						  end;
                  end;
              24: begin
                    for y:=0 to h-1 do
                    begin
							 P1 := Pointer(Integer(ddsd1.lpSurface)+(y+dy1)*ddsd1.lPitch);
							 P2 := Pointer(Integer(ddsd2.lpSurface)+(y+dy2)*ddsd2.lPitch);
							 Inc(PRGB(P1),dx1);
							 Inc(PRGB(P2),dx2);
							 for x:=0 to w-1 do
                      begin        
                        if ((PRGB(P1)^.R shl 16) or (PRGB(P1)^.G shl 8) or PRGB(P1)^.B<>tc1) and
                          ((PRGB(P2)^.R shl 16) or (PRGB(P2)^.G shl 8) or PRGB(P2)^.B<>tc2) then Exit;
                        Inc(PRGB(P1));
                        Inc(PRGB(P2));
                      end;
                    end;
                  end;
              32: begin
                    for y:=0 to h-1 do
                    begin
							 P1 := Pointer(Integer(ddsd1.lpSurface)+(y+dy1)*ddsd1.lPitch);
							 P2 := Pointer(Integer(ddsd2.lpSurface)+(y+dy2)*ddsd2.lPitch);
							 Inc(PDWORD(P1),dx1);
							 Inc(PDWORD(P2),dx2);
                      for x:=0 to w-1 do
                      begin
                        if (PDWORD(P1)^ and $FFFFFF<>tc1) and (PDWORD(P2)^ and $FFFFFF<>tc2) then Exit;
                        Inc(PDWORD(P1));
                        Inc(PDWORD(P2));
                      end;
                    end;
                  end;
            end;
          finally
				if suf1<>suf2 then suf2.UnLock;
			 end;
        end;
		finally
		  suf1.UnLock;
      end;
	 end;
	 Result := False;
  end;
end;
 

Share this post


Link to post
Share on other sites
Thanks for the post. I have a few DXSprite.pas addtions that will be added to the next Unoffical DelphiX. This should/could be one...



[ Michael Wilson | turbo sys-op | turbo.gamedev.net ]

Share this post


Link to post
Share on other sites
Would be nice to be a (tiny) part of that, I''m looking forward to it anyway! I''ve just stumbled over DelphiX two months ago, and I did not get much sleep since then...


Share this post


Link to post
Share on other sites