package djh.games.pavajong ; import java.awt.*; // // This code is released into the public domain as of 3/31/96. // d.j.hudek // /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // class PavaJongPreGame /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // // A PavaJongPreGame contains 4 PJBorderPanels (title, instructions, // options, control) and potentially a PavaJongGame // (depending on user actions). // // The title area contains a simple Label. // The instructions area contains a read-only TextArea. // The options area contains a title Label and // 3 option Labels along with their associated Choice objects. // The controls area contains a title Label and 4 Buttons. // // Depending on user actions, a PavaJongGame may be instantiated // and running, paused, or killed. // public class PavaJongPreGame extends Panel { ///////////////////////////////////////////////////////////////// // Class Data ///////////////////////////////////////////////////////////////// // title area protected static String THE_TITLE = "PAVAJONG"; // instructions protected static String INSTR_STRING = "PavaJong is a pong-like game.\n\n" + "The playing field is bounded on the top and bottom, " + "with the sides open. There are 'paddles' on the\n" + "left and right sides, which can be controlled by mouse " + "movements. Within the playing field are the\n" + "current ball as well as a number of colored targets. " + "Points are awarded when the ball strikes a target\n" + "(after giving up a reward, the target will release " + "the ball with randomly altered velocity and in a\n" + "random direction).\n\n" + "Use the paddles like a goal-keeper... keep the ball " + "from careening out of bounds by striking it with\n" + "the paddles. The LEFT paddle is SLAVED to the movement " + "of the RIGHT. The RIGHT paddle will follow \n" + "the movement of the mouse cursor whenever it is in " + "the right paddle area, and ONLY when it is in the\n" + "right paddle area (takes a bit of practice :-) ).\n\n" + "The middle region of the paddles is perfectly " + "elastic, while the top and bottom will impart more\n" + "force. Try to keep the ball in play for as long as " + "possible, striking the targets as often as possible.\n\n" + "You can choose different paddle sizes, ball speed, " + "and/or target pattern (note that the targets give \n" + "up higher rewards for more difficult paddle size or " + "ball speed settings). There are 3 balls per game.\n\n" + "Make some choices, start up a game, and have fun!" ; // options protected static String OPTION_STRING = " Make Some Choices... "; protected static String PAD_CH_SMALL = "Small (Expert)"; protected static String PAD_CH_MEDIUM = "Medium (Intermediate)"; protected static String PAD_CH_LARGE = "Large (Novice)"; protected static String PAD_CH_DEFAULT = PAD_CH_MEDIUM; protected static String PAD_CH_STRING = " Paddle Size: "; protected static String BALLSP_CH_SLOW = "Slow (Novice)"; protected static String BALLSP_CH_MEDIUM = "Medium (Intermediate)"; protected static String BALLSP_CH_FAST = "Fast (Expert)"; protected static String BALLSP_CH_DEFAULT = BALLSP_CH_MEDIUM; protected static String BALLSP_CH_STRING = " Ball Speed: "; protected static String TARGPAT_CH_SINGLE = "Single target in center"; protected static String TARGPAT_CH_V3 = "3 targets lined up vertically"; protected static String TARGPAT_CH_H3 = "3 targets lined up horizontally"; protected static String TARGPAT_CH_S4 = "4 targets in a square pattern"; protected static String TARGPAT_CH_DEFAULT = TARGPAT_CH_V3; protected static String TARGPAT_CH_STRING = " Target Pattern: "; // controls protected static String CONTROLS_STRING = " Play The Game... "; protected static String BUTTON_DEFAULTS = "Reset Options to Defaults"; protected static String BUTTON_NEWGAME = "Start New Game with Specified Options"; protected static String BUTTON_PAUSE = "Pause Current Game"; protected static String BUTTON_RESUME = "Resume Current Game"; protected static String BUTTON_KILLGAME = "Kill (dispose of) Current Game"; // fonts protected static Font bigBoldItalicFont = new Font( "Helvetica", Font.BOLD|Font.ITALIC, 24 ); protected static Font mediumBoldItalicFont = new Font( "Helvetica", Font.BOLD|Font.ITALIC, 18 ); protected static Font bigBoldFont = new Font( "Helvetica", Font.BOLD, 24 ); protected static Font mediumBoldFont = new Font( "Helvetica", Font.BOLD, 18 ); ///////////////////////////////////////////////////////////////// // Instance Variables ///////////////////////////////////////////////////////////////// protected PJBorderPanel titleGroupPanel; // title area protected PJBorderPanel instrGroupPanel; // instructions area protected PJBorderPanel optGroupPanel; // options area protected PJBorderPanel ctlGroupPanel; // controls area protected Label theTitleLabel; // title protected Choice paddleSizeCh; // option - paddle size protected Choice ballSpeedCh; // option - ball speed protected Choice targPatternCh; // option - target pattern protected Button defaultsB; // control - set options // to defaults protected Button newGameB; // control - start a new game protected Button pauseResumeB; // control - pause/resume // current game protected Button killGameB; // control - kill/dispose of // current game // options protected DifficultyLevel paddleLevel; protected DifficultyLevel paddleLevelDefault; protected DifficultyLevel ballSpLevel; protected DifficultyLevel ballSpLevelDefault; protected int targetPattern; protected int targetPatternDefault; // the game protected PavaJongGame theGame; protected boolean gameInProgress; ///////////////////////////////////////////////////////////////// // Constructor ///////////////////////////////////////////////////////////////// /** * Creates a "pre-game" area with game title, instructions, * various options (e.g., difficulty levels for paddle * size and ball speed), and controls to reset options and * start/pause/resume/kill a game */ public PavaJongPreGame() { super(); theGame = null; gameInProgress = false; paddleLevelDefault = new DifficultyLevel(); paddleLevelDefault.setIntermediate(); ballSpLevelDefault = new DifficultyLevel(); ballSpLevelDefault.setIntermediate(); targetPatternDefault = Playground.TARG_SINGLE; paddleLevel = paddleLevelDefault; ballSpLevel = ballSpLevelDefault; targetPattern = targetPatternDefault; titleGroupPanel = new PJBorderPanel(); instrGroupPanel = new PJBorderPanel(); optGroupPanel = new PJBorderPanel(); ctlGroupPanel = new PJBorderPanel(); paddleSizeCh = new Choice(); ballSpeedCh = new Choice(); targPatternCh = new Choice(); // // set up the overall title area // (animating this would be a nice touch... // for now, just use a static label) // titleGroupPanel.setLayout( new BorderLayout() ); theTitleLabel = new Label( THE_TITLE, Label.CENTER ); //theTitleLabel.setFont( bigBoldItalicFont ); theTitleLabel.setFont( bigBoldFont ); titleGroupPanel.add( "Center", theTitleLabel ); // // set up the instructions area // Uses a read-only TextArea // TextArea instrText = new TextArea(INSTR_STRING); instrText.setEditable( false ); instrGroupPanel.setLayout( new BorderLayout() ); instrGroupPanel.add( "Center", instrText ); // // set up options area // // Use GridBagLayout // // label1 choice1 // titleLabel label2 choice2 // label3 choice3 // GridBagLayout optGridBag = new GridBagLayout(); GridBagConstraints optConstraints = new GridBagConstraints(); optConstraints.fill = GridBagConstraints.BOTH; optGroupPanel.setLayout( optGridBag ); // title label spans three rows optConstraints.gridwidth = 1; optConstraints.gridheight = 3; Label optLabel = new Label( OPTION_STRING, Label.LEFT ); //optLabel.setFont( mediumBoldItalicFont ); optLabel.setFont( mediumBoldFont ); optGridBag.setConstraints( optLabel, optConstraints ); optGroupPanel.add( optLabel ); // other components take up one cell each optConstraints.gridwidth = 1; optConstraints.gridheight = 1; Label paddleLabel = new Label( PAD_CH_STRING, Label.RIGHT ); optConstraints.gridx = 1; optConstraints.gridy = 0; optGridBag.setConstraints( paddleLabel, optConstraints ); optGroupPanel.add( paddleLabel ); optConstraints.gridx += 1; // next column in this row paddleSizeCh.addItem( PAD_CH_SMALL ); paddleSizeCh.addItem( PAD_CH_MEDIUM ); paddleSizeCh.addItem( PAD_CH_LARGE ); paddleSizeCh.select( PAD_CH_DEFAULT ); optGridBag.setConstraints( paddleSizeCh, optConstraints ); optGroupPanel.add( paddleSizeCh ); Label ballLabel = new Label( BALLSP_CH_STRING, Label.RIGHT ); optConstraints.gridx = 1; optConstraints.gridy += 1; // next row optGridBag.setConstraints( ballLabel, optConstraints ); optGroupPanel.add( ballLabel ); optConstraints.gridx += 1; ballSpeedCh.addItem( BALLSP_CH_SLOW ); ballSpeedCh.addItem( BALLSP_CH_MEDIUM ); ballSpeedCh.addItem( BALLSP_CH_FAST ); ballSpeedCh.select( BALLSP_CH_DEFAULT ); optGridBag.setConstraints( ballSpeedCh, optConstraints ); optGroupPanel.add( ballSpeedCh ); Label targLabel = new Label( TARGPAT_CH_STRING, Label.RIGHT ); optConstraints.gridx = 1; optConstraints.gridy += 1; optGridBag.setConstraints( targLabel, optConstraints ); optGroupPanel.add( targLabel ); optConstraints.gridx += 1; targPatternCh.addItem( TARGPAT_CH_SINGLE ); targPatternCh.addItem( TARGPAT_CH_V3 ); targPatternCh.addItem( TARGPAT_CH_H3 ); targPatternCh.addItem( TARGPAT_CH_S4 ); targPatternCh.select( TARGPAT_CH_DEFAULT ); optGridBag.setConstraints( targPatternCh, optConstraints ); optGroupPanel.add( targPatternCh ); // // set up controls area // // Use GridBagLayout // // // button1 // button2 // titleLabel // button3 // button4 // // (sort of, given the limits of ASCII art) // GridBagLayout ctlGridBag = new GridBagLayout(); GridBagConstraints ctlConstraints = new GridBagConstraints(); ctlConstraints.fill = GridBagConstraints.BOTH; ctlGroupPanel.setLayout( ctlGridBag ); // title label spans four rows ctlConstraints.gridwidth = 1; ctlConstraints.gridheight = 4; Label ctlLabel = new Label( CONTROLS_STRING, Label.LEFT ); //ctlLabel.setFont( mediumBoldItalicFont ); ctlLabel.setFont( mediumBoldFont ); ctlGridBag.setConstraints( ctlLabel, ctlConstraints ); ctlGroupPanel.add( ctlLabel ); // other components take up one cell each ctlConstraints.gridwidth = 1; ctlConstraints.gridheight = 1; newGameB = new Button( BUTTON_NEWGAME ); ctlConstraints.gridx = 1; ctlConstraints.gridy = 0; ctlGridBag.setConstraints( newGameB, ctlConstraints ); ctlGroupPanel.add( newGameB ); defaultsB = new Button( BUTTON_DEFAULTS ); ctlConstraints.gridy += 1; // next row ctlGridBag.setConstraints( defaultsB, ctlConstraints ); ctlGroupPanel.add( defaultsB ); pauseResumeB = new Button( BUTTON_PAUSE ); pauseResumeB.disable(); // Enable later when game is started. ctlConstraints.gridy += 1; // The next row. ctlGridBag.setConstraints( pauseResumeB, ctlConstraints ); ctlGroupPanel.add( pauseResumeB ); killGameB = new Button( BUTTON_KILLGAME ); killGameB.disable(); // Enable later when game is started. ctlConstraints.gridy += 1; // next row ctlGridBag.setConstraints( killGameB, ctlConstraints ); ctlGroupPanel.add( killGameB ); // // lay out all the panels into "myself" // // Use GridLayout // setLayout( new GridLayout(4,1,2,2) ); add( titleGroupPanel ); add( instrGroupPanel ); add( optGroupPanel ); add( ctlGroupPanel ); } ///////////////////////////////////////////////////////////////// // Methods ///////////////////////////////////////////////////////////////// /* * resets game options to the defaults */ private void resetDefaultOptions() { paddleSizeCh.select( PAD_CH_DEFAULT ); ballSpeedCh.select( BALLSP_CH_DEFAULT ); targPatternCh.select( TARGPAT_CH_DEFAULT ); } /* * Examines the game option area and extracts the * current selections */ private void getCurrentOptions() { String pString = paddleSizeCh.getSelectedItem(); String bString = ballSpeedCh.getSelectedItem(); String tString = targPatternCh.getSelectedItem(); DifficultyLevel pDL = new DifficultyLevel(); DifficultyLevel bDL = new DifficultyLevel(); // Get Paddle Option if( pString.equals(PAD_CH_SMALL) ) { pDL.setExpert(); } else if( pString.equals(PAD_CH_MEDIUM) ) { pDL.setIntermediate(); } else if( pString.equals(PAD_CH_LARGE) ) { pDL.setNovice(); } else { pDL = paddleLevelDefault; } paddleLevel = pDL; // Get Ball Speed Option if( bString.equals(BALLSP_CH_SLOW) ) { bDL.setNovice(); } else if( bString.equals(BALLSP_CH_MEDIUM) ) { bDL.setIntermediate(); } else if( bString.equals(BALLSP_CH_FAST) ) { bDL.setExpert(); } else { bDL = ballSpLevelDefault; } ballSpLevel = bDL; // Get Target Pattern Option if( tString.equals(TARGPAT_CH_SINGLE) ) { targetPattern = Playground.TARG_SINGLE; } else if( tString.equals(TARGPAT_CH_V3) ) { targetPattern = Playground.TARG_VERT3; } else if( tString.equals(TARGPAT_CH_H3) ) { targetPattern = Playground.TARG_HORIZ3; } else if( tString.equals(TARGPAT_CH_S4) ) { targetPattern = Playground.TARG_SQUARE4; } else { targetPattern = targetPatternDefault; } } ////////////////// Overridden Methods //////////////////// /** * Paints a red border */ public synchronized void paint( Graphics g ) { Dimension d = size(); Color saveColor = g.getColor(); g.setColor( Color.red ); g.drawRect( 0, 0, d.width-1, d.height-1 ); g.drawRect( 1, 1, d.width-3, d.height-3 ); g.setColor( saveColor ); } /** * Use a 5 unit "breathing space" inset left/right/top/bottom */ public Insets insets() { return( new Insets(5,5,5,5) ); } /** * Handle depressions of buttons in the control area */ public synchronized boolean action( Event event, Object obj ) { boolean handledIt = false; // assume not, check if so if( event.target instanceof Button ) { String tempString = ((Button)(event.target)).getLabel(); if( tempString.equals(BUTTON_DEFAULTS) ) { resetDefaultOptions(); repaint(); } else if( tempString.equals(BUTTON_NEWGAME) ) { getCurrentOptions(); if( theGame != null ) { // get rid of old game theGame.stop(); ((Frame)theGame).dispose(); theGame = null; } // start up a new game theGame = new PavaJongGame( paddleLevel, ballSpLevel, targetPattern ); ((Frame)theGame).setTitle(THE_TITLE); ((Frame)theGame).pack(); ((Frame)theGame).show(); ((Frame)theGame).setResizable(false); theGame.init(); theGame.start(); gameInProgress = true; pauseResumeB.setLabel( BUTTON_PAUSE ); pauseResumeB.enable(); killGameB.enable(); handledIt = true; } else if( tempString.equals(BUTTON_PAUSE) || tempString.equals(BUTTON_RESUME) ) { if( theGame != null ) { if( gameInProgress ) { theGame.suspendGame(); pauseResumeB.setLabel( BUTTON_RESUME ); } else { theGame.resumeGame(); pauseResumeB.setLabel( BUTTON_PAUSE ); } gameInProgress = !gameInProgress; } handledIt = true; } else if( tempString.equals(BUTTON_KILLGAME) ) { if( theGame != null ) { theGame.stop(); ((Frame)theGame).dispose(); theGame = null; gameInProgress = false; pauseResumeB.setLabel( BUTTON_PAUSE ); pauseResumeB.disable(); killGameB.disable(); } handledIt = true; } } return( handledIt ); } }