tutorials.de Buch-Aktion 02/2012
ERLEDIGT
JA
ANTWORTEN
14
ZUGRIFFE
3067
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    HarryXVI HarryXVI ist offline Mitglied Gold
    Registriert seit
    Apr 2008
    Beiträge
    108
    Ich möchte einen Timer TiBewegung initialisieren
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    TMonster = class(TSprite)
      private
        TiBewegung: TTimer;
        procedure BewegungsTimer(Sender: TObject);
    .....
    procedure TMonster.init_BewegungsTimer;
    begin
    TiBewegung := TTimer.Create(nil);
    TiBewegung.Enabled := false;
    TiBewegung.OnTimer := self.BewegungsTimer;
    TiBewegung.Interval := 1000;
    end;

    Wenn ich den Timer vom Hauptformular "Karte" anmachen lasse
    Code :
    1
    2
    3
    4
    
    procedure TKarte.init_Monster(Monster: TMonster);
    ...
    Monster.init_BewegungsTimer;
    Monster.TiBewegung.Enabled := true;
    passiert nicht das, was in der Prozedur BewegungsTimer vereinbart wurde, sondern gar nix.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    procedure TMonster.BewegungsTimer(Sender: TObject);
    var z: integer;
    begin
    z := random(3);
    if zufall[z] = 1 then Left(100);                 //Left, Right, Up, Down sind geerbte Methoden des Typs TSprite.
    if zufall[z] = 2 then Right(100);
    if zufall[z] = 3 then Up(100);
    if zufall[z] = 4 then Down(100);
    end;


    Habe ich vielleicht mit dem AOwner was falsch gemacht, dass der doch nicht nil ist?
    Ich habe auf jeden Fall die zeitliche Reihenfolge beachtet: BewegungsTimer, init_BewegungsTimer, init_Monster
    Geändert von HarryXVI (09.04.09 um 17:51 Uhr)
     

  2. #2
    HarryXVI HarryXVI ist offline Mitglied Gold
    Registriert seit
    Apr 2008
    Beiträge
    108
    Das Problem hat sich erledigt.
     

  3. #3
    vop vop ist offline Mitglied Platin
    Registriert seit
    Mar 2004
    Beiträge
    676
    Das Problem hat sich erledigt.
    Wenn Du uns verrätst, wie, dann kann vielleicht noch jemand etwas daraus lernen.
    vop
     

  4. #4
    HarryXVI HarryXVI ist offline Mitglied Gold
    Registriert seit
    Apr 2008
    Beiträge
    108
    Code :
    1
    
    procedure TMonster.MAngriffsTimer(Sender: TObject);
    Das is die Ereignismethode des Timers.
    Direkt danach folgt die Prozedur, die den Timer erstellt.

    Code :
    1
    2
    3
    4
    5
    6
    7
    
    procedure TMonster.init_MAngriffsTimer;
    begin
    TiMAngriff := TTimer.Create(nil);
    TiMAngriff.Enabled := false;
    TiMAngriff.OnTimer := self.MAngriffsTimer;
    TiMAngriff.Interval := 1000;
    end;
    Ich weiß nicht warum, aber man kann die Ereignismethode dem OnTimer-Ereignis zuweisen, ohne einen Sender angeben zu müssen.

    Nachher kann man dann den Timer aktivieren und es funktioniert.
    Code :
    1
    
    Dander.TiMAngriff.Enabled := true;
    Dander ist vom Typ TMonster.
     

  5. #5
    Registriert seit
    Mar 2004
    Beiträge
    441
    Zitat Zitat von HarryXVI Beitrag anzeigen
    Code :
    1
    
    TiMAngriff.OnTimer := self.MAngriffsTimer;
    Ich weiß nicht warum, aber man kann die Ereignismethode dem OnTimer-Ereignis zuweisen, ohne einen Sender angeben zu müssen.
    Das liegt daran, daß du oben nicht die Methode OnTimer oder MAngriffsTimer aufrufst (dann würdest du tatsächlich den Sender benötigen). Es findet eine Zuordnung statt. Tatsächlich ist das OnTimer-"Ding" an sich ein Zeiger auf eine Speicheradresse, üblicherweise die Adresse, an der dann der auszuführende Code von OnTimer steht. Selbiges gilt für das MAngriffTimer-"Ding".
    Durch die obige Zuweisung sagst du deinem Programm quasi "wenn jetzt OnTimer stattfindet, dann mache mit der Programmausführung nicht bei OnTimer weiter sondern bei MAngriffsTimer".
    Das OnTimer-Ereignis selbst tritt dann automatisch ein (durch Aktivieren des Timer-Objekts) und dadurch kommt dann der MAngriffsTimer-Code zur Ausführung.
     

  6. #6
    HarryXVI HarryXVI ist offline Mitglied Gold
    Registriert seit
    Apr 2008
    Beiträge
    108
    weitere Frage zu Timern: Ich möchte programmieren, dass eine bestimmte Zeit, nachdem ich den Timer aktiviert habe, eine Prozedur aufgerufen wird und der Timer danach sofort deaktivert wird.

    Bsp: Eine Grafik verschwindet mit Destroy, 3 Sekunden später lädt Timer1 eine neue und schaltet sich selbst aus.

    Letzteres könnte mit Timer1.Enabled := false in der OnTimer-Methode realisiert werden. Aber wie funktioniert das andere?
     

  7. #7
    Registriert seit
    Mar 2004
    Beiträge
    441
    Zitat Zitat von HarryXVI Beitrag anzeigen
    Letzteres könnte mit Timer1.Enabled := false in der OnTimer-Methode realisiert werden. Aber wie funktioniert das andere?
    Genauso in der OnTimer-Methode, würde ich sagen. Entweder durch Methodenaufruf oder du schreibst den Code direkt in die Timermethode. Oder wie meinst du das?
     

  8. #8
    HarryXVI HarryXVI ist offline Mitglied Gold
    Registriert seit
    Apr 2008
    Beiträge
    108
    das ist nicht das Problem, damit komme ich zurecht und werde sehen, welche die bessere alternative ist.
    Nein, mir geht es darum:
    Zitat Zitat von HarryXVI
    eine bestimmte Zeit, nachdem ich den Timer aktiviert habe, eine Prozedur aufgerufen wird
    Wenn ich Timer1.Enabled := true setze, wird ja sofort das OnTimer-Ereignis ausgelöst. Wie kann ich dies um ein bestimmtes Zeitintervall verzögern?
     

  9. #9
    vop vop ist offline Mitglied Platin
    Registriert seit
    Mar 2004
    Beiträge
    676
    Du könntest einen weiterern Timer einsetzen, der nach 3 Sekunden feuert und von dem anderen Timer aktiviert wird.
     

  10. #10
    Registriert seit
    Mar 2004
    Beiträge
    441
    Zitat Zitat von vop Beitrag anzeigen
    Du könntest einen weiterern Timer einsetzen, der nach 3 Sekunden feuert und von dem anderen Timer aktiviert wird.
    So würde ich es wohl auch machen.
    Da ist resourcentechnisch sehr viel Platz, was Timer angeht. Einer (oder ein Dutzend) mehr oder weniger macht da nicht viel aus.
     

  11. #11
    HarryXVI HarryXVI ist offline Mitglied Gold
    Registriert seit
    Apr 2008
    Beiträge
    108
    Ich glaube, ihr versteht mich nicht richtig. Ich habe mal eine Zeitleiste gemalt, wie das Ereignis aussehen soll (siehe Anhang).

    Bei 1 aktiviert eine Methode den Timer. Zwischen 1 und 2 vergehen 10 Sekunden, bis der Timer das ausführt, was unter OnTimer vereinbart wurde. Darin ist seine Selbstabschaltung unter Punkt 3 Enabled := false enthalten. Zwischen 2 und 3 geschieht also das, was in OnTimer steht.

    Könnt ihr mir jetzt folgen? Außerdem, selbst wenn der Vorschlag von vop eine Möglichkeit wäre, wüsste ich nicht, wie ich das realisieren könnte.
    Miniaturansicht angehängter Grafiken Miniaturansicht angehängter Grafiken Timer zur Laufzeit-zeitleiste.bmp  
     

  12. #12
    Registriert seit
    Mar 2004
    Beiträge
    441
    Zitat Zitat von HarryXVI Beitrag anzeigen
    Könnt ihr mir jetzt folgen?
    Ich glaube, jetzt komme ich endlich einigermaßen dahinter, was du willst.
    Wenn ich das richtig verstehe, dann tritt Ereignis 1 nach 10 Sekunden (von Timer1) gesteuert auf.
    Nach Abarbeiten von Ereignis 1 soll 3 Sekunden gewartet werden, bevor Ereignis 1 erneut mit 10 Sekunden Vorlauf angesteuert werden kann, richtig?

    Also die billigste Methode wäre das Verlängern des Intervals von Timer1. Ich habe bisher noch keine Probleme damit gehabt, daß ein Timer direkt aktiviert wurde, aber wenn du sagst, daß das bei dir der Fall ist, dann könntest du Folgendes probieren:

    (Formular Form1 mit zwei Timern Timer1 und Timer2)
    Code :
    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
    33
    34
    35
    
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      // Wenn Timer2 läuft, dann wurde erst vor Kurzem ein Timer1-Ereignis ausgelöst
      // und das Timer1-Ereignis soll nicht erneut ablaufen. Daher wird nur dann
      // die Timer1-Methode ausgeführt, wenn Timer2 deaktiviert ist.
      if Timer2.Enabled = false then
      begin
        // Sicherstellen, daß kein zweites Timer-Ereignis dazwischen funkt
        Timer1.Enabled := false;
     
        // Und weil wir schon dabei sind, gleich den Timer neu initialisieren
        Timer1.Interval := 10 * 1000;
      
        // Ab hier wird dann der Krempel von Timer1 ausgeführt, was auch immer das sein soll
        // ...
     
        // So, Timer1 ist fertig. Jetzt soll die 3 Sekunden Sperrfrist laufen, bevor Timer1 wieder
        // aktiviert werden kann.
     
        // Erstmal Timer2 deaktivieren, damit der nicht quer läuft
        Timer2.Enabled := false;
     
        // Timer2 neu initialisieren
        Timer2.Interval := 3 * 1000;
     
        // Und den Timer laufen lassen. Um das erneute Aktivieren von Timer1 kümmert sich dann Timer2.
        Timer2.Enabled := true;
      end;
    end;
     
    procedure TForm1.Timer2Timer(Sender: TObject);
    begin
      Timer1.Enabled := true;
      Timer2.Enabled := false;
    end;

    Meinstest du so etwas? Leuchtet mir zwar immer noch nicht so recht ein, aber das sollte u.U. das sein, was du haben willst.
    Geändert von CSANecromancer (24.04.09 um 08:42 Uhr)
     

  13. #13
    HarryXVI HarryXVI ist offline Mitglied Gold
    Registriert seit
    Apr 2008
    Beiträge
    108
    Deine Idee war gut und ich habe sie nun so modifiziert, dass es in mein Programm passt. Das erläutere ich kurz (Timer1 heißt TiNeuMonster, Timer2 heißt TiAktiv).

    TiAktiv ist der Aktivator von TiNeuMonster, ist also die ganze Zeit an.
    Code :
    1
    2
    3
    4
    5
    
    procedure TKarte.FormCreate(Sender: TObject);
    begin
    ... TiAktiv.Interval := 1;
    TiAktiv.Enabled := true; ...
    end;

    Code :
    1
    2
    3
    4
    
    procedure TKarte.TiAktivTimer(Sender: TObject);
    begin
    if (Dander = nil) or (Seedle = nil) then TiNeuMonster.Enabled := true;
    end;
    Er prüft jede Millisekunde, ob eines der beiden Objekte leer ist, wenn ja, dann aktiviert er TiNeuMonster, der folgendes macht:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    procedure TKarte.TiNeuMonsterTimer(Sender: TObject);
    begin
    TiAktiv.Enabled := false;       
    TiNeuMonster.Enabled := false;  // keine Wiederholung des Timer-Ereignisses
    TiNeuMonster.Interval := 3000;
    if Dander = nil then begin
      Dander := TMonster.Create;
      init_monster(Dander,'Dander.bmp','Dander.txt');
      end;
    if Seedle = nil then begin
      Seedle := TMonster.Create;
      init_monster(Seedle,'Seedle.bmp','Seedle.txt');
      end;
    Dander.ausgewaehlt := false;
    Seedle.ausgewaehlt := false;
    TiAktiv.Enabled := true;  // Aktivierungstimer wieder anschalten
    end;

    TiNeuMonster schaltet TiAktiv aus, damit der ihn nicht nochmal aktivert. Er macht auch sich selbst aus, damit das OnTimer-Ereignis einmalig bleibt. Nach 3 Sekunden prüft er, welches Objekt leer ist und erstellt ein neues. Dann macht er seinen Aktivator wieder an, um erneut gerufen zu werden, wenn eines der Objekte leer ist.

    Edit: @CSANecromancer: Gut, dass du deine erste Antwort nochmal überarbeitet hast, war nämlich nicht sehr nett...
    Geändert von HarryXVI (26.04.09 um 18:20 Uhr)
     

  14. #14
    Registriert seit
    Mar 2004
    Beiträge
    441
    Edit: @CSANecromancer: Gut, dass du deine erste Antwort nochmal überarbeitet hast, war nämlich nicht sehr nett...
    Ich bin nicht unbedingt für Diplomatie oder Feingefühl bekannt.
    Ich versuche zu helfen, aber wenn einfach zu wenig Infos da sind, dann schreibe ich beim 20. Mal Nachfragen (nicht unbedingt alle im gleichen Thread) auch mal etwas deutlichere und interpretationsfreie Worte. Aber siehst ja: Kann auch sein, daß was Sinnvolles zusammen kommt.
     

  15. #15
    Butt4cak3 Tutorials.de Gastzugang
    Hallo,
    Ich suche jetzt schon seit etwa einer Stunde nach einer Lösung zu meinem Problem und bin letztendlich auf dieses Thema in diesem Forum gestoßen und ich dachte mir ich frage nach, auch wenn das hier schon etwas älter ist.

    Jedenfalls geht es mir darum, dass ich ein kleines Spiel in Delphi baue in dem man den Spieler (einen Kreis) von oben sieht und ihn mit W, A, S und D steuert. Mit der Maus kann man zielen und schießen. Erst habe ich das alles in einer einzigen Unit gemacht und dadurch die Möglichkeit gehabt einen Timer auf der Form zu platzieren.

    Jetzt will ich aber mehr Flexibilität. Das heißt, dass ich mir für den Spieler eine Klasse gebaut habe und jetzt an der für die Waffe sitze. Da diese ja in einem bestimmten Intervall schießen muss brauche ich einen Timer. Diesen habe ich auch schon erstellt, nur bekomme ich es einfach nicht gebacken das mit dem OnTimer-Event zu machen. Egal wo ich nachschaue: Ich versteh es nicht oder das Beispiel funktioniert bei mir nicht.

    Code :
    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
    33
    34
    35
    36
    
    type
      TWeapon = class
      TimerReload, TimerShot : TTimer;
      constructor Create(ShotInterval, ReloadTime : Integer);
      procedure ReloadTimer;
      procedure reload;
      private
        { private declarations }
      public
        { public declarations }
        Damage, Spread : Real;
        Ammo, MaxAmmo : Integer;
      end;
     
    implementation
     
    procedure TWeapon.ReloadTimer;
    begin
      // Hier wird Ammo dann auf MaxAmmo gesetzt
      TimerShot.Enabled := false;
    end;
     
    constructor TWeapon.Create(ShotInterval, ReloadTime : Integer); // Je nachdem wie ich das Spiel testen will ändere ich diese Werte
    begin
      TimerShot := TTimer.Create(NIL);
      TimerShot.Enabled := false;
      TimerShot.Interval := ShotInterval;
      // Hier muss nun soweit ich weiß festgelegt werden was bei OnTimer passiert
    end;
     
    procedure TWeapon.reload; // Diese Prozedur wird aufgerufen, wenn der Spieler die R-Taste drückt
    begin
      if TimerReload.Enabled = false then TimerReload.Enabled := true; // Der Timer wird gestartet, welcher sich nach einem Durchgang selbst wieder deaktiviert
    end;
     
    end.

    Jetzt wüsste ich gerne, wie ich erreiche, dass die ReloadTimer-Prozedur aufgerufen wird, wenn der Intervall rum ist. Das ist der Teil, der mir bis jetzt nicht gelungen ist...
     

Ähnliche Themen

  1. [LUA] Timer
    Von Danielku15 im Forum Sonstige Sprachen
    Antworten: 1
    Letzter Beitrag: 11.05.10, 13:19
  2. Timer!?
    Von mafu im Forum .NET Windows Forms
    Antworten: 4
    Letzter Beitrag: 15.07.07, 10:25
  3. Timer
    Von FJK im Forum PHP
    Antworten: 4
    Letzter Beitrag: 21.07.05, 15:39
  4. Timer
    Von mstank im Forum VisualStudio & MFC
    Antworten: 1
    Letzter Beitrag: 22.01.05, 08:55
  5. Timer in SWT
    Von trispo im Forum Swing, Java2D/3D, SWT, JFace
    Antworten: 1
    Letzter Beitrag: 27.12.04, 23:00