Dev commited on 2018-07-21 10:16:11
Showing 12 changed files, with 1414 additions and 0 deletions.
| ... | ... |
@@ -0,0 +1,170 @@ |
| 1 |
+/* |
|
| 2 |
+ * ScreenManager.java |
|
| 3 |
+ * |
|
| 4 |
+ * Created on 30 March, 2007, 12:35 AM |
|
| 5 |
+ * |
|
| 6 |
+ * To change this template, choose Tools | Template Manager |
|
| 7 |
+ * and open the template in the editor. |
|
| 8 |
+ */ |
|
| 9 |
+ |
|
| 10 |
+/** |
|
| 11 |
+ * |
|
| 12 |
+ * @author |
|
| 13 |
+ */ |
|
| 14 |
+import java.awt.*; |
|
| 15 |
+import java.awt.image.BufferStrategy; |
|
| 16 |
+import java.awt.image.BufferedImage; |
|
| 17 |
+import javax.swing.JFrame; |
|
| 18 |
+ |
|
| 19 |
+/** |
|
| 20 |
+ The ScreenManager class manages initializing and displaying |
|
| 21 |
+ full screen graphics modes. |
|
| 22 |
+*/ |
|
| 23 |
+public class ScreenManager {
|
|
| 24 |
+ |
|
| 25 |
+ private GraphicsDevice device; |
|
| 26 |
+ |
|
| 27 |
+ /** |
|
| 28 |
+ Creates a new ScreenManager object. |
|
| 29 |
+ */ |
|
| 30 |
+ public ScreenManager() {
|
|
| 31 |
+ GraphicsEnvironment environment = |
|
| 32 |
+ GraphicsEnvironment.getLocalGraphicsEnvironment(); |
|
| 33 |
+ device = environment.getDefaultScreenDevice(); |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ |
|
| 37 |
+ /** |
|
| 38 |
+ Returns a list of compatible display modes for the |
|
| 39 |
+ default device on the system. |
|
| 40 |
+ */ |
|
| 41 |
+ public DisplayMode[] getCompatibleDisplayModes() {
|
|
| 42 |
+ return device.getDisplayModes(); |
|
| 43 |
+ } |
|
| 44 |
+ |
|
| 45 |
+ |
|
| 46 |
+ /** |
|
| 47 |
+ Returns the current display mode. |
|
| 48 |
+ */ |
|
| 49 |
+ public DisplayMode getCurrentDisplayMode() {
|
|
| 50 |
+ return device.getDisplayMode(); |
|
| 51 |
+ } |
|
| 52 |
+ |
|
| 53 |
+ /** |
|
| 54 |
+ Enters full screen mode and changes the display mode. |
|
| 55 |
+ If the specified display mode is null or not compatible |
|
| 56 |
+ with this device, or if the display mode cannot be |
|
| 57 |
+ changed on this system, the current display mode is used. |
|
| 58 |
+ <p> |
|
| 59 |
+ The display uses a BufferStrategy with 2 buffers. |
|
| 60 |
+ */ |
|
| 61 |
+ public void setFullScreen(DisplayMode displayMode) {
|
|
| 62 |
+ JFrame frame = new JFrame("PuyoPuyo");
|
|
| 63 |
+ frame.setUndecorated(true); |
|
| 64 |
+ frame.setIgnoreRepaint(true); |
|
| 65 |
+ frame.setResizable(false); |
|
| 66 |
+ |
|
| 67 |
+ device.setFullScreenWindow(frame); |
|
| 68 |
+ if (displayMode != null && device.isDisplayChangeSupported()) |
|
| 69 |
+ {
|
|
| 70 |
+ try {
|
|
| 71 |
+ device.setDisplayMode(displayMode); |
|
| 72 |
+ } |
|
| 73 |
+ catch (IllegalArgumentException ex) { }
|
|
| 74 |
+ } |
|
| 75 |
+ else{
|
|
| 76 |
+ System.out.println("Unable to switch to fullscreen... Exiting.");
|
|
| 77 |
+ System.exit(1); |
|
| 78 |
+ } |
|
| 79 |
+ frame.createBufferStrategy(2); |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ |
|
| 83 |
+ /** |
|
| 84 |
+ Gets the graphics context for the display. The |
|
| 85 |
+ ScreenManager uses double buffering, so applications must |
|
| 86 |
+ call update() to show any graphics drawn. |
|
| 87 |
+ <p> |
|
| 88 |
+ The application must dispose of the graphics object. |
|
| 89 |
+ */ |
|
| 90 |
+ public Graphics2D getGraphics() {
|
|
| 91 |
+ Window window = device.getFullScreenWindow(); |
|
| 92 |
+ if (window != null) {
|
|
| 93 |
+ BufferStrategy strategy = window.getBufferStrategy(); |
|
| 94 |
+ return (Graphics2D)strategy.getDrawGraphics(); |
|
| 95 |
+ } |
|
| 96 |
+ else {
|
|
| 97 |
+ return null; |
|
| 98 |
+ } |
|
| 99 |
+ } |
|
| 100 |
+ |
|
| 101 |
+ |
|
| 102 |
+ /** |
|
| 103 |
+ Updates the display. |
|
| 104 |
+ */ |
|
| 105 |
+ public void update() {
|
|
| 106 |
+ Window window = device.getFullScreenWindow(); |
|
| 107 |
+ if (window != null) {
|
|
| 108 |
+ BufferStrategy strategy = window.getBufferStrategy(); |
|
| 109 |
+ if (!strategy.contentsLost()) {
|
|
| 110 |
+ strategy.show(); |
|
| 111 |
+ } |
|
| 112 |
+ } |
|
| 113 |
+ // Sync the display on some systems. |
|
| 114 |
+ // (on Linux, this fixes event queue problems) |
|
| 115 |
+ Toolkit.getDefaultToolkit().sync(); |
|
| 116 |
+ } |
|
| 117 |
+ |
|
| 118 |
+ |
|
| 119 |
+ /** |
|
| 120 |
+ Returns the window currently used in full screen mode. |
|
| 121 |
+ Returns null if the device is not in full screen mode. |
|
| 122 |
+ */ |
|
| 123 |
+ public Window getFullScreenWindow() {
|
|
| 124 |
+ return device.getFullScreenWindow(); |
|
| 125 |
+ } |
|
| 126 |
+ |
|
| 127 |
+ |
|
| 128 |
+ /** |
|
| 129 |
+ Returns the width of the window currently used in full |
|
| 130 |
+ screen mode. Returns 0 if the device is not in full |
|
| 131 |
+ screen mode. |
|
| 132 |
+ */ |
|
| 133 |
+ public int getWidth() {
|
|
| 134 |
+ Window window = device.getFullScreenWindow(); |
|
| 135 |
+ if (window != null) {
|
|
| 136 |
+ return window.getWidth(); |
|
| 137 |
+ } |
|
| 138 |
+ else {
|
|
| 139 |
+ return 0; |
|
| 140 |
+ } |
|
| 141 |
+ } |
|
| 142 |
+ |
|
| 143 |
+ |
|
| 144 |
+ /** |
|
| 145 |
+ Returns the height of the window currently used in full |
|
| 146 |
+ screen mode. Returns 0 if the device is not in full |
|
| 147 |
+ screen mode. |
|
| 148 |
+ */ |
|
| 149 |
+ public int getHeight() {
|
|
| 150 |
+ Window window = device.getFullScreenWindow(); |
|
| 151 |
+ if (window != null) {
|
|
| 152 |
+ return window.getHeight(); |
|
| 153 |
+ } |
|
| 154 |
+ else {
|
|
| 155 |
+ return 0; |
|
| 156 |
+ } |
|
| 157 |
+ } |
|
| 158 |
+ |
|
| 159 |
+ |
|
| 160 |
+ /** |
|
| 161 |
+ Restores the screen's display mode. |
|
| 162 |
+ */ |
|
| 163 |
+ public void restoreScreen() {
|
|
| 164 |
+ Window window = device.getFullScreenWindow(); |
|
| 165 |
+ if (window != null) {
|
|
| 166 |
+ window.dispose(); |
|
| 167 |
+ } |
|
| 168 |
+ device.setFullScreenWindow(null); |
|
| 169 |
+ } |
|
| 170 |
+} |
|
| 0 | 171 |
\ No newline at end of file |
| ... | ... |
@@ -0,0 +1,516 @@ |
| 1 |
+/* |
|
| 2 |
+ * backEnd.java |
|
| 3 |
+ * |
|
| 4 |
+ * Created on 31 March, 2007, 11:42 PM |
|
| 5 |
+ * |
|
| 6 |
+ * To change this template, choose Tools | Template Manager |
|
| 7 |
+ * and open the template in the editor. |
|
| 8 |
+ */ |
|
| 9 |
+ |
|
| 10 |
+import java.util.Arrays; |
|
| 11 |
+import java.util.Comparator; |
|
| 12 |
+import java.util.HashSet; |
|
| 13 |
+import java.util.Iterator; |
|
| 14 |
+import java.util.Stack; |
|
| 15 |
+import java.util.Vector; |
|
| 16 |
+ |
|
| 17 |
+/** |
|
| 18 |
+ * Holds all the logic that drives the game. |
|
| 19 |
+ * <p>The main engine of the game is comprised of the following |
|
| 20 |
+ * four methods: |
|
| 21 |
+ * <ul> |
|
| 22 |
+ * <li>{@link puyopuyo.backEnd#popPuyos(puyo[]) popPuyos} - This acts as an entry point to {@link puyopuyo.frontEnd# frontEnd} to the logic of the game.</li>
|
|
| 23 |
+ * <li>{@link puyopuyo.backEnd#probe(puyo) probe(puyo)} - It identifies the chain due to puyo passed to it as a parameter.</li>
|
|
| 24 |
+ * <li>{@link puyopuyo.backEnd#popAndMarkDroppings(HashSet) popAndMarkDroppings} - It removes the puyo from {@link puyopuyo.backEnd#boardMap boardMap}</li>
|
|
| 25 |
+ * and also marks the puyo which is to move down because of popping.</li> |
|
| 26 |
+ * <li>{@link puyopuyo.backEnd#settleDown(puyo) settleDown} - Moves down the puyo (and all those above it) to fill</li>
|
|
| 27 |
+ * in the void created due to popping of puyo.</li> |
|
| 28 |
+ * </ul> |
|
| 29 |
+ * </p> |
|
| 30 |
+ * @author Dev Ghai |
|
| 31 |
+ */ |
|
| 32 |
+public class backEnd extends puyo{
|
|
| 33 |
+ |
|
| 34 |
+ /** |
|
| 35 |
+ * Creates a new instance of backEnd, initialises the board |
|
| 36 |
+ * and pushes a pair of puyos in {@link puyopuyo.backEnd#boardMap boardMap} using {@link puyopuyo.backEnd#pushPuyos() pushPuyos}.
|
|
| 37 |
+ * {@link puyopuyo.backEnd#boardMap boardMap} is a two dimensional array that the heart of the game. It logically
|
|
| 38 |
+ * represents the game's board in memory in form of an array whose width |
|
| 39 |
+ * is equal to {@link puyopuyo.backEnd#puyosOnXAxis puyosOnXAxis} and height is equal to {@link puyopuyo.backEnd#puyosOnYAxis puyosOnYAxis}.
|
|
| 40 |
+ */ |
|
| 41 |
+ public backEnd() {
|
|
| 42 |
+ for (int i = 0; i<puyosOnXAxis; i++) |
|
| 43 |
+ for(int j = 0; j<puyosOnYAxis; j++) |
|
| 44 |
+ boardMap[i][j] = null; //=> board is initially empty |
|
| 45 |
+ pushPuyos(); //and let the game begin! |
|
| 46 |
+ } |
|
| 47 |
+ //Clean and Build the Project to see the following 2 values take effect. |
|
| 48 |
+ /** |
|
| 49 |
+ * Holds the number of puyos on X Axis. Modify this value to effectively |
|
| 50 |
+ * change the size of the board. Logic has been made to depend on it. |
|
| 51 |
+ */ |
|
| 52 |
+ int puyosOnXAxis = 6; |
|
| 53 |
+ /** |
|
| 54 |
+ * Holds the number of puyos on Y Axis. Modify this value to effectively |
|
| 55 |
+ * change the size of the board. Logic has been made to depend on it. |
|
| 56 |
+ */ |
|
| 57 |
+ int puyosOnYAxis = 12; |
|
| 58 |
+ /** |
|
| 59 |
+ * Holds the minimum length of the chain in terms of puyos that will cause puyos |
|
| 60 |
+ * to be popped from the board. |
|
| 61 |
+ */ |
|
| 62 |
+ int popmin = 4; |
|
| 63 |
+ /** |
|
| 64 |
+ * Stores the pair of puyos pushed onto the board. |
|
| 65 |
+ */ |
|
| 66 |
+ private puyo puyoPair [] = new puyo[2]; |
|
| 67 |
+ /** |
|
| 68 |
+ * Returns a pair of puyos in form of an one dimensional array. |
|
| 69 |
+ */ |
|
| 70 |
+ public puyo[] getPuyoPair(){
|
|
| 71 |
+ return puyoPair; |
|
| 72 |
+ } |
|
| 73 |
+ /** |
|
| 74 |
+ * Integer value that holds the score of the game. Popping of one puyo |
|
| 75 |
+ * adds 10 to the current score. |
|
| 76 |
+ */ |
|
| 77 |
+ private int score = 0; |
|
| 78 |
+ /** |
|
| 79 |
+ * Returns the current score. {@link puyopuyo.backEnd#score score} is incremented by 10 points when
|
|
| 80 |
+ * one puyo is popped. |
|
| 81 |
+ */ |
|
| 82 |
+ public int getScore(){
|
|
| 83 |
+ return score; |
|
| 84 |
+ } |
|
| 85 |
+ /** |
|
| 86 |
+ * A boolean value that tells whether the game is over or not. |
|
| 87 |
+ * |
|
| 88 |
+ * <p>This value is set in two cases - |
|
| 89 |
+ * <li> |
|
| 90 |
+ * <ol>When {@link puyopuyo.backEnd#pushPuyos() pushPuyos} is unable to push a pair on the board.</ol>
|
|
| 91 |
+ * <ol>When the user hits the Esc key, i.e. s/he wants to exit from the game.</ol> |
|
| 92 |
+ * </li></p> |
|
| 93 |
+ */ |
|
| 94 |
+ private boolean gameOver = false; |
|
| 95 |
+ /** |
|
| 96 |
+ * Logically tells if the game is over or not by returning the (boolean) value |
|
| 97 |
+ * of {@link puyopuyo.backEnd#gameOver gameOver}.
|
|
| 98 |
+ */ |
|
| 99 |
+ public boolean isGameOver(){
|
|
| 100 |
+ return gameOver; |
|
| 101 |
+ } |
|
| 102 |
+ |
|
| 103 |
+ /** |
|
| 104 |
+ * This method allows {@link puyopuyo.frontEnd# frontEnd} to set the gameOver to true.
|
|
| 105 |
+ * <p>Game ends in two cases - |
|
| 106 |
+ * <ol><li>When {@link puyopuyo.backEnd#pushPuyos() pushPuyos} is unable to push a pair on the board.</li>
|
|
| 107 |
+ * <li>When the user hits the Esc key, i.e. s/he wants to exit from the game.</li> |
|
| 108 |
+ * </ol></p> |
|
| 109 |
+ * @param status 'status' of the game to be copied to {@link gameOver}.
|
|
| 110 |
+ */ |
|
| 111 |
+ public void setGameOver(boolean status){
|
|
| 112 |
+ gameOver = status; |
|
| 113 |
+ } |
|
| 114 |
+ /** |
|
| 115 |
+ * This two dimensional array is the heart of the game. It logically |
|
| 116 |
+ * represents the game's board in memory in form of an array whose width |
|
| 117 |
+ * is equal to {@link puyopuyo.backEnd#puyosOnXAxis puyosOnXAxis} and height is equal to {@link puyopuyo.backEnd#puyosOnYAxis puyosOnYAxis}.
|
|
| 118 |
+ */ |
|
| 119 |
+ private puyo boardMap[][] = new puyo[puyosOnXAxis][puyosOnYAxis]; |
|
| 120 |
+ |
|
| 121 |
+ /** |
|
| 122 |
+ * Returns true if insertion successfully takes place in {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 123 |
+ * @param p Puyo to insert in boardMap |
|
| 124 |
+ * @param X X Co-ordinate of the insertion point. |
|
| 125 |
+ * @param Y Y co-ordinate of the insertion point. |
|
| 126 |
+ * @return Returns if the insertion was successful or not. |
|
| 127 |
+ */ |
|
| 128 |
+ private synchronized boolean insertInBoardMap(puyo p, int X, int Y){
|
|
| 129 |
+ /*If boardMap[X,Y] holds null => it is empty & the new point obeys |
|
| 130 |
+ * boundary conditions. Set the same and return true, |
|
| 131 |
+ * else that cell is filled or lies outside board, return false.*/ |
|
| 132 |
+ |
|
| 133 |
+ boolean newPointLiesOnBoard = (X>=0 & X<puyosOnXAxis) & (Y>=0 & Y<puyosOnYAxis); |
|
| 134 |
+ if(newPointLiesOnBoard && boardMap[X][Y]==null){
|
|
| 135 |
+ boardMap[X][Y] = p; |
|
| 136 |
+ return true; |
|
| 137 |
+ } |
|
| 138 |
+ //control will reach here only when the cell is previously filled or the point lies outside the board |
|
| 139 |
+ return false; |
|
| 140 |
+ } |
|
| 141 |
+ |
|
| 142 |
+ /** |
|
| 143 |
+ * Removes puyo from the {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 144 |
+ * @param X X co-ordinate in boardMap from which to remove puyo. |
|
| 145 |
+ * @param Y Y co-ordinate of boardMap from which to remove the puyo. |
|
| 146 |
+ */ |
|
| 147 |
+ private synchronized void removeFromBoardMap(int X, int Y){
|
|
| 148 |
+ boolean pointLiesOnBoard = (X>=0 & X<puyosOnXAxis) & (Y>=0 & Y<puyosOnYAxis); |
|
| 149 |
+ if (pointLiesOnBoard && boardMap[X][Y]!=null) |
|
| 150 |
+ boardMap[X][Y] = null; |
|
| 151 |
+ } |
|
| 152 |
+ |
|
| 153 |
+ /** |
|
| 154 |
+ * Returns {@link puyopuyo.backEnd#boardMap boardMap}. One of the main purposes of
|
|
| 155 |
+ * this method is to provide a two dimensional array to {@link puyopuyo.frontEnd# frontEnd}
|
|
| 156 |
+ * for printing the board onto screen. {@link puyopuyo.frontEnd#drawBoardMap() drawBoardMap}
|
|
| 157 |
+ * uses this method to extract the logical {@link puyopuyo.backEnd#boardMap boardMap} and print
|
|
| 158 |
+ * it onto the screen. |
|
| 159 |
+ * @return boardMap |
|
| 160 |
+ */ |
|
| 161 |
+ public puyo[][] getBoardMap(){
|
|
| 162 |
+ return boardMap; |
|
| 163 |
+ } |
|
| 164 |
+ /** |
|
| 165 |
+ * Generates a new {@link puyo# puyo} and randomly assigns color to the generated {@link puyo# puyo}.
|
|
| 166 |
+ * @return A puyo with randomly generated colors. |
|
| 167 |
+ */ |
|
| 168 |
+ private puyo getNewPuyo(){
|
|
| 169 |
+ Math.random(); //initiate the random number generator by first call |
|
| 170 |
+ puyo p = new puyo(); //initialize p |
|
| 171 |
+ switch((int)(Math.random()*10)%4) {
|
|
| 172 |
+ |
|
| 173 |
+ case 0: p = new puyo("./images/redPuyo.png", 'r'); //red puyo
|
|
| 174 |
+ break; |
|
| 175 |
+ case 1: p = new puyo("./images/greenPuyo.png", 'g'); //green puyo
|
|
| 176 |
+ break; |
|
| 177 |
+ case 2: p = new puyo("./images/bluePuyo.png", 'b'); //blue puyo
|
|
| 178 |
+ break; |
|
| 179 |
+ case 3: p = new puyo("./images/yellowPuyo.png", 'y'); //yellow puyo
|
|
| 180 |
+ } |
|
| 181 |
+ return p; |
|
| 182 |
+ } |
|
| 183 |
+ |
|
| 184 |
+ /** |
|
| 185 |
+ * Pushes a new pair of puyos in {@link puyopuyo.backEnd#boardMap boardMap} at the top of
|
|
| 186 |
+ * the board. If no new pair can be pushed, {@link puyopuyo.backEnd#gameOver gameOver} is set true via {@link puyopuyo.backEnd#setGameOver(boolean) setGameOver}.
|
|
| 187 |
+ */ |
|
| 188 |
+ |
|
| 189 |
+ |
|
| 190 |
+ |
|
| 191 |
+ public void pushPuyos(){
|
|
| 192 |
+ int centerX = (puyosOnXAxis-1)/2; |
|
| 193 |
+ if(boardMap[centerX][0]==null & boardMap[centerX+1][0]==null) {
|
|
| 194 |
+ puyo p1 = getNewPuyo(); |
|
| 195 |
+ puyo p2 = getNewPuyo(); |
|
| 196 |
+ p1.setX(centerX); p1.setY(0); |
|
| 197 |
+ boardMap[centerX][0] = p1; |
|
| 198 |
+ p2.setX(++centerX); p2.setY(0); //centerX+1 causes second puyo to be printed over first puyo |
|
| 199 |
+ //Hence v c only 1 puyo when a pair is pushed on board. |
|
| 200 |
+ boardMap[centerX][0] = p2; |
|
| 201 |
+ puyoPair[0] = p1; |
|
| 202 |
+ puyoPair[1] = p2; |
|
| 203 |
+ } else |
|
| 204 |
+ setGameOver(true); //!! |
|
| 205 |
+ } |
|
| 206 |
+ /** |
|
| 207 |
+ * Moves the puyo passed as parameter one positon to left in {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 208 |
+ * It also updates the property of the puyo after successfully moving it. |
|
| 209 |
+ * @param p puyo to be moved left. |
|
| 210 |
+ * @return True if puyo was successfully moved and its property updated, else false |
|
| 211 |
+ */ |
|
| 212 |
+ public boolean moveLeft(puyo p){
|
|
| 213 |
+ boolean retVal; |
|
| 214 |
+ if( retVal = insertInBoardMap(p, p.getX() - 1, p.getY()) ){
|
|
| 215 |
+ removeFromBoardMap(p.getX(), p.getY()); |
|
| 216 |
+ p.setX(p.getX()-1); //update the puyo's property |
|
| 217 |
+ } |
|
| 218 |
+ return retVal; |
|
| 219 |
+ } |
|
| 220 |
+ |
|
| 221 |
+ /** |
|
| 222 |
+ * Moves the puyo passed as parameter one positon to right in {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 223 |
+ * It also updates the property of the puyo after successfully moving it. |
|
| 224 |
+ * @return True if puyo was successfully moved and its property updated, else false |
|
| 225 |
+ * @param p Puyo to be moved right. |
|
| 226 |
+ */ |
|
| 227 |
+ public boolean moveRight(puyo p){
|
|
| 228 |
+ boolean retVal; |
|
| 229 |
+ if( retVal = insertInBoardMap(p, p.getX() + 1, p.getY())){
|
|
| 230 |
+ removeFromBoardMap(p.getX(), p.getY()); |
|
| 231 |
+ p.setX(p.getX()+1); //update puyo's property |
|
| 232 |
+ } |
|
| 233 |
+ return retVal; |
|
| 234 |
+ } |
|
| 235 |
+ |
|
| 236 |
+ /** |
|
| 237 |
+ * Moves the puyo passed as parameter one positon down in {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 238 |
+ * It also updates the property of the puyo after successfully moving it. |
|
| 239 |
+ * @return True if puyo was successfully moved and its property updated, else false |
|
| 240 |
+ * @param p Puyo to be moved down. |
|
| 241 |
+ */ |
|
| 242 |
+ public boolean moveDown(puyo p){
|
|
| 243 |
+ /* while(boundary conditions are ok & next cell is empty) |
|
| 244 |
+ * The loop will exit when an attempt will be made to insert an imaginary |
|
| 245 |
+ * puyo above the topmost puyo. |
|
| 246 |
+ */ |
|
| 247 |
+ if( insertInBoardMap(p, p.getX(), p.getY()+1) ){
|
|
| 248 |
+ removeFromBoardMap(p.getX(), p.getY()); |
|
| 249 |
+ p.setY(p.getY()+1); |
|
| 250 |
+ return true; |
|
| 251 |
+ } |
|
| 252 |
+ return false; |
|
| 253 |
+ } |
|
| 254 |
+ |
|
| 255 |
+ /** |
|
| 256 |
+ * Rotates clockwise the puyo p[1] around p[0]. |
|
| 257 |
+ * <p><b>DETAILED DESCRIPTION:</b><br> |
|
| 258 |
+ * p[0] will always be the pivot around which p[1] will rotate<br> |
|
| 259 |
+ * Determine the orientation of the pair: HORIZONTAL or VERTICAL<br> |
|
| 260 |
+ * Determine position of p[1] : NORTH EAST SOUTH or WEST<br> |
|
| 261 |
+ * Move according to the determined position.<br> |
|
| 262 |
+ * Simple?? |
|
| 263 |
+ * </p> |
|
| 264 |
+ * @param p Pair of puyos to rotate. |
|
| 265 |
+ */ |
|
| 266 |
+ public void rotate(puyo[] p){
|
|
| 267 |
+ //only a pair can be rotated |
|
| 268 |
+ if (p[0].getY()==p[1].getY()){
|
|
| 269 |
+ //=>lie in same row |
|
| 270 |
+ if(p[1].getX() == p[0].getX() + 1){
|
|
| 271 |
+ //p[1] is on right => move p[1] SOUTH |
|
| 272 |
+ if(insertInBoardMap(p[1], p[0].getX(), p[0].getY()+1)){
|
|
| 273 |
+ //the cell below p[0] is empty & successful move has taken place |
|
| 274 |
+ //nullify previous position and update the status of puyo p[1] |
|
| 275 |
+ boardMap[p[1].getX()][p[1].getY()] = null; |
|
| 276 |
+ p[1].setX(p[0].getX()); p[1].setY(p[0].getY()+1); |
|
| 277 |
+ } |
|
| 278 |
+ } else if(p[0].getX() == p[1].getX() + 1) {
|
|
| 279 |
+ //p[1] is on the left => move p[1] NORTH |
|
| 280 |
+ if(insertInBoardMap(p[1], p[0].getX(), p[0].getY()-1)){
|
|
| 281 |
+ boardMap[p[1].getX()][p[1].getY()] = null; |
|
| 282 |
+ p[1].setX(p[0].getX()); p[1].setY(p[0].getY()-1); |
|
| 283 |
+ } |
|
| 284 |
+ } |
|
| 285 |
+ }// horizontal case ends here |
|
| 286 |
+ else if(p[0].getX() == p[1].getX()){
|
|
| 287 |
+ //=> lie in the same column |
|
| 288 |
+ if(p[0].getY() == p[1].getY() + 1){
|
|
| 289 |
+ //p[1] is above p[0] => move p[1] EAST |
|
| 290 |
+ if(insertInBoardMap(p[1], p[0].getX()+1, p[0].getY())){
|
|
| 291 |
+ boardMap[p[1].getX()][p[1].getY()] = null; |
|
| 292 |
+ p[1].setX(p[0].getX() + 1); p[1].setY(p[0].getY()); |
|
| 293 |
+ } |
|
| 294 |
+ } else if(p[1].getY() == p[0].getY()+1){
|
|
| 295 |
+ //p[1] is below p[0] => move p[1] WEST |
|
| 296 |
+ if(insertInBoardMap(p[1], p[0].getX()-1, p[0].getY())){
|
|
| 297 |
+ boardMap[p[1].getX()][p[1].getY()] = null; |
|
| 298 |
+ p[1].setX(p[0].getX() - 1); p[1].setY(p[0].getY()); |
|
| 299 |
+ } |
|
| 300 |
+ } |
|
| 301 |
+ } |
|
| 302 |
+ }// end of the function |
|
| 303 |
+ |
|
| 304 |
+ /** |
|
| 305 |
+ * Holds all the puyos to be removed from the {@link puyopuyo.backEnd#boardMap boardMap} due to them forming a chain
|
|
| 306 |
+ * of {@link puyopuyo.backEnd#popmin popmin} length.
|
|
| 307 |
+ */ |
|
| 308 |
+ private Stack puyosToBePopped = new Stack(); |
|
| 309 |
+ /** |
|
| 310 |
+ * Holds the next set of puyos which have to be settled down and then checks |
|
| 311 |
+ * have to be made once they cannot move downwards anymore. |
|
| 312 |
+ */ |
|
| 313 |
+ private Stack nextSetOfPuyos = new Stack(); |
|
| 314 |
+ /** |
|
| 315 |
+ * It is the entry point for {@link puyopuyo.frontEnd# frontEnd}.
|
|
| 316 |
+ * |
|
| 317 |
+ * <p>It also acts as 'manager', controlling the three methods that comprise the core logic: |
|
| 318 |
+ * <ul> |
|
| 319 |
+ * <li>{@link puyopuyo.backEnd#probe(puyo) probe(puyo)}</li>
|
|
| 320 |
+ * <li>{@link puyopuyo.backEnd#popAndMarkDroppings(HashSet) popAndMarkDroppings(HashSet)}</li>
|
|
| 321 |
+ * <li>{@link puyopuyo.backEnd#settleDown(puyo) settleDown(puyo)}</li>
|
|
| 322 |
+ * </ul></p> |
|
| 323 |
+ * @param p Puyo for which chain has to be identified and popped from the board. |
|
| 324 |
+ */ |
|
| 325 |
+ public synchronized void popPuyos(puyo p[]){
|
|
| 326 |
+ //both of the puyos in the pair have settled down, check can begin with any puyo |
|
| 327 |
+ |
|
| 328 |
+ if(p.length == 0) return; //termination condition for recursion. no more puyos available to work on |
|
| 329 |
+ HashSet marked = new HashSet(); |
|
| 330 |
+ puyo[] temp; |
|
| 331 |
+ for(int i = 0; i<p.length; i++){
|
|
| 332 |
+ marked = probe(p[i]); |
|
| 333 |
+ if(marked.size()>=popmin) |
|
| 334 |
+ puyosToBePopped.push(new HashSet(marked)); |
|
| 335 |
+ marked.clear(); |
|
| 336 |
+ } |
|
| 337 |
+ |
|
| 338 |
+ while(!puyosToBePopped.isEmpty()){
|
|
| 339 |
+ temp = popAndMarkDroppings((HashSet)puyosToBePopped.pop()); |
|
| 340 |
+ if(temp.length > 0) |
|
| 341 |
+ nextSetOfPuyos.push(temp); |
|
| 342 |
+ } |
|
| 343 |
+ |
|
| 344 |
+ Iterator scan = nextSetOfPuyos.iterator();//iterator doesn't remove from stack. Popping is done in next loop |
|
| 345 |
+ while(scan.hasNext()){
|
|
| 346 |
+ temp = (puyo[])scan.next(); |
|
| 347 |
+ /*puyos are sorted in ascending order of getY() [popAndMarkDroppings returns a sorted array]. |
|
| 348 |
+ * The ones with greater value of Y need to be moved down before others otherwise they'll |
|
| 349 |
+ * block the path of puyos above them... eventually leaving some puyos hanging in mid air. |
|
| 350 |
+ */ |
|
| 351 |
+ for(int i=temp.length -1; i>=0; i--) |
|
| 352 |
+ settleDown(temp[i]); |
|
| 353 |
+ } |
|
| 354 |
+ while(!nextSetOfPuyos.isEmpty()) |
|
| 355 |
+ popPuyos((puyo[])nextSetOfPuyos.pop()); |
|
| 356 |
+ } |
|
| 357 |
+ |
|
| 358 |
+ /** |
|
| 359 |
+ * Settles the puyo passed as parameter down to the floor and also all the puyos above it. |
|
| 360 |
+ * @param p Puyo to be moved down. |
|
| 361 |
+ */ |
|
| 362 |
+ private synchronized void settleDown(puyo p){
|
|
| 363 |
+ int xPos = p.getX(); |
|
| 364 |
+ int yPos = p.getY(); |
|
| 365 |
+ //xPos and yPos are modified, xCopy and yCopy are used to check termination condition for recursion. |
|
| 366 |
+ while(p!=null && insertInBoardMap(p, xPos, yPos+1)){
|
|
| 367 |
+ p.setY(yPos+1); |
|
| 368 |
+ removeFromBoardMap(xPos, yPos); |
|
| 369 |
+ yPos++; |
|
| 370 |
+ } |
|
| 371 |
+ } |
|
| 372 |
+ |
|
| 373 |
+ |
|
| 374 |
+ /** |
|
| 375 |
+ * Holds the puyos to be popped from {@link puyopuyo.backEnd#boardMap boardMap} as they form chains of length >= {@link puyopuyo.backEnd#popmin popmin}.
|
|
| 376 |
+ */ |
|
| 377 |
+ private HashSet removePuyos = new HashSet(); |
|
| 378 |
+ |
|
| 379 |
+ /** |
|
| 380 |
+ * Returns the set of puyos to be moved down because of chains formed by |
|
| 381 |
+ * puyo, being passed as the argument. |
|
| 382 |
+ * @param p Puyo for which chains on the board have to be identified. |
|
| 383 |
+ * @return Set of puyos to be removed from the boardMap. |
|
| 384 |
+ */ |
|
| 385 |
+ private synchronized HashSet probe(puyo p){
|
|
| 386 |
+ |
|
| 387 |
+ removePuyos.add(p); //****mark the puyo for which checks have to be done |
|
| 388 |
+ |
|
| 389 |
+ |
|
| 390 |
+ int nextX = p.getX(), nextY = p.getY(); |
|
| 391 |
+ int directions[]={-1, +1};
|
|
| 392 |
+ |
|
| 393 |
+ /* Description of the following loop: |
|
| 394 |
+ * This method is called recursively and proceeds forward in the correct |
|
| 395 |
+ * direction. Correct direction here is defined as that direction where |
|
| 396 |
+ * a puyo with same color exists. procession is done by calling the same |
|
| 397 |
+ * function with the new puyo (stored in temp). |
|
| 398 |
+ * First it probes the one to left and proceeds in that direction, if |
|
| 399 |
+ * there's a proper match. Then the one to right is checked. The above |
|
| 400 |
+ * 2 activities are done in the first for loop. |
|
| 401 |
+ * Likewise, the second for loop checks first below current puyo and |
|
| 402 |
+ * then the puyo above it. |
|
| 403 |
+ * In both the loops, if a matching puyo exists above, below or to left |
|
| 404 |
+ * or right, the MATCHED puyo is added to the Set which holds the *unique* |
|
| 405 |
+ * puyos to be removed. Then the control passes onto MATCHED puyo. |
|
| 406 |
+ * Because the set holds unique values only, the control doesnot allow |
|
| 407 |
+ * probing to proceed in direction of puyo already matched. Hence the |
|
| 408 |
+ * control finally goes towards any uncharted direction. |
|
| 409 |
+ * MATCHED puyo is added because when we reach end of a chain, the last |
|
| 410 |
+ * puyo in a chain will not be added because the puyo from which the |
|
| 411 |
+ * control came will already be in the set, hence not allowing the last |
|
| 412 |
+ * matched puyo to be added to the set. |
|
| 413 |
+ */ |
|
| 414 |
+ for (int i = 0 ; i < directions.length; i++){
|
|
| 415 |
+ nextX = p.getX()+directions[i]; |
|
| 416 |
+ if( (nextX >= 0 & nextX < puyosOnXAxis) && boardMap[nextX][nextY]!=null){ //boundary conditions
|
|
| 417 |
+ if(p.getColor()==boardMap[nextX][nextY].getColor()){
|
|
| 418 |
+ if(removePuyos.add(boardMap[nextX][nextY])) |
|
| 419 |
+ //successful addition => temp has not been parsed previously, add it to set |
|
| 420 |
+ probe(boardMap[nextX][nextY]); //proceed forward with the check in its direction |
|
| 421 |
+ } |
|
| 422 |
+ } |
|
| 423 |
+ } |
|
| 424 |
+ nextX = p.getX(); //nextX was changed by above loop |
|
| 425 |
+ for (int i = 0 ; i < directions.length; i++){
|
|
| 426 |
+ nextY = p.getY()+directions[i]; |
|
| 427 |
+ if( (nextY >= 0 & nextY < puyosOnYAxis) && boardMap[nextX][nextY]!=null){ //boundary conditions
|
|
| 428 |
+ if(p.getColor()==boardMap[nextX][nextY].getColor()){
|
|
| 429 |
+ if(removePuyos.add(boardMap[nextX][nextY])) |
|
| 430 |
+ //successful addition => temp has not been parsed previously, add it to set |
|
| 431 |
+ probe(boardMap[nextX][nextY]); //proceed forward with the check in temp puyo's direction |
|
| 432 |
+ } |
|
| 433 |
+ }//end of if checking boundary condition |
|
| 434 |
+ } |
|
| 435 |
+ |
|
| 436 |
+ return removePuyos; |
|
| 437 |
+ |
|
| 438 |
+ }//end of probe() |
|
| 439 |
+ /** |
|
| 440 |
+ * Pop the puyos marked by {@link puyopuyo.backEnd#probe(puyo) probe(puyo)} and also identifies all the puyos which have
|
|
| 441 |
+ * to be moved down because of popping. |
|
| 442 |
+ * @param deletePuyos Puyos which have to be deleted from the boardMap. |
|
| 443 |
+ * @return Puyos which have to be moved down. |
|
| 444 |
+ */ |
|
| 445 |
+ private synchronized puyo[] popAndMarkDroppings(HashSet deletePuyos){ //:) pun intended
|
|
| 446 |
+ |
|
| 447 |
+ /* it works on vectors and returns an array of puyos. |
|
| 448 |
+ *Vectors are being used because they are already synchronized, can be |
|
| 449 |
+ *converted to arrays after everything is done and can be resized dynamically |
|
| 450 |
+ */ |
|
| 451 |
+ Vector v = new Vector(); |
|
| 452 |
+ puyo temp; |
|
| 453 |
+ puyo puyoAboveTemp; |
|
| 454 |
+ Iterator i = deletePuyos.iterator(); |
|
| 455 |
+ while(i.hasNext()){//goin thru each element exactly once
|
|
| 456 |
+ temp = (puyo)i.next(); //get an element from the set |
|
| 457 |
+ //popping routine// |
|
| 458 |
+ boardMap[temp.getX()][temp.getY()] = null; //remove temp from boardMap if not already removed |
|
| 459 |
+ score+=10; //increment score by 10 |
|
| 460 |
+ //---------------// |
|
| 461 |
+ //Marking routine// |
|
| 462 |
+ try{
|
|
| 463 |
+ do{
|
|
| 464 |
+ puyoAboveTemp = boardMap[temp.getX()][temp.getY()-1]; |
|
| 465 |
+ if( (puyoAboveTemp!=null && !v.contains(puyoAboveTemp)) & !deletePuyos.contains(puyoAboveTemp) ) //puyoAboveTemp has not been already marked |
|
| 466 |
+ v.add(puyoAboveTemp);//add it to set of puyos to be moved down |
|
| 467 |
+ temp = puyoAboveTemp; |
|
| 468 |
+ }while( temp!=null ); //puyo above the one being removed exists and is not the one to be popped |
|
| 469 |
+ } catch (ArrayIndexOutOfBoundsException e){
|
|
| 470 |
+ /* This happens in a very special case in which a pair falls down |
|
| 471 |
+ *and one among then is blocked at y=0 and the other falls down |
|
| 472 |
+ *making a chain in the coloumn which is filled till y=0. When |
|
| 473 |
+ *the chain pops, the above loop moves upward and on finding 'puyoAboveTemp' |
|
| 474 |
+ *above puyo at y=0, it reports this exception. because it is a |
|
| 475 |
+ *very special case, it need not be checked in the normal flow. |
|
| 476 |
+ * |
|
| 477 |
+ *When the exception occurs, the method should just continue with |
|
| 478 |
+ *popping the chain as all the puyos making up the column have been marked. |
|
| 479 |
+ *When exception has occured, control is already outside the loop and |
|
| 480 |
+ *should proceed normally with the outer while loop... |
|
| 481 |
+ */ |
|
| 482 |
+ puyoAboveTemp = null; |
|
| 483 |
+ } |
|
| 484 |
+ //---------------// |
|
| 485 |
+ temp = null; //puyoAboveTemp is null when control reaches here. |
|
| 486 |
+ }//end of while |
|
| 487 |
+ |
|
| 488 |
+ puyo[] movePuyosDown = new puyo[v.size()]; |
|
| 489 |
+ movePuyosDown = (puyo[])v.toArray(movePuyosDown); |
|
| 490 |
+ v.clear(); |
|
| 491 |
+ if(movePuyosDown.length > 1) |
|
| 492 |
+ Arrays.sort(movePuyosDown, new Comparator(){
|
|
| 493 |
+ public int compare(Object p1, Object p2){
|
|
| 494 |
+ if ( (p1!=null && !(p1 instanceof puyo)) & (p2!=null && !(p2 instanceof puyo)) ) |
|
| 495 |
+ throw new ClassCastException(); |
|
| 496 |
+ /*In case of one puyo being null, the one's that aint null is returned |
|
| 497 |
+ to be greater. If both are null, value corresponding to equality is returned*/ |
|
| 498 |
+ if( (p1 == null) & (p2 instanceof puyo) ) |
|
| 499 |
+ return -1; //once this evaluates to true, the control should not go further, thats y return statement is used here. |
|
| 500 |
+ else if ( (p1 instanceof puyo) & (p2 == null)) |
|
| 501 |
+ return 1; |
|
| 502 |
+ else if ( (p1 == null) & (p2 == null)) |
|
| 503 |
+ return 0; |
|
| 504 |
+ int retVal = 0; |
|
| 505 |
+ if ( ((puyo)p1).getY() < ((puyo)p2).getY() ) |
|
| 506 |
+ retVal = -1; |
|
| 507 |
+ else if ( ((puyo)p1).getY() > ((puyo)p2).getY()) |
|
| 508 |
+ retVal = 1; |
|
| 509 |
+ //if the two are equal, retVal = 0, which is the default value. |
|
| 510 |
+ return retVal; |
|
| 511 |
+ } |
|
| 512 |
+ } /* end of anonymous inner class*/ |
|
| 513 |
+ ); |
|
| 514 |
+ return movePuyosDown; |
|
| 515 |
+ } |
|
| 516 |
+} |
| ... | ... |
@@ -0,0 +1,611 @@ |
| 1 |
+/* |
|
| 2 |
+ * frontEnd.java |
|
| 3 |
+ * |
|
| 4 |
+ * Created on 30 March, 2007, 12:04 AM |
|
| 5 |
+ * |
|
| 6 |
+ * To change this template, choose Tools | Template Manager |
|
| 7 |
+ * and open the template in the editor. |
|
| 8 |
+ */ |
|
| 9 |
+ |
|
| 10 |
+import java.awt.AWTException; |
|
| 11 |
+import java.awt.Color; |
|
| 12 |
+import java.awt.Cursor; |
|
| 13 |
+import java.awt.DisplayMode; |
|
| 14 |
+import java.awt.Font; |
|
| 15 |
+import java.awt.Graphics2D; |
|
| 16 |
+import java.awt.Point; |
|
| 17 |
+import java.awt.RenderingHints; |
|
| 18 |
+import java.awt.Robot; |
|
| 19 |
+import java.awt.Toolkit; |
|
| 20 |
+import java.awt.Window; |
|
| 21 |
+import java.awt.event.KeyEvent; |
|
| 22 |
+import java.awt.event.KeyListener; |
|
| 23 |
+import java.awt.event.MouseEvent; |
|
| 24 |
+import java.awt.event.MouseListener; |
|
| 25 |
+import java.awt.event.MouseMotionListener; |
|
| 26 |
+import java.awt.image.ImageObserver; |
|
| 27 |
+import java.io.File; |
|
| 28 |
+import javax.swing.SwingUtilities; |
|
| 29 |
+ |
|
| 30 |
+/** |
|
| 31 |
+ * frontEnd manages the screen using {@link puyopuyo.ScreenManager# ScreenManager} and calls on {@link puyopuyo.backEnd# backEnd}
|
|
| 32 |
+ * to execute the logic. |
|
| 33 |
+ * @author Dev Ghai |
|
| 34 |
+ */ |
|
| 35 |
+public class frontEnd extends backEnd implements KeyListener, MouseMotionListener, MouseListener {
|
|
| 36 |
+ |
|
| 37 |
+ /** |
|
| 38 |
+ * <CODE>ImageObserver</CODE> object used to wait on puyo's image to |
|
| 39 |
+ * load so that its heigth and width can be determined. |
|
| 40 |
+ */ |
|
| 41 |
+ private ImageObserver observer; |
|
| 42 |
+ /** |
|
| 43 |
+ * Holds the width of the image representing the {@link puyopuyo.puyo# puyo}. It is assumed that all
|
|
| 44 |
+ * the images representing puyos have same height and width. |
|
| 45 |
+ */ |
|
| 46 |
+ private final int puyoWidth = getPuyoPair()[0].getImage().getWidth(observer); |
|
| 47 |
+ |
|
| 48 |
+ /** |
|
| 49 |
+ * Holds the height of the image representing the {@link puyopuyo.puyo# puyo}. It is assumed that all
|
|
| 50 |
+ * the images representing puyos have same height and width. |
|
| 51 |
+ */ |
|
| 52 |
+ private final int puyoHeight = getPuyoPair()[1].getImage().getHeight(observer); |
|
| 53 |
+ |
|
| 54 |
+ /** |
|
| 55 |
+ * Used for printing on screen. |
|
| 56 |
+ */ |
|
| 57 |
+ private Graphics2D g; |
|
| 58 |
+ /** |
|
| 59 |
+ * Returns the current graphics context. |
|
| 60 |
+ */ |
|
| 61 |
+ private Graphics2D getG(){
|
|
| 62 |
+ return g; |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ /** |
|
| 66 |
+ * Sets the current graphics context. |
|
| 67 |
+ */ |
|
| 68 |
+ private void setG(Graphics2D gr){ //used for initializing g
|
|
| 69 |
+ g = gr; |
|
| 70 |
+ } |
|
| 71 |
+ /** |
|
| 72 |
+ * Creates a new instance of <CODE>frontEnd</CODE> |
|
| 73 |
+ */ |
|
| 74 |
+ public frontEnd(){
|
|
| 75 |
+ } |
|
| 76 |
+ |
|
| 77 |
+ /** |
|
| 78 |
+ * <ul><li>Creates an instance of the class.</li> |
|
| 79 |
+ * <li>Initialises {@link puyopuyo.backEnd#backEnd() backEnd} by calling on its constructor.</li>
|
|
| 80 |
+ * <li>Adds the mouse and keyboard listeners.</li> |
|
| 81 |
+ * <li>Draws the complete screen for the first time.</li></ul> |
|
| 82 |
+ * @param autodetect Whether to autodetect the resolution at which to run the game. |
|
| 83 |
+ */ |
|
| 84 |
+ public frontEnd(boolean autodetect) {
|
|
| 85 |
+ super(); |
|
| 86 |
+ initializeGraphics(autodetect); |
|
| 87 |
+ |
|
| 88 |
+ //add the listeners |
|
| 89 |
+ Window window = screen.getFullScreenWindow(); |
|
| 90 |
+ window.addMouseListener(this); |
|
| 91 |
+ window.addMouseMotionListener(this); |
|
| 92 |
+ window.addKeyListener(this); |
|
| 93 |
+ |
|
| 94 |
+ drawBoardMap(); |
|
| 95 |
+ } |
|
| 96 |
+ |
|
| 97 |
+ /** |
|
| 98 |
+ * Object of {@link puyopuyo.ScreenManager# ScreenManager}.
|
|
| 99 |
+ */ |
|
| 100 |
+ private ScreenManager screen; |
|
| 101 |
+ /** |
|
| 102 |
+ * Array of supported display modes. |
|
| 103 |
+ */ |
|
| 104 |
+ private DisplayMode dm[]; |
|
| 105 |
+ /** |
|
| 106 |
+ * Font used for printing text on the screen. |
|
| 107 |
+ */ |
|
| 108 |
+ private Font f = new Font("Dialog", Font.PLAIN, 10); //initializing with a dummy value.
|
|
| 109 |
+ /** |
|
| 110 |
+ * Color of the border surrounding the playing area. |
|
| 111 |
+ */ |
|
| 112 |
+ private Color borderColor = Color.ORANGE; |
|
| 113 |
+ /** |
|
| 114 |
+ * Color of the board. This color is also used as a background color to fill the screen. |
|
| 115 |
+ */ |
|
| 116 |
+ private Color boardColor = Color.WHITE; |
|
| 117 |
+ /** |
|
| 118 |
+ * Width of the border surrounding the playing area, in pixels. |
|
| 119 |
+ */ |
|
| 120 |
+ private int borderWidth = 8; |
|
| 121 |
+ |
|
| 122 |
+ /** |
|
| 123 |
+ * <ul> |
|
| 124 |
+ * <li>Switch to most appropriate display resolution.</li> |
|
| 125 |
+ * <li>Switch to full screen if system allows to, else exit.</li> |
|
| 126 |
+ * <li>Determine the co-ordinates at which to print the score.</li> |
|
| 127 |
+ * <li>Initialize mouse.</li> |
|
| 128 |
+ * <li>Set the current Graphics context.</li> |
|
| 129 |
+ * <li>Initialize the font.</li> |
|
| 130 |
+ * </ul> |
|
| 131 |
+ * @param autodetect Enable autodetection of graphics mode or not. |
|
| 132 |
+ */ |
|
| 133 |
+ private void initializeGraphics(boolean autodetect){
|
|
| 134 |
+ boolean switchedToFullscreen = false; |
|
| 135 |
+ System.out.println("Initializing Graphics...");
|
|
| 136 |
+ screen = new ScreenManager(); |
|
| 137 |
+ if(autodetect){
|
|
| 138 |
+ dm = screen.getCompatibleDisplayModes(); |
|
| 139 |
+ System.out.println("Available Display Modes: ");
|
|
| 140 |
+ for(int i=dm.length-1 ; i>=0; i--){
|
|
| 141 |
+ System.out.println(dm[i].getWidth() + "x" + dm[i].getHeight() + " @ " + dm[i].getBitDepth() + " bits"); |
|
| 142 |
+ //Loop's runing in reverse dir coz in Windows systems, the modes are sorted |
|
| 143 |
+ //in asc order, and 1024x768 is given preference. |
|
| 144 |
+ if( (dm[i].getWidth() == 1024 && dm[i].getHeight() == 768) |
|
| 145 |
+ || (dm[i].getWidth() == 800 && dm[i].getHeight() == 600) ){
|
|
| 146 |
+ screen.setFullScreen(dm[i]); //switch to fullscreen only if its supported |
|
| 147 |
+ switchedToFullscreen = true; |
|
| 148 |
+ break; |
|
| 149 |
+ } |
|
| 150 |
+ } |
|
| 151 |
+ if(!switchedToFullscreen){
|
|
| 152 |
+ System.out.println("Your system doesn't support 1024x768 or 800x600 resolutions... \nAutoDetect failed!\nUsing the current DisplayMode");
|
|
| 153 |
+ screen.setFullScreen(screen.getCurrentDisplayMode()); |
|
| 154 |
+ } |
|
| 155 |
+ } |
|
| 156 |
+ else |
|
| 157 |
+ screen.setFullScreen(screen.getCurrentDisplayMode()); |
|
| 158 |
+ System.out.println("PuyosOnXAxis: " + puyosOnXAxis + ", puyosOnYxis: " + puyosOnYAxis);
|
|
| 159 |
+ System.out.println("Dimensions of puyo's image = " + puyoHeight + "x" + puyoHeight);
|
|
| 160 |
+ System.out.println("Playing area dimensions: " + playingAreaWidth + "x" + playingAreaHeight);
|
|
| 161 |
+ System.out.println("Full screened at configuration: " + screen.getWidth() + "x" + screen.getHeight() + " @ " + screen.getCurrentDisplayMode().getBitDepth() + " bits");
|
|
| 162 |
+ scoreX = (screen.getWidth()/2)-(fontsize*2); |
|
| 163 |
+ scoreY = screen.getHeight()-fontsize; |
|
| 164 |
+ initializeMouse(screen.getFullScreenWindow()); |
|
| 165 |
+ Graphics2D g = screen.getGraphics(); |
|
| 166 |
+ setG(g); |
|
| 167 |
+ getG().setRenderingHint( |
|
| 168 |
+ RenderingHints.KEY_TEXT_ANTIALIASING, |
|
| 169 |
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON); |
|
| 170 |
+ initializeFont(); |
|
| 171 |
+ } |
|
| 172 |
+ /** |
|
| 173 |
+ * Set the font file to use, over-riding the default font created during initialization. |
|
| 174 |
+ */ |
|
| 175 |
+ private void initializeFont(){
|
|
| 176 |
+ File fontfile = new File("Pokemon.ttf");
|
|
| 177 |
+ try{
|
|
| 178 |
+ f = Font.createFont(Font.TRUETYPE_FONT, fontfile); |
|
| 179 |
+ } catch(Exception ffe){
|
|
| 180 |
+ System.out.println("Font format Exception: " + ffe.toString());
|
|
| 181 |
+ } |
|
| 182 |
+ getG().setFont(f.deriveFont((float)fontsize)); |
|
| 183 |
+ System.out.println("Using font: " + fontfile.toString());
|
|
| 184 |
+ getG().setColor(Color.RED); |
|
| 185 |
+ } |
|
| 186 |
+ |
|
| 187 |
+ /** |
|
| 188 |
+ * Stores X co-ordinate of the board (board contains playing area) |
|
| 189 |
+ */ |
|
| 190 |
+ private int boardX; |
|
| 191 |
+ /** |
|
| 192 |
+ * Stores Y Co-ordinate of the board (board contains playing area) |
|
| 193 |
+ */ |
|
| 194 |
+ private int boardY = 10; |
|
| 195 |
+ /** |
|
| 196 |
+ * playingAreaWidth = {@link puyopuyo.frontEnd#puyoWidth puyoWidth} * {@link puyopuyo.backEnd#puyosOnXAxis puyosOnXAxis}.
|
|
| 197 |
+ */ |
|
| 198 |
+ private final int playingAreaWidth = puyoWidth * puyosOnXAxis; |
|
| 199 |
+ /** |
|
| 200 |
+ * playingAreaHeight = {@link puyopuyo.frontEnd#puyoHeight puyoHeight} * {@link puyopuyo.backEnd#puyosOnYAxis puyosOnYAxis}.
|
|
| 201 |
+ */ |
|
| 202 |
+ private final int playingAreaHeight = puyoHeight * puyosOnYAxis; |
|
| 203 |
+ /** |
|
| 204 |
+ * Size of the font used for printing text on the screen. |
|
| 205 |
+ */ |
|
| 206 |
+ private int fontsize = 50; |
|
| 207 |
+ /** |
|
| 208 |
+ * X co-ordinate of the point where score has to be printed. |
|
| 209 |
+ */ |
|
| 210 |
+ private int scoreX; |
|
| 211 |
+ /** |
|
| 212 |
+ * Y co-ordinate of the point where score has to be printed. |
|
| 213 |
+ */ |
|
| 214 |
+ private int scoreY; |
|
| 215 |
+ |
|
| 216 |
+ /** |
|
| 217 |
+ * Fills the screen with background color and draws the outline of the playing area. |
|
| 218 |
+ */ |
|
| 219 |
+ public void drawScreen(){
|
|
| 220 |
+ //fill the screen with background color |
|
| 221 |
+ getG().setColor(boardColor); |
|
| 222 |
+ getG().fillRect(0, 0, screen.getWidth(), screen.getHeight()); |
|
| 223 |
+ //Board has to be center aligned horizontally |
|
| 224 |
+ boardX = (screen.getWidth()/2) - ((playingAreaWidth+(2*borderWidth))/2); |
|
| 225 |
+ //Draw the board |
|
| 226 |
+ getG().setColor(borderColor); |
|
| 227 |
+ getG().fillRoundRect(boardX, |
|
| 228 |
+ boardY, |
|
| 229 |
+ playingAreaWidth+(borderWidth*2), |
|
| 230 |
+ playingAreaHeight+(borderWidth*2), |
|
| 231 |
+ borderWidth, |
|
| 232 |
+ borderWidth); |
|
| 233 |
+ getG().setColor(boardColor); |
|
| 234 |
+ getG().fillRoundRect(boardX + borderWidth, |
|
| 235 |
+ boardY + borderWidth, |
|
| 236 |
+ playingAreaWidth, |
|
| 237 |
+ playingAreaHeight, |
|
| 238 |
+ borderWidth, |
|
| 239 |
+ borderWidth); |
|
| 240 |
+ //Score Area |
|
| 241 |
+ getG().fillRect(boardX, screen.getHeight()-(fontsize*2), screen.getWidth()/2, fontsize*2); |
|
| 242 |
+ } |
|
| 243 |
+ |
|
| 244 |
+ /** |
|
| 245 |
+ * Draws puyos according to the {@link puyopuyo.backEnd#boardMap boardMap} within the playing
|
|
| 246 |
+ * area drawn by {@link puyopuyo.frontEnd#drawScreen() drawScreen}.
|
|
| 247 |
+ */ |
|
| 248 |
+ public synchronized void drawBoardMap(){
|
|
| 249 |
+ drawScreen(); //MS Windows specific. |
|
| 250 |
+ getG().setColor(boardColor); |
|
| 251 |
+ getG().fillRoundRect(boardX + borderWidth, |
|
| 252 |
+ boardY + borderWidth, |
|
| 253 |
+ playingAreaWidth, |
|
| 254 |
+ playingAreaHeight, |
|
| 255 |
+ borderWidth, |
|
| 256 |
+ borderWidth); |
|
| 257 |
+ //Score Area |
|
| 258 |
+ getG().fillRect(boardX, screen.getHeight()-(fontsize*2), screen.getWidth()/2, fontsize*2); |
|
| 259 |
+ puyo board[][] = super.getBoardMap(); |
|
| 260 |
+ for (int j=0; j<puyosOnYAxis; j++) |
|
| 261 |
+ for(int i=0; i<puyosOnXAxis; i++){
|
|
| 262 |
+ if(board[i][j]!=null) |
|
| 263 |
+ getG().drawImage(board[i][j].getImage(), |
|
| 264 |
+ boardX + borderWidth + (puyoWidth*i), |
|
| 265 |
+ boardY + borderWidth + (puyoHeight*j), |
|
| 266 |
+ null); |
|
| 267 |
+ } |
|
| 268 |
+ //Print the score |
|
| 269 |
+ getG().setColor(Color.RED); |
|
| 270 |
+ getG().drawString("Score: "+getScore(), scoreX, scoreY);
|
|
| 271 |
+ screen.update(); |
|
| 272 |
+ } |
|
| 273 |
+ |
|
| 274 |
+ /** |
|
| 275 |
+ * Direction in which to rotate the puyo. This value tells {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper}
|
|
| 276 |
+ * to move the pair one step left. |
|
| 277 |
+ */ |
|
| 278 |
+ private final int LEFT = 1; |
|
| 279 |
+ /** |
|
| 280 |
+ * Direction in which to rotate the puyo. This value tells {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper}
|
|
| 281 |
+ * to move the pair one step right. |
|
| 282 |
+ */ |
|
| 283 |
+ private final int RIGHT = 2; |
|
| 284 |
+ /** |
|
| 285 |
+ * Direction in which to rotate the puyo. This value tells {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper}
|
|
| 286 |
+ * to move the pair one step down, or in other words, accelerate their fall. |
|
| 287 |
+ */ |
|
| 288 |
+ private final int DOWN = 3; |
|
| 289 |
+ /** |
|
| 290 |
+ * It directs {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper} to rotate the pair.
|
|
| 291 |
+ */ |
|
| 292 |
+ private final int ROTATE = 4; |
|
| 293 |
+ |
|
| 294 |
+ /** |
|
| 295 |
+ * Tells whether the game is paused or not. If it is, all the Mouse and |
|
| 296 |
+ * Keyboard events are ignored. However, user is allowed to exit from the |
|
| 297 |
+ * game. |
|
| 298 |
+ */ |
|
| 299 |
+ private boolean paused = false; |
|
| 300 |
+ |
|
| 301 |
+ /** |
|
| 302 |
+ * Takes care of the movements on screen. |
|
| 303 |
+ * <p>Converts the pair of puyos on screen to single puyos and operates on them.<br> |
|
| 304 |
+ * Note that all calls to {@link puyopuyo.backEnd# backEnd }have been synchronized. This also ensures
|
|
| 305 |
+ * that though operations are performed on a pair, logically operations are |
|
| 306 |
+ * performed individually on each {@link puyopuyo.puyo# puyo}.
|
|
| 307 |
+ * </p> |
|
| 308 |
+ * @param direction Direction in which to move the pair, or rotate it clockwise. |
|
| 309 |
+ */ |
|
| 310 |
+ public synchronized void movementWrapper(int direction) {
|
|
| 311 |
+ if(paused == true || isGameOver()) return; |
|
| 312 |
+ boolean lowerCouldMove = false; |
|
| 313 |
+ boolean upperCouldMove = false; //used to detect 'collisions' |
|
| 314 |
+ int lower = -1; //index of the puyo which is lower when the 2 r vertically arranged |
|
| 315 |
+ int upper = -1; //if any of the values is modified, this implies the puyos are arranged vertically |
|
| 316 |
+ //Check the one which is below |
|
| 317 |
+ if( (getPuyoPair()[0].getY()-1) == getPuyoPair()[1].getY() ){
|
|
| 318 |
+ //puyo at [0] is below |
|
| 319 |
+ lower = 0; |
|
| 320 |
+ upper = 1; |
|
| 321 |
+ } else if ( (getPuyoPair()[1].getY()-1) == getPuyoPair()[0].getY() ){
|
|
| 322 |
+ //[1]'s below |
|
| 323 |
+ lower = 1; |
|
| 324 |
+ upper = 0; |
|
| 325 |
+ } |
|
| 326 |
+ switch(direction){
|
|
| 327 |
+ case LEFT: |
|
| 328 |
+ if( (getPuyoPair()[0].getY() != getPuyoPair()[1].getY()) & |
|
| 329 |
+ (getPuyoPair()[0].getX() != getPuyoPair()[1].getX())) |
|
| 330 |
+ return; //return back without doing anything if the puyos dont lie in single row or single column |
|
| 331 |
+ if (lower != -1){ //VERTICAL ORIENTATION [PATCH]
|
|
| 332 |
+ if(moveLeft(getPuyoPair()[lower])) |
|
| 333 |
+ moveLeft(getPuyoPair()[upper]); //move upper to left only if lower could move left first |
|
| 334 |
+ } |
|
| 335 |
+ //HORIZONTAL ORIENTATION: Check the one which is to left |
|
| 336 |
+ else if(getPuyoPair()[0].getX() == (getPuyoPair()[1].getX()-1) ){
|
|
| 337 |
+ //puyo at [0] is to left and both the puyos are joined |
|
| 338 |
+ moveLeft(getPuyoPair()[0]); |
|
| 339 |
+ moveLeft(getPuyoPair()[1]); |
|
| 340 |
+ } else{
|
|
| 341 |
+ //either the Xpositions are equal or [1]'s on left |
|
| 342 |
+ moveLeft(getPuyoPair()[1]); |
|
| 343 |
+ moveLeft(getPuyoPair()[0]); |
|
| 344 |
+ } |
|
| 345 |
+ break; |
|
| 346 |
+ case RIGHT: |
|
| 347 |
+ if( (getPuyoPair()[0].getY() != getPuyoPair()[1].getY()) & |
|
| 348 |
+ (getPuyoPair()[0].getX() != getPuyoPair()[1].getX())) |
|
| 349 |
+ return; //return back without doing anything if the puyos dont lie in single row or single column |
|
| 350 |
+ if (lower != -1){ //VERTICAL ORIENTATION [PATCH]
|
|
| 351 |
+ if(moveRight(getPuyoPair()[lower])) |
|
| 352 |
+ moveRight(getPuyoPair()[upper]); //move upper to left only if lower could move left first |
|
| 353 |
+ } |
|
| 354 |
+ //HORIZONTAL ORIENTATION: Check the one which is to right |
|
| 355 |
+ else if(getPuyoPair()[0].getX() == (getPuyoPair()[1].getX()-1) ){
|
|
| 356 |
+ //puyo at [1] is to right |
|
| 357 |
+ moveRight(getPuyoPair()[1]); |
|
| 358 |
+ moveRight(getPuyoPair()[0]); |
|
| 359 |
+ } else{
|
|
| 360 |
+ //either the X positions are equal or [0]'s on right |
|
| 361 |
+ moveRight(getPuyoPair()[0]); |
|
| 362 |
+ moveRight(getPuyoPair()[1]); |
|
| 363 |
+ } |
|
| 364 |
+ break; |
|
| 365 |
+ case DOWN: |
|
| 366 |
+ if(lower == -1){ //HORIZONTAL ORIENTATION => move any of the puyos first.
|
|
| 367 |
+ lower = 1; |
|
| 368 |
+ upper = 0; |
|
| 369 |
+ } |
|
| 370 |
+ lowerCouldMove = moveDown(getPuyoPair()[lower]); |
|
| 371 |
+ upperCouldMove = moveDown(getPuyoPair()[upper]); |
|
| 372 |
+ //launch chain rxn of popping if both couldn't move |
|
| 373 |
+ if( !lowerCouldMove & !upperCouldMove ){
|
|
| 374 |
+ popPuyos(getPuyoPair()); |
|
| 375 |
+ drawBoardMap(); |
|
| 376 |
+ //now that the 2 have settled, push a new pair on board |
|
| 377 |
+ pushPuyos(); |
|
| 378 |
+ } |
|
| 379 |
+ break; |
|
| 380 |
+ case ROTATE: rotate(getPuyoPair()); |
|
| 381 |
+ break; |
|
| 382 |
+ } |
|
| 383 |
+ drawBoardMap(); |
|
| 384 |
+ } |
|
| 385 |
+ |
|
| 386 |
+ /** |
|
| 387 |
+ * <CODE>KeyEvent</CODE> listener that is responsible for firing appropriate actions corresponding |
|
| 388 |
+ * to the key pressed. |
|
| 389 |
+ * <p><ul><b>UP ARROW KEY</b> - Rotate the pair.</ul> |
|
| 390 |
+ * <ul><b>LEFT ARROW KEY</b> - Move the pair to left.</ul> |
|
| 391 |
+ * <ul><b>RIGHT ARROW KEY</b> - Move the pair to right. |
|
| 392 |
+ * <ul><b>DOWN ARROW KEY</b> - Move the pair downwards/accelerate the fall.</ul> |
|
| 393 |
+ * <ul><b>SPACEBAR</b> - Pause the game.</ul> |
|
| 394 |
+ * <ul><b>ESC</b> - Quit from the game.</ul></p> |
|
| 395 |
+ * @param e Virtual code of the key pressed. |
|
| 396 |
+ */ |
|
| 397 |
+ public void keyPressed(KeyEvent e){
|
|
| 398 |
+ switch(e.getKeyCode()){
|
|
| 399 |
+ case KeyEvent.VK_ESCAPE: setGameOver(true); break; |
|
| 400 |
+ case KeyEvent.VK_LEFT: movementWrapper(LEFT); break; |
|
| 401 |
+ case KeyEvent.VK_RIGHT: movementWrapper(RIGHT); break; |
|
| 402 |
+ case KeyEvent.VK_DOWN: movementWrapper(DOWN); break; |
|
| 403 |
+ case KeyEvent.VK_UP: movementWrapper(ROTATE); break; |
|
| 404 |
+ case KeyEvent.VK_SPACE: paused = !paused; break; |
|
| 405 |
+ } |
|
| 406 |
+ } |
|
| 407 |
+ |
|
| 408 |
+ /** |
|
| 409 |
+ * <CODE>KeyListener</CODE> Interface: keyReleased. Ignored. |
|
| 410 |
+ */ |
|
| 411 |
+ public void keyReleased(KeyEvent e){
|
|
| 412 |
+ //do nothing! |
|
| 413 |
+ } |
|
| 414 |
+ |
|
| 415 |
+ /** |
|
| 416 |
+ * <CODE>KeyListener</CODE> Interface: keyTyped. Ignored. |
|
| 417 |
+ */ |
|
| 418 |
+ public void keyTyped(KeyEvent e){
|
|
| 419 |
+ //do nothing! |
|
| 420 |
+ } |
|
| 421 |
+ |
|
| 422 |
+ |
|
| 423 |
+ |
|
| 424 |
+ /** |
|
| 425 |
+ * From the <CODE>MouseListener</CODE> interface. <CODE>MouseListener</CODE> responsible for firing |
|
| 426 |
+ * appropriate events corresponding to the key pressed. |
|
| 427 |
+ */ |
|
| 428 |
+ public void mousePressed(MouseEvent e) {
|
|
| 429 |
+ movementWrapper(ROTATE) ; |
|
| 430 |
+ } |
|
| 431 |
+ |
|
| 432 |
+ /** |
|
| 433 |
+ * From the <CODE>MouseListener</CODE> interface. Ignored. |
|
| 434 |
+ */ |
|
| 435 |
+ public void mouseReleased(MouseEvent e) {
|
|
| 436 |
+ // do nothing |
|
| 437 |
+ } |
|
| 438 |
+ |
|
| 439 |
+ /** |
|
| 440 |
+ * From the <CODE>MouseListener</CODE> interface. Ignored. |
|
| 441 |
+ */ |
|
| 442 |
+ public void mouseClicked(MouseEvent e) {
|
|
| 443 |
+ // called after mouse is released - ignored |
|
| 444 |
+ } |
|
| 445 |
+ |
|
| 446 |
+ /** |
|
| 447 |
+ * From the <CODE>MouseListener</CODE> interface. Ignored. |
|
| 448 |
+ */ |
|
| 449 |
+ public void mouseEntered(MouseEvent e) {
|
|
| 450 |
+ //do nothing |
|
| 451 |
+ } |
|
| 452 |
+ |
|
| 453 |
+ /** |
|
| 454 |
+ * From the <CODE>MouseListener</CODE> interface. Ignored. |
|
| 455 |
+ */ |
|
| 456 |
+ public void mouseExited(MouseEvent e) {
|
|
| 457 |
+ //do nothing |
|
| 458 |
+ } |
|
| 459 |
+ |
|
| 460 |
+ /** |
|
| 461 |
+ * From the <CODE>MouseMotionListener</CODE> interface. Ignored. |
|
| 462 |
+ */ |
|
| 463 |
+ public void mouseDragged(MouseEvent e) {
|
|
| 464 |
+ //do nothing |
|
| 465 |
+ } |
|
| 466 |
+ |
|
| 467 |
+ /** |
|
| 468 |
+ * From the <CODE>MouseMotionListener</CODE> interface. Determines in which direction has |
|
| 469 |
+ * the mouse moved and then recenters it. |
|
| 470 |
+ */ |
|
| 471 |
+ public synchronized void mouseMoved(MouseEvent e) {
|
|
| 472 |
+ if(paused == true) return; |
|
| 473 |
+ // this event is from re-centering the mouse - ignore it |
|
| 474 |
+ if (isRecentering && |
|
| 475 |
+ centerLocation.x == e.getX() && |
|
| 476 |
+ centerLocation.y == e.getY()) {
|
|
| 477 |
+ isRecentering = false; |
|
| 478 |
+ } |
|
| 479 |
+ |
|
| 480 |
+ else {
|
|
| 481 |
+ int dx = e.getX() - mouseLocation.x; |
|
| 482 |
+ int dy = e.getY() - mouseLocation.y; |
|
| 483 |
+ if(dx<0) //Mouse moved left |
|
| 484 |
+ movementWrapper(LEFT); |
|
| 485 |
+ else if(dx>0) //Mouse moved right |
|
| 486 |
+ movementWrapper(RIGHT); |
|
| 487 |
+ else if(dy>0) //Mouse moved down |
|
| 488 |
+ movementWrapper(DOWN); |
|
| 489 |
+ //Movements towards north are to be ignored |
|
| 490 |
+ recenterMouse(); |
|
| 491 |
+ |
|
| 492 |
+ |
|
| 493 |
+ } |
|
| 494 |
+ mouseLocation.x = e.getX(); |
|
| 495 |
+ mouseLocation.y = e.getY(); |
|
| 496 |
+ } |
|
| 497 |
+ |
|
| 498 |
+ /** |
|
| 499 |
+ * Object of <CODE>Robot</CODE> class used for recentering the mouse. |
|
| 500 |
+ */ |
|
| 501 |
+ private Robot robot; |
|
| 502 |
+ /** |
|
| 503 |
+ * <CODE>Point</CODE> object storing the mouse's location. |
|
| 504 |
+ */ |
|
| 505 |
+ private Point mouseLocation; |
|
| 506 |
+ /** |
|
| 507 |
+ * Holds the center point of the screen. |
|
| 508 |
+ */ |
|
| 509 |
+ private Point centerLocation; |
|
| 510 |
+ /** |
|
| 511 |
+ * <CODE>Boolean</CODE> telling if the mouse is re-centering or not. |
|
| 512 |
+ */ |
|
| 513 |
+ private boolean isRecentering; |
|
| 514 |
+ |
|
| 515 |
+ /** |
|
| 516 |
+ * Initializes the mouse, recenters it and hides the mouse pointer. |
|
| 517 |
+ * @param window Window for which to initialize the mouse. |
|
| 518 |
+ */ |
|
| 519 |
+ private void initializeMouse(Window window){
|
|
| 520 |
+ //hide the mouse pointer |
|
| 521 |
+ Cursor invisibleCursor = |
|
| 522 |
+ Toolkit.getDefaultToolkit().createCustomCursor( |
|
| 523 |
+ Toolkit.getDefaultToolkit().getImage(""),
|
|
| 524 |
+ new Point(0,0),"invisible"); |
|
| 525 |
+ window.setCursor(invisibleCursor); |
|
| 526 |
+ System.out.println("Mouse Pointer is now hidden!");
|
|
| 527 |
+ |
|
| 528 |
+ mouseLocation = new Point(); |
|
| 529 |
+ centerLocation = new Point(); |
|
| 530 |
+ isRecentering = false; |
|
| 531 |
+ |
|
| 532 |
+ try {
|
|
| 533 |
+ robot = new Robot(); |
|
| 534 |
+ recenterMouse(); |
|
| 535 |
+ mouseLocation.x = centerLocation.x; |
|
| 536 |
+ mouseLocation.y = centerLocation.y; |
|
| 537 |
+ } catch (AWTException ex) {
|
|
| 538 |
+ System.out.println("Couldn't create Robot! Mouse initialization failed!!");
|
|
| 539 |
+ } |
|
| 540 |
+ } |
|
| 541 |
+ |
|
| 542 |
+ /** |
|
| 543 |
+ * Uses the <CODE>Robot</CODE> class to try to position the mouse in the |
|
| 544 |
+ * center of the screen. |
|
| 545 |
+ * <p>Note that use of the <CODE>Robot</CODE> class may not be available |
|
| 546 |
+ * on all platforms.</p> |
|
| 547 |
+ */ |
|
| 548 |
+ private synchronized void recenterMouse() {
|
|
| 549 |
+ Window window = screen.getFullScreenWindow(); |
|
| 550 |
+ if (robot != null && window.isShowing()) {
|
|
| 551 |
+ centerLocation.x = window.getWidth() / 2; |
|
| 552 |
+ centerLocation.y = window.getHeight() / 2; |
|
| 553 |
+ SwingUtilities.convertPointToScreen(centerLocation, |
|
| 554 |
+ window); |
|
| 555 |
+ isRecentering = true; |
|
| 556 |
+ robot.mouseMove(centerLocation.x, centerLocation.y); |
|
| 557 |
+ } |
|
| 558 |
+ } |
|
| 559 |
+ /** |
|
| 560 |
+ * Kills the thread and exits from the game while restoring the screen |
|
| 561 |
+ * and unhiding the mouse pointer. |
|
| 562 |
+ */ |
|
| 563 |
+ public void goodbye(){ //do cleanup ops before exiting
|
|
| 564 |
+ /* Restore Cursor |
|
| 565 |
+ * Restore Screen |
|
| 566 |
+ * Kill the thread |
|
| 567 |
+ */ |
|
| 568 |
+ System.out.println("GoodBye!!");
|
|
| 569 |
+ getG().setColor(Color.MAGENTA); |
|
| 570 |
+ getG().drawString("GoodBye!", 10, screen.getHeight()-50);
|
|
| 571 |
+ getG().drawString(":(", screen.getWidth()-100, screen.getHeight()-50);
|
|
| 572 |
+ screen.update(); |
|
| 573 |
+ try {
|
|
| 574 |
+ Thread.sleep(1000); |
|
| 575 |
+ } catch (InterruptedException ex) { }
|
|
| 576 |
+ Cursor normalCursor = |
|
| 577 |
+ Cursor.getDefaultCursor(); |
|
| 578 |
+ Window window = screen.getFullScreenWindow(); |
|
| 579 |
+ window.setCursor(normalCursor); |
|
| 580 |
+ screen.restoreScreen(); |
|
| 581 |
+ System.exit(0); |
|
| 582 |
+ } |
|
| 583 |
+ /** |
|
| 584 |
+ * 'Mainest' Method Of ALL :D |
|
| 585 |
+ * @param args the command line arguments |
|
| 586 |
+ */ |
|
| 587 |
+ public static void main(String[] args) {
|
|
| 588 |
+ frontEnd w; |
|
| 589 |
+ if(args.length>0 && args[0].equalsIgnoreCase(new String("autodetect")))
|
|
| 590 |
+ w = new frontEnd(true); |
|
| 591 |
+ else w = new frontEnd(false); |
|
| 592 |
+ |
|
| 593 |
+ while(!w.isGameOver()){
|
|
| 594 |
+ w.movementWrapper(3); //3 implies down |
|
| 595 |
+ try{
|
|
| 596 |
+ Thread.sleep(500); |
|
| 597 |
+ } catch (InterruptedException ex) {
|
|
| 598 |
+ System.out.println("Main Thread Interrupted! Reason: " + ex.toString());
|
|
| 599 |
+ } |
|
| 600 |
+ } |
|
| 601 |
+ try |
|
| 602 |
+ {
|
|
| 603 |
+ w.goodbye(); |
|
| 604 |
+ } |
|
| 605 |
+ catch (Exception e) |
|
| 606 |
+ {
|
|
| 607 |
+ System.out.println(e.toString()); |
|
| 608 |
+ } |
|
| 609 |
+ |
|
| 610 |
+ } |
|
| 611 |
+} |
| ... | ... |
@@ -0,0 +1,114 @@ |
| 1 |
+/* |
|
| 2 |
+ * puyo.java |
|
| 3 |
+ * |
|
| 4 |
+ * Created on 16 April, 2007, 3:00 AM |
|
| 5 |
+ * |
|
| 6 |
+ * To change this template, choose Tools | Template Manager |
|
| 7 |
+ * and open the template in the editor. |
|
| 8 |
+ */ |
|
| 9 |
+ |
|
| 10 |
+import java.awt.Image; |
|
| 11 |
+import javax.swing.ImageIcon; |
|
| 12 |
+ |
|
| 13 |
+/** |
|
| 14 |
+ * Creates a puyo object that holds all the its properties- |
|
| 15 |
+ * the image representing the puyo, logical x and y positions (in array {@link puyopuyo.backEnd#boardMap boardMap})
|
|
| 16 |
+ * and a character representing the color of the puyo. |
|
| 17 |
+ * @author Dev Ghai |
|
| 18 |
+ */ |
|
| 19 |
+public class puyo{
|
|
| 20 |
+ |
|
| 21 |
+ /** |
|
| 22 |
+ * Creates a new puyo and associates image file <b>filename</b> to the puyo |
|
| 23 |
+ * and sets its color to <b>c</b>. |
|
| 24 |
+ * @param filename File name of the image that has to be associated with the puyo. |
|
| 25 |
+ * @param c Color of the puyo |
|
| 26 |
+ * <p>Following are its possible values: |
|
| 27 |
+ * <ul> |
|
| 28 |
+ * <li>'r' - Red</li> |
|
| 29 |
+ * <li>'g' - Green</li> |
|
| 30 |
+ * <li>'b' - Blue</li> |
|
| 31 |
+ * <li>'y' - Yellow</li> |
|
| 32 |
+ * </ul> |
|
| 33 |
+ */ |
|
| 34 |
+ public puyo(String filename, char c){
|
|
| 35 |
+ image = new ImageIcon(filename).getImage(); |
|
| 36 |
+ x=0; |
|
| 37 |
+ y=0; |
|
| 38 |
+ color = c; |
|
| 39 |
+ } |
|
| 40 |
+ /** |
|
| 41 |
+ * Creates a default puyo without assigning any image or color to it. |
|
| 42 |
+ */ |
|
| 43 |
+ public puyo(){}
|
|
| 44 |
+ /** |
|
| 45 |
+ * Holds the image that represents the puyo. |
|
| 46 |
+ */ |
|
| 47 |
+ private Image image; |
|
| 48 |
+ |
|
| 49 |
+ /** |
|
| 50 |
+ * Returns the image associated with the puyo. |
|
| 51 |
+ */ |
|
| 52 |
+ public Image getImage(){
|
|
| 53 |
+ return image; |
|
| 54 |
+ } |
|
| 55 |
+ |
|
| 56 |
+ /** |
|
| 57 |
+ * Holds the X-Co-ordinate of the puyo in {@link puyopuyo.backEnd#boardMap}
|
|
| 58 |
+ */ |
|
| 59 |
+ private int x; |
|
| 60 |
+ |
|
| 61 |
+ /** |
|
| 62 |
+ * Returns the X-Co-ordinate of the puyo in {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 63 |
+ */ |
|
| 64 |
+ public int getX(){
|
|
| 65 |
+ return x; |
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+ /** |
|
| 69 |
+ * Sets the X-Co-ordinate of the puyo in {@link puyopuyo.backEnd#boardMap boardMap} to xPos.
|
|
| 70 |
+ * @param xPos New x position of puyo in {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 71 |
+ */ |
|
| 72 |
+ public void setX(int xPos){
|
|
| 73 |
+ x = xPos; |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ /** |
|
| 77 |
+ * Holds the Y-Co-ordinate of the puyo |
|
| 78 |
+ */ |
|
| 79 |
+ private int y; |
|
| 80 |
+ |
|
| 81 |
+ /** |
|
| 82 |
+ * Returns the Y-Co-ordinate of the puyo in the {@link puyopuyo.backEnd#boardMap boardMap}
|
|
| 83 |
+ */ |
|
| 84 |
+ public int getY(){
|
|
| 85 |
+ return y; |
|
| 86 |
+ } |
|
| 87 |
+ |
|
| 88 |
+ /** |
|
| 89 |
+ * Sets the Y-Co-ordinate of the puyo in {@link puyopuyo.backEnd#boardMap boardMap} to yPos.
|
|
| 90 |
+ * @param yPos New y position of puyo in {@link puyopuyo.backEnd#boardMap boardMap}.
|
|
| 91 |
+ */ |
|
| 92 |
+ public void setY(int yPos){
|
|
| 93 |
+ y = yPos; |
|
| 94 |
+ } |
|
| 95 |
+ |
|
| 96 |
+ /** |
|
| 97 |
+ * Holds the color of the puyo. The color is stored first letter of the color string. |
|
| 98 |
+ * For example 'r' is stored for red. |
|
| 99 |
+ */ |
|
| 100 |
+ private char color; |
|
| 101 |
+ |
|
| 102 |
+ /** |
|
| 103 |
+ * Returns the color of the puyo - |
|
| 104 |
+ * <ul> |
|
| 105 |
+ * <li>'r' - Red</li> |
|
| 106 |
+ * <li>'g' - Green</li> |
|
| 107 |
+ * <li>'b' - Blue</li> |
|
| 108 |
+ * <li>'y' - Yellow</li> |
|
| 109 |
+ * </ul> |
|
| 110 |
+ */ |
|
| 111 |
+ public char getColor(){
|
|
| 112 |
+ return color; |
|
| 113 |
+ } |
|
| 114 |
+} |
| ... | ... |
@@ -0,0 +1 @@ |
| 1 |
+java frontEnd |