![]() |
Delphi-Version: 2010
Mehrere Timer zur Laufzeit, optimieren?
Liste der Anhänge anzeigen (Anzahl: 1)
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; |
AW: Mehrere Timer zur Laufzeit, optimieren?
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.
|
AW: Mehrere Timer zur Laufzeit, optimieren?
Danke
Ja, da liegst du Richtig. Ich werde mir mal die Multimedia-Timer anschauen. EDIT: ![]() |
AW: Mehrere Timer zur Laufzeit, optimieren?
So etwas habe ich gemeint. Ansonsten kannst Du auch einmal bei
![]() |
AW: Mehrere Timer zur Laufzeit, optimieren?
Danke für die Seite ;)
Mhh hab CKs Timer eingebaut, doch leider ohne erfolg. Es liegt wohl an etwas anderem. |
AW: Mehrere Timer zur Laufzeit, optimieren?
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.
|
AW: Mehrere Timer zur Laufzeit, optimieren?
Zitat:
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:
und in der TimerProcedur steht
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;
Delphi-Quellcode:
Aber geholten hats trotzdem nicht^^.
(Sender as TCKMultimediaTimer).Enabled := false;
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. |
AW: Mehrere Timer zur Laufzeit, optimieren?
Kommt auf einen Versuch an, klingt aber erst einmal schlüssig.
|
AW: Mehrere Timer zur Laufzeit, optimieren?
Jap, läuft auf jedenfall besser ;) Dank dir Detlef
Jetzt werd ich mich an die anderen Timer ran machen ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz