Discussion:
Tetris programmieren - aber wie?
(zu alt für eine Antwort)
Sandro
2004-11-08 22:43:29 UTC
Permalink
Hallöchen.

Nachdem ich mein erstes Spiel in Java programmiert habe (Snake) wollte
ich mich nun an Tetris herantrauen. Nach einigen Überlegungen kam ich
aber zu keiner zündenden Idee. Kann mir vielleicht jemand einen Tipp
geben?
Ich hab auch schon wie verrückt nach nem Tutorial gegoogelt aber ohne
Erfolg.
Wäre echt super wenn mir jemand ein paar Hinweise geben könnte, damit
ich wenigstens irgendwo anfangen kann.
Wie implementiere ich am besten die verschiedenen Figuren, die
Rotation derer sowie die Kollisionsabfrage?
Da mir jegliche Idee fehlt, bin ich für jeden Rat dankbar
Kai-Uwe Klavei
2004-11-08 23:12:48 UTC
Permalink
Post by Sandro
Nachdem ich mein erstes Spiel in Java programmiert habe (Snake)
wollte ich mich nun an Tetris herantrauen. [...] Wäre echt super wenn
mir jemand ein paar Hinweise geben könnte, damit ich wenigstens
irgendwo anfangen kann. Wie implementiere ich am besten die
verschiedenen Figuren, die Rotation derer sowie die
Kollisionsabfrage? Da mir jegliche Idee fehlt, bin ich für jeden Rat
dankbar
http://www.ibm.com/developerworks/java/library/j-tetris/index.html
http://fivedots.coe.psu.ac.th/~ad/jg/
http://javaboutique.internet.com/tutorials/Java_Game_Programming/
http://www.gamedev.net/reference/articles/article1360.asp

Gruß Kai-Uwe
Frank Buss
2004-11-08 23:59:29 UTC
Permalink
Post by Sandro
Nachdem ich mein erstes Spiel in Java programmiert habe (Snake) wollte
ich mich nun an Tetris herantrauen. Nach einigen Überlegungen kam ich
aber zu keiner zündenden Idee. Kann mir vielleicht jemand einen Tipp
geben?
Ich hab auch schon wie verrückt nach nem Tutorial gegoogelt aber ohne
Erfolg.
neben den Tutorial und Beispielen kann es auch hilfreich sein, sich das
selbst zu erarbeiten, da man dabei viel lernen kann, vor allen Dingen,
wie Programmieraufgaben im allgemeinen angeht.
Post by Sandro
Wäre echt super wenn mir jemand ein paar Hinweise geben könnte, damit
ich wenigstens irgendwo anfangen kann.
da du ja schon ein Snake-Spiel programmiert hast, kannst du das als Basis
nehmen und einfach mal ein paar Steine fallen lassen.
Post by Sandro
Wie implementiere ich am besten die verschiedenen Figuren, die
Rotation derer sowie die Kollisionsabfrage?
Da mir jegliche Idee fehlt, bin ich für jeden Rat dankbar
die Figuren sind doch zweidimensionale Anordnungen von Stein / Nicht-
Stein Zuständen. Wie kann man sowas in Java darstellen? Drehung brauchst
du nur in 90 Grad Schritten, wie ändern sich dabei x/y-Koordinaten?
Kollisionsabfrage ist nach diesen Vorarbeiten dann trivial.
--
Frank Buß, ***@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Jonathan Heinen
2004-11-09 01:49:08 UTC
Permalink
Post by Frank Buss
die Figuren sind doch zweidimensionale Anordnungen von Stein / Nicht-
Stein Zuständen. Wie kann man sowas in Java darstellen? Drehung brauchst
du nur in 90 Grad Schritten, wie ändern sich dabei x/y-Koordinaten?
Kollisionsabfrage ist nach diesen Vorarbeiten dann trivial.
hmm ich habe die gesamten GeschiStunden der 12 damit verbracht mir zu
überlegen wie man die Steine schön dreht!
Als ich dann nach dem Abi in Kolumbien mal langeweile hatte meinte ich mir
wär eine Lösung eingefallen! Aber die bekam ich dann später nicht mehr hin
=) .. *G* ... ich habe mich entschieden das Aussehen jedes Steines mit jeder
Drehung zu merken =)

jonathan
Frank Buss
2004-11-09 11:16:00 UTC
Permalink
Post by Jonathan Heinen
hmm ich habe die gesamten GeschiStunden der 12 damit verbracht mir zu
überlegen wie man die Steine schön dreht!
Als ich dann nach dem Abi in Kolumbien mal langeweile hatte meinte ich
mir wär eine Lösung eingefallen! Aber die bekam ich dann später nicht
mehr hin =) .. *G* ... ich habe mich entschieden das Aussehen jedes
Steines mit jeder Drehung zu merken =)
da musst du dann ja jeden Stein viermal eintippen. Drehung ist recht
einfach und sollte auch in der Schule vorgekommen sein:

x' = x * cos(alpha) - y * sin(alpha)
y' = x * sin(alpha) + y * cos(alpha)

und da sin(90)=1 und cos(90)=0 ist, läßt sich das wunderbar vereinfachen:

x' = -y
y' = x

kann man mit etwas räumlichen Vorstellungsvermögen auch leicht sehen. Auf
ein Array angewendet und nach der Nullpunktverschiebung kopierst du also
nur jede Zeile des zu drehenden Array in eine Spalte des gedrehten Arrays.

Mal testen (tut mir leid, habe gerade meine Lisp-Phase :-)

(defun dreh-stein (stein)
(destructuring-bind (width height) (array-dimensions stein)
(let ((stein2 (make-array (list width height) :initial-element 0)))
(loop for x from 0 below width do
(loop for y from 0 below height do
(setf (aref stein2 (- height y 1) x)
(aref stein x y))))
stein2)))

(defun print-stein (stein)
(destructuring-bind (width height) (array-dimensions stein)
(loop for y from 0 below height do
(loop for x from 0 below width do
(princ (if (= 1 (aref stein x y)) "#" " ")))
(terpri))))

(defun test ()
(let ((stein (make-array '(4 4) :initial-contents
'((1 0 0 0)
(1 0 0 0)
(1 1 0 0)
(0 0 0 0)))))
(loop repeat 4 do
(print-stein stein)
(setf stein (dreh-stein stein)))))


(test) =>

###
#


#
#
##



#
###

##
#
#

klappt!
--
Frank Buß, ***@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Jonathan Heinen
2004-11-09 12:55:08 UTC
Permalink
Post by Frank Buss
Post by Jonathan Heinen
hmm ich habe die gesamten GeschiStunden der 12 damit verbracht mir zu
überlegen wie man die Steine schön dreht!
Als ich dann nach dem Abi in Kolumbien mal langeweile hatte meinte ich
mir wär eine Lösung eingefallen! Aber die bekam ich dann später nicht
mehr hin =) .. *G* ... ich habe mich entschieden das Aussehen jedes
Steines mit jeder Drehung zu merken =)
da musst du dann ja jeden Stein viermal eintippen. Drehung ist recht
x' = x * cos(alpha) - y * sin(alpha)
y' = x * sin(alpha) + y * cos(alpha)
Hmm ... die Betonung sollte auf SCHÖN drehen liegen!
Das Problem ist einfach das wenn man die Steine so dreht wie du das hier
vorschlägst gewisse Steine anfangen zu Hüpfen?
Also ganz sicher bin ich mir jetzt net man müsste das jetzt noch mal
ausprobieren aber die Frage ist irgendwie immer worum drehe ich?

z.B. der lange Stein der soll sich ja nicht um den Block oben links drehen
sonst rotiert der ja wie verück! .. Es ist vielmehr die Idee das der zweite
Block der sein sollte um den man dreht.

Ähnlich ist es auch bei dem T. Anders ist es beim Quadrat weil hier sollte
um den Mittelpunktgedreht werden ...

Ich weisnet ob du verstehst was ich meine!

Jonathan
Jochen Theodorou
2004-11-09 14:29:48 UTC
Permalink
Jonathan Heinen schrieb:

[...]
Post by Jonathan Heinen
Hmm ... die Betonung sollte auf SCHÖN drehen liegen!
Das Problem ist einfach das wenn man die Steine so dreht wie du das hier
vorschlägst gewisse Steine anfangen zu Hüpfen?
Also ganz sicher bin ich mir jetzt net man müsste das jetzt noch mal
ausprobieren aber die Frage ist irgendwie immer worum drehe ich?
das Problem sieht man ja schon beim "L", das Frank hier gezeigt hat.
Post by Jonathan Heinen
z.B. der lange Stein der soll sich ja nicht um den Block oben links drehen
sonst rotiert der ja wie verück! .. Es ist vielmehr die Idee das der zweite
Block der sein sollte um den man dreht.
Ähnlich ist es auch bei dem T. Anders ist es beim Quadrat weil hier sollte
um den Mittelpunktgedreht werden ...
Ich weisnet ob du verstehst was ich meine!
aber man könnte es sich auch ganz einfach machen und alles im Vorraus
abspeichern, als eine Art Sprite. Wenn man einfach ein 4x4-Feld nimmt,
mit einer 1 wo der Stein existiert und einer 0 wo nix ist, dann kann man
das ganze noch in ein byte packen

Ein "L" ist dann z.B.:

|Grundstellung | Drehung 1 | Drehung 2 | Drehung 3 |
|------------------------------------------------------
| " # " | " #" | " ## " | " " |
| " # " | " ###" | " # " | " ###" |
| " ## " | " " | " # " | " # " |
| " " | " " | " " | " " |
|------------------------------------------------------
| 4,4,6,0 | 1,7,0,0 | 6,2,2,0 | 0,7,4,0 |


die Werte unten sind die Werte für das byte[] - man kann natürlich auch
2 Werte in einem byte speichern, wenn man will, oder alles zusammen in
einem int...

class SpriteStruct {
byte row1, row2, row3, row4;
SpriteStruct (byte r1, byte r2, byte r3, byte r4) {
row1=r1; row2=r2; row3=r3; row4=r4;
}
}

(grmpf.. in C geht das irgendwie schöner)

SpriteStruct[] stoneL = new SpriteStruct[]{
new SpriteStruct(4,4,6,0),
new SpriteStruct(1,7,0,0),
new SpriteStruct(6,2,2,0),
new SpriteStruct(0,7,4,0)};

und das für alle Steine... diese Struktur kann man dann auch für
Kollisionstest benutzen indem <<, >> und & benutzt.

Ein Stein auf dem Feld müsste dann nur seine Position speichern und
welches "Drehbild" er ist.

class StoneOnField{
int structIndex;
SpriteStruct[] structs;
int x, y;
}

und eine drehung ist dann:

public void rotateLeft(){
structIndex = (structIndex+1)%4;
}

public void rotateRight(){
structIndex = (4+structIndex-1)%4;
}

oder auch:

public void rotate(boolean left) {
if (left) {
structIndex = (structIndex+1)%4;
} else {
structIndex = (4+structIndex-1)%4;
}
}

usw...

aber solche Pfennigfuchserei mit Rechenzeit ist ja nichtmehr so modern;)

Gruss theo
Jonathan Heinen
2004-11-10 07:12:53 UTC
Permalink
[...]
Post by Jochen Theodorou
aber man könnte es sich auch ganz einfach machen und alles im Vorraus
abspeichern, als eine Art Sprite. Wenn man einfach ein 4x4-Feld nimmt, mit
einer 1 wo der Stein existiert und einer 0 wo nix ist, dann kann man das
ganze noch in ein byte packen
|Grundstellung | Drehung 1 | Drehung 2 | Drehung 3 |
|------------------------------------------------------
| " # " | " #" | " ## " | " " |
| " # " | " ###" | " # " | " ###" |
| " ## " | " " | " # " | " # " |
| " " | " " | " " | " " |
|------------------------------------------------------
| 4,4,6,0 | 1,7,0,0 | 6,2,2,0 | 0,7,4,0 |
Hihi ... ja genau darum ging es ja =) .. Ich meinte ja ich hätte keine
andere Lösung gefunden um die Steine schön zu drehen =)
So habe ich es dann im enddefekt auch gemacht. Fand es aber nicht gerade die
schönste Lösung!

Jonathan
Jochen Theodorou
2004-11-10 12:45:33 UTC
Permalink
Post by Jonathan Heinen
[...]
Post by Jochen Theodorou
aber man könnte es sich auch ganz einfach machen und alles im Vorraus
abspeichern, als eine Art Sprite. Wenn man einfach ein 4x4-Feld nimmt, mit
einer 1 wo der Stein existiert und einer 0 wo nix ist, dann kann man das
ganze noch in ein byte packen
|Grundstellung | Drehung 1 | Drehung 2 | Drehung 3 |
|------------------------------------------------------
| " # " | " #" | " ## " | " " |
| " # " | " ###" | " # " | " ###" |
| " ## " | " " | " # " | " # " |
| " " | " " | " " | " " |
|------------------------------------------------------
| 4,4,6,0 | 1,7,0,0 | 6,2,2,0 | 0,7,4,0 |
Hihi ... ja genau darum ging es ja =) .. Ich meinte ja ich hätte keine
andere Lösung gefunden um die Steine schön zu drehen =)
So habe ich es dann im enddefekt auch gemacht. Fand es aber nicht gerade die
schönste Lösung!
Das Problem ist folgendes.. nehmen wir an du hast die Koordinaten ax,ay
und drehst um 0,0 dann ergibt sich folgendes:

Grundstellung: x=ax,y=ay
Drehung 1: x=-ay,y=ax
Drehung 2: x=-ax,y=-ay
Drehung 3: x=ay,y=-ax

das heisst rein rechnerisch kommt amn mit Drehung 4 dann auch wieder auf
die Grundstellung, das ist nicht das Problem. Das Problem ist, dass man
bei Spielen oft einen Kompromiss zwischen "gut aussehen" und "korrekt"
eingehen muss.das Problem liegt in dem Fall in der Wahl des
Mittelpunktes wenn du den Stein "####" betrachtest, so besteht er aus 4
Teilen: (-1.5,0),(-.5,0),(.5,0),(1.5,0) und sagen wir -1.5 geht von -2
bis -1, -.5 geht von -1 bis 0, aber was machen wir dann mit der 0? Ok,
sagen wir mal dass die 0 von 0-1 geht, .5 von 0-1 und 1.5 von 1-2, dann
bedeutet dass, das 0 und .5 den selben Bereich bezeichnen, was zu
Problemen führen könnte.. aber gut schauen wir uns dass mal graphisch an:

2112
+2" " " # " " " " # "
+1"####" Drehung-> " # " Drehung-> "####" Drehung-> " # "
-1" " " # " " " " # "
-2" " " # " " " " # "

und es gibt kein Problem
entsprechend gilt für das T: (-.5,0),(0,0),(+.5,0),(0,+0.5), das ist dann:

2112
+2" "
+1" ## "
-1" "
-2" "

und da fehlt plötzlich ein Teil, weil (0,0) und (0,.5) den selben
Bereich bezeichnen. Also neue Koordinaten: (-.5,0),(0,0),(+1.5,0),(0,+1.5):

2112
+2" # " " # " " " " # "
+1" ###" Drehung-> " ##" Drehung-> " ###" Drehung-> "# # "
-1" " " # " " " " # "
-2" " " " " # " " "

und plötzlich hängt der Stein nicht mehr zusammen man könnte die
Koordinaten nochmal ändern (-.5,0.5),(0,0.5),(+1.5,0.5),(0,+1.5):

2112
+2" # " " # " " " " # "
+1" ###" Drehung-> " ##" Drehung-> " " Drehung-> "## "
-1" " " # " " ###" " # "
-2" " " " " # " " "

und schon springt der Stein wieder ein wenig, dann erwarten würde man:

2112
+2" # " " # " " " " # "
+1" ###" Drehung-> " ##" Drehung-> " ###" Drehung-> " ## "
-1" " " # " " # " " # "
-2" " " " " " " "


Das Problem ist also nicht die Formel, oder den Mittelpunkt zu finden.
Das Problem ist, dass man man einen Bereich bezeichnet und dieser sich
optisch schlecht drehen lässt, wenn man gleiche Bereiche hat wie (0,0)
und (0.5,0), (0,.5) oder (.5,.5)

Will man es Graphics2D-mässig machen, so definiert man ein Polygon und
eine affine Transformation und hat dann nix praktisches für den
Kollisionstest.

So gesehen ist die Lösung von mir doch einfach, oder nicht? Und schön...
naja... du kannst dir die Zahlen ja berechnen lassen:

class SpriteStruct {
byte[] rows;
SpriteStruct (String[] rows) {
for (int i=0; i<4; i++) {
int n = 0;
for (int j=0; j<4; <++) {
int val = rows[i].charAt(j)!=' '?1:0;
n = n<<1 +val;
}
}
}
}

SpriteStruct[] stoneT = new SpriteStruct[]{
new SpriteStruct(new String[]{
" # "
" ###"
" "
" "
}),
new SpriteStruct(new String[]{
" # "
" ##"
" # "
" "
}),
new SpriteStruct(new String[]{
" "
" ###"
" # "
" "
}),
new SpriteStruct(new String[]{
" # "
" ## "
" # "
" "
})
};


oder wenn man es nebeneinander haben will:

SpriteStruct[] stoneT = buildStoneSpins(new String[]{
" # ", " # ", " ", " # "
" ###", " ##", " ###", " ## "
" ", " # ", " # ", " # "
" ", " ", " ", " "
});


und die entsprechende Funktion:

SpriteStruct[] buildStoneSpins(String[] parts) {
SpriteStruct[] structs = new SpriteStruct[4];
for (int i=0; i<4; i++) {
structs [i] = new SpriteStruct(new String[]{
parts[i],parts[i+4],parts[i+8],parts[i+16]
});
}
}

immer noch so unschön?


Gruss theo
Jonathan Heinen
2004-11-11 04:27:07 UTC
Permalink
.............


Also grundsätzlich sag ich ja nix gegen die Lösung =) Ich hab ja selbst
behauptet dass ich davon überzeugt bin das es anders nicht geht =) Ich
dachte das hätte ich auch klar gemacht! Aber gut schöner hätte ich es halt
gefunden wenn man den Stein nur einmal beschreiben muß und dann ne Funktion
hat die den Stein dreht. Auch wenn ich selbst der Überzeugung bin das es,
falls es diese Funktion geben sollte, sie auf keinen Fall trivial ist!

Jonathan

Frank Buss
2004-11-09 15:12:46 UTC
Permalink
Post by Jonathan Heinen
Hmm ... die Betonung sollte auf SCHÖN drehen liegen!
Das Problem ist einfach das wenn man die Steine so dreht wie du das
hier vorschlägst gewisse Steine anfangen zu Hüpfen?
Also ganz sicher bin ich mir jetzt net man müsste das jetzt noch mal
ausprobieren aber die Frage ist irgendwie immer worum drehe ich?
also ehrlich gesagt, mit so wenig räumlichen Vorstellungsvermögen würde
ich dir davon abraten, ein Spiel schreiben zu wollen. Etwas Mathematik
kann da helfen, das zu verbessern.

Mein Ansatz dreht um den Mittelpunkt. Ich hatte das "L" aber an den Rand
gelegt, daher sah das schlecht aus. Wenn man das in die Mitte legt, dann
springt das nicht mehr. Außerdem kann man je nach Steingröße und
Schwerpunkt des Steins entweder ein 3x3 oder 4x4 Array nehmen.

..#
###
...

.#.
.#.
.##

...
###
#..

##.
.#.
.#.
--
Frank Buß, ***@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Jonathan Heinen
2004-11-10 07:17:04 UTC
Permalink
[...]
Post by Frank Buss
also ehrlich gesagt, mit so wenig räumlichen Vorstellungsvermögen würde
ich dir davon abraten, ein Spiel schreiben zu wollen. Etwas Mathematik
kann da helfen, das zu verbessern.
Nana! =)
Post by Frank Buss
Mein Ansatz dreht um den Mittelpunkt. Ich hatte das "L" aber an den Rand
gelegt, daher sah das schlecht aus. Wenn man das in die Mitte legt, dann
springt das nicht mehr. Außerdem kann man je nach Steingröße und
Schwerpunkt des Steins entweder ein 3x3 oder 4x4 Array nehmen.
Ja da kommen wir der Sache schon etwas näher! Man kommt jedenfalls nicht
immer mit der selben Arraygröße aus!
Was machen wir den jetztz mit dem Langem also sozusagen dem I ?
3X3 passt er net rein! 4X4 hat er wieder 4 verschiedene Stellungen und ich
meine er sollte nur zwei haben!

Jonathan
Frank Buss
2004-11-10 20:05:20 UTC
Permalink
Post by Jonathan Heinen
Ja da kommen wir der Sache schon etwas näher! Man kommt jedenfalls
nicht immer mit der selben Arraygröße aus!
Was machen wir den jetztz mit dem Langem also sozusagen dem I ?
3X3 passt er net rein! 4X4 hat er wieder 4 verschiedene Stellungen und
ich meine er sollte nur zwei haben!
wie Jochen ja schon gut erklärt hat, das Problem ist doch nicht ganz so
einfach, wenn man keine Sprünge haben will. Ist also vielleicht besser,
alle Drehungen einfach selbst zu zeichnen, zumal bei zwei Steinen nur
jeweils 2 verschiedene Formen durch 90 Grad Drehungen möglich sind und bei
dem Quadrat gar nix gedreht wird, was man entsprechend optimiert
programmieren kann und sich somit Tipparbeit spart.

Übrigens: In ein paar Tagen poste ich einen neuen Wettbewerb (hier der
vorhergehende: http://www.frank-buss.de/challenge/index.html ), bei dem es
diesmal sogar Sachpreise zu gewinnen gibt, falls dir das Schreiben des
x-ten Tetris-Clones zu langweilig werden sollte :-)
--
Frank Buß, ***@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Ortwin Glück
2004-11-09 14:41:33 UTC
Permalink
Post by Jonathan Heinen
hmm ich habe die gesamten GeschiStunden der 12 damit verbracht mir zu
überlegen wie man die Steine schön dreht!
Du hättet lieber eine Stunde lang in Mathe aufgepasst wo es um
Rotationsmatrizen ging...
Peter Wernerus
2004-11-10 20:15:02 UTC
Permalink
Post by Ortwin Glück
Post by Jonathan Heinen
hmm ich habe die gesamten GeschiStunden der 12 damit verbracht mir zu
überlegen wie man die Steine schön dreht!
Du hättet lieber eine Stunde lang in Mathe aufgepasst wo es um
Rotationsmatrizen ging...
Sowas hattest du in Mathe? Respekt. Ich musste dafür in die
Computergrafik 1 Vorlesung. Nicht das es schwierig wäre, aber es hat
keine Sau interessiert.
Für Tetrix würde ich allerdings Look-Up-Tables verwenden. Sind ja nicht
so viele verschiedene Fälle. Wenn der Geschwindigkeitsvorteile bei Tetris
auch wahrscheinlich keine Rolle spielt und numerische Stabilität auch
irrelevant sind, so sind Look-Up-Table doch relative beliebt in der
Computergrafik. Speicher tritt halt gegenüber Performance mittlerweile in
den Hintergrund.

Grüße,
Peter Wernerus
Jochen Theodorou
2004-11-10 20:43:16 UTC
Permalink
Peter Wernerus schrieb:
[...]
Post by Peter Wernerus
Für Tetrix würde ich allerdings Look-Up-Tables verwenden.
Also das finde ich hier overkill, weil man ja nur 2 Drehungen hat 90°
links oder rechts. und für die eine Drehung gilt: x'=-y, y'=x und für
die andere: x'=y,y'=-x

Dafür braucht man keine Lookuptable bzw. es reicht die, die im code steht.
Post by Peter Wernerus
Sind ja nicht so viele verschiedene Fälle.
ja.. 2.. wobei einer nur die 3te Iteration des anderen ist
Post by Peter Wernerus
Wenn der Geschwindigkeitsvorteile bei Tetris
auch wahrscheinlich keine Rolle spielt und numerische Stabilität auch
irrelevant sind, so sind Look-Up-Table doch relative beliebt in der
Computergrafik.
Das wiederum stimmt, es ist beliebt. Ich erinnere mich noch sehr fut an
meine frühen Pascalzeiten, wo ich eine Festkommazahlenimplementierung
benutzt hatte um den Geschwindigkeitsvorteil bei Ganzzahloperationen zu
bekommen und dann natürlich auch Lookuptables verendet hatte... das ist
aber nix mit dem man anfangen sollte ein solches Problem zu lösen.
Post by Peter Wernerus
Speicher tritt halt gegenüber Performance mittlerweile in
den Hintergrund.
kommt immer auf das Problem und die bisherige Lösung an.. manchmal kann
man beides machen, Speicher sparen und Performance hinzu gewinnen.

Gruss theo
Daniel Kretzler
2004-11-09 10:00:42 UTC
Permalink
Post by Sandro
Hallöchen.
Nachdem ich mein erstes Spiel in Java programmiert habe (Snake) wollte
ich mich nun an Tetris herantrauen. Nach einigen Überlegungen kam ich
aber zu keiner zündenden Idee. Kann mir vielleicht jemand einen Tipp
geben?
Ich hab auch schon wie verrückt nach nem Tutorial gegoogelt aber ohne
Erfolg.
Wäre echt super wenn mir jemand ein paar Hinweise geben könnte, damit
ich wenigstens irgendwo anfangen kann.
Wie implementiere ich am besten die verschiedenen Figuren, die
Rotation derer sowie die Kollisionsabfrage?
Da mir jegliche Idee fehlt, bin ich für jeden Rat dankbar
ganz naiv wuerde ich mal folgendermassen herangehen:

'hintergrund' is ein grosser array, der zun"achst mit 'false' gefuellt
wird. (sobald steine zum liegen kommen, werden die entsprechenden felder
auf true gesetzt ... dazu spaeter mehr)

die figuren sind ebenfalls arrays, die ebenfalls nach dem true/false
schema belegt sind.
das quadrat is also ein 2x2 array, der nur aus true werten besteht, die
L foermige figur also ein 3X2 array, bei dem noch zwei felder auf false
gesetzt sind. beim rotieren wird die figur dann halt von nem 3x2 array
zu nem 2x3 array umkopiert. da das rotieren wohl ziemlich oft vorkommen
wird, wuerde ich fuer jede figur gleich alle moeglichen rotationsfiguren
anlegen. jedes fallende objekt hat dann die methoden rotateLeft() und
rotateRight(), die die gerade angezeigte Figur durch die jeweilige
Rotationsfigur ersetzen.

beim fallen der objekte kennst du ja immer deren momentane position.
beim weiterfallen sind sie eine zeile tiefer als momentan. also pruefst
du ob ein true wert deiner figur und ein true wert des 'hintergrunds'
aufeinander treffen wuerden, wenn die figur eine zeile tiefer rutscht.
ist dies der fall, so hast du eine kollision und darfst deshalb den
schritt des fallens nicht durchfuehren. die figur wird teil des
hintergrundes und das naechste objekt beginnt zu fallen.

bevor das neue objekt startet, musst du natuerlich noch pruefen ob die
letzte figur eine zeile vollstaendig aufgefuellt hat, so dass diese
geloescht werden kann. dazu bleibt dir nicht viel anderes uebrig, als
den hintergrund zeilenweise zu durchsuchen und zu pruefen ob alle
elemente der zeile auf true gesetzt sind.


optimierungsmoeglichkeiten gibt es sicher viele, aber du wolltest ja nur
ein paar ideen.
die datenstruktur des hintergrundes koennte man sicher anders
realisieren als durch ein array. gerade beim entfernen von vollen zeilen
und dem anschliessenden herabfallen der darueberliegenden zeilen koennte
man sich ein kopieren der herabfallende zeilen ersparen, wenn man jede
zeile als einzelnes objekt in einer queue implementieren wuerde. da
koennte man einfach das betreffende objekt loeschen und den zeiger auf
das naechste element verbiegen.
die queue implementierung erschwert aber die kollisionsabfrage und das
aktualisieren des hintergrundes im falle einer kollision etwas.
naja, so richtig schwer wird's auch nicht, aber is halt icht mehr ganz
so intuitiv dann.
die herabfallenden figuren koennte man natuerlich auch als queue der
einzelnen zeilen implementieren. evtl wuerde das die kollisionabfrage
wieder vereinfachen.
Loading...