/* * Tetris.java * * Copyright(c) 2002-2005, Particle Corp. * * Copying and distribution of this entire source code * is permitted in any medium, provided this copyright * notice is preserved. */ import java.applet.*; import java.awt.*; /** * simple tetris applet * (note: specifically made to be compatible with JDK 1.0) * * Note2: This applet works/looks best if applet size dimension * ratios are 10:20 (width:height). On a web page, this means * 200x400 is probably best. * * @author Alex S. * @version 0.0.2 */ public class Tetris extends Applet implements Runnable { private Thread thread; private int[][] screen; private Image doubleImage = null; private Graphics doubleGraphics = null; // piece fall speed (in milliseconds) private int speed; // pieces; each piece has 4 'dots', we store model coordinates // for those 'dots'. each piece also has 4 'orientations' (actually, // some pieces have less, but we're using all 4). private static final int[][][][] pieces = { { // #### {{0,1},{0,0},{0,-1},{0,-2}}, {{-1,0},{0,0},{1,0},{2,0}}, {{0,1},{0,0},{0,-1},{0,-2}}, {{-1,0},{0,0},{1,0},{2,0}} }, { // # // ## // # {{-1,0},{0,1},{1,0},{0,0}}, {{0,1},{1,0},{0,-1},{0,0}}, {{1,0},{0,-1},{-1,0},{0,0}}, {{0,-1},{-1,0},{0,1},{0,0}} }, { // ## // ## {{0,0},{0,-1},{1,0},{1,-1}}, {{0,0},{0,-1},{1,0},{1,-1}}, {{0,0},{0,-1},{1,0},{1,-1}}, {{0,0},{0,-1},{1,0},{1,-1}} }, { // ## // ## {{-1,0},{0,0},{0,1},{1,1}}, {{1,-1},{1,0},{0,0},{0,1}}, {{-1,0},{0,0},{0,1},{1,1}}, {{1,-1},{1,0},{0,0},{0,1}} }, { // ## // ## {{-1,1},{0,1},{0,0},{1,0}}, {{0,-1},{0,0},{1,0},{1,1}}, {{-1,1},{0,1},{0,0},{1,0}}, {{0,-1},{0,0},{1,0},{1,1}} }, { // # // ### {{-1,-1},{-1,0},{0,0},{1,0}}, {{-1,1},{0,1},{0,0},{0,-1}}, {{1,1},{1,0},{0,0},{-1,0}}, {{1,-1},{0,-1},{0,0},{0,1}} }, { // # // ### {{-1,1},{-1,0},{0,0},{1,0}}, {{-1,-1},{0,-1},{0,0},{0,1}}, {{1,-1},{1,0},{0,0},{-1,0}}, {{1,1},{0,1},{0,0},{0,-1}} } }; // base color for piece private static final Color[] colors = { new Color(0xBD,0x00,0x00), new Color(0x73,0x71,0x73), new Color(0x00,0xBE,0xBD), new Color(0x00,0xBE,0x00), new Color(0x00,0x00,0xBD), new Color(0xBD,0x00,0xBD), new Color(0xBD,0xBE,0x00) }; // highlight color for piece (upper left corner) private static final Color[] lcolors = { new Color(0xFF,0x00,0x00), new Color(0x9C,0x9A,0x9C), new Color(0x00,0xFF,0xFF), new Color(0x00,0xFF,0x00), new Color(0x00,0x00,0xFF), new Color(0xFF,0x00,0xFF), new Color(0xFF,0xFF,0x00) }; // dark highlight color for piece (lower right corner) private static final Color[] dcolors = { new Color(0x84,0x00,0x00), new Color(0x4A,0x4D,0x4A), new Color(0x00,0x82,0x84), new Color(0x84,0x82,0x00), new Color(0x00,0x00,0x84), new Color(0x84,0x00,0x84), new Color(0x84,0x82,0x00) }; // empty location private static final int EMPTY = pieces.length + 1; // current state of the game private int currentPiece; private int currentOrientation; private int currentX,currentY; // flag to indicate that the game is over. private boolean gameOver; /** * constructs a tetris object */ public Tetris(){ thread = null; screen = new int[20][10]; } /** * does initialization */ public void init(){ startGame(); // create double buffer (prevents flicker) doubleImage = createImage(size().width,size().height); doubleGraphics = doubleImage.getGraphics(); } /** * picks next piece and orientation */ public void pickPiece(){ currentPiece = (int)(Math.random()*pieces.length); currentOrientation = (int)(Math.random()*pieces[currentPiece].length); currentX = 5; currentY = 2; } /** * repaints the screen */ public void paint(Graphics g){ int[] xs = new int[3]; int[] ys = new int[3]; int w = size().width,h = size().height; int s = h / screen.length; doubleGraphics.setColor(Color.black); doubleGraphics.fillRect(0,0,w,h); // paint score String score = "["+(1000-speed)+"]"; doubleGraphics.setColor(Color.gray); doubleGraphics.setFont(new Font("Monospaced",Font.PLAIN,10)); // score is 1000 - speed (since 'speed' decreases with every droping // piece, this provides an accurate picture of how quickly the // person can think/react to falling pieces. doubleGraphics.drawString(score,10,10); if(gameOver){ // if game is over, display "game over" :-) doubleGraphics.setColor(Color.yellow); score = "Score: "+score; Font f = new Font("Monospaced",Font.BOLD,20); FontMetrics fm = getFontMetrics(f); int x = w/2 - fm.stringWidth(score) / 2; doubleGraphics.setFont(f); doubleGraphics.drawString(score,x,h/2-30); String gameOver = "GAME OVER"; f = new Font("Monospaced",Font.BOLD,30); fm = getFontMetrics(f); x = w/2 - fm.stringWidth(gameOver) / 2; doubleGraphics.setFont(f); doubleGraphics.drawString(gameOver,x,h/2); String clickToPlayAgain = "(Click To Play Again)"; f = new Font("Monospaced",Font.BOLD,12); fm = getFontMetrics(f); x = w/2 - fm.stringWidth(clickToPlayAgain) / 2; doubleGraphics.setFont(f); doubleGraphics.drawString(clickToPlayAgain,x,h/2+30); doubleGraphics.setColor(Color.lightGray); String copyright = "(c) 2002-2005, Particle"; f = new Font("Monospaced",Font.PLAIN,12); fm = getFontMetrics(f); x = w/2 - fm.stringWidth(copyright) / 2; doubleGraphics.setFont(f); doubleGraphics.drawString(copyright,x,h/2+50); }else{ // draw the pieces doubleGraphics.setColor(Color.darkGray); doubleGraphics.drawLine(0,4*s,w,4*s); for (int i=0;i 0){ currentOrientation = (currentOrientation + 1) % pieces[currentPiece].length; }else if(nextOr < 0){ currentOrientation = (currentOrientation - 1 + pieces[currentPiece].length) % pieces[currentPiece].length; } currentX += x; currentY += y; if(collisions()){ currentOrientation = oldOrient; currentX = oldX; currentY = oldY; retValue = false; } setPiece(currentPiece); return retValue; } /** * end the game */ private void endGame(){ gameOver = true; for (int i=0;i0;k--) for(j=0;j= 10) return true; if(my < 0 || my >= 20) return true; if(screen[my][mx] != EMPTY) return true; } return false; } /** * set piece */ private void setPiece(int value){ int[][] points = pieces[currentPiece][currentOrientation]; for(int i=0;i