Hallo,
sorry wegen Titel -> der Spamschutz spinnt wieder und nimmt mir nix an :roll:
Den Titel wollte ich "mehere Threads/Tasks in einem synchronisieren -> TaskPool" nennen.
ich habe mitbekommen dass man bei Spielen 2 Threads haben sollte:
Main Thread, AWT E.D.
Ich hatte schonmal ein Tetris programmiert, ganz klassisch, und bin damit gut zurecht gekommen.
Jetzt mach ich wieder ein Tetris-artiges Spiel, aber diesmal etwas effektvoller. Damit meine ich zB die Beweungen. Während im normalen Tetris die SpielSteine "von 0 auf 100" ihre Position oder Form ändern (man drückt ne Taste und plötzlich ist der Stein gedreht, der GameLoop bewegt den Stein alle x ms ein Feld nach unten, auch ohne Animation), soll bei mir alles flüssig animiert ablaufen.
Bei der Rotation eines Steines soll man so zB wirklich die Rotation sehen, d.h. ich bewege den Stein pixel per pixel mit sehr geringen Sleep-Times dazwischen, um das darzustellen.
Und hier bekomme ich jetzt ein Problem, das ich nicht mehr so angehen kann wie bei meinem Classic Tetris damals:
Ich habe viele Ereignisse im Spiel, die Unterbrechungen haben müssen, um zeichnerisch einen flüssigen Ablauf darstellen zu können. Die Eregnisse dauern unterschiedlich lange, die sleep-times sind auch verschieden. zB dreht sich ein Stein schneller ( = sleep time gering) als er sich nach unten bewegt ( = sleep time etwas länger).
Trotzdem muss alles gleichzeitig geschehen, und wenn der Stein halt schon fertig gedreht ist, bevor er sich ein Stück nach unten bewegt hat, dann ist das halt so. Ihr wisst, was ich meine.
Und dabei bleibt es ja nicht: Ich hab noch Kettenexplosionen usw.
Gut, ich dachte mir jetzt: Hm, da ich nicht anfangen kann, für jedes Event einen eigenen Thread zu starten (weil schnell alles ruckelt und abstürzt, wenn man mal eben 80+ Threads hat, was zB bei einer Kettenexplosion so sein würde), muss man kucken, dass man die einzelnen Aufgaben, die anstehen, in einen einzigen Thread packt (den Gameloop halt).
Aber irgendwie muss man die Threads ja synchronisieren, irgendwie ist das ziemlich übel :autsch:
Hier mal meine Herangehensweise:
Sagen wir, ich habe eine Klasse, die eine aufgabe beschreibt (und die erstmal abstrakt ist):
Das "Object" ist dann das, worauf dieses Event passiert, zB ein Spielstein. Die Methode toDo() überschreibt
ein Task dann so, dass darin steht, was passieren soll.
So wäre ein spezifischer Task zB "Task_SteinNachUntenBewegen":
Dieser Task würde nun heissen: Du hast nen Spielstein, bewege den insgesamt 10 Pixel nach unten
(weil du 10x die Methode, die in toDo() stehst aufrufen sollst). Das ganze dauert 100ms, weil du immer
10 ms warten sollst.
Gut, als letztes eine Klasse die irgendwie ne Liste von Tasks hat. Sagen wir mal, die Liste hat im Moment nur 2 Tasks, und es sind beide SteinNachUntenBewegen-Tasks. Die wurden jetz hinzugefügt und im Game sollen jetz 2 SpielSteine gleichzeitig sich runterbewegen.
So weit, so gut, das is einfach: Im GameLoop rufen wir die Methode fireTasks() auf, wo auch immer diese MEthode steht oder zu welchen Klasse sie gehört. Is ja erstmal egal.
Im Endeffekt würde das so aussehen, mit 2 Task_SteinNachUntenBewegen Tasks in der Liste:
edit:
Jetzt krieg ich wahrscheinlich ein paar virtuelle Fäuste ins Gesicht, aber ich lass erstmal eine konkrete Fragestellung weg, weil ich mir noch darüber klar werden möchte
Ich muss nochmal bisschen drüber nachdenken, um dann mein Problem konkret bennen zu können.
Ich bedanke mich hier schon mal bei jedem, der sich das durchgelesen hat -- es war NICHT umsonst
Es wär nett, wenn Interessierte mal wieder vorbeischauen, ich werde dann in den nächsten paar Minunten/Stunden meine genau Frage formulieren. Aber es ist schonmal gut zu wissen, worum es hier geht.
Dank euch
sorry wegen Titel -> der Spamschutz spinnt wieder und nimmt mir nix an :roll:
Den Titel wollte ich "mehere Threads/Tasks in einem synchronisieren -> TaskPool" nennen.
ich habe mitbekommen dass man bei Spielen 2 Threads haben sollte:
Main Thread, AWT E.D.
Ich hatte schonmal ein Tetris programmiert, ganz klassisch, und bin damit gut zurecht gekommen.
Jetzt mach ich wieder ein Tetris-artiges Spiel, aber diesmal etwas effektvoller. Damit meine ich zB die Beweungen. Während im normalen Tetris die SpielSteine "von 0 auf 100" ihre Position oder Form ändern (man drückt ne Taste und plötzlich ist der Stein gedreht, der GameLoop bewegt den Stein alle x ms ein Feld nach unten, auch ohne Animation), soll bei mir alles flüssig animiert ablaufen.
Bei der Rotation eines Steines soll man so zB wirklich die Rotation sehen, d.h. ich bewege den Stein pixel per pixel mit sehr geringen Sleep-Times dazwischen, um das darzustellen.
Und hier bekomme ich jetzt ein Problem, das ich nicht mehr so angehen kann wie bei meinem Classic Tetris damals:
Ich habe viele Ereignisse im Spiel, die Unterbrechungen haben müssen, um zeichnerisch einen flüssigen Ablauf darstellen zu können. Die Eregnisse dauern unterschiedlich lange, die sleep-times sind auch verschieden. zB dreht sich ein Stein schneller ( = sleep time gering) als er sich nach unten bewegt ( = sleep time etwas länger).
Trotzdem muss alles gleichzeitig geschehen, und wenn der Stein halt schon fertig gedreht ist, bevor er sich ein Stück nach unten bewegt hat, dann ist das halt so. Ihr wisst, was ich meine.
Und dabei bleibt es ja nicht: Ich hab noch Kettenexplosionen usw.
Gut, ich dachte mir jetzt: Hm, da ich nicht anfangen kann, für jedes Event einen eigenen Thread zu starten (weil schnell alles ruckelt und abstürzt, wenn man mal eben 80+ Threads hat, was zB bei einer Kettenexplosion so sein würde), muss man kucken, dass man die einzelnen Aufgaben, die anstehen, in einen einzigen Thread packt (den Gameloop halt).
Aber irgendwie muss man die Threads ja synchronisieren, irgendwie ist das ziemlich übel :autsch:
Hier mal meine Herangehensweise:
Sagen wir, ich habe eine Klasse, die eine aufgabe beschreibt (und die erstmal abstrakt ist):
Code:
public abstract class Task {
protected Object myItem;
protected int sleepDelay;
protected int loops; // oder duration, oder etwas ähnliches
public Task(int sleepTime, int loops, Object object) {
myItem = object;
this.sleepDelay = sleepTime;
this.loops = loops;
}
// hier noch getter für sleepDelay und loops
public abstract void toDo();
}
ein Task dann so, dass darin steht, was passieren soll.
So wäre ein spezifischer Task zB "Task_SteinNachUntenBewegen":
Code:
public class Task_SteinNachUntenBewegen extends Task{
public Task_SteinNachUntenBewegen(SpielStein stein) {
super(10, 10 ,stein);
}
@Override
public void toDo(){
(SpielStein) object . bewegeEinenPixelNachUnten();
}
}
Dieser Task würde nun heissen: Du hast nen Spielstein, bewege den insgesamt 10 Pixel nach unten
(weil du 10x die Methode, die in toDo() stehst aufrufen sollst). Das ganze dauert 100ms, weil du immer
10 ms warten sollst.
Gut, als letztes eine Klasse die irgendwie ne Liste von Tasks hat. Sagen wir mal, die Liste hat im Moment nur 2 Tasks, und es sind beide SteinNachUntenBewegen-Tasks. Die wurden jetz hinzugefügt und im Game sollen jetz 2 SpielSteine gleichzeitig sich runterbewegen.
So weit, so gut, das is einfach: Im GameLoop rufen wir die Methode fireTasks() auf, wo auch immer diese MEthode steht oder zu welchen Klasse sie gehört. Is ja erstmal egal.
Im Endeffekt würde das so aussehen, mit 2 Task_SteinNachUntenBewegen Tasks in der Liste:
Code:
public void fireTasks(){
int loops = listeVonTasks.get(0).getLoops();
int sleepTime = listeVonTasks.get(0).getSleepTime();
while(loops > 0){
for(int i = 0; i<listeVonTasks.size(); i++){
listeVonTasks.get(i).toDo();
}
meinSpielFenster.repaint(); // das kennt er halt
try{
Thread.sleep(sleepTime);
} catch (...) {}
loops--;
}
}
edit:
Jetzt krieg ich wahrscheinlich ein paar virtuelle Fäuste ins Gesicht, aber ich lass erstmal eine konkrete Fragestellung weg, weil ich mir noch darüber klar werden möchte
Ich bedanke mich hier schon mal bei jedem, der sich das durchgelesen hat -- es war NICHT umsonst
Es wär nett, wenn Interessierte mal wieder vorbeischauen, ich werde dann in den nächsten paar Minunten/Stunden meine genau Frage formulieren. Aber es ist schonmal gut zu wissen, worum es hier geht.
Dank euch