简体   繁体   English

Delphi 7 - 将 TImage 分配给 TImage 数组

[英]Delphi 7 - Assigning a TImage to array of TImage

I am making a custom battleship game, I have a 10x10 grid of objects (TImage).我正在制作一个自定义战舰游戏,我有一个 10x10 的对象网格(TImage)。 I need to change their .Picture property during runtime, for ships to appear on viewport.我需要在运行时更改它们的 .Picture 属性,以便船舶出现在视口上。 I need to change one's Picture property depending on the given coordinates, so I created the following array:我需要根据给定的坐标更改一个人的图片属性,所以我创建了以下数组:

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

and I have tried to assign them a TImage object like this:我尝试为它们分配一个 TImage 对象,如下所示:

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

which is supposed to contain links to all TImage objects on viewport (which exist in the Form pre-launch) so I can change one's SampleTImage.Picture property like this:它应该包含指向视口上所有 TImage 对象的链接(存在于表单预启动中),因此我可以像这样更改一个 SampleTImage.Picture 属性:

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

But this throws an Access violation error.但这会引发访问冲突错误。

Access violation at address 0046CF10 in module 'Project2.exe'.模块“Project2.exe”中地址 0046CF10 处的访问冲突。 Read of address 00000628.读取地址 00000628。

I have done a bit of research pre-posting this question, but everyone on the Stackoverflow, who asked similar questions were creating objects in runtime, in my case all TImage objects are created pre-runtime and are neded to be assigned to a double dimensional array, so I can change properties more 'conveniently'.我在发布这个问题之前做了一些研究,但是在 Stackoverflow 上提出类似问题的每个人都在运行时创建对象,在我的情况下,所有 TImage 对象都是在运行前创建的,并且需要分配给二维数组,因此我可以更“方便地”更改属性。

If it is impossible to do it this way, I would really like to see any possible optimal solution.如果不可能这样做,我真的很想看到任何可能的最佳解决方案。 :) :)

I am very sorry if this question was already asked and answered a dozen of times.如果这个问题已经被问过并回答了十几次,我很抱歉。 I am pretty new with this kind of object operating stuff.我对这种对象操作的东西很陌生。

Thanks for your time!谢谢你的时间! ;) ;)

I suggest you use a TImageList to store your images and display those on screen using TImages as needed.我建议您使用TImageList来存储您的图像并根据需要使用TImages在屏幕上显示这些图像。
Make sure the Images are transparent.确保图像是透明的。 You can duplicate images in the ImageList if you don't want to rotate them in code.如果您不想在代码中旋转它们,您可以在 ImageList 中复制图像。

If you store objects in an array, be aware that the array starts out zeros (or garbage).如果将对象存储在数组中,请注意数组从零(或垃圾)开始。
That's why you're getting errors.这就是为什么你会收到错误。

If you want to use an array, use something like this:如果要使用数组,请使用以下内容:

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;

Normally I'd advise against using TImages as sprites in a game, but for slow (non?) moving objects like battleships in the classic battleship game I guess it's fine.通常我会建议不要在游戏中使用 TImages 作为精灵,但是对于像经典战舰游戏中的战舰这样缓慢(非?)移动的物体,我想这很好。
Note that the images do not overlap, you just have square tiles of ships in your imagelist.请注意,图像不重叠,您的图像列表中只有方形的船舶图块。
One of the images in your imagelist must be a 'empty' bitmap with just a rect with a transparent color inside.您的图像列表中的图像之一必须是一个“空”位图,其中只有一个带有透明颜色的矩形。 This you assign to a rect if there is no battleship inside.如果里面没有战舰,你可以将它分配给一个矩形。

Obviously you need to do some bookkeeping regarding the status of the grid.显然,您需要对网格的状态进行一些记账。
This you put in a record.你把这个记录在案。

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

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

If you have the gridrect , then you don't need the images, you can just draw directly in the OnPaint event of the form.如果你有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}

Good luck.祝你好运。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM