Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Problem mit Timer -> Bewegung (wiederholen)


Waldkauz - Di 23.06.09 18:37
Titel: Problem mit Timer -> Bewegung (wiederholen)
Hallo

Ich wusste leider nicht, wie ich den Threadtitel sonst formulieren soll, tut mir leid, wenn er nicht sehr aussagekräftig ist.
Also, wenn die Kollisionsbedingung der Funktion erfüllt ist, dann soll sich ein Bild (Image2) vom oberen Bildrand zum unteren bewegen.
Es funktioniert aber leider nicht.
Wo ist das problem?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
if CheckCollision(Image1.Boundsrect,Shape1.Boundsrect) = true then
  begin
      Image2.Visible:=true;
      zaehler:=zaehler+1;
      Timer1.Enabled:=true;
  end

procedure TForm2.Timer1Timer(Sender: TObject);
var g:integer;
begin
randomize;
g:=random(4)+1;  //das Image soll sich mit einer zufälligen Geschwindigkeit bewegen
Image2.Top:=Image2.Top+g;
if Image2.Top >= (Panel1.Height-Image2.Height) then {wenn Image2 am unteren  Ende angelangt ist, soll es wieder vom oberen Rand starten}
          begin
            Image2.Top:=Panel1.Top;
          end;

end;


jaenicke - Di 23.06.09 18:53

user profile iconWaldkauz hat folgendes geschrieben Zum zitierten Posting springen:
Es funktioniert aber leider nicht.
Was passiert denn (nicht)?
1. Wo setzt du initial beim Einschalten des Timers Top des Images?
2. Liegt das Image auf dem Panel? Wenn ja, legst du mit Image2.Top := Panel1.Top; das Image evtl. außerhalb des sichtbaren Bereichs, da der obere Rand dann 0 wäre. (Denn dann beziehen sich die Koordinaten ja auf die linke obere Ecke des Panels.)

user profile iconWaldkauz hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
procedure TForm2.Timer1Timer(Sender: TObject);
var g:integer;
begin
randomize;
Randomize sollte nur einmal beim Start des Programms oder so aufgerufen werden um gute Zufallszahlen zu erhalten. Wenn du es im Timer aufrufst, lässt du den Prozessor nur unnötig mehr arbeiten. ;-)

Und richtige Namen für die Komponenten wären nebenbei auch eine gute Idee.


Waldkauz - Di 23.06.09 18:55

Das Problem ist, dass sich Image2 überhaupt nicht bewegt.
Ich setze am Anfang Image2 auf Panel1.Top (ist 0, aber falls ich das Panel doch mal verschieben möchte, muss ich nichts mehr ändern).


jaenicke - Di 23.06.09 19:02

user profile iconWaldkauz hat folgendes geschrieben Zum zitierten Posting springen:
ist 0, aber falls ich das Panel doch mal verschieben möchte, muss ich nichts mehr ändern
Sollte das Image auf dem Panel liegen, machst du es damit erst falsch, wie gesagt.
Wenn es neben dem Panel liegt, ist das natürlich korrekt.

Hast du denn einmal einen Haltepunkt gesetzt, ob die Kollision überhaupt gefunden wird? Und dann auf den Timer und geschaut, ob Top verändert wird?

Nebenbei fällt mir auf:
user profile iconWaldkauz hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
if CheckCollision(Image1.Boundsrect,Shape1.Boundsrect) = true then                    
Der Vergleich mit Booleanwerten (z.B. if x = true then) ist nicht nur unschön und unlogisch, sondern falsch.
Hier habe ich mal ein kleines Beispiel gebastelt, wann es schief geht:
http://www.delphi-forum.de/viewtopic.php?p=548760#548760
Mehr dazu steht hier:
http://www.delphi-treff.de/tutorials/objectpascal/programmierung-mit-boolean-werten/page/4/
Und warum das auch vollkommen unlogisch ist:
http://www.delphi-forum.de/viewtopic.php?p=560637#560637


Waldkauz - Di 23.06.09 19:11

okay, das mit dem Boolean habe ich verstanden.
Aber wie ist das mit dem Haltepunkt gemeint?


jaenicke - Di 23.06.09 19:14

Zum Debugger und Haltepunkten:
http://www.delphi-treff.de/delphi-ide/debugger/

Und als Demo, dass der Code so funktioniert, siehe Anhang. Das ist nur der selbe Quelltext, nur halt natürlich ordentlicher geschrieben.


Waldkauz - Di 23.06.09 20:29

Mein Programm ist ja so eine Art Arkanoid-Spiel.
D.h. der Ball (shape1) bewegt sich ständig mithilfe einer Sleep schleife.

Nun habe ich folgenden Quelltext:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
 if CheckCollision(Image1.Boundsrect,Shape1.Boundsrect)  then
  begin
      Image2.Visible:=true;
      zaehler:=zaehler+1;
      Timer1.Enabled:=true;
      break;
  end;

Das Problem ist jetzt, dass sich Image2 zwar bei einer Kollision zu bewegen beginnt, aber dafür der ball und alles andere was in der repeat until (Spielabbruchbedingung) - Schleife steht, stehen bleibt.

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

So, ich lade jetzt einfach mal die Datei hoch.
Vielleicht findet jemand das Problem.
Wundert euch bitte nicht über eventuelle unbenützte Variable, die hab ich schonmal für weitere Funktionen bereitgestellt.

Man muss das grüne Quadrat treffen. Dann "fällt" aus dem getroffenen Qudrat ein weiteres Image. Normalerweise sollte aber beim Treffen des grünen Quadrates der Ball weiterfliegen, und nicht stehenbleiben.


jaenicke - Di 23.06.09 20:35

Also sobald der Timer ausgelöst wurde, fallen die beiden gelben Rechtecke bei mir herunter immer wieder. :nixweiss:

// EDIT:
Zu deinem Edit: Ja, du springst doch mit Break aus deiner repeat Schleife heraus, wieso erwartest du also, dass diese weiterläuft? ;-)
Was dir vermutlich fehlt ist Application.ProcessMessages zu verwenden statt aus der Schleife zu springen.

Aber dein Konzept ist ungünstig. Entweder du machst das ereignisorientiert via Timer oder du machst eine dauerhafte Schleife. Aber beides zu kombinieren...


Waldkauz - Di 23.06.09 20:45

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Also sobald der Timer ausgelöst wurde, fallen die beiden gelben Rechtecke bei mir herunter immer wieder. :nixweiss:

// EDIT:
Zu deinem Edit: Ja, du springst doch mit Break aus deiner repeat Schleife heraus, wieso erwartest du also, dass diese weiterläuft? ;-)
Was dir vermutlich fehlt ist Application.ProcessMessages zu verwenden statt aus der Schleife zu springen.

Aber dein Konzept ist ungünstig. Entweder du machst das ereignisorientiert via Timer oder du machst eine dauerhafte Schleife. Aber beides zu kombinieren...


ja, das Application.ProcessMessages hat gefehlt (jetzt funktionierts).
Dass die beiden Rechtecke immer wieder runterfallen, gehört so (zumindest beim "Prototyp").
Ich muss es leider so machen, da die repeat until mit sleep - Schleife von meinem Lehrer vorgegeben wurde...