/* * Godmar Back * * my favorite tetris in Java * * University of Utah, Computer Systems Lab, 1995 * major rewrite for 1.1 event model etc. * Aug 1999 */ import java.awt.*; import java.awt.event.*; import java.io.*; public class Tetris extends java.applet.Applet implements Runnable { int sqlength; // length of tetris square int xoffset; // distance from left int yoffset; // distance from top int cols; // columns int rows; // rows int f[][]; // field int of[][]; // old field int what; // type of current piece Square curpiece[] = new Square[4]; // current piece boolean lost; // lost boolean stopped = true; // stopped boolean suspended = false; // the suggested off-switch boolean neednewpiece; // need new piece boolean showScore = true; // show the score Color colors[]; int curval, score=0; int level; // current level of difficulty int pieces; // nr of pieces dropped String highscorehost; short highscoreport; boolean blackwhite; // BW mode boolean justupdating = false; // applet is being loaded the first time public void init() { // applet is loaded the first time // System.out.println("codebase= " + getCodeBase() + // "\ndocumentbase= " + getDocumentBase()); String s = getParameter("squaresize"); sqlength = s == null ? 20 : (new Integer(s)).intValue(); s = getParameter("columns"); cols = s == null ? 10 : (new Integer(s)).intValue(); s = getParameter("rows"); rows = s == null ? 20 : (new Integer(s)).intValue(); s = getParameter("xoffset"); xoffset = s == null ? 200 : (new Integer(s)).intValue(); s = getParameter("yoffset"); yoffset = s == null ? 0 : (new Integer(s)).intValue(); s = getParameter("blackwhite"); blackwhite = s == null ? false : (new Boolean(s)).booleanValue(); s = getParameter("showscore"); showScore = s == null ? true : (new Boolean(s)).booleanValue(); highscorehost = getParameter("highscorehost"); s = getParameter("highscoreport"); highscoreport = (short)(s == null ? 4711 : (new Integer(s)).intValue()); f = new int[cols][rows+4]; of = new int[cols][rows+4]; // resize(sqlength*cols+xoffset*2, sqlength*(rows+3)); colors = new Color[8]; // off color colors[0] = new Color(40,40,40); if (blackwhite) { for(int i=1; i<8; i++) colors[i] = new Color(255, 255, 255); } else { colors[1] = new Color(255,0,0); // Default red - ok colors[2] = new Color(0,200,0); // green ? colors[3] = new Color(0,200,255); // light blue - ok colors[4] = new Color(255,255,0); // yellow - ok colors[5] = new Color(255,150,0); // orange - ok colors[6] = new Color(210,0,240); // purple ? colors[7] = new Color(40,0,240); // dark blue ? } for(int i = 0; i < 8; i++) { s = getParameter("color" + i); if (s != null) { // System.out.println("color" + i + "=`" + s + "'"); colors[i] = Color.decode(s); } // System.out.println(colors[i]); } addKeyListener(keyListener); addMouseListener(mouseListener); addComponentListener(componentListener); } // applet is started public void start() { for(int i=0; i 0) { score += curval; pieces++; level = 5 + pieces/30; } removelines(); newpiece(); neednewpiece = false; } else { neednewpiece = !movecurpiece(0, -1, false); if(!neednewpiece) curval -= 5; } repaint(); } stopped = true; if (highscorehost == null) return; /* System.out.println("switching to highscore..."); try { HighScore hs = new HighScore(this, highscorehost, highscoreport, score); } catch(Exception e) { getAppletContext().showStatus("highscore failed: "+e.getMessage()); } */ // this terminates second thread } private static final int RESTART = 1; private static final int LEFT = 2; private static final int RIGHT = 3; private static final int ROTATE = 4; private static final int DROP = 5; // key is pressed KeyListener keyListener = new KeyAdapter() { public void keyPressed(KeyEvent evt) { int action = -1; // System.out.println(evt); // write once, run anywhere at its finest. // we try to make this program compile under 1.1 and later, // so we must hardcode 1.2 constants not known to a 1.1 compiler. // // However, we want it to run under 1.0 and later on both Sun and Kaffe // which all deliver different codes and chars for the same keys // on my keyboard. // int key = evt.getKeyChar(); // try keychar first switch (key) { case 's': action = RESTART; break; case 'h': // left case java.awt.Event.LEFT: // jdk 1.0 action = LEFT; break; case 'k': // right case 'l': case java.awt.Event.RIGHT: action = RIGHT; break; case 'j': // rotate case java.awt.Event.UP: action = ROTATE; break; case ' ': // drop case java.awt.Event.DOWN: action = DROP; break; // try keycode second default: switch (evt.getKeyCode()) { // on the itsy, that's the left blue button case java.awt.event.KeyEvent.VK_ENTER: action = RESTART; break; // should work with and without numlock key case java.awt.event.KeyEvent.VK_LEFT: // jdk 1.1 case 226: /* java.awt.event.KeyEvent.VK_KP_LEFT */ // jdk 1.2 case java.awt.event.KeyEvent.VK_NUMPAD4: action = LEFT; break; case java.awt.event.KeyEvent.VK_RIGHT: case 227: /* java.awt.event.KeyEvent.VK_KP_RIGHT */ case java.awt.event.KeyEvent.VK_NUMPAD6: action = RIGHT; break; case java.awt.event.KeyEvent.VK_UP: case 224: /* java.awt.event.KeyEvent.VK_KP_UP */ case java.awt.event.KeyEvent.VK_NUMPAD8: action = ROTATE; break; case java.awt.event.KeyEvent.VK_DOWN: case 225: /* java.awt.event.KeyEvent.VK_KP_DOWN */ case java.awt.event.KeyEvent.VK_NUMPAD2: action = DROP; break; default: return; } break; } // allow only restart if game lost or suspended if (action != RESTART && (lost || suspended)) return; switch(action) { case RESTART: stop(); // stop old game start(); // start new game break; case LEFT: curval -= 5; movecurpiece(-1, 0, false); // we must set neednewpiece to false in case something // opened up so that a stuck piece got unstuck // otherwise, pieces may end up in the air // // this allows a lot of movement on the bottom line // even after a piece has reached the bottom line. I like it. // neednewpiece = false; repaint(); break; case RIGHT: curval -= 5; movecurpiece(1, 0, false); neednewpiece = false; repaint(); break; case ROTATE: if(what!=4) { curval -= 5; movecurpiece(0, 0, true); repaint(); } break; case DROP: while(movecurpiece(0, -1, false)) ; // if you omit the next line, even dropped pieces // can be moved. neednewpiece = true; repaint(); break; } } }; public Dimension getPreferredSize() { return (new Dimension(xoffset + cols * sqlength, yoffset + rows * sqlength)); } // we need to override this method, otherwise repaint() // will erase the whole screen, causing tremendous flickering public void update(Graphics g) { justupdating = true; // tell paint to draw only stuff that has changed paint(g); } // paint graphics on screen public synchronized void paint(Graphics g) { if (showScore) { g.setFont(new java.awt.Font("Helvetica", 0, 18)); int gx = sqlength; int gy = sqlength*rows/4; g.clearRect(gx, gy-25, xoffset-gx, 25); g.drawString("Score: " + score, gx, gy); gy += 30; g.clearRect(gx, gy-25, xoffset-gx, 25); g.drawString("Level: " + level, gx, gy); } for (int i=0; i= 0 && x < cols && y >= 0 && y < rows+4); } boolean IsEqual(Square s) { return x == s.x && y == s.y && c == s.c; } } } // end Tetris applet