[JAVA] Tetris - Rotation der Steine

Ich bin im Moment am grübeln, wie ich die Rotation der Steine in meinem Tetris-Spiel am besten programmiere.

Das Spielfeld ist ein zweidimensionales Array. Jetzt such ich eine Funktion die mir den aktuellen Spielstein um 90° dreht, mir fällt im Moment aber nicht ein, wie ich das realisieren könnte. Kann mir jemand helfen? Danke!

Gruß, Boar
 
Original von Boar
Das Spielfeld ist ein zweidimensionales Array.

Was mich noch interessieren würde: Wie stellst du die Steine als Java-Objekte dar?
Vielleicht kann ich dir helfen, wenn ich etwas mehr über deine bisherige Lösung des Problems "Tetris" (wichtige Quellcodestücke etc.) wüßte.

z.B. könnte man von jeder Form in jeder Ausrichtung ein Bild erstellen, oder die Formen aus einzelnen Quadraten zusammen setzen, oder oder oder

Bitte nähere Informationen :D
 
Oh, sorry! Das hab ich wohl vergessen zu erwähnen. Trotzdem schon mal danke für die Hilfe!

Ein Stein setzt sich bei mir aus einzelnen Quadraten zusammen. In einer int[][] Array speicher ich dann die Position (1 steht für belegtes Feld, 0 für freies Feld, 2 für den aktuellen Stein).

Die Steine haben zum Beispiel die folgenden Koordinaten (jeder Stein besteht aus 4 Quadraten):

Stein 1: [3][1], [4][1], [5][1], [6][1]

Stein 2: [3][1], [4][1], [4][2], [5][2]

Wenn ich dann die Pfeiltaste nach unten drück, bewegt sich jedes Quadrat des Steins von [x][y] zu [x][y+1]. Entsprechend verändert sich der x-Wert bei der links/rechts-Bewegung.

Nach einer 90°-Drehung müsste Stein 1 dann z.B. so aussehen: [3][1], [3][2], [3][3], [3][4].

Ich denke das war halbwegs verständlich. :) Wenn ich sonst noch was erklären soll sag bescheid.

Gruß, Boar
 
Also, ich hab da jetzt mal n bisschen was zusammen gecodet.

Theoretisch müsste es funktionieren, da ich aber keinen Java-Kompiler hab, konnt ichs nicht testen :rolleyes:

Kann auch sein, dass du einiges umschreiben musst (ich bin Java-Script gewöhnt, da kennt man keine Datentypen :D). Kann gut sein, dass ich bei der Variablen Deklaration nen Fehler gemacht hab, ganz sicher ist aber das Math.Round falsch (Glaube ich :D ).

Ich bin von folgender Situation ausgegangen:
Code:
// du hast einen 2D-Array:
matrix = new int [][];

// und beschreibst ihn mit leeren Feldern
for (i=; i< 10; i++ ) {
for (j=; j< 10; j++ ) {
matrix[i][j]= 0;
}
}

// Dann setzt man einen Stein zum Testen
matrix[3][1] = 2;
matrix[4][1] = 2;
matrix[5][1] = 2;
matrix[6][1] = 2;

// und führt die Funktion aus
rotate();

Hier dann die Funktion:
Code:
function rotate() {
steinRotated = new int[][];
centerX = new int;
centerY = new int;
stone = new int[][];
var k = 0;
// Das waren viele schöne Variablen

//Zuerst finden wir den aktiven Stein und schreiben ihn so auf, wie ich das sage ;-)
for (i=; i< 10; i++ ) {
for (j=; j< 10; j++ ) {
if(matrix[i][j] == 2) {
stone[k][0]= i;
stone[k][1]= j;
k++;
}
}
}
// k gibt an, wie viele Steine man aktiv hat (sollten 4 sein) + 1

// Nun wird dieser Stein aus der Matrix gelöscht
for (i=0; i<k; i++ ) {
matrix[stone[i][1]][stone[i][2]] = 0;
}

// Als nächstes bestimmen wir den Mittelpunkt des Steins:
for (i=0; i<k; i++ ) {
centerX = centerX + stein[i][1];
centerY = centerY + stein[i][2];
}
// Dazu berechnen wir den Durchschnitt der X bzw. Y Koordinaten
centerX = Math.round(centerX/k);
centerY = Math.round(centerY/k);

// Jetzt können wir jeden Stein einzeln drehen und in den neuen Array schreiben
for (i=0; i<k; i++ ) {

// Für X drehen nach Y:
if(stein[i][1] != centerX) {
if (stein[i][1] > centerX) {
steinRotated[i][2] = centerY + (stein[i][1] - centerX);
} else {
steinRotated[i][2] = centerY - (stein[i][1] - centerX);
}
}
// Für Y drehen nach X:
if(stein[i][2] != centerY) {
if (stein[i][2] > centerY) {
steinRotated[i][1] = centerX + (stein[i][2] - centerY);
} else {
steinRotated[i][1] = centerX - (stein[i][2] - centerY);
}
}
/*
 so wird:
 0000
 0000
 1234
 0000
 0000
 0000

zu:
 0000
 0040
 0030
 0020
 0010
 0000

*/
}
// Zum Schluß alles wieder in die Matrix einfügen:
for (i=0; i<k; i++ ) {
matrix[steinRotated[i][1]][steinRotated[i][2]] = 2;
}

// Funktion Ende
}

Ich hoffe du kannst mit dem Algotihmus was anfangen und er hilft dir.
Mir hats auf jeden Fall Spass gemacht ;)
 
Hi p-Logic!

Wow, das du dir so viel Mühe gibst hätt ich nicht gedacht, danke!

Ein paar Fragen hab ich dazu:
- die Variablen stone (z.B. Code-Zeile 13) und stein (z.B. Code-Zeile 39) sind die selben, oder?
- am Anfang(Code-Zeile 13 und 14) verwendest du stone[k][0] und stone[k][1], im weiteren Verlauf dann nur noch stone[k][1] und stone[k][2]. ich denke mal, dass das auch das gleiche ist,oder?

Wenn ich recht habe mit meinen Vermutungen, dann funktioniert dein Rotieralgorithmus nicht richtig. Der Fehler liegt bei der Berechnung von steinRotated, ich weiß aber nicht was da falsch ist.

Achso, und Math.round() kenn ich nicht. Das geht aber einfach mit einem cast-Befehl zu int:
centerX = (int) (centerX/k)
Da centerX aber schon vom Typ int ist, kann man den cast-Befehl auch weglassen (centerX=centerX/k) und das Ergebnis ist trotzdem eine ganze Zahl.

EDIT:
Ich hab mir jetzt was neues überlegt, es funktioniert zwar, aber noch nicht so wie ich das will. Ich lass einfach eine xy-Koordinate fest und dreh die anderen 3 um diesen festen Punkt. Das sieht dann so aus (den Code von p-Logic hab ich übernommen, nur die Drehung hab ich jetzt geändert):

Code:
//Die erste Koordinate bleibt unverändert
stoneRotated[0][0]=stone[0][0];
stoneRotated[0][1]=stone[0][1];

//Die neuen X-Werte:
stoneRotated[1][0]=stone[0][0]+(stone[0][1]-stone[1][1]);
stoneRotated[2][0]=stone[0][0]+(stone[0][1]-stone[2][1]);
stoneRotated[3][0]=stone[0][0]+(stone[0][1]-stone[3][1]);
            
//Die neuen Y-Werte:
stoneRotated[1][1]=stone[0][1]+(stone[0][0]-stone[1][0]);
stoneRotated[2][1]=stone[0][1]+(stone[0][0]-stone[2][0]);
stoneRotated[3][1]=stone[0][1]+(stone[0][0]-stone[3][0]);

Die Drehung funktioniert aber auch nicht 100% richtig, hoffentlich hat noch jemand eine bessere Idee.

Gruß, Boar
 
Original von Boar
Wow, das du dir so viel Mühe gibst hätt ich nicht gedacht, danke!
Kein Problem!
Original von Boar
Ein paar Fragen hab ich dazu:
- die Variablen stone (z.B. Code-Zeile 13) und stein (z.B. Code-Zeile 39) sind die selben, oder?
Stimmt! Erwischt :D!
Original von Boar
- am Anfang(Code-Zeile 13 und 14) verwendest du stone[k][0] und stone[k][1], im weiteren Verlauf dann nur noch stone[k][1] und stone[k][2]. ich denke mal, dass das auch das gleiche ist,oder?
Nochmal erwischt, wie gesagt, habs einfach so hin geschrieben und nicht getestet.
Original von Boar
Wenn ich recht habe mit meinen Vermutungen, dann funktioniert dein Rotieralgorithmus nicht richtig. Der Fehler liegt bei der Berechnung von steinRotated, ich weiß aber nicht was da falsch ist.
Ich hab zumindest was gefunden (wenn auch nicht den Fehler):
0000
0000
1234
0000
0000
0000
Wird um Stein 3 ((1+2+3+4)/4=2,5=3 | 4*3/4=3) gedreht:
0000
0040
0030
0020
0010
0000
Wird um Stein 2 (4*3/4=3 | (2+3+4+5)/4=3,5=4) gedreht:
0000
0000
0000
01234
0000
0000
Durch die gerundete Position Center "trudelt" der Stein aus dem Bild..

Original von Boar
Die Drehung funktioniert aber auch nicht 100% richtig, hoffentlich hat noch jemand eine bessere Idee.
An deiner Lösung kann ich eigentlich nichts finden, was funktioniert denn nicht?
 
Bei dem xxxx Stein (Also alle Quadrate in einer Reihe) funktioniert meine Rotations-Berechnung perfekt. Aber bei anderen Steinen (bei allen anderen) wie z.B. dem hier...

00000
0xx00
00xx0
00000

...macht er die Drehung falsch: Daraus wird dann nämlich das hier:

00000
0x000
0xx00
00x00
00000

Die Drehung passt net, der Stein dreht sich zwar, aber er verändert die Form (die Form sollte aber eigentlich gleich bleiben ;) ).

Ich hab jetzt schon vieles ausprobiert, aber die Variante die ich als letztes gepostet hab war die beste. Zufriedenstellend ist sie aber nicht (Es muss ja gehn, sonst gäbe es keine Tetris-Spiele :P ).

Gruß, Boar
 
Sch****! Ich merk grad, wir ham das ding gespiegel!

Ich versuch sofort was neues...

edit:
versuch mal:
Code:
//Die erste Koordinate bleibt unverändert
stoneRotated[0][0]=stone[0][0];
stoneRotated[0][1]=stone[0][1];

//Die neuen X-Werte:
stoneRotated[1][0]=stone[0][0]+(stone[0][1]-stone[1][1]);
stoneRotated[2][0]=stone[0][0]+(stone[0][1]-stone[2][1]);
stoneRotated[3][0]=stone[0][0]+(stone[0][1]-stone[3][1]);
            
//Die neuen Y-Werte:
stoneRotated[1][1]=stone[0][1]-(stone[0][0]-stone[1][0]);
stoneRotated[2][1]=stone[0][1]-(stone[0][0]-stone[2][0]);
stoneRotated[3][1]=stone[0][1]-(stone[0][0]-stone[3][0]);

Vielleicht gehts einfach..., ich rechnes mal durch...

edit2:
00000
00000
01200
00340
00000
00000
1. mal drehen:
//Die erste Koordinate bleibt unverändert
stoneRotated[0][0]=2;
stoneRotated[0][1]=3;

//Die neuen X-Werte:
stoneRotated[1][0]=2+(3-3)=2;
stoneRotated[2][0]=2+(3-4)=1;
stoneRotated[3][0]=2+(3-4)=1;

//Die neuen Y-Werte:
stoneRotated[1][1]=3-(2-3)=4;
stoneRotated[2][1]=3-(2-3)=4;
stoneRotated[3][1]=3-(2-4)=5;
00000
00000
01000
32000
40000
00000
2.mal drehen:
//Die erste Koordinate bleibt unverändert
stoneRotated[0][0]=2;
stoneRotated[0][1]=3;

//Die neuen X-Werte:
stoneRotated[1][0]=2+(3-4)=1;
stoneRotated[2][0]=2+(3-4)=1;
stoneRotated[3][0]=2+(3-5)=0;

//Die neuen Y-Werte:
stoneRotated[1][1]=3-(2-2)=3;
stoneRotated[2][1]=3-(2-1)=2;
stoneRotated[3][1]=3-(2-1)=2;
0. Spalte hinzu gefügt..
000000
430000
021000
000000
000000
000000
klappt zumindest mit diesem Stein :D
 
Hey! So gehts!

Ich unterzieh das ganze morgen dann mal einem ausführlichem Test, aber im Moment siehts so aus als würde es einwandfrei funktionieren.

Nochmal vielen Dank für deine Hilfe! Ich poste mein Prog dann mal wenn ich fertig bin.

Gruß, Boar
 
Verwendest du jetzt den Code mit Center, oder ohne?
is nämlich beides der selbe Fehler...

Ich fänds mit Center schöner :D
 
Im Moment verwende ich die Version ohne center, und zwar so:

Code:
//Die erste Koordinate bleibt unverändert
stoneRotated[0][0]=stone[0][0]+1;
stoneRotated[0][1]=stone[0][1];

// Die neuen X-Werte:
stoneRotated[1][0]=stone[0][0]+(stone[0][1]-stone[1][1])+1;
stoneRotated[2][0]=stone[0][0]+(stone[0][1]-stone[2][1])+1;
stoneRotated[3][0]=stone[0][0]+(stone[0][1]-stone[3][1])+1;
                        
// Die neuen Y-Werte:
stoneRotated[1][1]=stone[0][1]-(stone[0][0]-stone[1][0]);
stoneRotated[2][1]=stone[0][1]-(stone[0][0]-stone[2][0]);
stoneRotated[3][1]=stone[0][1]-(stone[0][0]-stone[3][0]);

Hab bei den x-Werten immer noch +1 addiert, da der Stein bei der Drehung sonst nicht auf der Stelle bleibt, sondern sich nach links bewegt.

EDIT:
Hab das Spiel jetzt soweit fertig.
Im Gegensatz zum normalen Tetris verschwinden die (horizontalen) Reihen nicht, wenn sie voll sind. Man muss versuchen das Feld (bis zum schwarzen Strich) lückenlos zu füllen. Sobald ein Stein auf dem schwarzen Strich liegt ist das Spiel beendet. Für jede Lücke erscheinen im nächsten Level 2 schwarze Steine. Wenn 50 oder mehr schwarze Steine da sind (also insgesamt mind. 25 Lücken) hat man verloren.

Zur Steuerung:
Pfeiltaste links/rechts/unten - Verschiebt den Stein in Pfeiltastenrichtung
Pfeiltaste oben - Drehung des Steins um 90° (Dank der Hilfe von p-Logic ;) )
Leertaste - Der Stein fällt sofort nach unten

Feedback, Kritik oder sonstige Tipps sind erwünscht.

Nochmal EDIT:
Meine Highscore: 1680 Pkt. am Ende von Level 6.

Gruß, Boar
 
Fragst du aus Interesse, oder weil das Spiel bei dir nicht läuft?

Ich hab das Java Runtime Environment (JRE) 1.5 drauf, hab aber gerade gesehen das Eclipse bei mir noch mit JRE 1.4.2 arbeitet.

Die .bat Datei (aus meinem zip-file) öffnet das Spiel mit dem javaw-Interpreter. Falls dir das JRE fehlt, das gibts hier: klick

Gruß, Boar
 
Lief nicht, weil ich zu ungeduldig war..
Hab JRE noch mal installiert und dann mal gewartet, bis sich was tut :D.

Ist gut geworden, fänds aber doch schöner wenn mans hinkriegt, dass sich die Steine auf der Stelle drehen ;)

Highscore: 93 Pt. am Ende von Level 1 :D
 
Zurück
Oben