Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package BOut;
- import com.golden.gamedev.*;
- import com.golden.gamedev.object.*;
- import com.golden.gamedev.object.background.*;
- import java.awt.*;
- import java.awt.event.KeyEvent;
- import java.awt.event.MouseEvent;
- import java.io.*;
- import java.util.Arrays;
- import java.util.Comparator;
- import java.util.Iterator;
- import static BOut.BreakOutEngine.*;
- /**
- * The menu screen. Currently just lets you select the level, but you could add high score tables, options, etc.
- * @author Paul Barba
- */
- public class GameMenu extends GameObject {
- /**
- * PlayField for the game choice menu screen;
- */
- private PlayField field;
- /**
- * Font used for the title of the game
- */
- private GameFont titleFont;
- /**
- * Font used for the name of the currently chosen level of the game
- */
- private GameFont choiceFont;
- /**
- * Sprite (roughly, "image") for moving forward in the menu list
- */
- private Sprite forward;
- /**
- * Sprite (roughly, "image") for moving backward in the menu list
- */
- private Sprite backward;
- /**
- * Sprite for playing the chosen level
- */
- private Sprite play;
- /**
- * Sprite for quitting entirely
- */
- private Sprite quit;
- /**
- * horiz position on which to center the level name
- */
- private int nameCenter;
- /**
- * vert position for the name
- */
- private int nameYpos;
- /**
- * vert position for the title
- */
- private int titleYpos;
- /*
- * New FileSet object to keep track of level files
- */
- FileSet level = new FileSet("levels", "Level\\d+\\.xml");
- /*
- * New FileSet object to keep track of archive files
- */
- FileSet archive = new FileSet(".", ".+\\.sav");
- /**
- * Default constructor -- nothing special
- * @param engine
- */
- public GameMenu (GameEngine engine)
- {
- super(engine);
- }
- /**
- * Prepares the "playing field" for rendering and receiving input actions
- */
- public void initResources ()
- {
- // Found in a search for 800x600 public domain images.
- Background bground = new ImageBackground(super.getImage(GraphicsDirectory + "MenuBackground.jpg"));
- field = new PlayField();
- field.setBackground(bground);
- // Fonts are used to write to the screen
- GameFontManager fontMgr = new GameFontManager();
- // This color is "half-strength" pure red
- titleFont = fontMgr.getFont(new Font("sansserif", Font.BOLD, 48), new Color(128, 0, 0));
- choiceFont = fontMgr.getFont(new Font("serif", Font.BOLD, 24), Color.BLACK);
- // find maximum width of names, to determine screen layout
- //Comment: call to scanArchiveFiles() method
- int maxWidth = scanArchiveFiles();
- int halfMaxWidth = (maxWidth + 1) / 2; // round up
- // approximate layout:
- // < level-name >
- // PLAY QUIT
- titleYpos = bground.getHeight() / 3;
- nameCenter = bground.getWidth() / 2;
- int gap = 10; // to separate forward/backward from name
- play = new Sprite(getImage(GraphicsDirectory + "PlayButton.png"));
- field.add(play);
- int startYpos = bground.getHeight() - 2*gap - play.getHeight();
- play.setLocation(nameCenter - play.getWidth() - gap, startYpos);
- quit = new Sprite(getImage(GraphicsDirectory + "QuitButton.png"));
- field.add(quit);
- quit.setLocation(nameCenter + gap, startYpos);
- forward = new Sprite(getImage(GraphicsDirectory + "RightButton.png"));
- field.add(forward);
- nameYpos = startYpos - gap - forward.getHeight();
- forward.setLocation(nameCenter+halfMaxWidth+gap, nameYpos);
- backward = new Sprite(getImage(GraphicsDirectory + "LeftButton.png"));
- field.add(backward);
- backward.setLocation(nameCenter-halfMaxWidth-gap-backward.getWidth(), nameYpos);
- }
- /**
- * are we displaying levels, or archives?
- */
- private enum Mode {
- Levels {
- State getChoosingState () { return State.ChoosingLevel; }
- State getQuittingState () { return State.QuittingLevel; }
- State getOppositeState () { return State.ChoosingArchive; }
- String getChoiceString (GameMenu menu) {
- if (menu.level.size() <= 0) { return ""; }
- return menu.level.currentDisplay();
- }
- String getMenuString (GameMenu menu) { return "(Level)"; }
- State getDeletingState (){ return State.ChoosingLevel;}
- },
- Archives {
- State getChoosingState () { return State.ChoosingArchive; }
- State getQuittingState () { return State.QuittingArchive; }
- State getOppositeState () { return State.ChoosingLevel; }
- String getChoiceString (GameMenu menu) {
- if (menu.archive.size() <= 0) { return ""; }
- return menu.archive.currentDisplay();
- }
- String getMenuString (GameMenu menu) { return "(Archive)"; }
- //comment: obtain the state for deleting archives
- State getDeletingState () { return State.DeletingArchive; }
- };
- // obtain the proper state for ordinary choosing in this mode
- abstract State getChoosingState ();
- // obtain the proper state for quitting in this mode
- abstract State getQuittingState ();
- // obtain the state for choosing in the opposite mode
- abstract State getOppositeState ();
- // obtain the appropriate String that might be displayed
- abstract String getChoiceString (GameMenu menu);
- // obtain the appropriate String that might be displayed above a menu item
- abstract String getMenuString (GameMenu menu);
- //comment: obtain the appropriate state for deleting in this mode
- abstract State getDeletingState ();
- }
- /**
- * the different possible input processing states
- */
- private enum State
- {
- // presenting choices of levels to play
- ChoosingLevel(Mode.Levels) {
- State gotForward (GameMenu menu) {
- menu.level.advance(1);
- menu.level.refresh();
- return this;
- }
- State gotBackward (GameMenu menu) {
- menu.level.advance(-1);
- menu.level.refresh();
- return this;
- }
- State gotPlay (GameMenu menu) {
- if (menu.level.size() <= 0)
- {
- return this; // no game to play
- }
- menu.parent.nextGameID = BreakOutEngine.BreakOutPlayGame;
- ((BreakOutEngine)menu.parent).nextLevel = menu.level.current().getAbsolutePath();
- return Finish;
- }
- },
- // presenting choices of archives to restore
- ChoosingArchive(Mode.Archives) {
- State gotForward (GameMenu menu) {
- menu.archive.advance(1);
- menu.archive.refresh();
- return this;
- }
- State gotBackward (GameMenu menu) {
- menu.archive.advance(-1);
- menu.archive.refresh();
- return this;
- }
- State gotPlay (GameMenu menu) {
- if (menu.archive.size()<= 0)
- {
- return this; // no archive to restore: ignore key
- }
- menu.parent.nextGameID = BreakOutEngine.BreakOutRestore;
- ((BreakOutEngine)menu.parent).restoreFilename = menu.archive.current().getAbsolutePath();
- return Finish;
- }
- State gotDelete (GameMenu menu) {
- if (menu.archive.size() <= 0)
- {
- return this; // no archive to restore: ignore key
- }
- return DeletingArchive.gotDelete(menu); }
- },
- // quit requested; awaiting confirmation
- QuittingLevel(Mode.Levels) {
- State gotYes (GameMenu menu) {
- menu.parent.nextGame = null;
- return Finish;
- }
- String getMenuString (GameMenu menu) { return "Quit entirely? Y or N"; }
- },
- // quit requested; awaiting confirmation
- QuittingArchive(Mode.Archives) {
- State gotYes (GameMenu menu) {
- menu.parent.nextGame = null;
- return Finish;
- }
- String getMenuString (GameMenu menu) { return "Quit entirely? Y or N"; }
- },
- //Comment: Deletes the current archive
- DeletingArchive(Mode.Archives){
- // respond to a Yes confirmation
- State gotYes (GameMenu menu) { return this; }
- State gotDelete (GameMenu menu)
- {
- menu.archive.current().getAbsoluteFile().delete();
- menu.scanArchiveFiles();
- return ChoosingArchive;
- }
- String getMenuString (GameMenu menu) { return "Delete this archive? Y or N"; }
- },
- // quit has been confirmed; level vs archive does not matter
- Finish(Mode.Levels) {
- boolean shouldFinish (GameMenu menu) { return true; }
- };
- // is this a state that is handling levels, or archives?
- private final Mode mode;
- // constructor, which distinguishes level states versus archive states
- State (Mode mode) { this.mode = mode; }
- // are we in a state that should exit this "game"?
- boolean shouldFinish (GameMenu menu) { return false; }
- // respond to a Yes confirmation
- State gotYes (GameMenu menu) { return this; }
- // respond to a No confirmation
- State gotNo (GameMenu menu) { return mode.getChoosingState(); }
- // respond to a move-forward-in-the-list request
- State gotForward (GameMenu menu) { return this; }
- // respond to a move-backward-in-the-list request
- State gotBackward (GameMenu menu) { return this; }
- // respond to a request to play the current choice
- State gotPlay (GameMenu menu) { return this; }
- // respond to a request to quit
- State gotQuit (GameMenu menu) { return mode.getQuittingState(); }
- // respond to a request to toggle between choosing a level or an archive
- State gotRestore (GameMenu menu) {
- State newState = mode.getOppositeState();
- return newState;
- }
- // get the current choice string to display
- String getChoiceString (GameMenu menu) { return mode.getChoiceString(menu); }
- // get the current string to display above the menu choice
- String getMenuString (GameMenu menu) { return mode.getMenuString(menu); }
- // get suitable starting state
- static State initial (Mode mode) { return mode.getChoosingState(); }
- // Comment: Default action is do nothing if D or Delete is pressed.
- State gotDelete (GameMenu menu) { return this; }
- }
- /**
- * the current input processing state
- */
- private State state = State.initial(Mode.Levels);
- private enum MyEvent {
- None,
- MoveForward,
- MoveBackward,
- No,
- Play,
- Quit,
- Restore,
- Yes,
- Delete;
- }
- /**
- * Checks mouse position and determines appropriate event, if any
- * @return the MyEvent for the current mouse position
- */
- private MyEvent getMouseEvent ()
- {
- if (mouseOver(forward))
- return MyEvent.MoveForward;
- else if (mouseOver(backward))
- return MyEvent.MoveBackward;
- else if (mouseOver(play))
- return MyEvent.Play;
- else if (mouseOver(quit))
- return MyEvent.Quit;
- else
- return MyEvent.None;
- }
- /**
- * Return the MyEvent for the current key pressed, if any
- * @return the MyEvent for the current key pressed (None if none)
- */
- private MyEvent getKeyEvent ()
- {
- if (bsInput.isKeyPressed(KeyEvent.VK_RIGHT))
- return MyEvent.MoveForward;
- else if (bsInput.isKeyPressed(KeyEvent.VK_LEFT))
- return MyEvent.MoveBackward;
- else if (bsInput.isKeyPressed(KeyEvent.VK_ENTER))
- return MyEvent.Play;
- else if (bsInput.isKeyPressed(KeyEvent.VK_N))
- return MyEvent.No;
- else if (bsInput.isKeyPressed(KeyEvent.VK_Q))
- return MyEvent.Quit;
- else if (bsInput.isKeyPressed(KeyEvent.VK_R))
- return MyEvent.Restore;
- else if (bsInput.isKeyPressed(KeyEvent.VK_Y))
- return MyEvent.Yes;
- else if (bsInput.isKeyPressed(KeyEvent.VK_D)||bsInput.isKeyPressed(KeyEvent.VK_DELETE))
- return MyEvent.Delete;
- else
- return MyEvent.None;
- }
- /**
- * Looks for keyboard or mouse input, converting to the
- * common type MyEvent
- * @return a MyEvent (None if nothing happened)
- */
- private MyEvent getEvent () {
- MyEvent event = MyEvent.None;
- if (bsInput.isMousePressed(MouseEvent.BUTTON1))
- event = getMouseEvent();
- else
- event = getKeyEvent();
- return event;
- }
- /**
- * Check for and process any input event
- */
- private void processInput () {
- switch (getEvent()) {
- case MoveForward: state = state.gotForward (this); break;
- case MoveBackward: state = state.gotBackward(this); break;
- case No: state = state.gotNo (this); break;
- case Play: state = state.gotPlay (this); break;
- case Quit: state = state.gotQuit (this); break;
- case Restore: state = state.gotRestore (this); break;
- case Yes: state = state.gotYes (this); break;
- case Delete: state = state.gotDelete (this); break;
- case None: break;
- }
- }
- /**
- * Called to update the screen.
- * Here just checks for input events and updates information for
- * rendering (or starts the chosen game)
- * @param elaspedTime time since last update (not very relevant here)
- */
- @Override
- public void update (long elapsedTime)
- {
- field.update(elapsedTime);
- processInput();
- if (state.shouldFinish(this))
- {
- finish();
- }
- }
- /**
- * paint the menu screen
- */
- public void render (Graphics2D g)
- {
- field.render(g);
- String title = "UMASS BREAKOUT";
- int titleWidth = titleFont.getWidth(title);
- titleFont.drawString(g, title, nameCenter-(titleWidth/2), titleYpos);
- String choice = state.getChoiceString(this);
- int choiceWidth = choiceFont.getWidth(choice);
- choiceFont.drawString(g, choice, nameCenter-(choiceWidth/2), nameYpos);
- String kind = state.getMenuString(this);
- int kindWidth = choiceFont.getWidth(kind);
- choiceFont.drawString(g, kind, nameCenter-(kindWidth/2), nameYpos - 10 - choiceFont.getHeight());
- }
- /**
- * Tests whether the mouse is currently over a given sprite.
- * Used for telling what to do on mouse presses.
- * @param s the sprite
- * @return true if the mouse is over the sprite
- */
- private boolean mouseOver(Sprite s)
- {
- return (getMouseX() >= s.getX() && getMouseX() < (s.getX() + s.getWidth ()) &&
- getMouseY() >= s.getY() && getMouseY() < (s.getY() + s.getHeight()));
- }
- private int scanArchiveFiles()
- {
- archive.refresh();
- // find maximum width of names, to determine screen layout
- int maxWidth = 0;
- Iterator<File> it = level.iterator();
- while(it.hasNext())
- {
- int width = choiceFont.getWidth(level.currentDisplay());
- if (maxWidth < width)
- {
- maxWidth = width;
- }
- it.next();
- }
- Iterator<File> it2 = archive.iterator();
- while(it2.hasNext())
- {
- int width = choiceFont.getWidth(archive.currentDisplay());
- if (maxWidth < width)
- {
- maxWidth = width;
- }
- it2.next();
- }
- return maxWidth;
- }
- }
Add Comment
Please, Sign In to add comment