Delphi 7 - 将 TImage 分配给 TImage 数组

Delphi 7 - Assigning a TImage to array of TImage

我正在制作自定义战舰游戏,我有一个 10x10 的对象网格 (TImage)。我需要在运行时更改它们的 .Picture 属性,以便船只出现在视口中。我需要根据给定的坐标更改图片 属性,因此我创建了以下数组:

image: array[1..10,1..10] of TImage;

我试过为它们分配一个像这样的 TImage 对象:

player1.image[1,1] := player1.bcvrA1;

它应该包含指向视口上所有 TImage 对象的链接(它存在于表单预启动中)所以我可以像这样更改一个 SampleTImage.Picture 属性:

image[x,y].Picture.LoadFromFile(SamleFile);

但这会引发访问冲突错误。

Access violation at address 0046CF10 in module 'Project2.exe'. Read of address 00000628.

我在发布这个问题之前做了一些研究,但是 Whosebug 上提出类似问题的每个人都在运行时创建对象,在我的例子中,所有 TImage 对象都是在运行时创建的,并且需要分配给一个双维数组,所以我可以更多地更改属性 'conveniently'.

如果这样做不可能,我真的很想看看任何可能的最佳解决方案。 :)

如果这个问题已经被问到并回答了十几次,我感到非常抱歉。我对这种对象操作的东西很陌生。

感谢您的宝贵时间! ;)

我建议您使用 TImageList 来存储图像并根据需要使用 TImages 在屏幕上显示这些图像。
确保图像是透明的。如果不想在代码中旋转图像,可以在 ImageList 中复制图像。

如果您将对象存储在数组中,请注意该数组从零(或垃圾)开始。
这就是你收到错误的原因。

如果你想使用数组,使用这样的东西:

procedure TForm1.CreateForm(Sender: TObject); 
begin
  //Init array here, no action needed, because all object members are zero to start with.
end;

procedure TForm1.AddShip(Location: TPoint; ImageIndex: integer);
var
  x,y: integer;
  NewImage: TImage;
  Bitmap: TBitmap;
begin
  x:= Location.x; y:= Location.y;
  if ImageArray[X, Y] = nil then begin
    NewImage:= TImage.Create(Self);
    NewImage.Parent:= Panel1;
    NewImage.Transparent:= true;
    NewImage.Left:= x * GridSize;
    NewImage.Top:= y * GridSize;
    ImageArray[x,y]:= NewImage;
  end;
  if ImageList1.GetBitmap(ImageIndex, Bitmap) then begin
    ImageArray[x,y].Picture.Assign(Bitmap);
  end else raise Exception.Create(Format('Cannot find an image with index %d in %s',[ImageIndex,'ImageList1']));
end;

通常我建议不要在游戏中使用 TImages 作为 sprite,但对于像经典战舰游戏中的战舰这样缓慢(非?)移动的物体,我想这没问题。
请注意,图像不会重叠,您的图像列表中只有方块的船。
图像列表中的图像之一必须是 'empty' 位图,其中只有一个内部透明颜色的矩形。如果里面没有战舰,你就把它分配给一个矩形。

显然,您需要对网格的状态做一些簿记。
这个你记下来了。

TGridRect = record
  shiptype: TShiptype;
  orientation: THorizontalOrVertical;
  shipsection: integer;
  HiddenFromEnemy: boolean;
end;

TGrid = array[0..9,0..9] of TGridRect;

如果你有gridrect,那么你不需要图片,直接在窗体的OnPaint事件中绘制即可。

procedure TForm1.Paint(Sender: TObject);
var
  GridRect: TGridRect;
  Bitmap: TBitmap;
  ImageIndex: integer;
begin
  for x:= 0 to 9 do begin
    for y:= 0 to 9 do begin
      GridRect:= Grid[x,y];
      ImageIndex:= Ord(GridRect.ShipType) * NumberOfParts 
                   + GridRect.ShipSection * (Ord(GridRect.Orientation)+1);
      Bitmap:= TBitmap.Create;
      try
        ImageList1.GetBitmap(ImageIndex, Bitmap);
        Panel1.Canvas.Draw(x*GridSize, y*GridSize, Bitmap);
      finally 
        Bitmap.Free;
      end;
    end; {for y}
  end; {for x}

祝你好运。