Arrays delphi中的碰撞检测(pascal)

Arrays delphi中的碰撞检测(pascal),arrays,delphi,collision-detection,pascal,Arrays,Delphi,Collision Detection,Pascal,我正在为我的A级项目制作我自己版本的太空入侵者,我被碰撞检测卡住了。当子弹击中入侵者时,我需要检测碰撞,我真的被卡住了 入侵者当前存储在2d数组中,并在计时器上移动,其代码如下: for Row:=1 to 5 do begin frmGame.Canvas.FillRect(WaveArea) for Column:=1 to 11 do begin frmGame.Canvas.Draw(30+Column*50+x, 180 Images[1].Picture.Graphic)

我正在为我的A级项目制作我自己版本的太空入侵者,我被碰撞检测卡住了。当子弹击中入侵者时,我需要检测碰撞,我真的被卡住了

入侵者当前存储在2d数组中,并在计时器上移动,其代码如下:

for Row:=1 to 5 do
begin
frmGame.Canvas.FillRect(WaveArea)
for Column:=1 to 11 do
  begin
    frmGame.Canvas.Draw(30+Column*50+x, 180 Images[1].Picture.Graphic);
    frmGame.Canvas.Draw(30+Column*50+x, 230 Images[2].Picture.Graphic);
  end;
 x:=x+xShift;
end;
if x>500 then
 tmrMoveInvaders.Enabled:=False;
const
  ColCount = 11;
  RowCount = 5;

type
  TCol = 0..ColCount - 1;
  TRow = 0..RowCount - 1;

  TGameForm = class(TForm)
  private
    FBullet: TShape;
    FTargets: array[TCol, TRow] of TImage;
    procedure CheckCollisions;
  end;

implementation

{$R *.dfm}

procedure TGameForm.CheckCollisions;
var
  Col: TCol;
  Row: TRow;
  R: TRect;
begin
  for Col := Low(TCol) to High(TCol) do
    for Row := Low(TRow) to High(TRow) do
      if IntersectRect(R, FTargets[Col, Row].BoundsRect, FBullet.BoundsRect) then
        FTargets[Col, Row].Visible := False;
end;
我写的冲突代码不起作用,但我不知道为什么。这可能是通过使用2D数组将图像加载到表单上的方式,但我不确定

碰撞程序的代码为:

Procedure Collision(img:TImage);
Var
 TargetLeft,BulletLeft:integer;
 TargetRight,BulletRight:integer;
 TargetTop,BulletTop:integer;
 TargetBottom,BulletBottom:integer;
 Hit:boolean;

begin
 with frmGame do
  hit:=true;
  TagetLeft:=img.Left;
  BulletLeft:=shpBullet.Left;
  TargetRight:=img.Left+46; //left + width of the image
  BulletRight:=shpBullet.Left+8;
  TargetTop:=img.Top;
  BulletTop:=shpBullet.Top;
  TargetBottom:=img.Top+42; //top + height of image
  BulletBottom:=shpBullet.Top+15;

  if (TargetBottom < BulletTop) then hit:=false;
  if (TargetTop > BulletBottom) then hit:=false;
  if (TargetRight < BulletLeft) then hit:=false;
  if (TargetLeft > BulletRight) then hit:=false;
  if not img.Visible then hit:=false;

  if hit=true then
   img.Visible:=false;
程序冲突(img:TImage);
变量
TargetLeft,BulletLeft:整数;
TargetRight、BulletRight:整数;
TargetTop,BulletTop:整数;
TargetBottom,BulletBottom:整数;
Hit:布尔型;
开始
用frmGame do
点击:=正确;
TagetLeft:=img.Left;
BulletLeft:=shpbilet.Left;
TargetRight:=图像左侧+46//左+图像的宽度
BulletRight:=SHPBilet.左+8;
TargetTop:=img.Top;
BulletTop:=shpbilet.Top;
TargetBottom:=图像顶部+42//图像的顶部+高度
BulletBottom:=SHPBilet.顶部+15;
如果(TargetBottomBulletBottom),则点击:=false;
如果(TargetRightBulletRight),则点击:=false;
如果图像不可见,则点击:=假;
如果hit=true,则
img.Visible:=假;

任何帮助都将不胜感激。

您的碰撞数学是正确的:当这四个检查中的一个为真时,则确实没有碰撞。所以你需要调试,因为很明显还有别的地方出了问题

首先从逻辑上开始调试:

  • 问:我到底在检查什么?A:图像和子弹的位置
  • 问:子弹的位置是什么?答:这是我在表单上看到的形状控件的
    边界反射。不会错的
  • 问:图像的位置是什么?答:相同:这是我在表单上看到的图像组件的边界矩形
  • 问:真的吗?A:是的。。。哦,等等;我自己画的图像!!!(哈,为什么??)
  • 问:那可能是原因吗?嗯,可能是
简而言之:在碰撞例程中,假设2D数组中的图像控件包含有关其在窗体上位置的信息。但我怀疑他们甚至不是这种形式的孩子,更不用说设置任何
左属性和
顶属性了,因为您可以使用
Canvas.draw来手动绘制它们

结论:按照绘制程序计算图像的位置。或者设置每个图像的
Parent
属性,并在更新例程中重写代码,方法是不绘制图像的图形,而是通过设置
Left
Top
重新定位阵列中的图像组件

评论:
  • 我完全同意Wouter的观点:由于许多语法错误,您的代码无法编译。请确保将真正的编译代码放在StackOverflow上,最好直接从源代码编辑器复制粘贴
  • 您可以使用简化碰撞检测,如下所示:

    for Row:=1 to 5 do
    begin
    frmGame.Canvas.FillRect(WaveArea)
    for Column:=1 to 11 do
      begin
        frmGame.Canvas.Draw(30+Column*50+x, 180 Images[1].Picture.Graphic);
        frmGame.Canvas.Draw(30+Column*50+x, 230 Images[2].Picture.Graphic);
      end;
     x:=x+xShift;
    end;
    if x>500 then
     tmrMoveInvaders.Enabled:=False;
    
    const
      ColCount = 11;
      RowCount = 5;
    
    type
      TCol = 0..ColCount - 1;
      TRow = 0..RowCount - 1;
    
      TGameForm = class(TForm)
      private
        FBullet: TShape;
        FTargets: array[TCol, TRow] of TImage;
        procedure CheckCollisions;
      end;
    
    implementation
    
    {$R *.dfm}
    
    procedure TGameForm.CheckCollisions;
    var
      Col: TCol;
      Row: TRow;
      R: TRect;
    begin
      for Col := Low(TCol) to High(TCol) do
        for Row := Low(TRow) to High(TRow) do
          if IntersectRect(R, FTargets[Col, Row].BoundsRect, FBullet.BoundsRect) then
            FTargets[Col, Row].Visible := False;
    end;
    
  • 尝试使用图形数组而不是图像:
    FTargets:TGraphic的数组[TCol,TRow]

  • 或者更好,如果所有目标都是相同的图像:将其设置为
    布尔值的2D数组,指示该坐标处的目标是否被击中
  • 停止使用全局表单变量(
    frmGame
    )。现在就停下来
  • 生成form类的所有例程和方法,如上所示
  • 将form类的所有全局变量设为私有字段,如上所示

代码的预期用途是什么?该代码的目的是检测子弹形状何时与入侵者图像重叠,然后不显示被击中的图像。目前的情况是子弹直接穿过入侵者的图像,但是子弹没有显示图像,而是在入侵者经过的地方划出一条线。好吧,进行一些调试。你知道如何使用调试器,对吗?我还建议你在纸上解决这些问题。图表纸。拿支铅笔,我觉得这段代码连编译都没有。这里有
TagetLeft
,而声明的变量称为
TargetLeft
,计算
top
left
的最佳方法是什么?与当前绘制图形的方法完全相同:
left:=30+列*50+x。谢谢你的建议,我明天会试一试。