Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Timer einmalig sofort auslösen. (https://www.delphipraxis.net/169634-timer-einmalig-sofort-ausloesen.html)

xDIMAx 1. Aug 2012 19:55

Delphi-Version: 7

Timer einmalig sofort auslösen.
 
Guten Tag, ich würde gerne, wie im Titel beschrieben, einen Timer einmalig sofort auslösen und dann wieder in den Normalzustand versetzen, ohne, dass es zu Dopplungen oder Ähnlichem kommt.

Um diesen Teil des Programms zu erklären:
Man hat einen Shape, der per Timer zufällig versetzt wird. Innerhalb des Intervalls muss der Shape berührt werden, damit "das Spiel" nicht vorbei ist. Wenn man sich verklickt endet das Spiel ohne, dass man den Shape noch klicken kann. Ich will nun verhindern, dass nachdem man entweder erfolgreich war, oder Game Over ist, direkt der nächste Schritt folgt. Also die Versetzung des Shapes, wenn man den Shape geklickt hat, oder der Punktescreen, wenn man verliert, weil entweder der Intervall abegelaufen ist und man nichts geklickt hat, oder sich verklickt hat.


Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
begin
  H:=1; //Zufällige Variable, um dem Timer anzuzeigen, ob die Form angeklickt wurde.
  Timer1.Interval:=1;
end;  

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  G:=0; //Zufällige Variable, um dem Timer anzuzeigen, ob der Shape angeklickt wurde.
  Timer1.Interval:=1;
end;  

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Form1.Timer1.Interval:=TI; //TI ist der ursprüngliche Timerintervall. //////////XXXXX//////////
  if (G=0) and (H=0) then
    begin                                              //Soll passieren, wenn der Shape innerhalb des Intervalls angeklickt wurde.
      G:=1;                                            //G:=1; Sorgt dafür, dass man den Shape anklicken muss, um den Then-Befehl auszuführen.
      H:=0;                                          
      Shape1.Left:=trunc(random*(Form1.Width-64))+16;
      Shape1.Top:=trunc(random*(Form1.Height-64))+64;
    end
  else
    begin
      Button1Click(Self); //Soll passieren, wenn entweder die Form oder gar nichts innerhalb des Intervalls angeklickt wurde.
    end;
end;
Das Problem ist nun, dass wenn ich den Timerintervall zurücksetzte (siehe Quellcode://///XXXXX/////), der ganze Then-Befehl nicht ausgeführt wird, wodurch der Ablauf des Intervalls keine Auswirkung mehr hat und man nur weiterkommt, indem man richtig klickt oder sich verklickt.
Also im Grunde funktioniert das Verlieren, durch Ablauf der Zeit nicht mehr.
Ich hoffe mein Problem irgendwie kenntlich machen oder mich viel zu wiederholen, hehe.


P.S. Für zukünftige Threads: Kann man den Titel des Threads noch verändern? Wenn ich ihn mir jetzt nochmal durchlese, kommt er mir ein bisschen komisch vor.

jfheins 1. Aug 2012 20:48

AW: Timer einmalig sofort auslösen.
 
Hallo erstmal :)

Zitat:

Zitat von xDIMAx (Beitrag 1176616)
P.S. Für zukünftige Threads: Kann man den Titel des Threads noch verändern? Wenn ich ihn mir jetzt nochmal durchlese, kommt er mir ein bisschen komisch vor.

Ja. Klicke auf bearbeiten und dann auf erweiterter Editor.

Zu deinem Problem: Ich würde das wie folgt lösen:
Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
begin
   H:=1; //Zufällige Variable, um dem Timer anzuzeigen, ob die Form angeklickt wurde.
   Timer1Timer(Sender);
end;

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
   Shift: TShiftState; X, Y: Integer);
begin
   G:=0; //Zufällige Variable, um dem Timer anzuzeigen, ob der Shape angeklickt wurde.
   Timer1Timer(Sender);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
   if (G=0) and (H=0) then
   begin //Soll passieren, wenn der Shape innerhalb des Intervalls angeklickt wurde.
      G:=1; //G:=1; Sorgt dafür, dass man den Shape anklicken muss, um den Then-Befehl auszuführen.
      H:=0;
      Shape1.Left:=trunc(random*(Form1.Width-64))+16;
      Shape1.Top:=trunc(random*(Form1.Height-64))+64;
   end
   else
   begin
      Button1Click(Self); //Soll passieren, wenn entweder die Form oder gar nichts innerhalb des Intervalls angeklickt wurde.
   end;
end;
Du hast ja schon am Ende der Timer1Timer Methode die Button1Click Methode aufgerufen. Auf die gleiche Weise lässt sich die Timer1Timer Methode aufrufen ohne dass der Timer tatsächlich ausgelöst hat.

Ach, und tu dir selbst einen Gefallen und benenne deine Variablen richtig. D.h. insbesondere keine globalen Variablen mit einem Buchstaben.

himitsu 1. Aug 2012 21:23

AW: Timer einmalig sofort auslösen.
 
Delphi-Quellcode:
Timer1Timer(nil);
und dann
Delphi-Quellcode:
if not Assigned(Sender) then
oder
Delphi-Quellcode:
if Sender = nil then
um zu prüfen, ob es "manuell" ausgelöst wurde.

Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
begin
  Button1Click(nil);
  // Aber wenn hier sowieso sonst nichts passiert, dann bei "OnClick" direkt das "Button1Click" angeben
end;
Aber ganz im Ernst, warum willst du auf Zwang zwei verschiedene Ereignisse dort einbauen, welche mit dem Timer eigentlich nichts zu tun haben?

Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
begin
  // verfehlt ... machwas, wenn danebengecklickt wird
  Timer1Timer(nil);
end;

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  // getroffen ... machwas, wenn es erwischt wurde
  ...
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  // Zeit abgelaufen (oder danabengeklickt) ... mach was, wenn es nicht erwischt wurde
  // über Assigned(Sender) kannst du unterscheiden, ob Zeit oder Klick
  ...
end;
Und dazu noch eine eigene "Verschiebe"-Prozedur, welche das Shape verschiebt und die von den Timer- und Klickereignissen aufgerufen wird.

xDIMAx 2. Aug 2012 07:31

AW: Timer einmalig sofort auslösen.
 
Also bei der, von jfheins genannten, Lösung kommt es scheinbar zu der von mir angesprochenen Dopplung, bei der der Timer einmal manuell und kurz darauf nochmal durch den Intervall ausgelöst wird.

Und bei der, von himitsu genannten, blick ich nicht wirklich durch: :(

Der Vorschlag funktioniert gut:
Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
begin
  // verfehlt ... machwas, wenn danebengecklickt wird
  Timer1Timer(nil);
end;
Aber deine erste Zeile verstehe ich nicht so wirklich.
Delphi-Quellcode:
Timer1Timer(nil);
und dann
Delphi-Quellcode:
if not Assigned(Sender) then
oder
Delphi-Quellcode:
if Sender = nil then
um zu prüfen, ob es "manuell" ausgelöst wurde.

Ich denke in der geht es genau um mein Problem, aber bin in Delphi noch Anfänger.
Ich probiere erst einmal ein bisschen rum und gucke ob ich nicht irgendwie dahinterkomme. ^^

EDIT: Also ich habe wirklich keine Ahnung. Alles, was ich versuche führt zu mehr Problemen. Man kann unabhängig von Start/Stop, das Spiel verlieren, gewinnen, alles anklicken. Ich weiß wirklich nicht weiter. :(

EDIT2:

Also ich habe es nun Folgendermaßen gemacht:

Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
begin
  H:=1;
  Timer1Timer(nil);
end;

procedure TForm1.Shape1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  G:=0;
  Timer1Timer(nil);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if F=1 then //Eine weitere Random-Variable. ^^ Sorry, ich ersetze die später.
    begin
      F:=0;
      Exit;
    end;
  if Sender=nil then
    begin
      F:=1;
    end;
  if (G=0) and (H=0) then
    begin
      G:=1;
      H:=0;
      Shape1.Left:=trunc(random*(Form1.Width-64))+16;
      Shape1.Top:=trunc(random*(Form1.Height-64))+64;
    end
  else
    begin
      Button1Click(Self);
    end;
end;
Es funktioniert.... Danke.

Wenn ihr eine Idee habt, wie ich das besser hinkriegen könnte, könnt ihr weiter Vorschläge machen. ^^

GHorn 2. Aug 2012 09:08

AW: Timer einmalig sofort auslösen.
 
Hallo,

welchen Interval-Wert hast du eingestellt? Wenn der größer als Null ist, tobt der Timer irgendwann von sich aus los.

Ich habe innerhalb des OnTimer-Events immer den Timer zunächst disabled und am Schluß enabled. Dann gibt's keine Überschneidungen.

Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  try
    //
    // Hier die Timer-Aktionen ...
    //
  finally
    Timer1.Enabled := True;
  end;
end;
Edit: Das Ganze noch in den try..finally Block gepackt, damit der
Timer in jedem Falle wieder aktiviert wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:13 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz