Delphi多个对象的碰撞检测问题

Delphi多个对象的碰撞检测问题,delphi,collision-detection,Delphi,Collision Detection,由于某些原因,我的冲突代码不能处理多个对象。它可以完美地与一个物体配合使用,但当我尝试同时与另一个物体配合使用时,它失败了,玩家可以通过每个物体移动。我计划在一个动态数组中创建对象,并为每个对象循环此代码,但它有相同的问题,因为运行两次代码会导致所有碰撞检测中断 1个对象工作的完整项目粘贴箱: 2个对象不工作的完整项目粘贴箱: 定时器程序,两个对象的碰撞检测代码复制两次: procedure TForm1.OnTick(Sender: TObject); var I

由于某些原因,我的冲突代码不能处理多个对象。它可以完美地与一个物体配合使用,但当我尝试同时与另一个物体配合使用时,它失败了,玩家可以通过每个物体移动。我计划在一个动态数组中创建对象,并为每个对象循环此代码,但它有相同的问题,因为运行两次代码会导致所有碰撞检测中断

1个对象工作的完整项目粘贴箱: 2个对象不工作的完整项目粘贴箱:

定时器程序,两个对象的碰撞检测代码复制两次:

        procedure TForm1.OnTick(Sender: TObject);
      var IntersectionRect: TRect;
    begin
    //First object
      if not(((Image1.Width + Image1.BoundsRect.TopLeft.x) >= Shape1.Left-10 ) and ((Image1.Width + Image1.BoundsRect.TopLeft.x) <= Shape1.Left+10 ) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect)) then
        begin
          if d = true then
          Image1.Left := Image1.Left + 5;
        end;
      if not((Image1.BoundsRect.BottomRight.Y >= Shape1.Top - 10) and (Image1.BoundsRect.BottomRight.Y <= Shape1.Top + 10) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect)) then
       begin
         if s = true then
          Image1.Top := Image1.Top + 5;
       end;
      if not((Image1.BoundsRect.TopLeft.X - 10 <= (Shape1.Left + Shape1.Width)) and (Image1.BoundsRect.TopLeft.X + 10 >= (Shape1.Left + Shape1.Width))  and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect)) then
      begin
        if a = true then
        Image1.Left := Image1.Left - 5;
      end;
     if not((Image1.BoundsRect.TopLeft.Y <= Shape1.BoundsRect.BottomRight.y + 10) and (Image1.BoundsRect.TopLeft.Y >= Shape1.BoundsRect.BottomRight.y - 10) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect)) then
      begin
        if w = true then
        Image1.Top := Image1.Top - 5;
      end;


    //second object
       if not(((Image1.Width + Image1.BoundsRect.TopLeft.x) >= Shape2.Left-10 ) and ((Image1.Width + Image1.BoundsRect.TopLeft.x) <= Shape2.Left+10 ) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape2.BoundsRect)) then
        begin
          if d = true then
          Image1.Left := Image1.Left + 5;
        end;
      if not((Image1.BoundsRect.BottomRight.Y >= Shape2.Top - 10) and (Image1.BoundsRect.BottomRight.Y <= Shape2.Top + 10) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape2.BoundsRect)) then
       begin
         if s = true then
          Image1.Top := Image1.Top + 5;
       end;
      if not((Image1.BoundsRect.TopLeft.X - 10 <= (Shape2.Left + Shape2.Width)) and (Image1.BoundsRect.TopLeft.X + 10 >= (Shape2.Left + Shape1.Width))  and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape2.BoundsRect)) then
      begin
        if a = true then
        Image1.Left := Image1.Left - 5;
      end;
     if not((Image1.BoundsRect.TopLeft.Y <= Shape2.BoundsRect.BottomRight.y + 10) and (Image1.BoundsRect.TopLeft.Y >= Shape2.BoundsRect.BottomRight.y - 10) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape2.BoundsRect)) then
      begin
        if w = true then
        Image1.Top := Image1.Top - 5;
      end;
end;
程序TForm1.OnTick(发送方:TObject);
var IntersectionRect:TRect;
开始
//第一个对象

如果不是(((Image1.Width+Image1.BoundsRect.TopLeft.x)>=Shape1.Left-10)和((Image1.Width+Image1.BoundsRect.TopLeft.x)=Shape1.Top-10)和(Image1.BoundsRect.BottomRight.Y=Shape2.Left-10)和((Image1.Width+Image1.BoundsRect.TopLeft.x)=Shape2.Top-10)和(Image1.BoundsRect.BottomRight.Y,代码实际上是这样说的“如果A不与B碰撞A不与C碰撞,则移动”您需要的是相反的“如果A不与B碰撞A不与C碰撞,则移动”,例如

现在所有这些都没有经过测试-我只是想告诉你如何继续-我不会为你写代码。另外,你需要重复s,w和a


但是,希望您现在能够看到正确构建代码的价值。

这非常有用,但您如何才能将其更改为适用于对象数组?因为您不能在每次希望它适用于新对象时向所有IF语句中添加另一个AND语句。您的代码是为“高效快速操作”而设计的,而不是为了健壮性d易于维护。您需要认真重构它,分离碰撞检测和移动功能。这当然会降低代码运行速度,但有一些优化可以使其运行更快,例如在检测到碰撞时中断碰撞检测循环。一旦分离了该功能,expa对任意数量的形状进行绑定成了儿戏。此外,您的代码更易于阅读和维护。公平地说,剪切和粘贴块也不是一个真正的选项。此外,我将颠倒逻辑-使用s、d、a和w来确定使用了哪种碰撞检测,而不是确定是否存在碰撞,然后确定是否存在碰撞f我们可以移动。您的操作方式有很多错误。老实说,我看不出如何在数组中使用if语句,因为我无法为数组中的每个形状添加无限多的if语句。例如:
// both objects
      if (not(((Image1.Width + Image1.BoundsRect.TopLeft.x) >= Shape1.Left-10 ) and ((Image1.Width + Image1.BoundsRect.TopLeft.x) <= Shape1.Left+10 ) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect))
      and (not(((Image1.Width + Image1.BoundsRect.TopLeft.x) >= Shape2.Left-10 ) and ((Image1.Width + Image1.BoundsRect.TopLeft.x) <= Shape2.Left+10 ) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape2.BoundsRect)) ) then
        begin
          if d = true then
          Image1.Left := Image1.Left + 5;
        end;
if not(((Image1.Width + Image1.BoundsRect.TopLeft.x) >= Shape1.Left-10 ) and ((Image1.Width + Image1.BoundsRect.TopLeft.x) <= Shape1.Left+10 ) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect)) then
        begin
          if d = true then
          Image1.Left := Image1.Left + 5;
        end;
        if d = true then
          if not(((Image1.Width + Image1.BoundsRect.TopLeft.x) >= Shape1.Left-10 ) and ((Image1.Width + Image1.BoundsRect.TopLeft.x) <= Shape1.Left+10 ) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect)) then
          begin
            Image1.Left := Image1.Left + 5;
          end;
function CollideD( Image1 : TImage Shape1Rect : TShape );  // or as appropriate
begin
              if not(((Image1.Width + Image1.BoundsRect.TopLeft.x) >= Shape1.Left-10 ) and ((Image1.Width + Image1.BoundsRect.TopLeft.x) <= Shape1.Left+10 ) and IntersectRect(IntersectionRect, Image1.BoundsRect, Shape1.BoundsRect)) then Result := FALSE else Result := TRUE; 

end;

procedure MoveD( Iamge1 : TImage );
begin
     Image1.Left := Image1.Left + 5;
end;

...

  if d = true then
   if not CollideD( Image1, Shape1 ) then 
   begin
     MoveD( Image1 );
   end;
var
  iCanMove : Boolean;

...

   iCanMove := TRUE;
   if d then
   begin

     for I := 0 to ShapeList.Count - 1 do
     begin
       if CollideD( Image1, ShapeList[ I ] ) then
       begin
         iCanMove : FALSE;
         break; 
       end;
     end;
     if iCanMove then MoveD( Image1 );
   end;