Jump to content
  • Advertisement

Archived

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

madison

TImageSprite.PixelCheck - bug

This topic is 6363 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Advertisement
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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!