// import necessary packages import java.applet.*; import java.awt.*; import java.net.*; import java.awt.event.*; // Inherit the applet class from the class Applet public class Tetrinophilus extends Applet implements Runnable, MouseListener, KeyListener { // Game state information private boolean notBegun = true; private boolean paused = true; private boolean sendNew = true; private boolean gameover = false; // Images and purely graphical items private Image frame; private Image splash; private Image dblImage; private Image panda; private Graphics dbg; private Pupil leftEye; private Pupil rightEye; // define a new thread private Thread th; // Game objects private TetrisPiece tb; private TetrisPiece next_piece; private TetrisMatrix tm; private GrabBag gb; private Player p; private int dropped_spaces; // Game constants. private static final int[] time_interval = {900, 810, 729, 590, 477, 386, 312, 252, 203, 164, 135, 112, 94, 84, 74, 65, 55, 44, 35, 22}; private static final int[] bonus = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096}; // Initialize game variables. public void init() { frame = getImage(getCodeBase(), "land1.gif"); splash = getImage(getCodeBase(), "splash.gif"); panda = getImage(getCodeBase(), "bgimage1.gif"); th = new Thread(this); newGame(); addMouseListener(this); addKeyListener(this); } // Start up the applet. public void start() { th.start(); } // For leaving the browser. public void destroy () {} public void run () { // lower ThreadPriority Thread.currentThread().setPriority(Thread.MIN_PRIORITY); // run forever while(true) { // Pause before dropping the block down a line try { Thread.sleep(time_interval[p.getLevel()]); } catch (InterruptedException e) { } if (!paused) { // If the Tetroid can move down, drop it, otherwise, add it to the Matrix and get a new one. if (tb.checkDown(tm)) tb.moveDown(); else { // If the Tetroid is within the playable field, add it to the Matrix, else Game over. if (tb.checkPosition(tm)) { paused = true; // Add dropped Tetroid to the Matrix int lines = tm.addTetroid(tb); // Update score if (lines > 0) p.addLines(lines); p.addScore(dropped_spaces * bonus[p.getLevel()]); dropped_spaces = 0; // Get a new piece and update next piece tb = next_piece; tb.move(-10, -10); next_piece = getNewPiece(); next_piece.move(10, 10); // Pause the game before dropping next piece. try { Thread.sleep(150); } catch (InterruptedException e) { } paused = false; } else // Game over { paused = true; // Game over animation sequence for (int i = 19; i > -1; i--) { tm.grayOutLine(i); repaint(); try { Thread.sleep(50); } catch (InterruptedException e) {} } gameover = true; } } } // repaint the applet repaint(); // set ThreadPriority to maximum value Thread.currentThread().setPriority(Thread.MAX_PRIORITY); } } private void newGame() { leftEye = new Pupil(7, 70, 180, 55, 73, 6); rightEye = new Pupil(6, 96, 175, 95, 99, 6); tm = new TetrisMatrix(); gb = new GrabBag(); p = new Player(); tb = getNewPiece(); next_piece = getNewPiece(); next_piece.move(10, 10); dropped_spaces = 0; sendNew = false; gameover = false; } // Get a new Tetroid private TetrisPiece getNewPiece() { int n = gb.getNext(); TetrisPiece ret = new TetroidI(); switch (n) { case 1: ret = new TetroidI(); break; case 2: ret = new TetroidO(); break; case 3: ret = new TetroidT(); break; case 4: ret = new TetroidS(); break; case 5: ret = new TetroidZ(); break; case 6: ret = new TetroidJ(); break; case 7: ret = new TetroidL(); break; } return ret; } // Draw the game onscreen public void paint (Graphics g) { // Display the splash page if not started yet. if (notBegun) g.drawImage(splash, 0, 0, this); // Display the game. else { if (!gameover) { // Draw the Panda leftEye.update(tb.getX()*25 + 25, tb.getY()*25+25); leftEye.draw(g); rightEye.update(tb.getX()*25 + 25, tb.getY()*25+25); rightEye.draw(g); g.drawImage(panda,24,25,this); // Draw frame g.drawImage(frame,0,0,this); // Draw active Tetroid tb.draw(g); // Draw the matrix tm.draw(g); // Draw next piece next_piece.draw(g); } else // Game over screen { // Draw the matrix tm.draw(g); // Draw background image g.drawImage(frame,0,0,this); // Draw Game Over Text g.setColor(Color.BLACK); g.drawString("GAME OVER", 355, 130); g.drawString("Double-click for new game.", 320, 148); } // Write out the player's data. g.setColor(Color.white); g.drawString("Level: " + p.getLevel(), 350, 40); g.drawString("Lines: " + p.getLines(), 350, 55); g.drawString("Score: " + p.getScore(), 350, 70); } } // Update Method using double buffering. public void update(Graphics g) { // initialize buffer if (dblImage == null) { dblImage = createImage(this.getSize().width, this.getSize().height); dbg = dblImage.getGraphics(); } // clear screen in background dbg.setColor(getBackground()); dbg.fillRect(0,0,this.getSize().width, this.getSize().height); // draw elements in background dbg.setColor(getForeground()); paint(dbg); // draw image on the screen g.drawImage(dblImage,0,0,this); } // Method to handle mouse events public void mouseClicked( MouseEvent e ) { if ((notBegun || gameover) && e.getClickCount() == 2) { paused = false; notBegun = false; if (gameover) newGame(); } } public void mouseExited(MouseEvent e) { } public void mousePressed( MouseEvent e ) { } public void mouseReleased( MouseEvent e ) { } public void mouseEntered(MouseEvent e) { } // Method to handle keyboard events public void keyPressed (KeyEvent e) { int key = e.getKeyCode(); switch (key) { // user presses left cursor key case KeyEvent.VK_LEFT: if (!paused) tb.moveLeft(tm); repaint(); break; // user presses right cursor key case KeyEvent.VK_RIGHT: if (!paused) tb.moveRight(tm); repaint(); break; // user presses down cursor key case KeyEvent.VK_DOWN: if (!paused) { if (tb.checkDown(tm)) { tb.moveDown(); dropped_spaces++; } } repaint(); break; // User presses up cursor key case KeyEvent.VK_UP: if (!paused) { while (tb.checkDown(tm)) { tb.moveDown(); dropped_spaces++; } } repaint(); break; case KeyEvent.VK_A: if (!paused) tb.rotateLeft(tm); repaint(); break; // User presses "S" key case KeyEvent.VK_S: if (!paused) tb.rotateRight(tm); repaint(); break; // User presses Space Bar case KeyEvent.VK_SPACE: paused = !paused; break; } } public void keyTyped (KeyEvent e) { } public void keyReleased (KeyEvent e) { } }