AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Mehrere Timer zur Laufzeit, optimieren?

Ein Thema von pustekuchen · begonnen am 19. Okt 2010 · letzter Beitrag vom 19. Okt 2010
Antwort Antwort
Benutzerbild von pustekuchen
pustekuchen

Registriert seit: 27. Aug 2010
264 Beiträge
 
Delphi 11 Alexandria
 
#1

Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 13:44
Delphi-Version: 2010
Guten Tag,

Es geht sich um folgendes. Ich bin zurzeit dabei ein Spiel zu programmieren.
Es ist so das alle Gegner 1px bewegt werden, dannach wird eine Procedur aufgerufen die prüft, ob die Türme noch ein Ziel haben, wenn nicht wird der Gegner der in der Reichweite des Turmes liegt und am nahsten dran ist zum Ziel. Zuletzt wird ein Timer für den Turm erstellt.

Dieser prüft dann jedes mal ob das Ziel noch in Reichweite ist. Wenn ja "schießt" es auf den Gegner.
Hat der Gegner dann <=0 Lebenspunkte, wird der Timer wieder freigegeben.
Sonst soll er halt den Intervall abwarten und nochmal die Timer Procedure ausführen.

Das ganze läuft aber in der Praxis nicht wirklich flüssig ab
Es sieht so aus als würde immer nur ein timer ablaufen. Also wenn dort 10 Türme stehen, wird trotzdem nur alle 0,5 sek geschossen.
Wodran könnte es liegen? Wie kann man das ganze Optimieren?

Hier sind die Proceduren und im Anhang lad ich noch die Compilierte .exe hoch, fals man es sich genau anschauen möchte.

Delphi-Quellcode:
procedure TFormMain.moveEnemies(value: TGameStatus);
var
  fieldX, fieldY: Integer;
  i,k,j: Integer;
  tmpField :array of TNextField;
begin
  SetLength(tmpField,High(EnemyManager.enemys[Player.Level]));
  for k := 0 to High(EnemyManager.enemys[Player.Level]) do
  begin
    fieldX := (EnemyManager.enemys[Player.Level][k].Pixels.X ) div 32;
    fieldY := (EnemyManager.enemys[Player.Level][k].Pixels.Y ) div 32;
    tmpField[k] := map.Playground[fieldX][fieldY].nextField;
  end;

  for j := 0 to 31 do
  begin
    for i := 0 to High(EnemyManager.enemys[Player.Level]) do
    begin
      if EnemyManager.enemys[Player.Level][i].isRunning then
      begin
        case tmpField[i] of
          nfDown: EnemyManager.moveEnemy(EnemyManager.enemys[Player.Level][i],nfDown);
          nfRight: EnemyManager.moveEnemy(EnemyManager.enemys[Player.Level][i],nfRight);
          nfLeft: EnemyManager.moveEnemy(EnemyManager.enemys[Player.Level][i],nfLeft);
          nfUp: EnemyManager.moveEnemy(EnemyManager.enemys[Player.Level][i],nfUp);
          nfStay:
          begin
            EnemyManager.enemys[Player.Level][i].isRunning := false;
            EnemyManager.enemys[Player.Level][i].HP := 0;
            Player.Lives := (Player.Lives -1);
            lblLives.Caption := 'Leben: ' +IntToStr(Player.Lives);
            if Player.Lives = 0 then
            begin
              isUpgrading := False;
              SetGameStatus(gsGAMEOVER);
              LastFocus.fieldKind := fkUkn;
              exit;
            end;
          end;
        end;
        if tmpField[i] <> nfStay then
          FightManager.Fight(i);
      end;
    end;
    Draw;
  end;
end;
Delphi-Quellcode:
procedure TFightManager.Fight(indexOfEnemy: integer);
var i,k: integer;
  minDistance,distance: Integer;
  targetChanged: Boolean;
  tw: TFightTower;
  enemy: TEnemy;
begin
  if (EM.enemys[FormMain.Player.Level][indexOfEnemy].isRunning ) then
  begin
    for I := 0 to listTower.Count -1 do
    begin
      tw := (TObject(listTower.Items[i]) as TFightTower );
      if (tw.target = -1) then
      begin
        targetChanged := false;
        minDistance :=tw.range div 2;
        for k := 0 to High(EM.enemys[FormMain.Player.Level]) do
        begin
          enemy := EM.enemys[FormMain.Player.Level][k];
          if enemy.isRunning then
          begin
            distance := getDistanceFromTowerToEnemy(tw,enemy);
            if (minDistance > distance) and ( distance < tw.range div 2) then
            begin
              minDistance := distance;
              tw.target := k;
              targetChanged := true;
            end
          end;
        end;
        if targetChanged then
        begin
          FormMain.lblActTarget.caption := 'Ziel: ' + IntToStr((TObject(listTower.Items[i]) as TFightTower ).target);
          FormMain.lblActTargetsHP.Caption := 'HP des Ziels: '+ IntToStr((TObject(EM.enemys[FormMain.Player.Level][(TObject(listTower.Items[i]) as TFightTower ).target]) as TEnemy ).HP);
          createTimer(tw);
        end;
      end
    end;
  end;
end;
Delphi-Quellcode:
procedure TFightManager.CreateTimer(tower: TTower);
var timer: TTimer;
  a: integer;
begin
  timer := TTimer.Create(nil);
  timer.Enabled := False;
  timer.Interval := Round((tower as TFightTower).Speed * 1000);
  timer.OnTimer := TimerProc;
  timer.Enabled := true;
  a := listTower.IndexOf(tower);
  listTowerTimer.AddObject(IntToStr(a),timer);
end;
Delphi-Quellcode:
procedure TFightManager.TimerProc(Sender: TObject);
var a,distance,target: integer;
  enemy: TEnemy;
  tw: TFightTower;
  b: string;
begin
  a := listTowerTimer.IndexOfObject(Sender);
  b := listTowerTimer.Strings[a];
  tw := TObject(listTower.Items[StrToInt(b)]) as TFightTower;
  target := tw.target;
  if (target > -1) then
  begin
    enemy := EM.enemys[FormMain.Player.Level][target];
    distance := getDistanceFromTowerToEnemy(tw,enemy );
    if (distance < (tw.range div 2)) then
    begin
      ShotOnEnemy(tw.Damage,target);
      FormMain.lblActTarget.caption := 'Ziel: ' + IntToStr(tw.target);
      FormMain.lblActTargetsHP.Caption := 'HP des Ziels: '+ IntToStr(enemy.HP);

      if enemy.HP <= 0 then
      begin
        tw.target := -1;
        listTowerTimer.Delete(listTowerTimer.IndexOfObject(Sender));
        (Sender as TTimer).Free;
      end;
    end
    else
    begin
       tw.target := -1;
       listTowerTimer.Delete(listTowerTimer.IndexOfObject(Sender));
      (Sender as TTimer).Free;
    end;
  end
  else
    (Sender as TTimer).Free;
end;
Angehängte Dateien
Dateityp: rar TD.rar (423,8 KB, 7x aufgerufen)

Geändert von pustekuchen (19. Okt 2010 um 13:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.534 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 13:56
Sehe ich das richtig, dass Du den Timer immer wieder neu erzeugst und wieder freigibst? Evtl. wäre es überlegenswert, einen Multimedia-Timer zu verwenden, und zwar einen je Objekt, das bewegt werden soll. Aber das ist nur so ein Gedanke, ich war zu faul, den gesamten Code nachzulesen und nachzuvollziehen.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von pustekuchen
pustekuchen

Registriert seit: 27. Aug 2010
264 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 13:58
Danke
Ja, da liegst du Richtig. Ich werde mir mal die Multimedia-Timer anschauen.

EDIT: Ist dieser hier richtig?

Geändert von pustekuchen (19. Okt 2010 um 14:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.534 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 14:05
So etwas habe ich gemeint. Ansonsten kannst Du auch einmal bei Torry vorbeischauen.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von pustekuchen
pustekuchen

Registriert seit: 27. Aug 2010
264 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 14:20
Danke für die Seite
Mhh hab CKs Timer eingebaut, doch leider ohne erfolg. Es liegt wohl an etwas anderem.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.534 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 14:24
Erzeugst/zerstörst Du den/die Timer immer noch dynamisch? Das würde ich so nicht machen, da dabei ja auch Zeit verbraten wird. Besser wäre es IMO, den bzw. die Timer einmalig anzulegen und gff. zu disablen. Außerdem könnte man das schön OOP lösen, indem die ganzen Spielobjekte selbstständig agieren und dafür jeweils einen eigenen Timer erzeugen. Aber das ist vielleicht noch etwas zu hoch gegriffen.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von pustekuchen
pustekuchen

Registriert seit: 27. Aug 2010
264 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 14:52
Zitat:
Erzeugst/zerstörst Du den/die Timer immer noch dynamisch? Das würde ich so nicht machen, da dabei ja auch Zeit verbraten wird. Besser wäre es IMO, den bzw. die Timer einmalig anzulegen und gff. zu disablen. Außerdem könnte man das schön OOP lösen, indem die ganzen Spielobjekte selbstständig agieren und dafür jeweils einen eigenen Timer erzeugen. Aber das ist vielleicht noch etwas zu hoch gegriffen.
Ja, hatte ich
Hab jetzt so gemacht, das jedes Spielobjekt seinen eigenen Timer hat.
Es sieht nun folgender maßen aus:

Delphi-Quellcode:
 if targetChanged then
        begin
          if (listTowerTimer.IndexOfObject(tw.timer) = -1) then
            setTimer(tw)
          else
            tw.timer.Enabled := true;
        end;
Delphi-Quellcode:
procedure TFightManager.setTimer(tower: TTower);
var timer: TCKMultimediaTimer;
  a: integer;
begin
  timer := (tower as TFightTower).timer;
  timer.Interval := Round((tower as TFightTower).Speed * 1000);
  timer.OnTimer := TimerProc;
  timer.Enabled := true;
  listTowerTimer.AddObject(IntToStr(listTower.IndexOf(tower)),timer);
end;
und in der TimerProcedur steht     (Sender as TCKMultimediaTimer).Enabled := false; Aber geholten hats trotzdem nicht^^.

Ich glaube dort ist ein Denkfehler von mir drin, ich glaub ich weiß auch schon wo.
Sobald ein Gegner in die Reichweite eines Turmes läuft, dauert es erstmal die Intervall bis der Turm schießt. Doch es soll eigentlich so sein, das er direkt schießt und dann die Intervall abwartet und dann wieder etc.
Müsste ja dann funktionieren, indem ich die intervall zuerst auf 1 setzt und in der Timer Procedure auf den normalen Wert.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.534 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 15:04
Kommt auf einen Versuch an, klingt aber erst einmal schlüssig.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von pustekuchen
pustekuchen

Registriert seit: 27. Aug 2010
264 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Mehrere Timer zur Laufzeit, optimieren?

  Alt 19. Okt 2010, 15:15
Jap, läuft auf jedenfall besser Dank dir Detlef
Jetzt werd ich mich an die anderen Timer ran machen
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:03 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