====== Implementing a Simple Single Keystroke Menu ====== ---- The following version of SpriteDemoPanel implements an on-screen menu that allows you to choose a level of snowfall or to Quit when the animation starts. The animation also listens for an Esc key press to return to the menu. * [[http://rockhopper.monmouth.edu/~jchung/cs498gd/fa13/labs/menu/simple_kb/snow_slow_sprite_menu.zip | Complete zip archive of animation source]] /* * Modified for simple, single-keystroke menu (jchung, 11/2011) */ /* * Modified for Snowflake sprites (jchung) */ /* * Description: Demo with sprites (Updated on July 19, 2009) */ import java.awt.*; import java.awt.image.*; // for BufferedImage. import java.io.*; // to read Files. import javax.imageio.*; // to load image below. import java.util.*; import java.awt.event.*; // for FocusListner, KeyListener import javax.swing.*; // FocusListener, KeyListener added for kb event handling: public class SpriteDemoPanel extends JPanel implements Runnable, FocusListener, KeyListener { private static final long serialVersionUID = 1L; public static final int MAX_SPRITES = 30; private Thread animator; private int fps, frame, delay; private GameSprite [] sprites; // Added on-screen menu private boolean menuOn; private Font f = new Font("monospaced", Font.BOLD, 20); // Added menu-driven number of snowflakes private int numSnowflakes; // Panel background: BufferedImage background; // Snowflake crosswind: double wind; double windx; // how much to change wind value by private void initSprites() { sprites = new GameSprite[MAX_SPRITES]; RandomCoordinates randCoords = new RandomCoordinates(MAX_SPRITES); Random generator = new Random(); for (int count = 0; count < MAX_SPRITES; count++) { sprites[count] = new SnowflakeSprite( (double) randCoords.getXCoordAt(count), (double) randCoords.getYCoordAt(count), fps); // Now passing fps to Sprites. } } // This constructor is not used: public SpriteDemoPanel() { fps = 30; delay = (1000 / fps); initSprites(); // setDoubleBuffered applies to this JPanel. setDoubleBuffered( true ); } // This constructor is used: public SpriteDemoPanel (int initFPS) { fps = initFPS; delay = (1000 / fps); initSprites(); // Read the background.png image in current directory: try { background = ImageIO.read( new File( "background.png" ) ); } catch (Exception ex) {} setDoubleBuffered( true ); // to handle keyboard events: addFocusListener(this); addKeyListener(this); setFocusable(true); // Start with on-screen menu: menuOn = true; } public void paintComponent (Graphics g) { // Clear the panel: // g.clearRect(0, 0, this.getWidth(), this.getHeight()); // Instead of clearing the panel, draw a background image instead: g.drawImage( background, 0, 0, null ); // Added the on-screen menu; when the menu's on, stop the snow: if (menuOn) { g.setFont(f); g.setColor(Color.WHITE ); g.drawString("1) Flurry", 200, 300); g.drawString("2) Fall", 200, 350); g.drawString("3) Blizzard", 200, 400); g.drawString("4) Quit", 200, 450); } else { // Draw numSnowflakes snowflakes, where numSprites is set by the // menu choices above: for (int count=0; count < numSnowflakes; count++) sprites[count].drawSprite(g); } } public void start() { animator = new Thread(this); animator.start(); } public void stop() { animator = null; } public void run() { long start = System.currentTimeMillis(); Thread current = Thread.currentThread(); while (current == animator) { try { // Delay depending on how far we are behind start += delay; Thread.sleep(Math.max(0, start - System.currentTimeMillis())); } catch (InterruptedException e) { System.err.println("An error occurred: " + e.toString()); e.printStackTrace(); } // Draw the frame repaint(); // Update the sprites for (int count = 0; count < MAX_SPRITES; count++) { sprites[count].updateSprite(); sprites[count].moveSprite(); } // Figure out how fast it is running if (start + 1000 < System.currentTimeMillis()) { start = System.currentTimeMillis(); } // Advance the frame frame++; } } public void keyPressed (KeyEvent e) { // Will try to emulate a crosswind effect on snowflakes with // left/right arrow keys. Shift+ makes for stronger // crosswind. int key = e.getKeyCode(); // Keyboard code for the key that was pressed // windx is in pixels per second: if ( e.isShiftDown() ) windx = 30.0; else windx = 10.0; switch (key) { case (KeyEvent.VK_LEFT): wind = wind - windx; break; case (KeyEvent.VK_RIGHT): wind = wind + windx; break; case (KeyEvent.VK_ESCAPE): // Escape to menu menuOn = true; break; case (KeyEvent.VK_1): // Process menu options numSnowflakes = 10; menuOn = false; break; case (KeyEvent.VK_2): numSnowflakes = 20; menuOn = false; break; case (KeyEvent.VK_3): numSnowflakes = MAX_SPRITES; menuOn = false; break; case (KeyEvent.VK_4): System.exit(0); } for (int count = 0; count < MAX_SPRITES; count++) sprites[count].setXspeed( wind ); repaint(); } public void keyTyped (KeyEvent e) {} public void keyReleased (KeyEvent e) {} public void focusGained (FocusEvent e) {} public void focusLost (FocusEvent e) {} } ----