package Application;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Menu;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
/* Game */
/* author: Edward Walsh */
/* Aug 5 2010 */
/* */
/* Framework for a sprite game */
/* */
/* AGREEMENT: */
/* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED */
/* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE */
/* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, */
/* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND */
/* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */
/* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING */
/* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */
/* THE POSSIBILITY OF SUCH DAMAGE. */
/* When the Program is made available in source code form: */
/* a) it must be made available under this Agreement; and */
/* b) a copy of this Agreement must be included with each copy of */
/* the Program. */
/* The Modifications that You create or to which You contribute */
/* are governed by the terms of this Agreement. You may not remove */
/* or alter this Agreement. */
/* */
/**
* Panel that displays all the graphics in the game.
* <p>
* Why do I need a panel--why can't I display the graphics in the frame?
* I want to the top of the graphics area to be at y=0.
* <p>
* Offscreen buffers are used to create a rock-solid animation that does not blink.
* <p>
* Focus is given to the panel so that the panel can listen for key presses.
* <p>
* The clock invokes repaint 15 times per second.
*/
public class GameBoard extends JPanel {
/**
*
*/
private final Game game;
private final Concentration concentration;
/** offscreen buffers are used to create a rock-solid animation that does not blink */
protected Image offscreenImage = null;
/** offscreen buffers are used to create a rock-solid animation that does not blink */
protected Graphics offscreenGraphics = null;
/**
* Constructor for the main panel in this game;
* all of the graphics are displayed on this panel.
* <p>
* <pre>
* Focus is given to the panel so that the panel can listen for key pressed.
* NOTE: Focus determines who receives the characters that are typed on the keyboard--
* the entity that has the focus receives the characters.
* A keyboard listener is created to listen for key pressed.
* A clock is created; the clock invokes repaint 15 times per second.
* </pre>
* <p>
* @param game TODO
*/
public GameBoard(Game game, Concentration concentration) {
this.game = game;
this.concentration = concentration;
/* allow this panel to get the focus */
setFocusable(true);
/* give this panel the focus */
requestFocus();
/* Now that this panel has the focus, this panel can receive keyboard events */
addKeyListener(new MyKeyListener(this.game));
/* this window can receive mouse motion events */
addMouseMotionListener(new MyMouseMotionListener(this.game));
/* this window can receive mouse events */
addMouseListener(new MyMouseListener(this.game));
/* start a clock that invokes repaint 15 times per second */
new ThreadClock(this).start();
/* add menu bar */
game.setLayout(new BorderLayout());
game.add(menuBar(this.game), BorderLayout.NORTH);
}//MyPanel
/**
* Method that creates a new menu
* @return a menuBar
* @author Cody Balos
*/
public JMenuBar menuBar(Game game) {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("Options");
menu.addMouseListener(new MyMouseListener(this.game));
menu.addKeyListener(new MyKeyListener(this.game));
menu.addMouseMotionListener(new MyMouseMotionListener(this.game));
menuBar.add(menu);
// Add restart menu item
JMenuItem restart = new ActionMenuItem(new RestartAction(concentration));
menuBar.add(Box.createHorizontalGlue());
menu.add(restart);
return menuBar;
}
/**
* Repaint all the graphics that are on the screen.
* The graphics are painted onto an off-screen buffer.
* When the buffer is completely painted, the buffer is displayed on this panel.
*/
public void paintComponent(Graphics g){
/* rawMouseClicked is set WHENEVER the mouse is clicked */
/* We will use a buffer so that we notice the click */
/* ONLY at the top of this loop--i.e. we do NOT want */
/* the state of the mouse click to change in the middle */
/* of this loop. */
this.game.setBufferedMouseClicked(this.game.isRawMouseClicked());
this.game.setRawMouseClicked(false);
/* if the off-screen buffer has not yet been created, create it */
if (offscreenImage==null) {
offscreenImage = createImage(getWidth(), getHeight());
offscreenGraphics = offscreenImage.getGraphics();
/* allow the developer to init sprites */
this.game.initalizeSprites();
}//if
/* if a human changed the width or the height of the frame */
/* then create a new off-buffer that is the same size as the frame. */
if ( (offscreenImage.getWidth(this)!= getWidth())
|| (offscreenImage.getHeight(this)!= getHeight()) ) {
offscreenImage = createImage(getWidth(), getHeight());
offscreenGraphics = offscreenImage.getGraphics();
requestFocus();
}//if
/* if this panel lost the focus, get the focus back. */
/* Why? We want this panel to be able to respond to key presses. */
/* WARNING: If you are planning on adding GUI controls */
/* to your game, then you will need to comment this out. */
if (hasFocus()==false) requestFocus();
/* clear/erase/delete the old image that is on the off-screen buffer */
offscreenGraphics.setColor(Color.WHITE);
offscreenGraphics.fillRect
(0,
0,
offscreenImage.getWidth(this),
offscreenImage.getHeight(this));
offscreenGraphics.setColor(Color.BLACK);
/* paint the new image onto the off-screen buffer */
this.game.paintFrame(offscreenGraphics);
/* render the off-screen buffer onto the screen */
g.drawImage(offscreenImage,0,0,this);
/* We do NOT want future iterations of paintComponent() */
/* to respond to any mouse clicks that THIS iteration */
/* of paintComponent() have already responded to. */
this.game.setBufferedMouseClicked(false);
}//paintComponent
}//MyPanel