PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Spiel: Problem - gleichzeitige Bewegung 2er Spielfiguren


Kristin
17.10.2002, 14:33
Hallo Leute,

ich soll für meine Schule einen Bomberman-Clone schreiben und stehe gerade vor dem Problem meine beiden Spielfiguren gleichzeitig zu bewegen.
Man kann ja über die Ereignisse "OnKeyPressed" oder "OnKeyDown" (welche ich verwendet hab) auf Tastatureingaben reagieren.
Also hab ich eine Methode "moveFigur" geschrieben, die bei OnKeyDown aufgerufen wird. In dieser Methode schau ich, welche Taste gedrückt wurde und zeichne dementsprechend die Spielfigur neu.
Nu hab ich ja aber 2 Spielfiguren - wenn ich zur Zeit (nahezu) gleichzeitig beide Spielfiguren bewege - dann bewegt sich immer erst das Männchen wo zuerst gedrückt wurde - und wenn das fertig gelaufen ist, dann das andere :mauer:
Das kanns ja aber irgendwie nicht sein :(

Zu dem Thema "gleichzeitig" fallen mir nur Threads ein, aber ich denke, daß das auch ohne Threads zu lösen ist ( . . . nur wie, nur wie)

Weis da jemand einen Rat?

Grüße

Kristin


DerWolf
17.10.2002, 16:23
Versuchs doch mal mit ner Timer Komponente oder so

Jan Krüger
17.10.2002, 16:54
threads sind auf jeden fall vorzuziehen (ein sehr komplexer selbstgeschriebener scheduler geht natürlich auch :)), denn bei der lösung mit dem timer (die auch das gewünschte ergebnis bringt) werden sonst während des bewegungsvorganges alle anderen evtl. nötigen abläufe blockiert.

Felix Kaiser
17.10.2002, 17:07
So wie ich das sehe lässt moveFigur eine Figur nicht nur neuzeichnen, sondern >bewegen<. Wenn du keine Threads wünschst, dann lasse nach jedem Zeichenschritt der Bewegung die zweite Figur zeichnen, bevor du eine kleine Pause machst (damit die Bewegung recht gleichmäßig bleibt).

Kristin
18.10.2002, 12:29
Hi,

also ich weis leider nicht genau, wie ihr das mit dem Timer meint . . . aber vielleicht könnte mir das jemand mal kurz erklären? *hundeaugenmach*

@Felix Kaiser: So was in der Art hatte ich mir auch schon vorgestellt, nur wird meine "movefigur" ja aufgerufen, wenn ich eine Taste drücke. Dann wird der Tastendruck abgearbeitet und erst danach wird auf einen nachfolgenden Tastendruck mit dem erneuten ausführen der Methode reagiert. Das heißt, ich könnte zwar die 2. Figur neuzeichnen, aber es bringt nichts, da ich dort ja noch nicht weis, ob und welche Taste danach gedrückt wurde.

Ansonsten zu den Threads, sind die in Delphi leicht zu handeln?
Denn ich musste mal Threads in Java für meine Ausbildung machen und bin daran leider kläglich gescheitert, weswegen ich auch noch ein Semester hinten dran hängen darf und es dieses nochmal versuchen muss.
Daher hab ich zur Zeit ein kleines Threads-Trauma ^:(

Grüße

Kristin

Felix Kaiser
18.10.2002, 13:50
Geht ganz einfach: Datei -> Neu -> dann durchklicken bis zum Auswahldialog mit allmöglichem Kram, dort wählst du dann einen Thread, der deinem Projekt hinzugefügt wird. Dadurch wird die Threadkomponente erstellt und in einer Unit ablegt. Den Kram mit MoveFigur kannst du dann in die Prozedur Execute des Threads packen. Wenn du dann die zweite Taste abgerufen hast, brauchst du nur noch ein Objekt deines Thread mit TDeinThread.Create erstellen. Bei Delphi ist auch ein Beispiel für Threads dabei, welches Sortieralgorhythmen demonstriert.

Lord_Otter
18.10.2002, 16:14
Bei TThread-Create muss man als Parameter noch übergeben, ob der Thread manuell gestartet werden soll oder nicht.
Wenn du TThread.Create(FALSE) aufrufst, startet der Thread, bei TThread.Create(TRUE) musst du den Thread manuell starten.

Kristin
18.10.2002, 21:54
Ich hab da noch eine Frage zu den Threads

Kann ich aus einem Thread heraus auf Variablen oder Methoden auf meinem Hauptformular zugreifen?
Oder kann ich beim starten eines Threads Variablen übergeben?

Denn ich würde ja in meinem Thread die Bewegung meiner Figur zeichnen. Die Korrdinaten muss ich dann ja haben, das TImage Objekt, die Bilder die ich zeichnen möchte und und und

Grüße

Kristin

Felix Kaiser
18.10.2002, 22:23
Lesen aus Variablen ist kein Problem. Für alles andere musst du Synchronize benutzen. Ansonsten kann es schwerwiegende Zugriffsverletzungen geben. Mit Synchronize kannst du eine Prozedur (Methode) aus dem Hauptthread aufrufen, die allerdings keinerlei Parameter empfangen kann.

Ich würde dir vorschlagen: Lasse die beiden Tastencodes verarbeiten und falls notwendig erstelle einen Thread, der über Synchronize das zweite Move für die zweite Figur aufruft.

Kristin
18.10.2002, 22:32
Dann hab ich ja aber immer noch das Problem, dass ich während ich den 1. Tastendruck verarbeite, noch keine Daten zu dem 2. Tastendruck hab - folglich auch keinen Thread für den 2. starten kann.

Wie sollte denn die Möglichkeit mit einem Timer funktionieren? Vielleicht erreiche ich ja damit was ich möchte . . . :rolleyes:

Lord_Otter
19.10.2002, 09:24
Also mit Threads müsste das besser gehen als mit dem Timer.
Wie ermittelst du überhaupt den Tastendruck ?
Per Ereignis oder wie ?

Ereignis würde ich nicht verwenden...

Kristin
19.10.2002, 12:04
@Lord_otter:

Wie kann ich denn noch einen Tastendruck ermitteln? Ich hab da leider nicht so die Erfahrungen und kannte bisher nur die Möglichkeit mit dem Ereignis . . . ^_^'

Felix Kaiser
19.10.2002, 12:54
Denk doch mal in eine ganz andere Richtung. Immer wenn eine Taste gedrückt wurde und die Figur animiert werden muss, kannst du doch einen Thread öffnen, der die Figur bewegen lässt. Natürlich musst du vorher prüfen, ob die Figur nicht schon bewegt wird, falls schon, ignorieren, falls nicht, Thread öffnen, Figur bewegen lassen und den Thread wieder freigeben. Damit sollte es dann keinerlei Probleme geben!

Lord_Otter
19.10.2002, 14:11
Das ist besser als die erste Lösung, finde ich. Mit dem Überprüfen hätte ich das so gemacht:

constructor TMoveThread.Create(fn:Byte);
begin
inherited Create(FALSE); // Thread sofort starten
FigurNr :=fn;
end;

var movefigueres: array[1..MaxFigures];

procedure TMoveThread.Execute;
begin
{ Bewegung überprüfen }
if movefigures[FigurNr] then Exit; // Figur wird schon bewegt
movefigures[FigurNr] :=true; // Figur nr FigurNr wird bewegt
{ Figur bewegen }
...
movefigures[FigurNr] :=false; // Figur wird nicht mehr bewegt
end;


Dabei soll FigurNr die Nummer der Figur sein.
In dem Block von TMoveThread.Execute, wo die Figur bewegt werden soll, musst du natürlich regelmäßig überprüfen, ob Terminated TRUE ist.
Wenn Terminated TRUE ist, muss der Thread abgebrochen werden.
Dabei solltest du in diesem Fall so vorgehen:

if Terminated then begin
movefigures[FigurNr] :=false;
Exit;
end;

Aber eine noch bessere Möglichkeit ist folgende:

constructor TMoveThread.Create(fn:Byte);
begin
inherited Create(FALSE); // Thread sofort starten
FigurNr :=fn;
OnTerminate :=StopMove;
end;

var movefigueres: array[1..MaxFigures];

procedure TMoveThread.Execute;
begin
{ Bewegung überprüfen }
if movefigures[FigurNr] then Exit; // Figur wird schon bewegt
movefigures[FigurNr] :=true; // Figur nr FigurNr wird bewegt
{ Figur bewegen }
...
end;

procedure TMoveThread.StopMove;
begin
movefigures[FigurNr] :=false;
end;


In diesem Fall wird StopMove automatisch aufgerufen, wenn der Thread beendet wird.

Kristin
21.10.2002, 20:19
@Lord_Otter:

Deine Möglichkeit sieht sehr interessant aus, und ich denke ich werde sie mal ausprobieren.
Aber ein Problem hätte ich dabei noch - und zwar muss ich ja um den Thread benutzen zu können die Thread-Unit im Hauptformular angeben. Aber in der Thread-Unit muss ich um auf Objekte auf dem Hauptformular zugreifen zu können die Hauptformular Unit angeben - das wäre aber ein überkreuz zugriff von Units und das geht nicht.
Mache ich was falsch? Oder wie soll ich das sonst machen - denn um meine Figur zubewegen muss ich halt auf mein TImage Objekt auf dem Hauptformular zugreifen.

Grüße

Kristin

Kristin
22.10.2002, 19:59
:confused:
Ich glaub ich bin zu blöd für Threads, ich bekomme das einfach nicht hin :(
Ich krieg den Thread ums verrecken nicht zum laufen . . .
Ich werde mich jetzt erstmal anderen Problemen widmen und wenn ich dann wieder beim Thema bin, dann melde ich mich wieder hier.

Trotzdem Danke für eure tolle Hilfe!

Grüße

Kristin