Source files:
Tetris.java
import javax.swing.JFrame;
public class Tetris {
public static void main(String[] args) {
JFrame window = new JFrame("Tetris Game");
TetrisPanel content = new TetrisPanel();
window.setContentPane(content);
window.setSize(215, 435);
window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
window.setResizable(false);
// User can't change the window's size.
window.setVisible(true);
}
}
TetrisApplet.java
import javax.swing.JApplet;
public class TetrisApplet extends JApplet {
// Start the applet
public void init() {
setContentPane( new TetrisPanel() );
}
}
TetrisPanel.java
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
/**
* This panel implementsis a simple tetris game.
*/
public class TetrisPanel extends JPanel {
private Timer timer;
private int height, width;
boolean[][] mesh; // the Tetris field mesh
int middle=5; // the middle of the new element
private Stone stone; // new stone object
Random generator = new Random();
int randomStone = this.generator.nextInt(7) + 1;
public TetrisPanel() {
// The constructor
setBackground(Color.WHITE);
ActionListener action = new ActionListener() {
// Defines the action taken each time the timer fires.
public void actionPerformed(ActionEvent evt) {
moveDown();
repaint();
}
};
timer = new Timer( 150, action ); // Fires every 100 milliseconds.
addMouseListener( new MouseAdapter() {
// The mouse listener simply requests focus when the user
// clicks the panel.
public void mousePressed(MouseEvent evt) {
requestFocus();
}
} );
addFocusListener( new FocusListener() {
// The focus listener starts the timer when the panel gains
// the input focus and stops the timer when the panel loses
// the focus. It also calls repaint() when these events occur.
public void focusGained(FocusEvent evt) {
timer.start();
repaint();
}
public void focusLost(FocusEvent evt) {
timer.stop();
repaint();
}
} );
addKeyListener( new KeyAdapter() {
// The key listener responds to keyPressed events on the panel. Only
// the left-, right-, down-, and up-arrow keys have any effect. The left- and
// right-arrow keys move the stone while up-arrow is to rotate,
// down-arrow move the block fast to the bottom.
public void keyPressed(KeyEvent evt) {
// This routine is called each time the user presses
// a key on the keyboard (while the applet has the keyboard
// focus). The value of evt.getKeyCode() tells which
// key was pressed. For this applet, only the three of the
// arrow keys will have any effect. The codes for the
// four arrow keys are KeyEvent.VK_UP, KeyEvent.VK_DOWN,
// KeyEvent.VK_LEFT, and KeyEvent.VK_RIGHT.
int code = evt.getKeyCode(); // which key was pressed
if (code == KeyEvent.VK_LEFT) {
// Move the stone left. (If the move is not posible, the stone
// will stay where it is, ot the position will be adjusted
// in the stone.stoneMoveLeft(boolean[][]) method.)
stone = stone.stoneMoveLeft(mesh);
}
else if (code == KeyEvent.VK_RIGHT) {
// Move the stone right. (If the move is not posible, the stone
// will stay where it is, ot the position will be adjusted
// in the stone.stoneMoveRight(boolean[][]) method.)
stone = stone.stoneMoveRight(mesh);
}
else if (code == KeyEvent.VK_DOWN) {
// move the stone fast down
moveDown();
}
else if (code == KeyEvent.VK_UP){
// rotate the stone counterclockwise
stone = stone.stoneRotateCounterClockwise(mesh, randomStone);
}
} // end keyPressed()
} );
} // end constructor
public boolean fullLine(boolean[][] mesh, int y){
// test if a y line is full
for(int x=0; x < mesh[y].length; x++){
if(!mesh[y][x]){
return false;
}
}
return true;
} // end fullLine
public boolean[][] removeLine(boolean[][] mesh){
if(fullLine(mesh, 0)){
// if the top line is full, remove it
for(int x=0; x < mesh[0].length; x++){
mesh[0][x]=false;
}
}
for(int l=1; l < mesh.length; l++){
// go trough all lines to the bottom exept the top one
if(fullLine(mesh, l)){ // if the line is full
for(int y=l; y>0; y--){
// remove the line (replace with the line over it)
for(int x=0; x < mesh[y].length; x++){
mesh[y][x] = mesh[y-1][x];
}
}
for(int x=0; x < mesh[0].length; x++){
mesh[0][x]=false;
}
}
}
return mesh;
}
public void moveDown(){
if(this.stone.stoneCollision(this.mesh)){
this.mesh = this.stone.updateMesh(this.mesh);
this.mesh = removeLine(this.mesh);
// Pick a random number from 1 to 7, which represents a stone
this.randomStone = this.generator.nextInt(7) + 1;
/*
* if(this.stone.isThePlayerDead(this.mesh, this.middle, this.randomStone)){
* this.stone = this.stone.newStone(this.middle, this.randomStone);
* this.mesh = this.stone.updateMesh(this.mesh);
* this.stone.stoneDraw(this.theCanvas, this.mesh);
* this.theCanvas.close();
* this.endOfWorld("Du bist tot :-)");
* } else
* this.stone = this.stone.newStone(this.middle, this.randomStone);
* //Testen ob der Spielser tot ist
*/
this.stone = this.stone.newStone(this.middle, this.randomStone);
} else {
this.stone = this.stone.stoneDrop();
}
}
public void draw(Graphics g){
// draw the hole thing
this.stone.stoneDraw(g, this.mesh);
}
/**
* The paintComponent() method draws the current state of the game. It
* draws a gray or cyan border around the panel to indicate whether or not
* the panel has the input focus. It draws the stone and calling draw() method.
*
*/
public void paintComponent(Graphics g) {
super.paintComponent(g); // Fill panel with background color, white.
if (stone == null){ // initialize the begin components of the game
width = getWidth();
height = getHeight();
stone = new Stone(middle);
stone = stone.newStone(middle, randomStone);
mesh = new boolean[20][10];
for(int i=0; i < mesh.length; i++){
for(int j=0; j < mesh[i].length; j++){
mesh[i][j]=false;
}
}
}
if (hasFocus())
g.setColor(Color.CYAN);
else {
g.setColor(Color.RED);
g.drawString("click to start", 65, 190);
g.setColor(Color.GRAY);
}
g.drawRect(0,0,width-1,height-1);
g.drawRect(1,1,width-3,height-3);
g.drawRect(2,2,width-5,height-5);
draw(g);
} // end drawFrame()
// Nested class Stone
private class Stone {
Block[] block; // Array with 4 blocks (stone)
Block b; // Block
public Stone(int middle){
// constructor for new block in the middle of the Field
this.b = new Block(middle, 0);
} // end constructor
public Stone(Block block1, Block block2, Block block3, Block block4){
// constructor for stone (4 blocks)
this.block = new Block[4];
this.block[0] = block1;
this.block[1] = block2;
this.block[2] = block3;
this.block[3] = block4;
} // end Stone()
public Stone newStone(int middle, int n){
// Create new Stone
// n - random number of stone type
Block block2 = new Block(middle, 0);
Block block1 = new Block(block2.getX(), block2.getY()+1);
Block block3 = new Block(0,0);
Block block4 = new Block(0,0);
switch(n){
case 1:
block3 = new Block(block1.getX()+1, block1.getY());
block4 = new Block(block1.getX()+1, block1.getY()+1);
break;
case 2:
block3 = new Block(block1.getX()-1, block1.getY());
block4 = new Block(block1.getX()-1, block1.getY()+1);
break;
case 3:
block3 = new Block(block1.getX()-1, block1.getY());
block4 = new Block(block1.getX()+1, block1.getY());
break;
case 4:
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX()+1, block1.getY()+1);
break;
case 5:
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX()-1, block1.getY()+1);
break;
case 6:
block3 = new Block(block2.getX()-1, block2.getY());
block4 = new Block(block1.getX()-1, block1.getY());
break;
case 7:
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX(), block1.getY()+2);
break;
default:
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX(), block1.getY()+2);
break;
}
Stone newstone = new Stone (block1, block2, block3, block4);
return newstone;
} // end newStone()
public boolean stoneCollision(boolean[][] mesh){
// Bottom collision detection
for(int i=0; i < this.block.length; i++){
// to trough every block
// and test it if the down move is posible
if(this.block[i].collision(mesh)){
return true;
}
}
return false;
} // end stoneCollision()
public boolean[][] updateMesh(boolean[][] mesh){
// mark the cells in the mesh as occupied
for(int i=0; i < this.block.length; i++){
mesh[this.block[i].getY()][this.block[i].getX()]=true;
}
return mesh;
} // end updateMesh
public Stone stoneDrop(){
// move the stone downwards
for(int i=0; i < this.block.length; i++){
this.block[i] = this.block[i].drop();
}
return new Stone(block[0], block[1], block[2], block[3]);
} // end stoneDrop
public Stone stoneMoveLeft(boolean[][] mesh){
// move the stone left if it is posible
for(int i=0; i < this.block.length; i++){
// if one of the blocks is not left moveable
if(!this.block[i].isMoveableLeft(mesh)){
// return the old stone
return new Stone(block[0], block[1], block[2], block[3]);
}
}
for(int i=0; i < this.block.length; i++){
this.block[i] = this.block[i].blockMoveLeft();
}
return new Stone(block[0], block[1], block[2], block[3]);
} // end stoneMoveLeft
public Stone stoneMoveRight(boolean[][] mesh){
// move the stone right if it is posible
for(int i=0; i < this.block.length; i++){
// if one of the blocks is not right moveable
if(!this.block[i].isMoveableRight(mesh)){
// return the old stone
return new Stone(block[0], block[1], block[2], block[3]);
}
}
for(int i=0; i < this.block.length; i++){
this.block[i] = this.block[i].blockMoveRight();
}
return new Stone(block[0], block[1], block[2], block[3]);
} // end stoneMoveRight
public boolean isTurnableCounterClockwise (boolean[][] mesh, Block centerBlock){
// Checks if it's allowed to rotate the block (this)
// by 90 degrees counterclockwise around centerBlock.
// the method is used in stoneRotateCounterClockwise()
for(int i=0; i < this.block.length; i++){
// rotate a this.block[i] around centerBlock
Block testBlock = this.block[i].rotateCounterClockwise(centerBlock);
if(!testBlock.isAValidMove(mesh)){
// if the result block is in a collision
return false; // return false
}
}
return true;
// return true if neither of the blocks in the stone are in collision
} // end isTurnableCounterClockwise
boolean isTurnableClockwise (boolean[][] mesh, Block centerBlock){
// Checks if it's allowed to rotate the block (this)
// by 90 degrees counterclockwise around centerBlock.
// the method is used in stoneRotateCounterClockwise()
for(int i=0; i < this.block.length; i++){
//rotate a this.block[i] around centerBlock
Block testBlock = this.block[i].rotateClockwise(centerBlock);
if(!testBlock.isAValidMove(mesh)){
// if the result block is in a collision
return false; // return false
}
}
return true;
// return true if neither of the blocks in the stone are in collision
} // end is TurnableClockwise
Stone stoneRotateCounterClockwise(boolean[][] mesh, int randomStone){
// turn the stone left
for(int i=0; i < this.block.length; i++){
// test every block in the stone as turningpoint
// See isTurnableCounterClockwise.
if(isTurnableCounterClockwise(mesh, this.block[i]) && randomStone != 6){
// if the turn of the sotne is possible and
// the stone is not a quadrat (quadrat do not rotate)
for (int j=0; j < this.block.length; j++){
// rotate all the blocks in the stone
this.block[j] = this.block[j].rotateCounterClockwise(this.block[i]);
}
// and return the new stone
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
// if a collision is detected, test anader block in the stone as turningpoint
}
// if no block can be used as a turningpoing, return the old stone
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
} // end stoneRotateCounterClockwise()
Stone stoneRotateClockwise(boolean[][] mesh, int randomStone){
// turn the stone right
for(int i=0; i < this.block.length; i++){
// test every block in the stone as turningpoint
// See isTurnableClockwise.
if(isTurnableClockwise(mesh, this.block[i]) && randomStone != 6){
// if the turn of the sotne is possible and
// the stone is not a quadrat (quadrat do not rotate)
for (int j=0; j < this.block.length; j++){
// rotate all the blocks in the stone
this.block[j] = this.block[j].rotateClockwise(this.block[i]);
}
// and return the new stone
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
// if a collision is detected,
// test another block in the stone as turningpoint
}
// if no block can be used as a turningpoing, return the old stone
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
} // end stoneRotateClockwise()
public void stoneDraw(Graphics g, boolean[][] mesh){
// draw the stone
for(int i=0; i < this.block.length; i++){
// draw every block from the stone
this.block[i].drawFrame(g, mesh);
}
} // end stoneDraw
// Nested class Block
private class Block {
int x;
int y;
int DELTA = 1;
int SIZE = 20;
public Block(int x, int y){
this.x = x;
this.y = y;
} // Constructor
public int getX(){ // Method whitch returns X Block cordinate
return this.x;
}
public int getY(){ // Method whitch returns Y Block cordinate
return this.y;
}
public int meshToPixels(int i){
// Method whitch returns the real pixel cordinates
return i = i * this.SIZE + 3;
}
public boolean collision(boolean[][] mesh){ // Collision detection
if(this.y >= mesh.length-1) // If the block has reached the floor
return true;
else if(mesh[this.y+this.DELTA][this.x]) //if there is a block under
return true;
else
return false;
}
public Block drop(){ // The next move of the block
return new Block(this.x, this.y + this.DELTA);
}
// Create a virtual block and test if it's posible to exists
// If the virtual block is in no collision condition, then it becomes real
public boolean isAValidMove(boolean[][] mesh) {
if(this.y > mesh.length-1 || //
this.x > mesh[this.y].length-1 || // The block is out of bound
this.x < 0 || //
mesh[this.y][this.x]) // The block is over another block
return false;
return true;
}
// The functionality of the method should be integrated in isAValidMove.
// The method is still.
public boolean isMoveableLeft(boolean[][] mesh){
if(this.x > 0 && mesh[this.y][this.x-this.DELTA])
// if a block exists from left
return false;
else if(this.x < = 0) // if the block is out of bound from left
return false;
else
return true;
}
public Block blockMoveLeft(){ // Create block on left
return new Block(this.x - this.DELTA, this.y);
}
// The functionality of the method should be integrated in isAValidMove.
public boolean isMoveableRight(boolean[][] mesh){
if(this.x < mesh[this.y].length-1 && mesh[this.y][this.x+this.DELTA])
// if a block exists from right
return false;
else if(this.x >= mesh[this.y].length-1)
// if the block is out of bound from right
return false;
else
return true;
}
public Block blockMoveRight(){ // Create block on right
return new Block(this.x + this.DELTA, this.y);
}
//Drehen ein Block rechts
// Achtung: Nicht anfassen
// Rotates the point (this) clockwise by 90 degrees
// around the parameter (that).
public Block rotateClockwise(Block that){
return new Block(that.x+(this.y-that.y), that.y-(this.x-that.x));
}
// Derhen ein Block links
// Achtung: Nicht anfassen
// Rotates the point (this) counter clockwise by 90 degrees
// around the parameter (that).
public Block rotateCounterClockwise(Block that){
return new Block(that.x-(this.y-that.y), that.y+(this.x-that.x));
}
synchronized public void drawFrame(Graphics g, boolean[][] mesh) {
// This routine is called to draw the next frame of the animation.
// The parameter, g, is a graphics context for drawing the frame.
// The parameter mesh, is the boolean array whith the saved block.
// Here, methods are called to process and draw each of the
// three objects in the scene.
// First, fill the whole drawing area with green
g.setColor(Color.red);
for(int y=0; y < mesh.length; y++){
for(int x=0; x < mesh[y].length; x++){
if(mesh[y][x]){
g.fillRect(meshToPixels(x), meshToPixels(y), this.SIZE, this.SIZE);
}
}
}
g.fillRect(meshToPixels(this.x), meshToPixels(this.y), this.SIZE, this.SIZE);
}
} // end Block class
} // end Stone class
}
tetris.scm
import idraw.*;
import geometry.*;
import colors.*;
import java.util.Random;
class Field extends World{
AColor BACKGROUND = new White();
Stone stone;
int width;
int height;
int middle;
double time;
boolean[][] mesh;
Random generator = new Random();
int randomStone = this.generator.nextInt(7) + 1;
Field(int width, int height, double time){
this.width = width;
this.height = height;
this.middle = width/2;
this.stone = new Stone(this.middle);
this.stone = this.stone.newStone(this.middle, this.randomStone);
this.time = time;
this.bigBang(this.stone.stoneMeshToPixels(this.width), this.stone.stoneMeshToPixels(this.height), this.time);
mesh = new boolean[20][10];
for(int i=0; i < mesh.length; i++){
for(int j=0; j < mesh[i].length; j++){
mesh[i][j]=false;
}
}
}
//change the world, i.e. move the Block downwards
synchronized public void onTick(){
moveDown();
}
// Testen ob eine Linie voll ist
public boolean lineFull(boolean[][] mesh, int y){
for(int x=0; x < mesh[y].length; x++){
if(!mesh[y][x]){ // ob eine Stelle in der Linie false ist
return false; // liefern false
}
}
return true;
}
// Loeschen eine Linie
public boolean[][] removeLine(boolean[][] mesh){
if(lineFull(mesh, 0)){
for(int x=0; x < mesh[0].length; x++)
mesh[0][x] = false;
}
// Probieren jede Zeile ob die voll ist?
// wenn ja
// uberschreibe jede Zeile mit der oberen Zeile bis zum ganz oben
for(int l=1; l < mesh.length; l++){
if(lineFull(mesh, l)){
for(int y=l; y>=1; y--){
for(int x=0; x < mesh[y].length; x++){
mesh[y][x] = mesh[y-1][x];
}
}
for(int x=0; x < mesh[0].length; x++){
mesh[0][x] = false;
}
}
}
return mesh;
}
public void moveDown(){
if(this.stone.stoneCollision(this.mesh)){
this.mesh = this.stone.updateMesh(this.mesh);
this.mesh = removeLine(this.mesh);
this.randomStone = this.generator.nextInt(7) + 1;
// Waehlen eine zufahle Zahl von 1 bis 7, die entspricht das Blocknummer
if(this.stone.isThePlayerDead(this.mesh, this.middle, this.randomStone)){
this.stone = this.stone.newStone(this.middle, this.randomStone);
this.mesh = this.stone.updateMesh(this.mesh);
this.stone.stoneDraw(this.theCanvas, this.mesh);
this.theCanvas.close();
this.endOfWorld("Du bist tot :-)");
} else
this.stone = this.stone.newStone(this.middle, this.randomStone);
// Testen ob der Spielser tot ist
} else {
this.stone = this.stone.stoneDrop();
}
}
//draw the world, do not change the world here
public void draw(){
this.stone.stoneDraw(this.theCanvas, this.mesh);
}
//change zhe world
synchronized public void onKeyEvent(String Key){
if (Key.equals("q")){
this.theCanvas.close();
this.endOfWorld("Spiel zuende!");
}
else{
if (Key.equals("a")){
this.stone = this.stone.stoneMoveLeft(this.mesh);
} else if (Key.equals("d")) {
this.stone = this.stone.stoneMoveRight(this.mesh);
} else if (Key.equals("s")){
moveDown();
} else if (Key.equals("w")){
this.stone = this.stone.stoneRotateCounterClockwise(this.mesh, this.randomStone);
} else if (Key.equals("e")){
this.stone = this.stone.stoneRotateClockwise(this.mesh, this.randomStone);
} else {}
}
}
}
class Stone{
Block[] block;
Block b;
Stone(int middle){
this.b = new Block(middle, 0);
}
Stone(Block block1, Block block2, Block block3, Block block4){
this.block = new Block[4];
this.block[0]= block1;
this.block[1]= block2;
this.block[2]= block3;
this.block[3]= block4;
}
// Erzeugen neues Stein
Stone newStone(int middle, int n){ // n - random number of the stone, w - the weith of the mesh
Block block2 = new Block(middle, 0); // Die Numerierung ist vertauscht um
Block block1 = new Block(block2.getX(), block2.getY()+1); // die Rotation zu beguenstigt
Block block3 = new Block(0,0);
Block block4 = new Block(0,0);
if(n == 1){
block3 = new Block(block1.getX()+1, block1.getY());
block4 = new Block(block1.getX()+1, block1.getY()+1);
} else if (n == 2){
block3 = new Block(block1.getX()-1, block1.getY());
block4 = new Block(block1.getX()-1, block1.getY()+1);
} else if (n == 3){
block3 = new Block(block1.getX()-1, block1.getY());
block4 = new Block(block1.getX()+1, block1.getY());
} else if (n == 4){
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX()+1, block1.getY()+1);
} else if (n == 5){
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX()-1, block1.getY()+1);
} else if (n == 6){
block3 = new Block(block2.getX()-1, block2.getY());
block4 = new Block(block1.getX()-1, block1.getY());
} else if (n == 7){
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX(), block1.getY()+2);
} else {
block3 = new Block(block1.getX(), block1.getY()+1);
block4 = new Block(block1.getX(), block1.getY()+2);
}
Stone newstone = new Stone (block1, block2, block3, block4);
return newstone;
}
int stoneMeshToPixels(int i){
return block[0].meshToPixels(i);
}
// Testen ob die Elementen den obesten Rand erreicht werden
boolean isThePlayerDead(boolean[][] mesh, int middle, int n){
Stone newstone = newStone(middle, n);
for(int i=0; i < newstone.block.length; i++){
if(!newstone.block[i].isAValidMove(mesh))
return true;
}
return false;
}
boolean stoneCollision(boolean[][] mesh){
for(int i=0; i < this.block.length; i++){
if (this.block[i].collision(mesh))
return true;
}
return false;
}
// Aktualisierung das Mesh wenn Kollision getroffen wird.
synchronized boolean[][] updateMesh(boolean[][] mesh){
for(int i=0; i < this.block.length; i++)
mesh[this.block[i].getY()][this.block[i].getX()]=true;
return mesh;
}
synchronized Stone stoneDrop(){
for(int i=0; i < this.block.length; i++)
this.block[i] = this.block[i].drop();
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
synchronized Stone stoneMoveLeft(boolean[][] mesh){
for(int i=0; i < this.block.length; i++){
if(!this.block[i].isMoveableLeft(mesh))
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
for(int i=0; i < this.block.length; i++){
this.block[i] = this.block[i].moveLeft();
}
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
synchronized Stone stoneMoveRight(boolean[][] mesh){
for(int i=0; i < this.block.length; i++){
if(!this.block[i].isMoveableRight(mesh))
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
for(int i=0; i < this.block.length; i++){
this.block[i] = this.block[i].moveRight();
}
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
// Checks if it's allowed to rotate the block (this) by 90 degrees counterclockwise around b.
boolean isTurnableCounterClockwise (boolean[][] mesh, Block b){
for(int i=0; i < this.block.length; i++){
// See isTurnableCounterClockwise.
Block testBlock = this.block[i].rotateCounterClockwise(b);
if(!testBlock.isAValidMove(mesh))
return false;
}
return true;
}
// Checks if it's allowed to rotate the block (this) by 90 degrees clockwise around b.
boolean isTurnableClockwise (boolean[][] mesh, Block b){
for(int i=0; i < this.block.length; i++){
// See isTurnableCounterClockwise.
Block testBlock = this.block[i].rotateClockwise(b);
if(!testBlock.isAValidMove(mesh))
return false;
}
return true;
}
// Drehen das Stein links
Stone stoneRotateCounterClockwise(boolean[][] mesh, int randomStone){
for(int i=0; i < this.block.length; i++){ // Testen jedes Stein als Turningpoint
// See isTurnableCounterClockwise.
if(isTurnableCounterClockwise(mesh, this.block[i]) && randomStone != 6){
for (int j=0; j < this.block.length; j++){
this.block[j] = this.block[j].rotateCounterClockwise(this.block[i]);
}
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
}
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
// Drehen das Stein rechts
Stone stoneRotateClockwise(boolean[][] mesh, int randomStone){
for(int i=0; i < this.block.length; i++){ // Testen jedes Stein als Turningpoint
// See isTurnableClockwise.
if(isTurnableClockwise(mesh, this.block[i]) && randomStone != 6){
for (int j=0; j < this.block.length; j++){
this.block[j] = this.block[j].rotateClockwise(this.block[i]);
}
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
}
return new Stone(this.block[0], this.block[1], this.block[2], this.block[3]);
}
synchronized public void stoneDraw(Canvas c, boolean[][] mesh){
for(int i=0; i < this.block.length; i++)
this.block[i].draw(c, mesh);
}
}
class Block{
int x;
int y;
int DELTA = 1;
int SIZE = 20;
Block (int x, int y){
this.x = x;
this.y = y;
}
int getX(){
return this.x;
}
int getY(){
return this.y;
}
int meshToPixels(int i){
return i = i*this.SIZE;
}
// Collision detection
synchronized boolean collision(boolean[][] mesh){
if(this.y < mesh.length-1 && mesh[this.y+this.DELTA][this.x]){ // wenn unter ein Element existiert
return true;
} else if(this.y >= mesh.length-1){ // Collision mit dem Boden
return true;
} else {return false;}
}
synchronized Block drop(){
return new Block(this.x, this.y + this.DELTA);
}
// Probier ob eine block in eine Collision steht
// Normalleweise wird eine TestBlock erzeugen und getestet.
// Wenn das position ok ist, dann wird das TestBlock als neues Block genommen.
boolean isAValidMove(boolean[][] mesh){
if (this.y > mesh.length-1 || //
this.x > mesh[this.y].length-1 || // Ob das Block im Mesh liegt
this.x < 0 || //
mesh[this.y][this.x]) // Ob das Block auf einen anderen Blockliegt
return false;
return true;
}
// Diese Funktion muss ersetzt mit isAValidMove werden. (die Funktion ist noch benutzt)
boolean isMoveableLeft(boolean[][] mesh){
if(this.x > 0 && mesh[this.y][this.x-DELTA]){ // wenn von Links ein Element existiert
return false;
} else if (this.x < = 0){ // Collision mit den linken Rand
return false;
} else {
return true;
}
}
synchronized Block moveLeft(){
return new Block(this.x - this.DELTA, this.y);
}
// Diese Funktion muss ersetzt mit isAValidMove werden. (die Funktion ist noch benutzt)
boolean isMoveableRight(boolean[][] mesh){
if(this.x < mesh[this.y].length-1 && mesh[this.y][this.x+DELTA]){ // wenn von Rechts ein Element existiert
return false; // return false;
} else if (this.x >= mesh[this.y].length-1){ // Collision mit dem rechten Rand
return false;
} else {
return true;
}
}
synchronized Block moveRight(){
return new Block(this.x + this.DELTA, this.y);
}
// Drehen ein Block rechts
// Achtung: Nicht anfassen
// Rotates the point (this) clockwise by 90 degrees around the parameter (that).
synchronized public Block rotateClockwise(Block that){
return new Block(that.x+(this.y-that.y), that.y-(this.x-that.x));
}
// Derhen ein Block links
// Achtung: Nicht anfassen
// Rotates the point (this) counter clockwise by 90 degrees around the parameter (that).
synchronized public Block rotateCounterClockwise(Block that){
return new Block(that.x-(this.y-that.y), that.y+(this.x-that.x));
}
// zeichnen das Stern
synchronized void draw(Canvas c, boolean[][] mesh){
for(int y=0; y < mesh.length; y++){
for(int x=0; x < mesh[y].length; x++){
if(mesh[y][x]){ //Zeichnen alle Elementen in mesh Array die true sind
c.drawRect(new Posn(meshToPixels(x), meshToPixels(y)), this.SIZE, this.SIZE, new Red());
}
}
} // Zeichnen dem bewegenden Block
c.drawRect(new Posn(meshToPixels(this.x), meshToPixels(this.y)), this.SIZE, this.SIZE, new Red());
}
}