Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Application Processmessages zum bewegen von Charakteren (https://www.delphipraxis.net/12639-application-processmessages-zum-bewegen-von-charakteren.html)

Flogo 1. Dez 2003 16:53


Application Processmessages zum bewegen von Charakteren
 
Sorry ich war mir nicht ganz sicher mit der Kategorie aber da es aus einem Spiel kommt und sich vielleicht anwendungsbezogen auch ganz anders lösen lässt hab ichs mal hier reingestellt (in der Hoffnung, dass sich hier ein Spieleprogger findet der das gleiche Problem hatte).

Also; es geht um ein 2D-Point'n'Klick-Adventure bei dem man an bestimmte Stellen des Screens klicken kann. der Charakter läuft dann an die entsprechende Stelle. Wenn man während er unterwegs ist eine andere Stelle anklickt läuft er direkt dahin. Ich habe das realisiert indem ich eine TPoint Variable (Ziel) genommen habe und die bei einem Klick auf die entsprechenden Koordinaten gesetzt habe. Ein Timer verschiebt das Bild des Charakters immer einen Schritt in Richtung Ziel. Soweit klappt das auch ganz gut nur will ich jetzt manchmal folgendes machen: Laufe dahin, wenn du angekommen bist tue...

Das Hab ich folgendermaßen versucht:
Delphi-Quellcode:
Ziel := TempZiel;
result := false;
repeat
  application.processmessages;
  if Ziel <> TempZiel then exit;
until Position = Ziel;
result := true;
Leider wird der Timer nicht im Application.processmesasages ausgelöst -> Das Spiel hängt sich in einer Endlosschleife auf, Die Figur bewegt sich keinen Milimeter :gruebel:

Ich hoffe das war jetzt nicht zu kompliziert und irgendjemand da draußen kann mir helfen

[edit=sakura] Leerzeichen in den Titel eingefügt. Mfg, sakura[/edit]

WtF 2. Dez 2003 08:19

Re: Application.processmessages zum bewegen von Charakteren
 
Hallo Flogo,
Wie wärs wenn du deinen eigenen Timer schreibst, und die zeit in der schleife überprüfst. Dann überspringt er das event vieleicht nicht, kannst ja mal ausprobieren.
Mfg

Phoenix 2. Dez 2003 08:31

Re: Application.processmessages zum bewegen von Charakteren
 
Da wirst Du mit Processmessages ein Problem haben.

Ich würde hergehen, und einen eigenen Thread alleine mit dem Neuzeichnen beauftragen und die Position der Figur in einem weiteren setzen.

In der (komplexen) Spieleprogrammierung wirst Du früher oder später sowieso nicht um Threads herumkommen.

Flogo 2. Dez 2003 19:16

Re: Application Processmessages zum bewegen von Charakteren
 
@WtF:
Wie genau meinst du das mit dem Zeit überprüfen?

@Phoenix:
Warum spinnt das App.ProMess da? Führt denn wirklich kein Weg an Threads vorbei?
Wenn nicht: Kannst du mir ein gutes Tutorial empfehlen oder ein Stückchen code geben? Ich hab nämlich keine Ahnung von Threads.

PS: Ursprünglich sollte es gar nicht so komplex werden. Als ich angefangen hab wußte ich noch nicht mal was von OOP :oops: Aber "es wächst" also warum nicht die Gelegenheit nutzen und was über Threads lernen

WtF 3. Dez 2003 07:50

Re: Application Processmessages zum bewegen von Charakteren
 
Hier ich hab n thread tuturial von Luckie drangehangen.

Das mit der Zeit:
Du speichert die zeit an einer stelle und an der nächstens überprüfst du ob schon die gewünschte zeit erreicht ist. Aber ich geb dir auch den Tip mit Threads zu arbeiten! Guck dir lieber das tut an und versuche dein glück!Und geh mal auf Luckies Homepage, da findest du alles mögliche.
Mfg

http://www.luckie-online.de/tutorials/threads/

[edit=Luckie]Anhang durch Link ersetzt. Da ist nämlich noch mehr. :zwinker: Mfg, Luckie[/edit]

MyRealName 3. Dez 2003 10:14

Re: Application Processmessages zum bewegen von Charakteren
 
Das Problem mit ProcessMessages ist ja bei Dir das, daß Du alle anderen und Dich selbst aufforderst, die Nachrichtenwarteschlange abzuarbeiten. Du hast aber keine Nachricht in der Queue, die das Sprite bewegt :P

Threads dafür sind :warn: unsinn ! Es reicht vollkommen aus, wenn Du Dir per HiResTimer die Position des Sprites änderst und es zum Neuzeichnen auffordest. Das kann zum Bsp durch PostMessage passieren.

LG, MyRealName

Luckie 3. Dez 2003 10:28

Re: Application Processmessages zum bewegen von Charakteren
 
Zitat:

Zitat von MyRealName
Threads dafür sind :warn: unsinn !

Und warum? :roll: Threads sinbd dafür sehr wohl geeignet.

MyRealName 3. Dez 2003 13:28

Re: Application Processmessages zum bewegen von Charakteren
 
Meiner Meinung nach sinnloser Overhead. Genannte Windows-Messages reichen dafür aus. Threads bringen Inkonsistenz ins Programm und 'ne Menge Verwaltungsaufwand (EnterCriticalSection etc.). Nix geht über das gute alte PostMessage :cheers: SendMessage...
Ich würde sogar soweit gehen zu sagen, mein Prog macht nicht mehr als 25-30 frames, weil man eh ned mehr anzeigen braucht, egal, wie schnell die cpu ist. Den Rest der Zeit idle ich lieber rum :mrgreen:

MyRealName

Flogo 3. Dez 2003 14:24

Re: Application Processmessages zum bewegen von Charakteren
 
Wie würde das denn ohne/mit Threads gehen? könntet ihr mir ein bisschen Code geben :roll:
Ich muss ja zugeben ich fürcht mich noch vor den Threads :duck: ich verlier so schon fast den Überblick. Wenns also irgendwie einfacher geht nur her damit. Werd mir aber auf jeden Fall auch mal das Thread Tutor durchlesen.

Flogo 9. Dez 2003 19:29

Re: Application Processmessages zum bewegen von Charakteren
 
Hab mir das Threadtutorial jetzt durchgelesen aber :wall: ich verstehs immer noch nicht.
Was muss ich denn in den Thread auslagern: Den Timer? oder die Funktion zum Wegberechnen? oder die Funktion zum Zeichnen?
Soll ich die gesammten Objekte in den Thread stellen oder nur einzelne Proceduren?
Wie komm ich jetzt an die Meldung "Angekommen" oder "Ziel geändert"? brauch ich dazu nicht wieder ein Application.ProcessMessages im Haupt-Thread?
Ihr seht ich hab immer noch keine Ahnung :oops: und freu mich deshalb über jede Hilfe :thuimb:

MyRealName 15. Dez 2003 13:20

Re: Application Processmessages zum bewegen von Charakteren
 
also als erstes mußt Du die WndProc Deines Hauptfensters überschreiben, damit Du mitbekommst, daß 'ne Nachricht reinkommt. Dann registrierst Du Dir eine eindeutige Nachricht mit RegisterWindowMessage

var FMyMessage : Cardinal;
begin
FMyMessage := RegisterWindowMessage('MySpecialPChar_unique');
end;

in der WndProc testest Du dann, ob es Diene Nachricht ist und arbeitest sie ab.

function TProductGen.WndProc(var Msg: TMessage): Integer;
begin
If Msg.Msg = FMyMessage Then begin
// insert your code here
end;
inherited;
end; // WndProc

Dann brauchst Du nur noch 'nen HiRes-Timer, der dich alle x-millisekunden anhaut, so daß Du ein SendMessage machen kannst. Gleichzeit setzt Du die neuen Positionen, damit sich Deine Sprites auch bewegen.

MRN

Flogo 17. Dez 2003 22:23

Re: Application Processmessages zum bewegen von Charakteren
 
Habs immer noch nicht ganz verstanden :oops:
heißt das ich muss irgendwann sagen
sendmessage(FMyMessage)
und eine procedrue OnMyMessage schreibendie das dann verarbeitet?
Wie kann ich dann sagen lauf dahin. Wenn du angekommen bist mache ... wenn das ziel geändert wurde mache wasanderes.
die gleiche frage stellt sich mir übrigens auch noch bei threads :gruebel:

Flogo 12. Jan 2004 22:43

Re: Application Processmessages zum bewegen von Charakteren
 
Ok Ich hab jetzt mit Threads hin und her experimentiert und bin zu folgendem Ergebnis gekommen:

Delphi-Quellcode:
Unit1:

procedure TForm1.FormCreate(Sender: TObject);
begin
  An := TAnim.Create(Self);
  An.Parent := self;
  Level1 := Level.Create(false);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if An <> nil then
    An.DoMove; // verschiebt die Animation um ein Paar Pixel Richtung Ziel
end;

procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Level1.Klick(Point(x,y));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Level1.running := false;
end;

end.
... und das Level (ausgelagert im Thread)
Delphi-Quellcode:
unit2:
procedure Level.Execute;
begin
  { Place thread code here }
  running := true;
  repeat
    Application.ProcessMessages;
  until running = false;
end;

procedure Level.Klick(APoint: TPoint);
begin
  if Walkto(APoint) then showmessage('Angekommen')
  else showmessage('Ziel geändert');
end;

function Level.WalkTo(APoint: TPoint): Boolean;
begin
  synchronize(Ziel(APoint));
  result := false;
  repeat
    Application.ProcessMessages;
    if (Form1.An.Ziel.X <> APoint.X) or (Form1.An.Ziel.Y = APoint.Y) then
    exit;
  until (Form1.An.Left = APoint.X) and (Form1.An.Top = APoint.Y);
  result := true;
end;

procedure Level.Ziel(APoint: TPoint);
begin
  Form1.An.Ziel := APoint;
end;

end.
bekomme dabei aber die Fehlermeldung "Incompatible Types 'TThreadMethod' and 'Procedure'"

Bin ich auf der richtigen Spur? Wie gehts weiter? Was ist der Unterschied zwischen TThreadMethod und Procedure?

Luckie 12. Jan 2004 22:50

Re: Application Processmessages zum bewegen von Charakteren
 
Zitat:

Zitat von MyRealName
Meiner Meinung nach sinnloser Overhead.

Man muss ja nicht das TThread-Objekt der VCL nehmen.

Zitat:

Threads bringen Inkonsistenz ins Programm und 'ne Menge Verwaltungsaufwand (EnterCriticalSection etc.).
Nicht, wenn man weiß was man macht und dies dann noch richtig macht. Kurz eingfach Quatsch deine Aussage. Aber wenn es nach deiner Aussage ginge, dann hätte ich fast nur inkonsistente Anwendungen auf meinem Rechner. :roll:
Und ich weiß, wo von ich rede. ich habe mich mit Threads schon auseinander gesetzt. Tutorial gibt es dazu auf meiner Seite.

Zitat:

Nix geht über das gute alte PostMessage :cheers: SendMessage...
Schön und wenn Code parallel abgearbeitet werden soll?

Flogo 12. Jan 2004 23:04

Re: Application Processmessages zum bewegen von Charakteren
 
Zitat:

Zitat von Luckie
Zitat:

Zitat von MyRealName
Meiner Meinung nach sinnloser Overhead.

Man muss ja nicht das TThread-Objekt der VCL nehmen.

Bitte mach mich jetzt nicht nervös *zuckenimauge* :freak: Jetzt hab ich grad so halb verstanden wie das damit funktioniert und jetzt soll ich sie nicht benutzen?
Zitat:

Zitat von Luckie
Nicht, wenn man weiß was man macht und dies dann noch richtig macht.

und genau da liegt mein Problem (siehe oben)

Luckie 12. Jan 2004 23:05

Re: Application Processmessages zum bewegen von Charakteren
 
Dann kuck dir mal mein Tutorial an.

Flogo 12. Jan 2004 23:19

Re: Application Processmessages zum bewegen von Charakteren
 
@Lukie
Hab noch was älteres von dir gefunden. und habs jetzt auch mal mit globalen Variablen versucht. allerdings hängt er sich jetzt am anfang von synchronize(Ziel) auf. Du hast am ende gesagt "Alles ausgebessert"
Aber wie?
[Edit] Ok habs im Tutorial gesehen was du geändert hast
Mein Code sieht jetzt so aus:
Code:
function Level.WalkTo(APoint: TPoint): Boolean;
begin
  WalkToPoint := APoint; // WalkToPoint = Global im thread deklarierte Variable
  synchronize(Ziel);     // hier bleibt er hängen
// ... Rest wie oben
end;

procedure Level.Ziel;
begin
  Form1.An.SetZiel(WalkToPoint); // Diese Stelle wird nie ausgeführt
end;
[/edit]

Flogo 15. Jan 2004 19:08

Re: Application Processmessages zum bewegen von Charakteren
 
Irgendwie stellt sich mir hier immer öfter die Frage ob ich überhaupt auf dem richtigen weg bin?

Wenn ich nach dem Klick warten will bis die Figur an einer bestimmten Stelle ist, dann muss ich doch das Programm anhalten.
Aber um die Figur zu bewegen muss ich doch gleichzeitig das Programm weiter laufen lassen. Eigentlich sollte das ja das Application.processmessages erledigen, was in einem Testprogramm auch funktioniert. Aber anscheinend will mein Timer nicht mehr anspringen wenn das Prog mal in der Application.PM Schleife hängt

Niko 15. Jan 2004 19:56

Re: Application Processmessages zum bewegen von Charakteren
 
Zitat:

Zitat von Flogo
Wenn ich nach dem Klick warten will bis die Figur an einer bestimmten Stelle ist, dann muss ich doch das Programm anhalten.

Nein, warum das nicht geht hast du ja selbst geschrieben :wink: .

Ich würde folgendes Prinzip nehmen:
Bei Mausklick:
Delphi-Quellcode:
Bewegen := true;
NeuePosition := Mausposition;
In Timer-Ereignis:
Delphi-Quellcode:
if Bewegen = true then
  if NeuePosition <> AktuellePosition then
    AktuellePosition := VerschiebeFigur;
  else
  begin
    Bewegen := false;
    MachWasWennFigurAngekommen;
  end;
wobei VerschiebeFigur die Position zurückgibt, an die die Figur verschoben wurde.

Natürlich lässt sich der Code für das Timer-Ereignis genausogut auch in einen Thread packen. Solange er aber keine umfangreichen Berechnungen anstellt, halte ich das nicht für nötig.

[EDIT=Niko]Wechselstaben verbuchtelt[/EDIT]

Flogo 16. Jan 2004 07:37

Re: Application Processmessages zum bewegen von Charakteren
 
Erstmal vielen Dank für die Hilfe! :thuimb:
Aber ein kleines Problem hab ich immer noch:
Da es bei einem Adventure ja stark davon abhängt wann wohin geklickt wird, habe ich mir eine Klasse TLevel geschrieben und davon die einzelnen Level abgeleitet. Jedes abgeleitete Level ist nacher im Spiel eine Szene und verarbeitet den Klick (Wenn auf die Tür mit dem Cursor "Betritt" geklickt wird -> Lade neues Level)
Da diese Levelprogrammierung eigentlich den Hauptteil des Programms ausmachen wird, wäre es doch irgendwie ungeschickt wenn die Hälfte der Programmierung im Timer steckt. Ich könnte natürlich mit Flags arbeiten und im MachWasWennFigurAngekommen; Abfragen welches Level und welcher Punkt gemeint war, aber auch das stell ich mir unübersichtlich vor.

Zitat:

Zitat von Niko
Natürlich lässt sich der Code für das Timer-Ereignis genausogut auch in einen Thread packen. Solange er aber keine umfangreichen Berechnungen anstellt, halte ich das nicht für nötig.

Wäre das dafür vielleicht eine Lösung? kann ich dann mein "Level" solange anhalten bis der Timer die Figur an eine Stelle gebracht hat? und muß die Figur mit ihrer Bewegen-Methode dann auch in den Thread?

[edit] Tag korrigiert [/edit]

Niko 16. Jan 2004 20:15

Re: Application Processmessages zum bewegen von Charakteren
 
Warum deklarierst du nicht in TLevel die zwei Methoden VerschiebeFigur und MachWasWennFigurAngekommen (evtl. als abstract)?
Dann brauchst du nur noch eine Variable vom Typ TLevel, in der du das aktuelle Level speicherst und kannst im Timer über diese auf die entsprechende Methoden des aktuellen Levels zugreifen. Falls du die Levels sowieso schon in einem Array oder ähnlich verwaltest, reicht auch ein Integer in dem du den Index des aktuellen Levels ablegst.

Flogo 17. Jan 2004 03:13

Re: Application Processmessages zum bewegen von Charakteren
 
Das war ja ungefähr die Idee von oben. Nur ist das Problem dabei eben, dass es (selbst in einem Level) viele verschiedene Sachen gibt, die nach einem Klick passieren können:

- Klick auf die Tür -> gehe zur Tür -> Lade neues Level
- "Nimm"-Klick auf Schaufel -> gehe zur Schaufel -> sag was -> nimm Schaufel
- ...

Werde es aber wahrscheinlich trotzdem so machen und irgendwie mit Indices hantieren.

Vielen Dank euch allen nochmal :dp:

Flogo 11. Feb 2004 17:51

Re: Application Processmessages zum bewegen von Charakteren
 
Wollte mich nur noch mal zurückmelden und sagen wie ichs gelöst hab.
Ich habe einen Workaround gefunden:
Der DxTimer (von DelphiX ;) ) spricht zwar nicht auf das Application.ProcessMessages an, aber der normale Delphi-Timer tut das genau so wie ich mir das vorgestellt hab. Nur das er keine Eigenschaft FPS hat aber das lässt sich ja leicht nachbauen.
Es läuft jetzt wieder alles so wie es am Anfang war, nur mit einem anderen Timer. *schulternzuck* Naja wenigstens weiß ich jetzt was Threads sind und hab noch n paar andere Sachen auf dem Weg dahin gelernt! Danke DP :dp:

Seniman 11. Feb 2004 20:32

Re: Application Processmessages zum bewegen von Charakteren
 
Hallo ihr alle,

vielleicht habe ich das ursprüngliche Problem nicht richtig verstanden, aber meines Erachtens ist das nicht so schwierig.
Flogo, hab ich das richtig verstanden, dass du die Figur im Spiel herumlaufen lässt und möchtest, dass etwas bestimmtes passiert, wenn sie ankommt?
Dann speicher doch irgendwie mit ein paar Variablen, was genau passieren soll, wenn die Figur ankommt und setz in die Timer-Schleife einmal die If-Abfrage, ob die Figur angekommen ist. Lass die Repeat-Until-Schleife einfach weg. Dann sollte die Figur weiterhin laufen können, und wenn sie ankommen, passiert eben das, was du willst.

[Edit: Oh, ich hab nicht gesehen, dass da noch eine zweite Seite war. Hat sich wohl schon erledigt]

Grüße
Seniman

Flogo 11. Feb 2004 20:39

Re: Application Processmessages zum bewegen von Charakteren
 
Das hat Niko ja auch schon vorgeschlagen. Das Problem dabei ist nur das je nach Aktion, Stelle im Spiel, Stelle im Level, Mauscursor und Level, ja eine ganz andere Aktion ausgeführt werden soll.
Aber wie gesagt es ist gelöst und läuft auf die Art die ich schon am Anfng wollte nur eben mit einem anderen Timer.
Trotzdem Danke für deinen Vorschlag! :cheers:


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:24 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 by Thomas Breitkreuz