Текущий архив: 2004.01.13;
Скачать: CL | DM;
ВнизНужен collision check Найти похожие ветки
← →
Mihey (2003-06-26 00:04) [0]Уважаемые Мастера!
Мне нужно реализовать проверку столкновений одного изображения с другим (именно изображений, а не их рамок). Если у вас есть наработки по этому поводу, то поделитесь. Интересует простая реализация, используя Canvas.Pixels.
← →
pasha676 (2003-06-26 13:28) [1]Сравнивать положение каждой точки или можно по цветам.
← →
Mihey (2003-06-26 14:40) [2]Спасибо, всё как всегда придётся писать самому. Ладно, вот вам реализация для DelphiX:
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: DDSURFACEDESC;
r1, r2: TRect;
tc1, tc2: DWORD;
x, y, w, h: Integer;
P1, P2: Pointer;
begin
r1 := rect1;
with rect2 do r2 := Bounds(x2-x1, y2-y1, Right-Left, Bottom-Top);
Result := OverlapRect(r1, r2);
if (suf1=nil) or (suf2=nil) then Exit;
if DoPixelCheck and Result then
begin
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, rect1);
ClipRect(r2, rect2);
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));
ddsd1.dwSize := SizeOf(ddsd1);
if suf1.Lock(r1, 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;
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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
for x:=0 to w-1 do
begin
with PRGB(P1)^ do if (R shl 16) or (G shl 8) or B<>tc1 then Exit;
with PRGB(P2)^ do if (R shl 16) or (G shl 8) or 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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
for x:=0 to w-1 do
begin
if (PDWORD(P1)^<>tc1) and (PDWORD(P2)^<>tc2) then Exit;
Inc(PDWORD(P1));
( PDWORD(P2) [2] Спасибо, всё как всегда придётся писать самому. Ладно, вот вам реализация для DelphiX:
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: DDSURFACEDESC;
r1, r2: TRect;
tc1, tc2: DWORD;
x, y, w, h: Integer;
P1, P2: Pointer;
begin
r1 := rect1;
with rect2 do r2 := Bounds(x2-x1, y2-y1, Right-Left, Bottom-Top);
Result := OverlapRect(r1, r2);
if (suf1=nil) or (suf2=nil) then Exit;
if DoPixelCheck and Result then
begin
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, rect1);
ClipRect(r2, rect2);
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));
ddsd1.dwSize := SizeOf(ddsd1);
if suf1.Lock(r1, 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;
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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
for x:=0 to w-1 do
begin
with PRGB(P1)^ do if (R shl 16) or (G shl 8) or B<>tc1 then Exit;
with PRGB(P2)^ do if (R shl 16) or (G shl 8) or 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*ddsd1.lPitch);
P2 := Pointer(Integer(ddsd2.lpSurface)+y*ddsd2.lPitch);
for x:=0 to w-1 do
begin
if (PDWORD(P1)^<>tc1) and (PDWORD(P2)^<>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;
Страницы: 1 вся ветка
Текущий архив: 2004.01.13;
Скачать: CL | DM;
Память: 0.47 MB
Время: 0.007 c