/********************************************************** * * Ultimate Tetris * * Ultimate Tetris is a Java Tetris clone with a few new game modes. * **********************************************************/ import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.Random; public class Tetris extends Applet implements Runnable, KeyListener { int width, height; Thread TThread = null; // Main thread volatile boolean trunning = false; // true if TThread is running, false if not long ltm, ltd; volatile GSurface gs1, gs2; volatile boolean plock; Font mfont; volatile byte keysdown; volatile boolean ingame; // True if in game, false if not volatile int blockmap[][]; // Block map volatile int btics; // Block tics volatile int ctics; // Control tics // Current shape volatile boolean cshape[][] = new boolean[4][4]; // Shape volatile int shapec, shapex, shapey; // Shape color and shape position volatile int score = 0; // Score volatile int sitem = 0; // Currently selected menu item volatile boolean uchallenge = false; // Ultimate challenge mode volatile boolean splitmode = false; // Split mode volatile boolean fillmode = false; // Fill mode volatile boolean hmode = false; // Hardcore mode Random Rnd; // Key constants static final byte KEY_UPARROW = 0x1; // Up arrow key static final byte KEY_DOWNARROW = 0x2; // Down arrow key static final byte KEY_LEFTARROW = 0x4; // Left arrow key static final byte KEY_RIGHTARROW = 0x8; // Right arrow key static final byte KEY_X = 0x10; // X key static final byte KEY_SPEED = 0x20; // Speed key // Misc constants static final int BLOCKSIZE = 20; // Block size static final int BLOCKSIZEH = 4; // Block size in Hardcore mode static final int BTICS = 500; // Block tics static final int CTICS = 100; // Control tics static final int CTICSS = 10; // Control tics with speed static final int FIRSTITEM = 0; // First menu item static final int LASTITEM = 4; // Last menu item public void init() { Dimension d; Rnd = new Random(); setBackground(Color.black); d = getSize(); width = d.width; height = d.height; gs1 = new GSurface(this, width, height); gs2 = new GSurface(this, width, height); mfont = new Font("Times New Roman", Font.BOLD, 20); gs1.g.setFont(mfont); gs2.g.setFont(mfont); addKeyListener(this); TThread = new Thread(this); TThread.setPriority(Thread.MAX_PRIORITY); ingame = false; } public void destroy() { stop(); } public void start() { trunning = true; TThread.start(); } public void stop() { trunning = false; } public void run() { boolean shapehit; GSurface tgs; int t; long ctm; do { ctm = System.currentTimeMillis(); ltd = ctm - ltm; ltm = ctm; if (ingame) { btics -= ltd; if (btics <= 0) { btics = BTICS; MoveDown(); // Move shape down one square } if ((keysdown & 0xe) == 0) ctics = 0; else { ctics -= ltd; if (ctics <= 0) { ctics = ((keysdown & KEY_SPEED) == KEY_SPEED) ? CTICSS : CTICS; // Do controls t = -1; if ((keysdown & KEY_DOWNARROW) == KEY_DOWNARROW) MoveDown(); // Move down one square if ((keysdown & KEY_LEFTARROW) == KEY_LEFTARROW) t = 0; if ((keysdown & KEY_RIGHTARROW) == KEY_RIGHTARROW) t = 1; if (t != -1) { shapehit = false; for (int posx = 0; posx < cshape.length; posx++) { for (int posy = 0; posy < cshape[posx].length; posy++) { if (cshape[posx][posy]) { if (t == 0) { // Move left if ((shapex+posx)==0) { shapehit = true; } else if (blockmap[shapex+posx-1][shapey+posy]>0) shapehit = true; } else { // Move right if ((shapex+posx)==(blockmap.length-1)) { shapehit = true; } else if (blockmap[shapex+posx+1][shapey+posy]>0) shapehit = true; } } } } if (!shapehit) if (t == 0) { shapex--; } else { shapex++; } } } } } gs2.g.setColor(Color.black); gs2.g.fillRect(0, 0, width, height); // Clear screen if (ingame) { for (int posx = 0; posx < blockmap.length; posx++) { for (int posy = 0; posy < blockmap[posx].length; posy++) { // Draw blocks if ((posx>=shapex)&&(posy>=shapey)&&(posx<(shapex+cshape.length))&&(posy<(shapey+cshape[0].length))) { if (cshape[posx-shapex][posy-shapey]) { t = shapec; } else { t = blockmap[posx][posy]; } } else { t = blockmap[posx][posy]; } if (t > 0) { gs2.g.setColor(new Color(t >> 16, (t & 0xFF00) >> 8, t & 0xFF)); // Pull color data out of t if (hmode) {gs2.g.fillRect(posx * BLOCKSIZEH + 1, posy * BLOCKSIZEH + 1, BLOCKSIZEH - 2, BLOCKSIZEH - 2); } else { gs2.g.fillRect(posx * BLOCKSIZE + 1, posy * BLOCKSIZE + 1, BLOCKSIZE - 2, BLOCKSIZE - 2); } // Draw block } } } } else { if (sitem == 0) { gs2.g.setColor(Color.green); } else { gs2.g.setColor(Color.white); } gs2.g.drawString("Start New Game", 60, 60); if (sitem == 1) { gs2.g.setColor(Color.green); } else { gs2.g.setColor(Color.white); } gs2.g.drawString("Ultimate Challenge Mode", 60, 80); if (sitem == 2) { gs2.g.setColor(Color.green); } else { gs2.g.setColor(Color.white); } gs2.g.drawString("Split Mode", 60, 100); if (sitem == 3) { gs2.g.setColor(Color.green); } else { gs2.g.setColor(Color.white); } gs2.g.drawString("Fill Mode", 60, 120); if (sitem == 4) { gs2.g.setColor(Color.green); } else { gs2.g.setColor(Color.white); } gs2.g.drawString("Hardcore Mode", 60, 140); gs2.g.setColor(Color.green); if (uchallenge) { gs2.g.fillOval(45, 67, 10, 10); } else { gs2.g.drawOval(45, 67, 10, 10); } if (splitmode) { gs2.g.fillOval(45, 87, 10, 10); } else { gs2.g.drawOval(45, 87, 10, 10); } if (fillmode) { gs2.g.fillOval(45, 107, 10, 10); } else { gs2.g.drawOval(45, 107, 10, 10); } if (hmode) { gs2.g.fillOval(45, 127, 10, 10); } else { gs2.g.drawOval(45, 127, 10, 10); } } gs2.g.setColor(Color.white); gs2.g.drawString("Score: " + score, 0, 20); tgs = gs2; gs2 = gs1; while (plock); gs1 = tgs; repaint(); while (System.currentTimeMillis() == ltm); } while (trunning); } /**************************************************************** * * NewGame * * Starts a new game * ****************************************************************/ void NewGame() { score = 0; if (hmode) { blockmap = new int[125][125]; } else { blockmap = new int[25][25]; } if (splitmode) { // If split mode, have a line separating the top and bottom halves if (hmode) { for (int posx = 0; posx <= 62; posx++) blockmap[posx][60] = 0x0000FF; for (int posx = 63; posx < blockmap.length; posx++) blockmap[posx][61] = 0x0000FF; } else { for (int posx = 0; posx <= 12; posx++) blockmap[posx][15] = 0x0000FF; for (int posx = 13; posx < blockmap.length; posx++) blockmap[posx][16] = 0x0000FF; } } if (fillmode) { // If fill mode, fill bottom part with checker pattern for (int posx = 0; posx < blockmap.length; posx++) { if (hmode) { for (int posy = 79; posy < blockmap[posx].length; posy++) { if (((posx+posy)&1)==0) blockmap[posx][posy] = 0x0000FF; } } else { for (int posy = 19; posy < blockmap[posx].length; posy++) { if (((posx+posy)&1)==0) blockmap[posx][posy] = 0x0000FF; } } } } NewShape(); // Select a shape ingame = true; btics = BTICS; ctics = CTICS; } /**************************************************************** * * EndGame * * Ends the current game * ****************************************************************/ void EndGame() { ingame = false; } /**************************************************************** * * NewShape * * Selects a new shape * ****************************************************************/ void NewShape() { if (Rnd.nextInt(40) == 0) { switch (Rnd.nextInt(15)) { case 0: // X block cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=false;cshape[2][3]=true;cshape[3][3]=false; break; case 1: // Diagonal cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=true; cshape[0][1]=false;cshape[1][1]=false;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 2: // U-shaped block cshape[0][0]=true;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=true; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=true; cshape[0][2]=true;cshape[1][2]=false;cshape[2][2]=false;cshape[3][2]=true; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=true; break; case 3: cshape[0][0]=true;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=false;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=true; break; case 4: // 4x4 block cshape[0][0]=true;cshape[1][0]=true;cshape[2][0]=true;cshape[3][0]=true; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=true; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=true; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=true; break; case 5: // + block cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=true;cshape[2][3]=false;cshape[3][3]=false; break; case 6: // 3x3 U block cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=false;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=false; break; case 7: // T block cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=true;cshape[2][3]=false;cshape[3][3]=false; break; case 8: cshape[0][0]=false;cshape[1][0]=true;cshape[2][0]=true;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=true; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=true; cshape[0][3]=false;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=false; break; case 9: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=true; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=false; break; case 10: // 4x3 rectangle cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=true; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=true; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=true; break; case 11: // 4x2 rectangle cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=true; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=true; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 12: // 4 triangle block cshape[0][0]=true;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=true; break; case 13: // 3 triangle block cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=false; break; case 14: // H block cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=false;cshape[2][3]=true;cshape[3][3]=false; break; } } else { switch (Rnd.nextInt(18)) { case 0: // Line cshape[0][0]=false;cshape[1][0]=true;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=true;cshape[2][3]=false;cshape[3][3]=false; break; case 1: // Square cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 2: // 1x1 square cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 3: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 4: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 5: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=false;cshape[2][1]=true;cshape[3][1]=true; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 6: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=false;cshape[2][2]=true;cshape[3][2]=true; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 7: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 8: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 9: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=false;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 10: cshape[0][0]=false;cshape[1][0]=true;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=false; break; case 11: cshape[0][0]=false;cshape[1][0]=true;cshape[2][0]=true;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=true;cshape[2][3]=false;cshape[3][3]=false; break; case 12: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=true;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=false;cshape[2][3]=true;cshape[3][3]=false; break; case 13: // Line 2 cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=false;cshape[2][2]=false;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=false; break; case 14: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=false;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 15: cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; case 16: // 3x3 square cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=true;cshape[1][1]=true;cshape[2][1]=true;cshape[3][1]=false; cshape[0][2]=true;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=true;cshape[1][3]=true;cshape[2][3]=true;cshape[3][3]=false; break; case 17: // Line 3 cshape[0][0]=false;cshape[1][0]=false;cshape[2][0]=false;cshape[3][0]=false; cshape[0][1]=false;cshape[1][1]=false;cshape[2][1]=false;cshape[3][1]=false; cshape[0][2]=false;cshape[1][2]=true;cshape[2][2]=true;cshape[3][2]=false; cshape[0][3]=false;cshape[1][3]=false;cshape[2][3]=false;cshape[3][3]=false; break; } } if ((! uchallenge) && (Rnd.nextInt(20) == 0)) { shapec = Rnd.nextInt(0x1000000); } else { switch (Rnd.nextInt(6)) { case 0: shapec = 0xFF0000; break; case 1: shapec = 0x00FF00; break; case 2: shapec = 0x0000FF; break; case 3: shapec = 0xFFFF00; break; case 4: shapec = 0x00FFFF; break; case 5: shapec = 0xFF00FF; break; } } switch (Rnd.nextInt(4)) { case 1: RotateShape(); break; case 2: RotateShape(); RotateShape(); break; case 3: RotateShape(); RotateShape(); RotateShape(); break; } if (hmode) { shapex = 60; } else { shapex = 10; } shapey = 0; } /****************************************************** * * MoveDown * * Moves the current shape down one square, doing * collision detection and row checking * ******************************************************/ public void MoveDown() { boolean shapehit = false; boolean rowcomplete; int numrows = 0; for (int posx = 0; posx < cshape.length; posx++) { for (int posy = 0; posy < cshape[posx].length; posy++) { if (cshape[posx][posy]) { if ((shapey+posy)==(blockmap[0].length-1)) { shapehit = true; } else if (blockmap[shapex+posx][shapey+posy+1]>0) { shapehit = true; } } } } if (shapehit) { // Shape hit something for (int posx = 0; posx < cshape.length; posx++) { for (int posy = 0; posy < cshape[posx].length; posy++) { if (cshape[posx][posy]) blockmap[shapex+posx][shapey+posy] = shapec; } } // Check for rows for (int rpos = blockmap[0].length - 1; rpos >= 0; rpos--) { rowcomplete = true; for (int cpos = 0; cpos < blockmap.length; cpos++) { if ((blockmap[cpos][rpos] == 0) || (uchallenge && (blockmap[cpos][rpos] != blockmap[0][rpos]))) rowcomplete = false; // Row not complete } if (rowcomplete) { numrows++; // Move all blocks above down one space for (int rpos2 = rpos; rpos2 >= 0; rpos2--) { for (int cpos2 = 0; cpos2 < blockmap.length; cpos2++) { if (rpos2 <= 0) { blockmap[cpos2][rpos2] = 0; } else { blockmap[cpos2][rpos2] = blockmap[cpos2][rpos2-1]; } } } rpos++; // Check same row again, in case the row that was above it was also complete } } score += 1000 * (int)Math.pow(numrows, 2); if ((shapey - cshape[0].length) <= 0) EndGame(); NewShape(); // Select a new shape } else shapey++; } /************************************************** * * RotateShape * * Rotates the current shape 90 degrees clockwise, * doing collision detection * **************************************************/ public void RotateShape() { boolean tshape[][] = new boolean[4][4]; // Temporary shape for (int posx = 0; posx < cshape.length; posx++) { for (int posy = 0; posy < cshape[posx].length; posy++) { tshape[3-posy][posx] = cshape[posx][posy]; if (((shapex+posx)<0)||((shapex+posx)>=blockmap.length)||((shapey+posy)<0)||((shapey+posy)>=blockmap[0].length)) return; // Don't rotate shape, because one or more blocks would be outside the grid } } for (int posx = 0; posx < cshape.length; posx++) { for (int posy = 0; posy < cshape[posx].length; posy++) { if (tshape[posx][posy]&&(blockmap[shapex+posx][shapey+posy]>0)) return; // Don't rotate shape, because shape would collide with one or more blocks } } cshape = tshape; } public void paint(Graphics g) { plock = true; g.drawImage(gs1.img, 0, 0, null); plock = false; } // Override update method to prevent flickering public void update(Graphics screen) { paint(screen); } public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case 38: // Up arrow key keysdown |= KEY_UPARROW; break; case 40: // Down arrow key keysdown |= KEY_DOWNARROW; break; case 37: // Left arrow key keysdown |= KEY_LEFTARROW; break; case 39: // Right arrow key keysdown |= KEY_RIGHTARROW; break; case 88: // X key keysdown |= KEY_X; break; case 17: // Speed key keysdown |= KEY_SPEED; break; } if (ingame) { if ((keysdown & KEY_X) == KEY_X) RotateShape(); // Rotate shape } else { if ((keysdown & KEY_X) == KEY_X) { switch (sitem) { case 0: // New game NewGame(); break; case 1: // Ultimate challenge mode uchallenge = ! uchallenge; break; case 2: // Split mode splitmode = ! splitmode; break; case 3: // Fill mode fillmode = ! fillmode; break; case 4: // Hardcore mode hmode = ! hmode; break; } } if ((keysdown & KEY_UPARROW) == KEY_UPARROW) sitem = (sitem == FIRSTITEM) ? LASTITEM : sitem - 1; if ((keysdown & KEY_DOWNARROW) == KEY_DOWNARROW) sitem = (sitem == LASTITEM) ? FIRSTITEM : sitem + 1; } } public void keyReleased(KeyEvent e) { switch (e.getKeyCode()) { case 38: // Up arrow key keysdown &= ~KEY_UPARROW; break; case 40: // Down arrow key keysdown &= ~KEY_DOWNARROW; break; case 37: // Left arrow key keysdown &= ~KEY_LEFTARROW; break; case 39: // Right arrow key keysdown &= ~KEY_RIGHTARROW; break; case 88: // X key keysdown &= ~KEY_X; break; case 17: // Speed key keysdown &= ~KEY_SPEED; break; } } // Declare unused methods public void keyTyped(KeyEvent e) {} } /****************************************** * * GSurface * * Represents a surface that can be written to with a Graphics object and displayed onscreen * ******************************************/ class GSurface { public Image img; public Graphics g; public GSurface(Component c, int width, int height) { img = c.createImage(width, height); g = img.getGraphics(); } }