Array mit 2 Datentypen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
setblockmaster
Beiträge: 6
Registriert: Di 15. Dez 2020, 19:00

Array mit 2 Datentypen

Beitrag von setblockmaster »

Guten Tag liebe Mitglieder,
ich möchte ein kleines Spiel in Lazarus nachbauen. Dazu benötige ich eine größere Anzahl Bilder, welche auf dem Bildschirm auftauchen. Diese Bilder erstelle ich mit:

Code: Alles auswählen

var Chicks : array[0..5] of TImage;
 ...
var i : Integer;
begin
   for i := 0 to 5 do 
      begin
         Chicks[i] := TImage.Create(Nil);
         Chicks[i].Parent := Form1;
         Chicks[i].[...]
      end;
end;
(nicht fragen, warum das Chicks heißt)

Das funktioniert auch soweit. Mithilfe einer Sinusfunktion sollen sich diese Bilder nun über den Bildschirm bewegen. Die Parameter möchte werden dann zufällig erstellt und sollen am Besten zu jedem Bild gespeichert werden. Das sind 4 Parameter und 2 Standortinformationen. Diese werden alle als Doubles gespeichtert.
Nun gibt es natürlich das Problem, dass ein Array ja nur einen Datentypen halten kann. Ist es dennoch irgendwie möglich, dass ich Doubles zu jedem Image abspeichern kann?
Es soll quasi so "aussehen":

Code: Alles auswählen

   |Img1|Img2|Img3|Img4| (alle vom Typ TImage)
a: | 3  | 7  | ...       (alle vom Typ Double)
b: |0.1 |0,5 | ...
c: ...
d: ...
Ich hoffe, dass es irgendwie verständlich ist, was ich meine und dass jemand von euch mir helfen kann.
Ein schönes Wochenende!

Mit freundlichen Grüßen
Lucas

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Array mit 2 Datentypen

Beitrag von six1 »

Erstell dir doch erst mal einen Type.

Code: Alles auswählen

type TChicks  = record
     Chicks : TImage;
     Chicks_left:double;
     Chicks_top:double;
end;     
Dann definierst du ein Array mit dem Type:

My_Chicks: array of TChicks ;


Später kannst du dann die Größe festlegen mit:
setlength(My_Chicks, 5);

Image createn und free-en nicht vergessen...

Wenn du magst, kannst du mal hier reinschauen: viewtopic.php?f=11&t=13468
Ich habe da ausgiebig Gebrauch von Types gemacht.
Gruß, Michael

setblockmaster
Beiträge: 6
Registriert: Di 15. Dez 2020, 19:00

Re: Array mit 2 Datentypen

Beitrag von setblockmaster »

Danke für die Hilfe!
Ich habe damit jetzt begonnen. Allerdings kommt nun ein SIGSEGV Fehler. Vielleicht kannst du mir helfen. Mein Code dazu sieht nun so aus:

Code: Alles auswählen

type
  TChicks = record
    Chicks : TImage;
    Chicks_x : Double;
    Chicks_y : Double;
    a,b,c,d : Double;
  end;
  
...

var MyChicks : array of TChicks;

...

procedure TForm1.Button3Click(Sender: TObject);   //Startknopf
var i : Integer;
  randA,randB,randD,randX : Double;
begin
  SetLength(MyChicks, 5);
  for i := 0 to 5 do
  begin
    MyChicks[i].Chicks := TImage.Create(Nil);
    MyChicks[i].Chicks.Parent := Form1;
    MyChicks[i].Chicks.Name := 'chicken' + IntToStr(i);
    MyChicks[i].Chicks.Picture.LoadFromFile('chicken.png');
    MyChicks[i].Chicks.Stretch := true;

    randA := Random(10) / 10;
    randB := Random(10) / 100;
    randD := Random(500);
    randX := Random(1280);

    MyChicks[i].a := randA;        //Info: Wenn ich diese Zeile auskommentiere, dann kommt der Fehler nicht.
    MyChicks[i].b := randB;
    MyChicks[i].c := 1;
    MyChicks[i].d := randD;
    MyChicks[i].Chicks_x := randX;

  end;
end;
Kannst du mir sagen, was mein Fehler ist?

Mit freundlichen Grüßen
Lucas

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Array mit 2 Datentypen

Beitrag von wp_xyz »

Wenn du mit SetLength(MyChicks, 5) das Array for 5 Elemente vorbereitest, kann der Index nur von 0 bis 4 laufen (dynamische Arrays beginnen immer mit 0: Index 0, 1, 2, 3, 4 = 5 Elemente). Bei dir geht die for-Schleife aber bis 5.

setblockmaster
Beiträge: 6
Registriert: Di 15. Dez 2020, 19:00

Re: Array mit 2 Datentypen

Beitrag von setblockmaster »

Ach bin ich lost. Danke

setblockmaster
Beiträge: 6
Registriert: Di 15. Dez 2020, 19:00

Re: Array mit 2 Datentypen

Beitrag von setblockmaster »

Einen schönen Sonntag,
six1 hat geschrieben:
Sa 8. Mai 2021, 12:40
Image createn und free-en nicht vergessen...
Bisher funktioniert alles so, wie ich es möchte. Die Images fliegen übers Bild, wenn ich auf Start drücke. Nun habe ich zu jedem Image eine Prozedur für das Ereignis OnClick zugewiesen mit:

Code: Alles auswählen

MyChicks[i].Chicks.OnClick := @ChickClick;
Nun möchte ich, dass das Bild verschwindet, wenn ich es anklicke, da ich es nicht mehr brauche. Ich habe darüber nachgedacht, dass man es freigeben könnte. Nur wie mache ich das? Kann man da mit dem Sender arbeiten?

Code: Alles auswählen

procedure TForm1.ChickClick(Sender: TObject);
Sollte das nicht gehen oder sinnlos sein, dann würde ich einfach mit der Eigenschaft visible arbeiten.

Habt Alle einen wunderschönen sonnigen Sonntag!

Benutzeravatar
kupferstecher
Beiträge: 418
Registriert: Do 17. Nov 2016, 11:52

Re: Array mit 2 Datentypen

Beitrag von kupferstecher »

Freeen geht über den Sender:

Code: Alles auswählen

procedure TForm1.ChickClick(Sender: TObject);
begin
  Sender.Free;
end;
Aber! Dann hast du in deinem Array noch einen Eintrag TChick, das kein TImage mehr hat und dabei noch auf die alte Adresse zeigt. Der nächste Crash ist damit vorprogrammiert.

Du könntest das Image auf 'nil' setzen, dann kannst du später abprüfen, ob das Image noch existiert:

Code: Alles auswählen

MyChicks[i].Chicks:= nil;
Das geht aber nicht direkt über den 'Sender', du bräuchtest den Index des Chicks. Was eine gute Lösung dafür ist, hängt von den Umständen ab.

EDIT: Mit Visible zu arbeiten kann in dem Fall eine Lösung sein, das kannst du dann nämlich auch später wieder abfragen.

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Array mit 2 Datentypen

Beitrag von six1 »

(Sender as TImage).visible:=false;
Gruß, Michael

siro
Beiträge: 730
Registriert: Di 23. Aug 2016, 14:25
OS, Lazarus, FPC: Windows 11
CPU-Target: 64Bit
Wohnort: Berlin

Re: Array mit 2 Datentypen

Beitrag von siro »

ich schreib das immer so rum:
TImage(Sender).visible:=false;
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Array mit 2 Datentypen

Beitrag von six1 »

...tja, wenn man sich mal etwas angewöhnt hat :D

wenn der Sender kein TImage ist, knallt es an der selben Stelle :lol:
Gruß, Michael

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Array mit 2 Datentypen

Beitrag von Socke »

six1 hat geschrieben:
Mo 10. Mai 2021, 11:36
wenn der Sender kein TImage ist, knallt es an der selben Stelle :lol:
Der as Operator wirft im Fehlerfall eine Ausnahme. Damit es dann nicht knallt, braucht es schon eine passende Fehlerbehandlung.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Array mit 2 Datentypen

Beitrag von six1 »

:D

Code: Alles auswählen

if (Sender is TImage) then
  (Sender as TImage).visible:=false;
jetzt ist es ordentlich
Gruß, Michael

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Array mit 2 Datentypen

Beitrag von wp_xyz »

six1 hat geschrieben:
Mo 10. Mai 2021, 11:47
:D

Code: Alles auswählen

if (Sender is TImage) then
  (Sender as TImage).visible:=false;
jetzt ist es ordentlich
(Sender as TImage) wiederholt die Prüfung, die (Sender is TImage) schon gemacht hat, du kannst gleich den Type-Cast machen:

Code: Alles auswählen

 if (Sender is TImage) then
   TImage(Sender).Visible := false; 
Denselben Code wende ich selbst auch immer wieder an. Allerdings muss ich selbstkritisch sagen, dass das eigentlich zu übervorsichtig ist und Fehler verschleiert. Wenn du sicher bist, dass Sender nur ein TImage sein kann, solltest du es drauf ankommen lassen und auf die "if"-Abfrage verzichten und direkt "as" verwenden -- denn das wirft eine Exception und zeigt an, dass etwas faul ist. Mit der "if" Abfrage dagegen wirst du auf den Fehler nicht hingewiesen und er tritt vielleicht anderwo, an viel schwieriger zu findender Stelle auf.

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Array mit 2 Datentypen

Beitrag von Socke »

wp_xyz hat geschrieben:
Mo 10. Mai 2021, 12:02
Denselben Code wende ich selbst auch immer wieder an. Allerdings muss ich selbstkritisch sagen, dass das eigentlich zu übervorsichtig ist und Fehler verschleiert. Wenn du sicher bist, dass Sender nur ein TImage sein kann, solltest du es drauf ankommen lassen und auf die "if"-Abfrage verzichten und direkt "as" verwenden -- denn das wirft eine Exception und zeigt an, dass etwas faul ist. Mit der "if" Abfrage dagegen wirst du auf den Fehler nicht hingewiesen und er tritt vielleicht anderwo, an viel schwieriger zu findender Stelle auf.
Hier kann man in Tests mit Assertions arbeiten. Diese werden nur in das Programm übersetzt, wenn der Compilerschalter -Sa gesetzt ist.
Den Typecast kann man dann auch noch ganz elegant verstecken:

Code: Alles auswählen

procedure TForm1.ChickClick(Sender: TObject);
var
  Chick: TImage absolute Sender;
begin
  Assert(Sender is TImage, 'Unexpected Sender class.');
  
  Chick.Visible := False;
end;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Antworten