![]() |
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:
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:
Ziel := TempZiel;
result := false; repeat application.processmessages; if Ziel <> TempZiel then exit; until Position = Ziel; result := true; 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] |
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 |
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. |
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 |
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 ![]() [edit=Luckie]Anhang durch Link ersetzt. Da ist nämlich noch mehr. :zwinker: Mfg, Luckie[/edit] |
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 |
Re: Application Processmessages zum bewegen von Charakteren
Zitat:
|
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 |
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. |
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: |
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 |
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: |
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:
... und das Level (ausgelagert im Thread)
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.
Delphi-Quellcode:
bekomme dabei aber die Fehlermeldung "Incompatible Types 'TThreadMethod' and 'Procedure'"
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. Bin ich auf der richtigen Spur? Wie gehts weiter? Was ist der Unterschied zwischen TThreadMethod und Procedure? |
Re: Application Processmessages zum bewegen von Charakteren
Zitat:
Zitat:
Und ich weiß, wo von ich rede. ich habe mich mit Threads schon auseinander gesetzt. Tutorial gibt es dazu auf meiner Seite. Zitat:
|
Re: Application Processmessages zum bewegen von Charakteren
Zitat:
Zitat:
|
Re: Application Processmessages zum bewegen von Charakteren
Dann kuck dir mal mein Tutorial an.
|
Re: Application Processmessages zum bewegen von Charakteren
@Lukie
Hab ![]() Aber wie? [Edit] Ok habs im Tutorial gesehen was du geändert hast Mein Code sieht jetzt so aus:
Code:
[/edit]
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; |
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 |
Re: Application Processmessages zum bewegen von Charakteren
Zitat:
Ich würde folgendes Prinzip nehmen: Bei Mausklick:
Delphi-Quellcode:
In Timer-Ereignis:
Bewegen := true;
NeuePosition := Mausposition;
Delphi-Quellcode:
wobei VerschiebeFigur die Position zurückgibt, an die die Figur verschoben wurde.
if Bewegen = true then
if NeuePosition <> AktuellePosition then AktuellePosition := VerschiebeFigur; else begin Bewegen := false; MachWasWennFigurAngekommen; end; 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] |
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:
[edit] Tag korrigiert [/edit] |
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. |
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: |
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: |
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 |
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 19:04 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