/* MazeGame Class * By Tyler Compton for Team Tyro * * This is a very simple and minimal map game. It's official name is * "Color Maze Game." */ import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Canvas; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import org.lwjgl.LWJGLException; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.GL11; import sql.InfoPackage; import threads.SendData; import etc.Constants; import etc.ErrorReport; import etc.MazeMap; public class MazeGame extends Applet { private static final long serialVersionUID = 1L; private static int[][] map; // Universal map array private static int [] recActions; // Stores all the keys pressed. [DIR_RIGHT,UP,DOWN,LEFT] private static int currentAction; // Keeps track of which part of recActions your using. Basically just a counter for recActions private static int rCurrentAction; // Replay current action, just for replaying private static int operation; // The phase of the test. 0= moving around, playing game. 1= Replaying the game 2= Finished with testing, sending data. private static java.util.Date startDate, endDate; // Actual day, time, milliseconds that you played the game. private static String sTime, eTime; private static boolean [] keyRefresh; //Makes sure that holding a button won't machine-gun it. [true=its up, and can be pressed. False=it's being pressed] private static int pX, pY; // Player x and y (within the map array) private static boolean xFlash; private static int xFlashClock; Canvas display_parent; boolean running; Thread gameThread, sendThread; int cirTheta, cirRadius; boolean cirInc; boolean showDiagonal = true; /** Function startLWJGL() * Executes LWJGL's startup methods. */ public void startLWJGL() { gameThread = new Thread() { public void run() { running = true; try { Display.setParent(display_parent); Display.create(); initGL(); } catch(LWJGLException ex) { ErrorReport e = new ErrorReport(ex.getMessage()); e.makeFile(); return; } mainLoop(); } }; gameThread.start(); } /** Function stopLWJGL * Stops the game thread. */ public void stopLWJGL() { running = false; try { gameThread.join(); } catch(InterruptedException ex) { ErrorReport e = new ErrorReport(ex.getMessage()); e.makeFile(); } } /** Function start() * Placeholder for the expected start() method in applets. */ public void start() { } /** Function stop() * Placeholder for the expected stop() method in applets. */ public void stop() { } /** Function destroy() * Destroys the canvas. */ public void destroy() { remove(display_parent); super.destroy(); } /** Function init() * Initializes the canvas and global variables */ public void init() { System.out.printf("TestGame V0.8.0\n"); setLayout(new BorderLayout()); try { display_parent = new Canvas() { private static final long serialVersionUID = 1L; public final void addNotify() { super.addNotify(); startLWJGL(); } public final void removeNotify() { stopLWJGL(); super.removeNotify(); } }; display_parent.setSize(600,600); add(display_parent); display_parent.setFocusable(true); display_parent.requestFocus(); display_parent.setIgnoreRepaint(true); setVisible(true); } catch(Exception ex) { ErrorReport e = new ErrorReport(ex.getMessage()); e.makeFile(); throw new RuntimeException("Unable to create display!"); } xFlashClock = 0; map = makeMaze(); pX = Constants.MAP_WIDTH/2; pY = 0; keyRefresh = new boolean [6]; recActions = new int [50000]; operation = 3; currentAction = 0; cirTheta = 0; cirRadius = 0; cirInc = true; MazeMap maze = new MazeMap(); maze.loadConstMap("cbbbccccccccbbbbcccccbbbbbbcbbbbcbbbcbsbccbcbbbbcccbccc" + "bccccbbbbcbcbbbcbbbcbbbbbcbcbbbcbcccbbbbbcccccccccbbbbbbbcbbbbbbb" + "bbbcbbbbccccccccccbcbbbbbbbbbcbbbcccbbbbcccbbcccccccbbbbcbccccbcc" + "cbcbbbbcbbbbbbcbcbcbbbbcbwcccbcbcbcbbbbcbbbbcbbbcbcbbbbcccccccccc" + "ccbbbb"); for(int x=0; x<Constants.MAP_WIDTH; x++) { for(int y=0; y<Constants.MAP_HEIGHT; y++) { map[x][y] = maze.getSpace(x,y); if(map[x][y] == Constants.MAP_START) { pX = x; pY = y; } } } } /** Function initGL() * Calls OpenGL initialization functions. */ protected void initGL() { // Init OpenGL GL11.glMatrixMode(GL11.GL_PROJECTION); GL11.glLoadIdentity(); GL11.glOrtho(-300, 300, -300, 300, 1, -1); GL11.glMatrixMode(GL11.GL_MODELVIEW); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); } /** Function begin() * Sets up OpenGL and lwjgl and contains the main loop. */ private void mainLoop() { // Start main loop while(running) { // Clears screen and depth buffer GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Rendering render(); if(operation == 0) { // Testing in progress checkKeys(); if(map[pX][pY] == Constants.MAP_WIN) { endDate = new java.util.Date(); SimpleDateFormat sdf; sdf = new SimpleDateFormat("hh:mm:ss.SSS"); eTime = sdf.format(endDate); SendData sender = new SendData(packUp(sTime, eTime, recActions)); sendThread = new Thread(sender); sendThread.start(); operation = 2; } } else if(operation == 1) { // Replay debug feature if(rCurrentAction < currentAction) { replayGame(recActions, rCurrentAction); rCurrentAction++; } } else if(operation == 2) { // Pending send if(!sendThread.isAlive()) { System.out.printf("Finished sending... Bringing to success page.\n"); InfoPackage pack = new InfoPackage(); String tTime = pack.getTime(); try { getAppletContext().showDocument(new URL(getCodeBase()+"thanks.php?time=" + tTime ),"_top"); } catch (MalformedURLException ex) { System.out.println(ex.getMessage()); } operation = 4; } else { if(cirTheta >= 360) { cirTheta = 0; } else { cirTheta++; } if(cirRadius >= 300) { cirInc = false; } else if(cirRadius <= 0) { cirInc = true; } if(cirInc) { cirRadius++; } else { cirRadius--; } double cirX, cirY; GL11.glColor3f(1,1,1); for(int j=0; j<8; j++) { double cTheta = cirTheta + (j*45); if(cTheta > 360) { cTheta = cTheta-360; } cirX = cirRadius * Math.sin(cTheta*(3.14159f/180)); cirY = cirRadius * Math.cos(cTheta*(3.14159f/180)); GL11.glBegin(GL11.GL_TRIANGLE_FAN); GL11.glVertex2d(cirX,cirY); for (int i=0; i<360*4; i++) { double x2 = cirX+Math.sin((double)(i/4)*(3.14159/180))*20; double y2 = cirY+Math.cos((double)(i/4)*(3.14159/180))*20; GL11.glVertex2d(x2,y2); } GL11.glEnd(); } } } else if(operation == 3) { // Wait for user to start testing GL11.glColor4d(0.0, 0.0, 0.0, 0.5); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(-300, 300); GL11.glVertex2f( 300, 300); GL11.glVertex2f( 300, -300); GL11.glVertex2f(-300, -300); GL11.glEnd(); if(Mouse.isButtonDown(0)) { operation = 0; startDate = new java.util.Date(); SimpleDateFormat sdf; sdf = new SimpleDateFormat("hh:mm:ss.SSS"); sTime = sdf.format(startDate); } } else if(operation == 4) { // Everything's finished. Shut up and sit quietly } if(xFlashClock > 0) { xFlashClock--; if(xFlashClock % 300 == 0) { xFlash = !xFlash; } } Display.update(); } Display.destroy(); } /** Function replayGame(int [] s_recActions, int s_length) * Replays the set of actions from the array s_recActions to the point * specified by int s_length. */ private void replayGame(int [] s_recActions, int s_length) { switch(s_recActions[s_length]) { case Constants.DIR_DOWN: pY++; break; case Constants.DIR_UP: pY--; break; case Constants.DIR_RIGHT: pX++; break; case Constants.DIR_LEFT: pX--; break; } try { Thread.sleep(100); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } } /** Function render() * Draws all visible objects. */ private void render() { int x, y; // Bottom left corner coordinates (for readability) // Left box x = -300; y = -100; setColor(pX-1, pY, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); // Right box x = 100; y = -100; setColor(pX+1, pY, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); // Up box x = -100; y = 100; setColor(pX, pY-1, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); // Down box x = -100; y = -300; setColor(pX, pY+1, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); if(showDiagonal) { // Top-Left box x = -300; y = 100; setColor(pX-1, pY-1, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); // Top-Right box x = 100; y = 100; setColor(pX+1, pY-1, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); // Bottom-Left box x = -300; y = -300; setColor(pX-1, pY+1, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); // Bottom-Right box x = 100; y = -300; setColor(pX+1, pY+1, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); } // Center box x = -100; y = -100; setColor(pX, pY, map); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+200,y +0); GL11.glVertex2f(x+200,y+200); GL11.glVertex2f(x +0,y+200); GL11.glEnd(); // Player x = -50; y = -50; GL11.glColor3f(1,1,1); GL11.glBegin(GL11.GL_QUADS); GL11.glVertex2f(x ,y ); GL11.glVertex2f(x+100,y +0); GL11.glVertex2f(x+100,y+100); GL11.glVertex2f(x +0,y+100); GL11.glEnd(); if(xFlash) { GL11.glColor3f(1, 0, 0); GL11.glBegin(GL11.GL_POLYGON); GL11.glVertex2f(x+ 80, y+100); GL11.glVertex2f(x+100, y+100); GL11.glVertex2f(x+100, y+ 80); GL11.glVertex2f(x+ 20, y+ 0); GL11.glVertex2f(x+ 0, y+ 0); GL11.glVertex2f(x+ 0, y+ 20); GL11.glEnd(); GL11.glBegin(GL11.GL_POLYGON); GL11.glVertex2f(x+ 0, y+ 80); GL11.glVertex2f(x+ 0, y+100); GL11.glVertex2f(x+ 20, y+100); GL11.glVertex2f(x+100, y+ 20); GL11.glVertex2f(x+100, y+ 0); GL11.glVertex2f(x+ 80, y+ 0); GL11.glEnd(); } } /** Function setColor(int x, int y, int [][] tmap) * Returns a fitting color based on what is on the given * coordinates on the given map. */ private void setColor(int x, int y, int [][] tmap) { if(x<0 || y<0 || x>Constants.MAP_WIDTH-1 || y>Constants.MAP_HEIGHT-1) { GL11.glColor3f(1,0,0); return; } switch(tmap[x][y]) { case Constants.MAP_BLOCK: GL11.glColor3f(1,0,0); break; case Constants.MAP_SPACE: GL11.glColor3f(0,0,1); break; case Constants.MAP_WIN: GL11.glColor3f(0,1,0); break; case Constants.MAP_START: GL11.glColor3f(0,0,1); break; } } /** Function checkKeys() * Reads for key input and acts accordingly. More specifically, * the player is moved from arrow key presses. */ private void checkKeys() { // Check for "Up" key if(Keyboard.isKeyDown(Keyboard.KEY_UP) && keyRefresh[Constants.DIR_UP]) { if(movePlayer(Constants.DIR_UP, pX, pY, map)) { pY--; recActions[currentAction] = Constants.DIR_UP; currentAction++; } else if(xFlashClock <= 0) { xFlashClock = 1000; } keyRefresh[Constants.DIR_UP] = false; } else if(!Keyboard.isKeyDown(Keyboard.KEY_UP)) { keyRefresh[Constants.DIR_UP] = true; } // Check for "Down" key if(Keyboard.isKeyDown(Keyboard.KEY_DOWN) && keyRefresh[Constants.DIR_DOWN]) { if(movePlayer(Constants.DIR_DOWN, pX, pY, map)) { pY++; recActions[currentAction] = Constants.DIR_DOWN; currentAction++; } else if(xFlashClock <= 0) { xFlashClock = 1000; } keyRefresh[Constants.DIR_DOWN] = false; } else if(!Keyboard.isKeyDown(Keyboard.KEY_DOWN)) { keyRefresh[Constants.DIR_DOWN] = true; } // Check for "Left" key if(Keyboard.isKeyDown(Keyboard.KEY_LEFT) && keyRefresh[Constants.DIR_LEFT]) { if(movePlayer(Constants.DIR_LEFT, pX, pY, map)) { pX--; recActions[currentAction] = Constants.DIR_LEFT; currentAction++; } else if(xFlashClock <= 0) { xFlashClock = 1000; } keyRefresh[Constants.DIR_LEFT] = false; } else if(!Keyboard.isKeyDown(Keyboard.KEY_LEFT)) { keyRefresh[Constants.DIR_LEFT] = true; } // Check for "Right" key if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT) && keyRefresh[Constants.DIR_RIGHT]) { if(movePlayer(Constants.DIR_RIGHT, pX, pY, map)) { pX++; recActions[currentAction] = Constants.DIR_RIGHT; currentAction++; } else if(xFlashClock <= 0) { xFlashClock = 1000; } keyRefresh[Constants.DIR_RIGHT] = false; } else if(!Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) { keyRefresh[Constants.DIR_RIGHT] = true; } } /** Function movePlayer(int dir, int x, int y, int [][] tmap) * Checks move requests for validity. Returns true if no * obstructions would keep the player from moving in that direction. */ private boolean movePlayer(int dir, int x, int y, int [][] tmap) { switch(dir) { case Constants.DIR_UP: if(y>0) { if(tmap[x][y-1] != Constants.MAP_BLOCK) { return true; } else { return false; } } else { return false; } // break; case Constants.DIR_DOWN: if(y<Constants.MAP_HEIGHT-1) { if(tmap[x][y+1] != Constants.MAP_BLOCK) { return true; } else { return false; } } else { return false; } // break; case Constants.DIR_LEFT: if(x>0) { if(tmap[x-1][y] != Constants.MAP_BLOCK) { return true; } else { return false; } } else { return false; } case Constants.DIR_RIGHT: if(x<Constants.MAP_HEIGHT-1) { if(tmap[x+1][y] != Constants.MAP_BLOCK) { return true; } else { return false; } } else { return false; } default: System.out.printf("Error: Unexpected direction in movePlayer.\n"); } return false; } /** Method InfoPackage packUp(java.util.Date sD, java.util.Date eD, int[] a) * sD startDate * eD endDate * a=recActions* */ private InfoPackage packUp(String sTime, String eTime, int[] a) { InfoPackage out = new InfoPackage(); out.setTimes(sTime, eTime); out.setActions(a); return out; } /** Function makeMaze() * Initiates the maze. */ private int[][] makeMaze() { int [][] out = new int [Constants.MAP_WIDTH][Constants.MAP_HEIGHT]; for(int x=0; x<Constants.MAP_WIDTH; x++) { for(int y=0; y<Constants.MAP_HEIGHT; y++) { out[x][y] = Constants.MAP_BLOCK; } } return out; } }