GitList
Repositories
Help
Report an Issue
puyopuyo
Code
Commits
Branches
Tags
Search
Tree:
2419458
Branches
Tags
master
puyopuyo
frontEnd.java
adding puyopuyo code.
Dev
commited
2419458
at 2018-07-21 10:16:11
frontEnd.java
Blame
History
Raw
/* * frontEnd.java * * Created on 30 March, 2007, 12:04 AM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ import java.awt.AWTException; import java.awt.Color; import java.awt.Cursor; import java.awt.DisplayMode; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.Robot; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.image.ImageObserver; import java.io.File; import javax.swing.SwingUtilities; /** * frontEnd manages the screen using {@link puyopuyo.ScreenManager# ScreenManager} and calls on {@link puyopuyo.backEnd# backEnd} * to execute the logic. * @author Dev Ghai */ public class frontEnd extends backEnd implements KeyListener, MouseMotionListener, MouseListener { /** * <CODE>ImageObserver</CODE> object used to wait on puyo's image to * load so that its heigth and width can be determined. */ private ImageObserver observer; /** * Holds the width of the image representing the {@link puyopuyo.puyo# puyo}. It is assumed that all * the images representing puyos have same height and width. */ private final int puyoWidth = getPuyoPair()[0].getImage().getWidth(observer); /** * Holds the height of the image representing the {@link puyopuyo.puyo# puyo}. It is assumed that all * the images representing puyos have same height and width. */ private final int puyoHeight = getPuyoPair()[1].getImage().getHeight(observer); /** * Used for printing on screen. */ private Graphics2D g; /** * Returns the current graphics context. */ private Graphics2D getG(){ return g; } /** * Sets the current graphics context. */ private void setG(Graphics2D gr){ //used for initializing g g = gr; } /** * Creates a new instance of <CODE>frontEnd</CODE> */ public frontEnd(){ } /** * <ul><li>Creates an instance of the class.</li> * <li>Initialises {@link puyopuyo.backEnd#backEnd() backEnd} by calling on its constructor.</li> * <li>Adds the mouse and keyboard listeners.</li> * <li>Draws the complete screen for the first time.</li></ul> * @param autodetect Whether to autodetect the resolution at which to run the game. */ public frontEnd(boolean autodetect) { super(); initializeGraphics(autodetect); //add the listeners Window window = screen.getFullScreenWindow(); window.addMouseListener(this); window.addMouseMotionListener(this); window.addKeyListener(this); drawBoardMap(); } /** * Object of {@link puyopuyo.ScreenManager# ScreenManager}. */ private ScreenManager screen; /** * Array of supported display modes. */ private DisplayMode dm[]; /** * Font used for printing text on the screen. */ private Font f = new Font("Dialog", Font.PLAIN, 10); //initializing with a dummy value. /** * Color of the border surrounding the playing area. */ private Color borderColor = Color.ORANGE; /** * Color of the board. This color is also used as a background color to fill the screen. */ private Color boardColor = Color.WHITE; /** * Width of the border surrounding the playing area, in pixels. */ private int borderWidth = 8; /** * <ul> * <li>Switch to most appropriate display resolution.</li> * <li>Switch to full screen if system allows to, else exit.</li> * <li>Determine the co-ordinates at which to print the score.</li> * <li>Initialize mouse.</li> * <li>Set the current Graphics context.</li> * <li>Initialize the font.</li> * </ul> * @param autodetect Enable autodetection of graphics mode or not. */ private void initializeGraphics(boolean autodetect){ boolean switchedToFullscreen = false; System.out.println("Initializing Graphics..."); screen = new ScreenManager(); if(autodetect){ dm = screen.getCompatibleDisplayModes(); System.out.println("Available Display Modes: "); for(int i=dm.length-1 ; i>=0; i--){ System.out.println(dm[i].getWidth() + "x" + dm[i].getHeight() + " @ " + dm[i].getBitDepth() + " bits"); //Loop's runing in reverse dir coz in Windows systems, the modes are sorted //in asc order, and 1024x768 is given preference. if( (dm[i].getWidth() == 1024 && dm[i].getHeight() == 768) || (dm[i].getWidth() == 800 && dm[i].getHeight() == 600) ){ screen.setFullScreen(dm[i]); //switch to fullscreen only if its supported switchedToFullscreen = true; break; } } if(!switchedToFullscreen){ System.out.println("Your system doesn't support 1024x768 or 800x600 resolutions... \nAutoDetect failed!\nUsing the current DisplayMode"); screen.setFullScreen(screen.getCurrentDisplayMode()); } } else screen.setFullScreen(screen.getCurrentDisplayMode()); System.out.println("PuyosOnXAxis: " + puyosOnXAxis + ", puyosOnYxis: " + puyosOnYAxis); System.out.println("Dimensions of puyo's image = " + puyoHeight + "x" + puyoHeight); System.out.println("Playing area dimensions: " + playingAreaWidth + "x" + playingAreaHeight); System.out.println("Full screened at configuration: " + screen.getWidth() + "x" + screen.getHeight() + " @ " + screen.getCurrentDisplayMode().getBitDepth() + " bits"); scoreX = (screen.getWidth()/2)-(fontsize*2); scoreY = screen.getHeight()-fontsize; initializeMouse(screen.getFullScreenWindow()); Graphics2D g = screen.getGraphics(); setG(g); getG().setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); initializeFont(); } /** * Set the font file to use, over-riding the default font created during initialization. */ private void initializeFont(){ File fontfile = new File("Pokemon.ttf"); try{ f = Font.createFont(Font.TRUETYPE_FONT, fontfile); } catch(Exception ffe){ System.out.println("Font format Exception: " + ffe.toString()); } getG().setFont(f.deriveFont((float)fontsize)); System.out.println("Using font: " + fontfile.toString()); getG().setColor(Color.RED); } /** * Stores X co-ordinate of the board (board contains playing area) */ private int boardX; /** * Stores Y Co-ordinate of the board (board contains playing area) */ private int boardY = 10; /** * playingAreaWidth = {@link puyopuyo.frontEnd#puyoWidth puyoWidth} * {@link puyopuyo.backEnd#puyosOnXAxis puyosOnXAxis}. */ private final int playingAreaWidth = puyoWidth * puyosOnXAxis; /** * playingAreaHeight = {@link puyopuyo.frontEnd#puyoHeight puyoHeight} * {@link puyopuyo.backEnd#puyosOnYAxis puyosOnYAxis}. */ private final int playingAreaHeight = puyoHeight * puyosOnYAxis; /** * Size of the font used for printing text on the screen. */ private int fontsize = 50; /** * X co-ordinate of the point where score has to be printed. */ private int scoreX; /** * Y co-ordinate of the point where score has to be printed. */ private int scoreY; /** * Fills the screen with background color and draws the outline of the playing area. */ public void drawScreen(){ //fill the screen with background color getG().setColor(boardColor); getG().fillRect(0, 0, screen.getWidth(), screen.getHeight()); //Board has to be center aligned horizontally boardX = (screen.getWidth()/2) - ((playingAreaWidth+(2*borderWidth))/2); //Draw the board getG().setColor(borderColor); getG().fillRoundRect(boardX, boardY, playingAreaWidth+(borderWidth*2), playingAreaHeight+(borderWidth*2), borderWidth, borderWidth); getG().setColor(boardColor); getG().fillRoundRect(boardX + borderWidth, boardY + borderWidth, playingAreaWidth, playingAreaHeight, borderWidth, borderWidth); //Score Area getG().fillRect(boardX, screen.getHeight()-(fontsize*2), screen.getWidth()/2, fontsize*2); } /** * Draws puyos according to the {@link puyopuyo.backEnd#boardMap boardMap} within the playing * area drawn by {@link puyopuyo.frontEnd#drawScreen() drawScreen}. */ public synchronized void drawBoardMap(){ drawScreen(); //MS Windows specific. getG().setColor(boardColor); getG().fillRoundRect(boardX + borderWidth, boardY + borderWidth, playingAreaWidth, playingAreaHeight, borderWidth, borderWidth); //Score Area getG().fillRect(boardX, screen.getHeight()-(fontsize*2), screen.getWidth()/2, fontsize*2); puyo board[][] = super.getBoardMap(); for (int j=0; j<puyosOnYAxis; j++) for(int i=0; i<puyosOnXAxis; i++){ if(board[i][j]!=null) getG().drawImage(board[i][j].getImage(), boardX + borderWidth + (puyoWidth*i), boardY + borderWidth + (puyoHeight*j), null); } //Print the score getG().setColor(Color.RED); getG().drawString("Score: "+getScore(), scoreX, scoreY); screen.update(); } /** * Direction in which to rotate the puyo. This value tells {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper} * to move the pair one step left. */ private final int LEFT = 1; /** * Direction in which to rotate the puyo. This value tells {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper} * to move the pair one step right. */ private final int RIGHT = 2; /** * Direction in which to rotate the puyo. This value tells {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper} * to move the pair one step down, or in other words, accelerate their fall. */ private final int DOWN = 3; /** * It directs {@link puyopuyo.frontEnd#movementWrapper(int) movementWrapper} to rotate the pair. */ private final int ROTATE = 4; /** * Tells whether the game is paused or not. If it is, all the Mouse and * Keyboard events are ignored. However, user is allowed to exit from the * game. */ private boolean paused = false; /** * Takes care of the movements on screen. * <p>Converts the pair of puyos on screen to single puyos and operates on them.<br> * Note that all calls to {@link puyopuyo.backEnd# backEnd }have been synchronized. This also ensures * that though operations are performed on a pair, logically operations are * performed individually on each {@link puyopuyo.puyo# puyo}. * </p> * @param direction Direction in which to move the pair, or rotate it clockwise. */ public synchronized void movementWrapper(int direction) { if(paused == true || isGameOver()) return; boolean lowerCouldMove = false; boolean upperCouldMove = false; //used to detect 'collisions' int lower = -1; //index of the puyo which is lower when the 2 r vertically arranged int upper = -1; //if any of the values is modified, this implies the puyos are arranged vertically //Check the one which is below if( (getPuyoPair()[0].getY()-1) == getPuyoPair()[1].getY() ){ //puyo at [0] is below lower = 0; upper = 1; } else if ( (getPuyoPair()[1].getY()-1) == getPuyoPair()[0].getY() ){ //[1]'s below lower = 1; upper = 0; } switch(direction){ case LEFT: if( (getPuyoPair()[0].getY() != getPuyoPair()[1].getY()) & (getPuyoPair()[0].getX() != getPuyoPair()[1].getX())) return; //return back without doing anything if the puyos dont lie in single row or single column if (lower != -1){ //VERTICAL ORIENTATION [PATCH] if(moveLeft(getPuyoPair()[lower])) moveLeft(getPuyoPair()[upper]); //move upper to left only if lower could move left first } //HORIZONTAL ORIENTATION: Check the one which is to left else if(getPuyoPair()[0].getX() == (getPuyoPair()[1].getX()-1) ){ //puyo at [0] is to left and both the puyos are joined moveLeft(getPuyoPair()[0]); moveLeft(getPuyoPair()[1]); } else{ //either the Xpositions are equal or [1]'s on left moveLeft(getPuyoPair()[1]); moveLeft(getPuyoPair()[0]); } break; case RIGHT: if( (getPuyoPair()[0].getY() != getPuyoPair()[1].getY()) & (getPuyoPair()[0].getX() != getPuyoPair()[1].getX())) return; //return back without doing anything if the puyos dont lie in single row or single column if (lower != -1){ //VERTICAL ORIENTATION [PATCH] if(moveRight(getPuyoPair()[lower])) moveRight(getPuyoPair()[upper]); //move upper to left only if lower could move left first } //HORIZONTAL ORIENTATION: Check the one which is to right else if(getPuyoPair()[0].getX() == (getPuyoPair()[1].getX()-1) ){ //puyo at [1] is to right moveRight(getPuyoPair()[1]); moveRight(getPuyoPair()[0]); } else{ //either the X positions are equal or [0]'s on right moveRight(getPuyoPair()[0]); moveRight(getPuyoPair()[1]); } break; case DOWN: if(lower == -1){ //HORIZONTAL ORIENTATION => move any of the puyos first. lower = 1; upper = 0; } lowerCouldMove = moveDown(getPuyoPair()[lower]); upperCouldMove = moveDown(getPuyoPair()[upper]); //launch chain rxn of popping if both couldn't move if( !lowerCouldMove & !upperCouldMove ){ popPuyos(getPuyoPair()); drawBoardMap(); //now that the 2 have settled, push a new pair on board pushPuyos(); } break; case ROTATE: rotate(getPuyoPair()); break; } drawBoardMap(); } /** * <CODE>KeyEvent</CODE> listener that is responsible for firing appropriate actions corresponding * to the key pressed. * <p><ul><b>UP ARROW KEY</b> - Rotate the pair.</ul> * <ul><b>LEFT ARROW KEY</b> - Move the pair to left.</ul> * <ul><b>RIGHT ARROW KEY</b> - Move the pair to right. * <ul><b>DOWN ARROW KEY</b> - Move the pair downwards/accelerate the fall.</ul> * <ul><b>SPACEBAR</b> - Pause the game.</ul> * <ul><b>ESC</b> - Quit from the game.</ul></p> * @param e Virtual code of the key pressed. */ public void keyPressed(KeyEvent e){ switch(e.getKeyCode()){ case KeyEvent.VK_ESCAPE: setGameOver(true); break; case KeyEvent.VK_LEFT: movementWrapper(LEFT); break; case KeyEvent.VK_RIGHT: movementWrapper(RIGHT); break; case KeyEvent.VK_DOWN: movementWrapper(DOWN); break; case KeyEvent.VK_UP: movementWrapper(ROTATE); break; case KeyEvent.VK_SPACE: paused = !paused; break; } } /** * <CODE>KeyListener</CODE> Interface: keyReleased. Ignored. */ public void keyReleased(KeyEvent e){ //do nothing! } /** * <CODE>KeyListener</CODE> Interface: keyTyped. Ignored. */ public void keyTyped(KeyEvent e){ //do nothing! } /** * From the <CODE>MouseListener</CODE> interface. <CODE>MouseListener</CODE> responsible for firing * appropriate events corresponding to the key pressed. */ public void mousePressed(MouseEvent e) { movementWrapper(ROTATE) ; } /** * From the <CODE>MouseListener</CODE> interface. Ignored. */ public void mouseReleased(MouseEvent e) { // do nothing } /** * From the <CODE>MouseListener</CODE> interface. Ignored. */ public void mouseClicked(MouseEvent e) { // called after mouse is released - ignored } /** * From the <CODE>MouseListener</CODE> interface. Ignored. */ public void mouseEntered(MouseEvent e) { //do nothing } /** * From the <CODE>MouseListener</CODE> interface. Ignored. */ public void mouseExited(MouseEvent e) { //do nothing } /** * From the <CODE>MouseMotionListener</CODE> interface. Ignored. */ public void mouseDragged(MouseEvent e) { //do nothing } /** * From the <CODE>MouseMotionListener</CODE> interface. Determines in which direction has * the mouse moved and then recenters it. */ public synchronized void mouseMoved(MouseEvent e) { if(paused == true) return; // this event is from re-centering the mouse - ignore it if (isRecentering && centerLocation.x == e.getX() && centerLocation.y == e.getY()) { isRecentering = false; } else { int dx = e.getX() - mouseLocation.x; int dy = e.getY() - mouseLocation.y; if(dx<0) //Mouse moved left movementWrapper(LEFT); else if(dx>0) //Mouse moved right movementWrapper(RIGHT); else if(dy>0) //Mouse moved down movementWrapper(DOWN); //Movements towards north are to be ignored recenterMouse(); } mouseLocation.x = e.getX(); mouseLocation.y = e.getY(); } /** * Object of <CODE>Robot</CODE> class used for recentering the mouse. */ private Robot robot; /** * <CODE>Point</CODE> object storing the mouse's location. */ private Point mouseLocation; /** * Holds the center point of the screen. */ private Point centerLocation; /** * <CODE>Boolean</CODE> telling if the mouse is re-centering or not. */ private boolean isRecentering; /** * Initializes the mouse, recenters it and hides the mouse pointer. * @param window Window for which to initialize the mouse. */ private void initializeMouse(Window window){ //hide the mouse pointer Cursor invisibleCursor = Toolkit.getDefaultToolkit().createCustomCursor( Toolkit.getDefaultToolkit().getImage(""), new Point(0,0),"invisible"); window.setCursor(invisibleCursor); System.out.println("Mouse Pointer is now hidden!"); mouseLocation = new Point(); centerLocation = new Point(); isRecentering = false; try { robot = new Robot(); recenterMouse(); mouseLocation.x = centerLocation.x; mouseLocation.y = centerLocation.y; } catch (AWTException ex) { System.out.println("Couldn't create Robot! Mouse initialization failed!!"); } } /** * Uses the <CODE>Robot</CODE> class to try to position the mouse in the * center of the screen. * <p>Note that use of the <CODE>Robot</CODE> class may not be available * on all platforms.</p> */ private synchronized void recenterMouse() { Window window = screen.getFullScreenWindow(); if (robot != null && window.isShowing()) { centerLocation.x = window.getWidth() / 2; centerLocation.y = window.getHeight() / 2; SwingUtilities.convertPointToScreen(centerLocation, window); isRecentering = true; robot.mouseMove(centerLocation.x, centerLocation.y); } } /** * Kills the thread and exits from the game while restoring the screen * and unhiding the mouse pointer. */ public void goodbye(){ //do cleanup ops before exiting /* Restore Cursor * Restore Screen * Kill the thread */ System.out.println("GoodBye!!"); getG().setColor(Color.MAGENTA); getG().drawString("GoodBye!", 10, screen.getHeight()-50); getG().drawString(":(", screen.getWidth()-100, screen.getHeight()-50); screen.update(); try { Thread.sleep(1000); } catch (InterruptedException ex) { } Cursor normalCursor = Cursor.getDefaultCursor(); Window window = screen.getFullScreenWindow(); window.setCursor(normalCursor); screen.restoreScreen(); System.exit(0); } /** * 'Mainest' Method Of ALL :D * @param args the command line arguments */ public static void main(String[] args) { frontEnd w; if(args.length>0 && args[0].equalsIgnoreCase(new String("autodetect"))) w = new frontEnd(true); else w = new frontEnd(false); while(!w.isGameOver()){ w.movementWrapper(3); //3 implies down try{ Thread.sleep(500); } catch (InterruptedException ex) { System.out.println("Main Thread Interrupted! Reason: " + ex.toString()); } } try { w.goodbye(); } catch (Exception e) { System.out.println(e.toString()); } } }