将菜单添加到Java Game

时间:2011-11-26 20:38:42

标签: java swing menu

我一直在努力通过David Brackeen开发Java游戏并遇到问题。我正在修改游戏并将其拉开以更好地理解它是如何工作的。我不知道如何添加菜单,如第3章中所示的菜单。任何指导都表示赞赏。

我一直在寻找ScreenManager和GameManager,了解如何做到这一点。我知道游戏如何获得屏幕大小,我只需要推动如何显示菜单。

以下是代码:

ScreenManager.java

package com.brackeen.javagamebook.graphics;

import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;
import javax.swing.JLabel; 

/**
The ScreenManager class manages initializing and displaying
full screen graphics modes.
*/
public class ScreenManager {

private GraphicsDevice device;

/**
    Creates a new ScreenManager object.
*/
public ScreenManager() {
    GraphicsEnvironment environment =
        GraphicsEnvironment.getLocalGraphicsEnvironment();
    device = environment.getDefaultScreenDevice();
}


/**
    Returns a list of compatible display modes for the
    default device on the system.
*/
public DisplayMode[] getCompatibleDisplayModes() {
    return device.getDisplayModes();
}


/**
    Returns the first compatible mode in a list of modes.
    Returns null if no modes are compatible.
*/
public DisplayMode findFirstCompatibleMode(
    DisplayMode modes[])
{
    DisplayMode goodModes[] = device.getDisplayModes();
    for (int i = 0; i < modes.length; i++) {
        for (int j = 0; j < goodModes.length; j++) {
            if (displayModesMatch(modes[i], goodModes[j])) {
                return modes[i];
            }
        }

    }

    return null;
}


/**
    Returns the current display mode.
*/
public DisplayMode getCurrentDisplayMode() {
    return device.getDisplayMode();
}


/**
    Determines if two display modes "match". Two display
    modes match if they have the same resolution, bit depth,
    and refresh rate. The bit depth is ignored if one of the
    modes has a bit depth of DisplayMode.BIT_DEPTH_MULTI.
    Likewise, the refresh rate is ignored if one of the
    modes has a refresh rate of
    DisplayMode.REFRESH_RATE_UNKNOWN.
*/
public boolean displayModesMatch(DisplayMode mode1,
    DisplayMode mode2)

{
    if (mode1.getWidth() != mode2.getWidth() ||
        mode1.getHeight() != mode2.getHeight())
    {
        return false;
    }

    if (mode1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
        mode2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
        mode1.getBitDepth() != mode2.getBitDepth())
    {
        return false;
    }

    if (mode1.getRefreshRate() !=
        DisplayMode.REFRESH_RATE_UNKNOWN &&
        mode2.getRefreshRate() !=
        DisplayMode.REFRESH_RATE_UNKNOWN &&
        mode1.getRefreshRate() != mode2.getRefreshRate())
     {
         return false;
     }

     return true;
}


/**
    Enters full screen mode and changes the display mode.
    If the specified display mode is null or not compatible
    with this device, or if the display mode cannot be
    changed on this system, the current display mode is used.
    <p>
    The display uses a BufferStrategy with 2 buffers.
*/
public void setFullScreen(DisplayMode displayMode) {
    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setUndecorated(true);
    frame.setIgnoreRepaint(true);
    frame.setResizable(false);





    device.setFullScreenWindow(frame);


    if (displayMode != null &&
        device.isDisplayChangeSupported())
    {
        try {
            device.setDisplayMode(displayMode);
        }
        catch (IllegalArgumentException ex) { }
        // fix for mac os x
        frame.setSize(displayMode.getWidth(),
            displayMode.getHeight());

    }
    // avoid potential deadlock in 1.4.1_02
    try {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                frame.createBufferStrategy(2);
            }
        });
    }
    catch (InterruptedException ex) {
        // ignore
    }
    catch (InvocationTargetException  ex) {
        // ignore
    }


}


/**
    Gets the graphics context for the display. The
    ScreenManager uses double buffering, so applications must
    call update() to show any graphics drawn.
    <p>
    The application must dispose of the graphics object.
*/
public Graphics2D getGraphics() {
    Window window = device.getFullScreenWindow();
    if (window != null) {
        BufferStrategy strategy = window.getBufferStrategy();
        return (Graphics2D)strategy.getDrawGraphics();
    }
    else {
        return null;
    }
}


/**
    Updates the display.
*/
public void update() {
    Window window = device.getFullScreenWindow();
    if (window != null) {
        BufferStrategy strategy = window.getBufferStrategy();
        if (!strategy.contentsLost()) {
            strategy.show();
        }
    }
    // Sync the display on some systems.
    // (on Linux, this fixes event queue problems)
    Toolkit.getDefaultToolkit().sync();
}


/**
    Returns the window currently used in full screen mode.
    Returns null if the device is not in full screen mode.
*/
public JFrame getFullScreenWindow() {
    return (JFrame)device.getFullScreenWindow();
}


/**
    Returns the width of the window currently used in full
    screen mode. Returns 0 if the device is not in full
    screen mode.
*/
public int getWidth() {
    Window window = device.getFullScreenWindow();
    if (window != null) {
        return window.getWidth();
    }
    else {
        return 0;
    }
}


/**
    Returns the height of the window currently used in full
    screen mode. Returns 0 if the device is not in full
    screen mode.
*/
public int getHeight() {
    Window window = device.getFullScreenWindow();
    if (window != null) {
        return window.getHeight();
    }  
    else {
        return 0;
    }
}


/**
    Restores the screen's display mode.
*/
public void restoreScreen() {
    Window window = device.getFullScreenWindow();
    if (window != null) {
        window.dispose();
    }
    device.setFullScreenWindow(null);
}


/**
    Creates an image compatible with the current display.
*/
public BufferedImage createCompatibleImage(int w, int h,
    int transparancy)
{
    Window window = device.getFullScreenWindow();
    if (window != null) {
        GraphicsConfiguration gc =
            window.getGraphicsConfiguration();
        return gc.createCompatibleImage(w, h, transparancy);
    }
    return null;
}
}

GameManager.java

package com.brackeen.javagamebook.tilegame;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.Iterator;

import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.sampled.AudioFormat;

import com.brackeen.javagamebook.graphics.*;
import com.brackeen.javagamebook.sound.*;
import com.brackeen.javagamebook.input.*;
import com.brackeen.javagamebook.test.GameCore;
import com.brackeen.javagamebook.tilegame.sprites.*;

/**
GameManager manages all parts of the game.
*/
public class GameManager extends GameCore {

public static void main(String[] args) {
    new GameManager().run();
}

// uncompressed, 44100Hz, 16-bit, mono, signed, little-endian
private static final AudioFormat PLAYBACK_FORMAT =
    new AudioFormat(44100, 16, 1, true, false);

private static final int DRUM_TRACK = 1;

public static final float GRAVITY = 0.002f;



private Point pointCache = new Point();
private TileMap map;
private MidiPlayer midiPlayer;
private SoundManager soundManager;
private ResourceManager resourceManager;
private Sound prizeSound;
private Sound boopSound;
private Sound jacksound; 
private InputManager inputManager;
private TileMapRenderer renderer;
public  Boolean panimation = false; 
public Boolean playing = false; 
private int points; 

private GameAction moveLeft;
private GameAction moveRight;
private GameAction jump;
private GameAction exit;
private GameAction pause; 


public void init() {
    super.init();

    // set up input manager
    initInput();

    // start resource manager
    resourceManager = new ResourceManager(
    screen.getFullScreenWindow().getGraphicsConfiguration());

    // load resources
    renderer = new TileMapRenderer();
    renderer.setBackground(
        resourceManager.loadImage("background.png"));

    // load first map
    map = resourceManager.loadNextMap();

    // load sounds
    soundManager = new SoundManager(PLAYBACK_FORMAT);
    prizeSound = soundManager.getSound("sounds/prizes.wav");
    boopSound = soundManager.getSound("sounds/boop2.wav");
    jacksound = soundManager.getSound("sounds/jack.wav"); 

    // start music
    midiPlayer = new MidiPlayer();
    Sequence sequence =
        midiPlayer.getSequence("sounds/music.midi");
    midiPlayer.play(sequence, true);
    toggleDrumPlayback();
}


/**
    Closes any resurces used by the GameManager.
*/
public void stop() {
    super.stop();
    midiPlayer.close();
    soundManager.close();
}

public void pause() {

    if(!panimation){
    panimation = true;
    soundManager.setPaused(true); 
    midiPlayer.setPaused(true);

    }
    else{
    panimation = false; 
    soundManager.setPaused(false); 
    midiPlayer.setPaused(false);  
    } 



    } 


private void initInput() {
    moveLeft = new GameAction("moveLeft");
    moveRight = new GameAction("moveRight");
    jump = new GameAction("jump",
        GameAction.DETECT_INITAL_PRESS_ONLY);
    exit = new GameAction("exit",
        GameAction.DETECT_INITAL_PRESS_ONLY);
    pause = new GameAction("pause", 
        GameAction.DETECT_INITAL_PRESS_ONLY);  

    inputManager = new InputManager(
        screen.getFullScreenWindow());
    inputManager.setCursor(InputManager.INVISIBLE_CURSOR);

    inputManager.mapToKey(moveLeft, KeyEvent.VK_LEFT);
    inputManager.mapToKey(moveRight, KeyEvent.VK_RIGHT);
    inputManager.mapToKey(jump, KeyEvent.VK_SPACE);
    inputManager.mapToKey(exit, KeyEvent.VK_ESCAPE);
    inputManager.mapToKey(pause, KeyEvent.VK_F1); 
}


private void checkInput(long elapsedTime) {

    if (exit.isPressed()) {
        stop();
        String spoints = Integer.toString(points);
        System.out.println("Points: " + spoints); 
    }

    if (pause.isPressed()){
            pause(); 

        } 

    Player player = (Player)map.getPlayer();
    if (player.isAlive()) {
        float velocityX = 0;
        if (moveLeft.isPressed()) {
            velocityX-=player.getMaxSpeed();
        }
        if (moveRight.isPressed()) {
            velocityX+=player.getMaxSpeed();
        }
        if (jump.isPressed()) {
            player.jump(false);
        }


        player.setVelocityX(velocityX);
    }

}


public void draw(Graphics2D g) {
    renderer.draw(g, map,
        screen.getWidth(), screen.getHeight());
}


/**
    Gets the current map.
*/
public TileMap getMap() {
    return map;
}


/**
    Turns on/off drum playback in the midi music (track 1).
*/
public void toggleDrumPlayback() {
    Sequencer sequencer = midiPlayer.getSequencer();
    if (sequencer != null) {
        sequencer.setTrackMute(DRUM_TRACK,
            !sequencer.getTrackMute(DRUM_TRACK));
    }
}


/**
    Gets the tile that a Sprites collides with. Only the
    Sprite's X or Y should be changed, not both. Returns null
    if no collision is detected.
*/
public Point getTileCollision(Sprite sprite,
    float newX, float newY)
{
    float fromX = Math.min(sprite.getX(), newX);
    float fromY = Math.min(sprite.getY(), newY);
    float toX = Math.max(sprite.getX(), newX);
    float toY = Math.max(sprite.getY(), newY);

    // get the tile locations
    int fromTileX = TileMapRenderer.pixelsToTiles(fromX);
    int fromTileY = TileMapRenderer.pixelsToTiles(fromY);
    int toTileX = TileMapRenderer.pixelsToTiles(
        toX + sprite.getWidth() - 1);
    int toTileY = TileMapRenderer.pixelsToTiles(
        toY + sprite.getHeight() - 1);

    // check each tile for a collision
    for (int x=fromTileX; x<=toTileX; x++) {
        for (int y=fromTileY; y<=toTileY; y++) {
            if (x < 0 || x >= map.getWidth() ||
                map.getTile(x, y) != null)
            {
                // collision found, return the tile
                pointCache.setLocation(x, y);
                return pointCache;
            }
        }
    }

    // no collision found
    return null;
}


/**
    Checks if two Sprites collide with one another. Returns
    false if the two Sprites are the same. Returns false if
    one of the Sprites is a Creature that is not alive.
*/
public boolean isCollision(Sprite s1, Sprite s2) {
    // if the Sprites are the same, return false
    if (s1 == s2) {
        return false;
    }

    // if one of the Sprites is a dead Creature, return false
    if (s1 instanceof Creature && !((Creature)s1).isAlive()) {
        return false;
    }
    if (s2 instanceof Creature && !((Creature)s2).isAlive()) {
        return false;
    }

    // get the pixel location of the Sprites
    int s1x = Math.round(s1.getX());
    int s1y = Math.round(s1.getY());
    int s2x = Math.round(s2.getX());
    int s2y = Math.round(s2.getY());

    // check if the two sprites' boundaries intersect
    return (s1x < s2x + s2.getWidth() &&
        s2x < s1x + s1.getWidth() &&
        s1y < s2y + s2.getHeight() &&
        s2y < s1y + s1.getHeight());
}


/**
    Gets the Sprite that collides with the specified Sprite,
    or null if no Sprite collides with the specified Sprite.
*/
public Sprite getSpriteCollision(Sprite sprite) {

    // run through the list of Sprites
    Iterator i = map.getSprites();
    while (i.hasNext()) {
        Sprite otherSprite = (Sprite)i.next();
        if (isCollision(sprite, otherSprite)) {
            // collision found, return the Sprite
            return otherSprite;
        }
    }

    // no collision found
    return null;
}


/**
    Updates Animation, position, and velocity of all Sprites
    in the current map.
*/
public void update(long elapsedTime) {
    Creature player = (Creature)map.getPlayer();






    // player is dead! start map over
    if (player.getState() == Creature.STATE_DEAD) {
        map = resourceManager.reloadMap();
        return;
    }

    // get keyboard/mouse input
    checkInput(elapsedTime);

    if (!panimation) {  //If game is paused, it stops the updating of the animation. 


    // update player
    updateCreature(player, elapsedTime);
    player.update(elapsedTime);

    // update other sprites
    Iterator i = map.getSprites();
    while (i.hasNext()) {
        Sprite sprite = (Sprite)i.next();
        if (sprite instanceof Creature) {
            Creature creature = (Creature)sprite;
            if (creature.getState() == Creature.STATE_DEAD) {
                i.remove();
            }
            else {
                updateCreature(creature, elapsedTime);
            }
        }
        // normal update
        sprite.update(elapsedTime);
    }
    } 

}


/**
    Updates the creature, applying gravity for creatures that
    aren't flying, and checks collisions.
*/
private void updateCreature(Creature creature,
    long elapsedTime)
{

    // apply gravity
    if (!creature.isFlying()) {
        creature.setVelocityY(creature.getVelocityY() +
            GRAVITY * elapsedTime);
    }

    // change x
    float dx = creature.getVelocityX();
    float oldX = creature.getX();
    float newX = oldX + dx * elapsedTime;
    Point tile =
        getTileCollision(creature, newX, creature.getY());
    if (tile == null) {
        creature.setX(newX);
    }
    else {
        // line up with the tile boundary
        if (dx > 0) {
            creature.setX(
                TileMapRenderer.tilesToPixels(tile.x) -
                creature.getWidth());
        }
        else if (dx < 0) {
            creature.setX(
                TileMapRenderer.tilesToPixels(tile.x + 1));
        }
        creature.collideHorizontal();
    }
    if (creature instanceof Player) {
        checkPlayerCollision((Player)creature, false);
    }

    // change y
    float dy = creature.getVelocityY();
    float oldY = creature.getY();
    float newY = oldY + dy * elapsedTime;
    tile = getTileCollision(creature, creature.getX(), newY);
    if (tile == null) {
        creature.setY(newY);
    }
    else {
        // line up with the tile boundary
        if (dy > 0) {
            creature.setY(
                TileMapRenderer.tilesToPixels(tile.y) -
                creature.getHeight());
        }
        else if (dy < 0) {
            creature.setY(
                TileMapRenderer.tilesToPixels(tile.y + 1));
        }
        creature.collideVertical();
    }
    if (creature instanceof Player) {
        boolean canKill = (oldY < creature.getY());
        checkPlayerCollision((Player)creature, canKill);
    }

}


/**
    Checks for Player collision with other Sprites. If
    canKill is true, collisions with Creatures will kill
    them.
*/
public void checkPlayerCollision(Player player,
    boolean canKill)
{
    if (!player.isAlive()) {
        return;
    }

    // check for player collision with other sprites
    Sprite collisionSprite = getSpriteCollision(player);
    if (collisionSprite instanceof PowerUp) {
        acquirePowerUp((PowerUp)collisionSprite);
    }
    else if (collisionSprite instanceof Creature) {
        Creature badguy = (Creature)collisionSprite;
        if (canKill) {
            // kill the badguy and make player bounce
            soundManager.play(boopSound);
            badguy.setState(Creature.STATE_DYING);
            player.setY(badguy.getY() - player.getHeight());
            player.jump(true);
        }
        else {
            // player dies!
            player.setState(Creature.STATE_DYING);
            points = 0; 
        }
    }
}


/**
    Gives the player the speicifed power up and removes it
    from the map.
*/
public void acquirePowerUp(PowerUp powerUp) {
    // remove it from the map
    map.removeSprite(powerUp);
    Player player = (Player)map.getPlayer();

    if (powerUp instanceof PowerUp.Star) {
        // do something here, like give the player points
        soundManager.play(prizeSound);
        points = points + 5; 
    }
    else if (powerUp instanceof PowerUp.Music) {
        // change the music
        player.setMaxSpeed();

        if (! playing){
         soundManager.play(jacksound);
         playing = true; 
         }
         else
         {
         //Do nothing
         }


        toggleDrumPlayback();
    }
    else if (powerUp instanceof PowerUp.Goal) {
        // advance to next map
        soundManager.play(prizeSound,
        new EchoFilter(2000, .7f), false);
        map = resourceManager.loadNextMap();
    }
}

}

本书的章节中有一个示例菜单。

MenuTest.java

package com.brackeen.javagamebook.tilegame;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import com.brackeen.javagamebook.graphics.*;
import com.brackeen.javagamebook.sound.*;
import com.brackeen.javagamebook.input.*;
import com.brackeen.javagamebook.test.GameCore;
import com.brackeen.javagamebook.tilegame.sprites.*;

/**
Extends the InputManagerTest demo and adds Swing buttons
for pause, config and quit.
*/
public class Menu extends InputManager
implements ActionListener
{

public static void main(String[] args) {
    new Menu().run();
}

protected GameAction configAction;

private JButton playButton;
private JButton configButton;
private JButton quitButton;
private JButton pauseButton;
private JPanel playButtonSpace;

public void init() {
    super.init();
    // make sure Swing components don't paint themselves
    NullRepaintManager.install();

    // create an addtional GameAction for "config"
    configAction = new GameAction("config");

    // create buttons
    quitButton = createButton("quit", "Quit");
    playButton = createButton("play", "Continue");
    pauseButton = createButton("pause", "Pause");
    configButton = createButton("config", "Change Settings");

    // create the space where the play/pause buttons go.
    playButtonSpace = new JPanel();
    playButtonSpace.setOpaque(false);
    playButtonSpace.add(pauseButton);

    JFrame frame = super.screen.getFullScreenWindow();
    Container contentPane = frame.getContentPane();

    // make sure the content pane is transparent
    if (contentPane instanceof JComponent) {
        ((JComponent)contentPane).setOpaque(false);
    }

    // add components to the screen's content pane
    contentPane.setLayout(new FlowLayout(FlowLayout.LEFT));
    contentPane.add(playButtonSpace);
    contentPane.add(configButton);
    contentPane.add(quitButton);

    // explicitly layout components (needed on some systems)
    frame.validate();
}


/**
    Extends InputManagerTest's functionality to draw all
    Swing components.
*/
public void draw(Graphics2D g) {
    super.draw(g);
    JFrame frame = super.screen.getFullScreenWindow();

    // the layered pane contains things like popups (tooltips,
    // popup menus) and the content pane.
    frame.getLayeredPane().paintComponents(g);
}


/**
    Changes the pause/play button whenever the pause state
    changes.
*/
public void setPaused(boolean p) {
    super.setPaused(p);
    playButtonSpace.removeAll();
    if (isPaused()) {
        playButtonSpace.add(playButton);
    }
    else {
        playButtonSpace.add(pauseButton);
    }
}


/**
    Called by the AWT event dispatch thread when a button is
    pressed.
*/
public void actionPerformed(ActionEvent e) {
    Object src = e.getSource();
    if (src == quitButton) {
        // fire the "exit" gameAction
        super.exit.tap();
    }
    else if (src == configButton) {
        // doesn't do anything (for now)
        configAction.tap();
    }
    else if (src == playButton || src == pauseButton) {
        // fire the "pause" gameAction
        super.pause.tap();
    }
}


/**
    Creates a Swing JButton. The image used for the button is
    located at "../images/menu/" + name + ".png". The image is
    modified to create a "default" look (translucent) and a
    "pressed" look (moved down and to the right).
    <p>The button doesn't use Swing's look-and-feel and
    instead just uses the image.
*/
public JButton createButton(String name, String toolTip) {

    // load the image
    String imagePath = "../images/menu/" + name + ".png";
    ImageIcon iconRollover = new ImageIcon(imagePath);
    int w = iconRollover.getIconWidth();
    int h = iconRollover.getIconHeight();

    // get the cursor for this button
    Cursor cursor =
        Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);

    // make translucent default image
    Image image = screen.createCompatibleImage(w, h,
        Transparency.TRANSLUCENT);
    Graphics2D g = (Graphics2D)image.getGraphics();
    Composite alpha = AlphaComposite.getInstance(
        AlphaComposite.SRC_OVER, .5f);
    g.setComposite(alpha);
    g.drawImage(iconRollover.getImage(), 0, 0, null);
    g.dispose();
    ImageIcon iconDefault = new ImageIcon(image);

    // make a pressed iamge
    image = screen.createCompatibleImage(w, h,
        Transparency.TRANSLUCENT);
    g = (Graphics2D)image.getGraphics();
    g.drawImage(iconRollover.getImage(), 2, 2, null);
    g.dispose();
    ImageIcon iconPressed = new ImageIcon(image);

    // create the button
    JButton button = new JButton();
    button.addActionListener(this);
    button.setIgnoreRepaint(true);
    button.setFocusable(false);
    button.setToolTipText(toolTip);
    button.setBorder(null);
    button.setContentAreaFilled(false);
    button.setCursor(cursor);
    button.setIcon(iconDefault);
    button.setRolloverIcon(iconRollover);
    button.setPressedIcon(iconPressed);

    return button;
}

}

0 个答案:

没有答案