Entwickler-Ecke

Multimedia / Grafik - Karte für ein Spiel


Gosa - Mo 08.07.02 22:11
Titel: Karte für ein Spiel
Ich probiere gerade ein Karte zu machen die aus vielen Images bzw später Sprites bestehen soll. Also wie ein Schachbrett.

Ich will aber nicht jedes image da per Hand hinsetzen.


Quelltext
1:
2:
3:
4:
5:
6:
7:
For l:= 0 to 9 do
Begin
  For j := 0 to 9 do
  Begin
    CreateControl(TImage, 'I' + inttostr(l+1) + '_' + inttostr(j+1), j*10, l*10, 10, 10);
    End;
End;


Delphi erstellt mir so ein Feld von 10 * 10 images.

So mein Problem: Wie kann ich den jetzt zumbeispiel diesen Images Bilder zuweisen?

Ich hätte das gern wie ein array das irgendwie so aussieht: Image[1..10,1..10] und wo ich dann .picture hinterschreiben kann.

Danke schonmal im voraus für jede Hilfe!

Code-Tag eingefügt. Marc


Tino - Di 09.07.02 09:21

Hallo,

ich würde es ungefähr so machen:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
Uses
  ExtCtrls;

Const
  cMaxLengthX = 10;
  cMaxLengthY = 10;

Type
  tImageArray = Array [1..cMaxLengthX, 1..cMaxLengthY] Of tImage;

Var
  vImages: tImageArray;

Procedure TForm1.FormCreate(Sender: TObject);
Var
  Idx1,
  Idx2: Integer;
  Img: tImage;
Begin
  For Idx1 := 1 To cMaxLengthX Do
    For Idx2 := 1 To cMaxLengthY Do
      Begin
        vImages [Idx1, Idx2] := tImage.Create (Self);
        With vImages [Idx1, Idx2] Do
          Begin
            Parent := Self;
            SetBounds (Idx1 * 10, Idx2 * 10, 10, 10);
          End;
      End;
End;
Wenn Du noch Fragen zum Code hast... dann posten :-D

Gruß
TINO

PS: Hab den Code nicht getestet!


Gosa - Di 09.07.02 12:03

:D

Vielen Dank!!!

Ich habe alles verstanden und funktioniert bei mir auch perfekt!!!


Gosa - Di 09.07.02 13:01

Jetzt habe ich wieder ein neues Problem :D.

Ich möchte das etwas passiert wenn man auf ein Image raufdrückt. Also eine Onclick procedure aber ich habe keine Ahnung wie das geht.

Irgendwie sowas:


Quelltext
1:
2:
3:
4:
procedure TForm1.vImageClick(Sender: TObject);
begin
  MessageDlg('Color: ' + inttostr(5), mtInformation, [mbOk], 0); 
end;


So geht das aber nicht...


Tino - Di 09.07.02 13:24

Du musst das OnClick-Event einer Procedure zuweisen.

Quelltext
1:
2:
3:
4:
5:
6:
    With vImages [Idx1, Idx2] Do 
     Begin 
      Parent := Self; 
      SetBounds (Idx1 * 10, Idx2 * 10, 10, 10); 
      OnClick := vImageClick;  // Hinzufügen!!!
     End;
Gruß


Gosa - Di 09.07.02 14:08

Ahh danke funktioniert!!!

Vielen Dank...

Ich finde in der Hilfe leider immer nicht da was ich suche.


Gosa - Di 09.07.02 15:27

Schon wieder eine frage dazu... :D

Jedes Image soll eine 'Höhe' haben. Ich habe eine Record das vMap heist. Dadrin steht Höhe, gebäude,.... Wenn man nun auf ein Image Klickt soll sich ein fenster öffnen und mir sagen wie hoch das gelände ist... welches Gebäude da steht usw...

Mein Problem ist jetzt, dass wenn ich auf ein Image Klicke die Koordinaten brauche.

Ich habe soetwas:

Quelltext
1:
2:
3:
4:
procedure TForm1.vImageClick(Sender: TObject);
begin
  MessageDlg('Height: ' + vMap[IdX,IdY].height, mtInformation, [mbOk], 0);
end;


Wie kriege ich jetzt für vMap[x,y] die werte x und y?


damadmax - Di 09.07.02 15:42

Du hast doch beim Zeichnen die Koordinaten ausgerechnet, an denen die Images stehen.

Nun musst du die Formel oder Gleichung nur umdrehen, also rückwärtz rechnen. Dann müsstest du eigentlich die Koordinaten innerhalb deines Array herausbekommen.


Tino - Di 09.07.02 15:51

Nur das ich Dich richtig verstehe: Du möchtest zu jedem tImage eine weiter Infomation (in diesem Fall die Höhe) hinterlegen, oder?

Wenn es so ist würde ich den Type tImageArray ändern:

Quelltext
1:
2:
3:
4:
5:
6:
7:
Type
  tImageInfo = Record
      Image: tImage:
      Height: Integer;
    End;

tImageArray = Array [1..cMaxLengthX, 1..cMaxLengthY] Of tImageInfo;
Jetzt müsstest Du natürlich den Code von oben (FormCreate) anpassen und zusätzlich die Info (Height) mit angeben.

Außerdem müsstest Du dann eine Funktion einbauen der Du als Parameter eine tImage-Komponenten übergibst und als Ergebnis bekommst Du das entsprechende tImageInfo-Record zurück. Damit du halt an die zusätzlichen Infos kommst.

Die Funktion könnte so aussehen:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
Function Form1.GetImageInfo (aImage: tImage): tImageInfo;
Var
  Idx1,
  Idx2: Integer;
Begin
  Result := nil;

  For Idx2 := 1 To cMaxLengthX Do
    For Idx2 := 1 To cMaxLengthY Do
      If vImages [Idx1, Idx2].Image = aImage Then
        Begin
          Result := vImages [Idx1, Idx2];
          Exit;
        end;
End;

Gruß


Gosa - Di 09.07.02 15:52

hmmm

Ich habe in der Variable vImage vom Typ : Array[1..cShownMapMaxLengthX, 1..cShownMapMaxLengthY] Of tImage die Images drin.

Die werden ja wärend des laufendem Programm erst erzeugt. Ich habe also keine Formel die ich umdrehen kann... Ich denke es gibt ein weg das man hier : procedure TForm1.vImageClick(Sender: TObject); was dran ändert und dann werden die variablen mir mit übergeben.

procedure TForm1.vImageClick(X : Integer; Y :Integer); irgendwie sowas brauche ich.


Gosa - Di 09.07.02 15:56

@Tino

Ja so kann man das machen das möchte ich aber nicht so gerne so machen. Die Karte soll scrollbar sein. Ich habe also im hintergrund noch ein record wo drin steht wie hoch etwas ist und so. Wenn ich nun die Images mit in dieses record das ein ziemlcih grosses array ist dann habe ich viele Images die nie benutzt werden da man ja nicht die ganze Karte auf den Bidlschirm bekommt.


Tino - Di 09.07.02 16:09

Gut, dann reicht es wenn Du die o. g. Funktion (GetImageInfo) umschreibst so das diese nicht mehr das tImageInfo-Record zurück gibt sondern halt die Positionen X und Y.

Das sollte doch helfen, oder?


Gosa - Di 09.07.02 16:24

Werde ich nicht so richtig schlau draus :D

Ich brache in dieser Procedur Idx1 und Idx2 von dem Image auf das man klickt. (vImages [Idx1, Idx2])


Das wird jetzt die zweite version von einem Spiel von einem Freund und mir. Die erste Version die nicht gut ist kann man sich runterladen... wenn jemand interresiert ist.
http://home.t-online.de/home/rathjen.tobias/

Hat aber viele bugs...


Tino - Di 09.07.02 17:31

Du wirst nicht schlau daraus? Was verstehst Du denn nicht?

Das Problem das Du hast ist doch jetzt das beim Klick auf ein tImage das OnClick-Event aufgerufen wirst und Du nun die die X und Y Koordinaten des Image im Array benötigst, oder?

Nimm einfach mein Code von oben und mach es genau so. Du gehst Reihe für Reihe im Array die Element ab und schaust nach ob das entspr. Image das ist welches angeklickt wurde.

So würde ich die Funktion definieren:

Quelltext
1:
2:
3:
4:
5:
Funktion GetImageXY (aImage: tImage; Var X,Y: Integer): Boolean;
Begin
  { hier der Code der das Image im Array sucht und bei
    Erfolg die X und Y Werte zurück gibt! }
End;

Deine OnClick-Methode könnte dann so aussehen:

Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TForm1.vImageClick(Sender: TObject);
Var
  X, Y: Integer;
begin
  If GetImage (tImage (Sender), X, Y) Then
    MessageDlg('Height: ' + vMap[X,Y].height, mtInformation, [mbOk], 0);    
end;

Gruß


Gosa - Mi 10.07.02 01:31

Also was ich daran nicht verstehe ist dieses Resault := nil; und dann bei dem was du noch geschrieben hast da verstehe ich nicht wie ich die X und Y werte bekommen kann wenn die funktion mir ein boolean wert zurückgibt.

Aber das wie ich das machen soll hab ich verstanden und auch hinbekommen. Ich brauche dafür aber zwei funktionen.

Die Variablen sind etwas anders jetzt und ich benutze immoment statt images labels damit ich nicht soviel malen muss.



Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
procedure TForm1.vImageClick(Sender: TObject);
var IdX, IdY : integer;
    X, Y: Integer;
begin
  IdX := GetLabelX(tLabel (Sender), X, Y);
  IdY := GetLabelY(tLabel (Sender), X, Y);
  MessageDlg('Height: ' + inttostr(vMap[IdX,IdY].height), mtInformation, [mbOk], 0);
end;

Function GetLabelX(aLabel : tLabel; X,Y :integer): integer;
var IdX, IdY : integer;
Begin
  For IdY := 1 To cShownMapMaxLengthX Do
    For IdX := 1 To cShownMapMaxLengthY Do
      If vlabel[IdX, IdY] = aLabel Then
        Begin
          Result := IdX;
          Exit;
        end;
end;

Function GetLabelY(aLabel : tLabel; X,Y :integer): integer;
var IdX, IdY : integer;
Begin
  For IdY := 1 To cShownMapMaxLengthX Do
    For IdX := 1 To cShownMapMaxLengthY Do
      If vlabel[IdX, IdY] = aLabel Then
        Begin
          Result := IdY;
          Exit;
        end;
end;


Das geht so... Trozdem würde ich das gern in eine funktion bringen aber ich weis nicht wie ich das machen kann das eine funktion zwei werte zurückgibt...

Aber das ist wohl das nil das ich nicht verstehe.

Vielen Dank für die ganze Hilfe Tino!!!


Tino - Mi 10.07.02 02:59

Hi,

eine Funktion kann nur einen Wert zurückliefern.
Function Test: Integerliefert Dir einen Integer Wert zurück. Wenn man z. B. mehrer Werte zurück haben möchte dann gibt es 2 Möglichkeiten:

  1. Man definiert einen Record in dem die Werte definiert sind:

    Quelltext
    1:
    2:
    3:
    4:
    5:
    6:
    7:
    Type
      tMyValue = Record
          Value1,
          Value2: Integer;
        End;

    Function Test: tMyValue;

  2. oder man definiert Variablen-Parameter. Diese Parameter werden wie andere Parameter definiert zusätzlich mit der Angabe VAR:
    Procedure Test (Var Value1, Value2: Integer);Such mal in der Delphi-Hilfe nach Variblen-Parameter. Dann sollte der Unterschied eingentlich klar sein :-D

Hier nun die Funktion:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
Procedure GetLabel(aLabel : tLabel; X,Y :integer);
var IdX, IdY : integer;
Begin
 For IdY := 1 To cShownMapMaxLengthX Do
  For IdX := 1 To cShownMapMaxLengthY Do
   If vlabel[IdX, IdY] = aLabel Then
    Begin
     x := idx;
     y := idy;
     Exit;
    end;

  x := 0;
  y := 0;
end;

procedure TForm1.vImageClick(Sender: TObject);
var 
  X, Y: Integer;
begin
  GetLabelX (tLabel (Sender), X, Y);
  MessageDlg (
      'Height: ' + IntToStr(vMap[X,Y].height), 
      mtInformation, [mbOk], 0
    );
end;


Gruß


Gosa - Mi 10.07.02 04:08

Danke!!! funktioniert

Hab aber schon wieder Frage.

Wie kann ich einem Image ein Bild von einer ImageListe zuweisen?

Image1.picture := ImageList.picture(index);

So wäre das schön geht aber nicht und die Hilfe ist mir da auch leider nicht wirklich hilfreich.


Tino - Mi 10.07.02 11:13

Die ImageList hat eine Mehtode GetBitmap!

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Var
  Bmp: tBitmap;
Begin
  Bmp := tBitmap.Create;
  ImageList.GetBitmap (1, Bmp);
  Image1.Picture.Bitmap.Assign (Bmp);
  Bmp.Free;
End;

Gruß
TINO


Gosa - Mi 10.07.02 15:59

Vielen Dank Tino! Es funktioniert jetzt alles!