Tetrisklone
Grundprinzip:
In einem begrenzten Spielfeld fallen zufällig bestimmte Steine von oben nach unten. Der Spieler kann sowohl die Steine drehen und als auch die Position, auf der sie landen, verändern. Werden komplette Reihen gebildet, lösen sich diese auf und der Spieler erhält Punkte. Die Geschwindigkeit, mit der die Steine hinunter fallen, erhöht sich pro Level. Nach einer bestimmten Anzahl aufgelöster Reihen erreicht der Spieler das nächste Level. Das Spiel endet; wenn der Spieler keine Reihen mehr auflösen kann und die Steine bis an den oberen Spielfeldrand reichen.Grunddesign:
Wir teilen das Spielfeld erstmal in ein Raster auf:_ _ _ _ _ |_|_|_|_|_| |_|_|_|_|_| |_|_|_|_|_| |_|_|_|_|_| |_|_|_|_|_| |_|_|_|_|_|Als nächstes haben wir unsere Spielsteine.
Ein Spielstein besteht aus mehreren Blöcken.
Bsp:
_
_ _ |_|
_ _ _ _ |_| |_| _ _ _ |_|
_|_|_| |_|_|_ _|_| |_|_ |_|_| _|_|_ |_|
|_|_| |_|_| |_|_| |_|_| |_|_| |_|_|_| |_|
Aus dieser Grundidee ergeben sich drei nötige Klassen: Block, Stone, Field.Ein Block hat eine X- und Y-Koordinate sowie eine Farbe. Die Koordinaten sind relativ zu dem übergeordneten Objekt.
Ein Stein besteht aus mehreren Blöcken.
Das Feld besteht immer aus einem gerade herabfallenden Stein sowie verschiedenen Blöcken.
Blöcke: ( Block.scala )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
package de.blauerfalke.tetris import java.awt.Color import java.awt.Graphics object Block { val blockSize = 10 def apply(b:(Int,Int), c:Color) = new Block(b, c) def apply(x:Int, y:Int, c:Color) = new Block((x,y), c) } class Block(var p:(Int,Int),var c:Color) { def paint(g:Graphics) { g.setColor(c) g.fillRect(p._1*Block.blockSize , p._2*Block.blockSize , Block.blockSize, Block.blockSize) } }
Block(0,0,Color.green)
Steine: ( Stone.scala )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
package de.blauerfalke.tetris import java.awt.Graphics import java.awt.Color import java.util.Random object Stone { def apply(typ:Int) = { typ match { case -1 => new Stone(Array()) case 1 => new Stone(Array( Block(0,0,Color.blue) ,Block(0,1,Color.blue) ,Block(0,2,Color.blue) ,Block(1,2, Color.blue) )) case 2 => new Stone(Array( Block(1,0,Color.green) ,Block(1,1,Color.green) ,Block(1,2,Color.green) ,Block(0,2,Color.green) )) case 3 => new Stone(Array( Block(0,0,Color.red) ,Block(0,1,Color.red) ,Block(1,1,Color.red) ,Block(1,2,Color.red) )) case 4 => new Stone(Array( Block(1,0,Color.orange),Block(1,1,Color.orange),Block(0,1,Color.orange),Block(0,2,Color.orange))) case 5 => new Stone(Array( Block(1,0,Color.pink) ,Block(1,1,Color.pink) ,Block(0,1,Color.pink) ,Block(1,2,Color.pink) )) case 6 => new Stone(Array( Block(0,0,Color.yellow),Block(1,0,Color.yellow),Block(0,1,Color.yellow),Block(1,1,Color.yellow))) case 7 => new Stone(Array( Block(0,0,Color.cyan) ,Block(0,1,Color.cyan) ,Block(0,2,Color.cyan) ,Block(0,3,Color.cyan) )) } } } class Stone(var blocks:Array[Block]) { var p = (0,0) //position def down() { p = (p._1, p._2+1) } def paint(g:Graphics) { for(b <- blocks) b.paint(g) } }
Spielfeld: ( Field.scala )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
package de.blauerfalke.tetris import scala.swing.Component import java.awt.Graphics2D import java.awt.Color class Field extends Component { val fieldWidth = 11 val fieldHeight = 16 var stone:Stone = Stone(1) override def paintComponent(g: Graphics2D) { g.setColor(Color.black) g.fillRect(0,0, fieldWidth*Block.blockSize ,fieldHeight*Block.blockSize) stone.paint(g) } }
Damit das Ganze jetzt auch angezeigt werden kann, brauchen wir noch ein Hauptfenster: ( Main.scala )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
package de.blauerfalke.tetris import swing.SimpleGUIApplication import swing.MainFrame object Main extends SimpleGUIApplication { def top = new MainFrame { //Frametitle title="Tetris" //Size und Position location=new java.awt.Point(200, 200) minimumSize=new java.awt.Dimension(200, 300) contents = new Field() } }
Hier noch einmal die komplette Lektion 1: TetrisLection1.zip