import java.awt.event.ActionListener; import javax.swing.*; import
java.awt.image.*; import java.awt.event.*; import java.awt.*;
public class GamePanel extends JPanel implements Runnable,
ImageManager {
private static final int PWIDTH = 500;
private static final int PHEIGHT = 360;
private static final int RUNNING_ORGANISER = 16;
private static final int MAX_FRAME_SKIPS = 5;
private static final String TILES_DEC = "TilesDec.txt";
private static final String IMAGE_DEC = "ImageDec.txt";
private static final int MAX_HITS = 10;
private Thread animator;
private volatile boolean running = false;
private volatile boolean isPaused = false;
private long period;
private Mario marioTop;
private MarioSprite mario;
private FireBallSprite fireball;
private FrameLayers frameMan;
private TileManager tilesMan;
private long gameStartTime;
private int timeSpentInGame;
private volatile boolean gameOver = false;
private int score = 0;
private Font msgsFont;
private FontMetrics metrics;
private Graphics boardGraphics;
private Image boardImage = null;
private boolean showTitleScreen;
private BufferedImage storyIm;
public GamePanel(Mario mm, long period) {
marioTop = mm;
this.period = period;
setDoubleBuffered(false);
setBackground(Color.white);
setPreferredSize( new Dimension(PWIDTH, PHEIGHT));
setFocusable(true);
requestFocus();
addKeyListener (new KeyAdapter() {
public void keyPressed(KeyEvent e)
{ processKeyPress(e); }
public void keyReleased(KeyEvent e)
{ processKeyRelease(e); }
});
LoadImage ldImage = new LoadImage(IMAGE_DEC);
tilesMan = new TileManager(PWIDTH, PHEIGHT, TILES_DEC, ldImage);
int brickMoveSize = tilesMan.getMoveSize();
frameMan = new FrameLayers(PWIDTH, PHEIGHT, brickMoveSize, ldImage);
knight = new MarioSprite(PWIDTH, PHEIGHT, brickMoveSize, tilesMan, ldImage, (int)(period/1000000L) ); // in ms
fireball = new FireBallSprite(PWIDTH, PHEIGHT, ldImage, this, mario);
storyIm = ldImage.getImage("title");
showTitleScreen = true;
isPaused = true;
msgsFont = new Font("Monospaced", Font.BOLD, 24);
metrics = this.getFontMetrics(msgsFont);
}
private void processKeyPress(KeyEvent e) {
int keyCode = e.getKeyCode();
if ((keyCode == KeyEvent.VK_ESCAPE) || (keyCode == KeyEvent.VK_Q) || (keyCode == KeyEvent.VK_END))
running = false;
if (keyCode == KeyEvent.VK_O) {
if (showTitleScreen) {
showTitleScreen = false;
isPaused = false;
}
}
if (!isPaused && !gameOver) {
if (keyCode == KeyEvent.VK_LEFT) {
mario.moveLeft();
tilesMan.moveRight();
frameMan.moveRight();
}
else if (keyCode == KeyEvent.VK_RIGHT) {
knight.moveRight();
tilesMan.moveLeft();
frameMan.moveLeft();
} else if (keyCode == KeyEvent.VK_UP) {
knight.jump();
}
}
}
private void processKeyRelease(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_LEFT) {
mario.stayStill();
tilesMan.stayStill();
frameMan.stayStill();
} else if (keyCode == KeyEvent.VK_RIGHT) {
mario.stayStill();
tilesMan.stayStill();
frameMan.stayStill();
} else if (keyCode == KeyEvent.VK_UP && keyCode == KeyEvent.VK_RIGHT) {
mario.stayStill();
tilesMan.moveLeft();
frameMan.moveLeft();
} else if (keyCode == KeyEvent.VK_UP && keyCode == KeyEvent.VK_LEFT) {
mario.stayStill();
tilesMan.moveRight();
frameMan.moveRight();
}
}
public void addNotify() {
super.addNotify();
startGame();
}
private void startGame() {
if (animator == null || !running) {
animator = new Thread(this);
animator.start();
}
}
// ------------- game life cycle methods ------------
public void resumeGame() {
if (!showTitleScreen)
isPaused = false;
}
public void pauseGame() {
isPaused = true;
}
public void stopGame() {
running = false;
}
// ----------------------------------------------
public void run() {
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
gameStartTime = System.nanoTime();
beforeTime = gameStartTime;
running = true;
while(running) {
gameUpdate();
gameRender();
paintScreen();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime/1000000L);
} catch(InterruptedException ex){
}
overSleepTime = (System.nanoTime() - afterTime) - sleepTime;
}
else {
excess -= sleepTime;
overSleepTime = 0L;
if (++noDelays >= RUNNING_ORGANISER) {
Thread.yield();
noDelays = 0;
}
}
beforeTime = System.nanoTime();
int skips = 0;
while((excess > period) && (skips < MAX_FRAME_SKIPS)) {
excess -= period;
gameUpdate();
skips++;
}
}
System.exit(0);
}
private void gameUpdate() {
if (!isPaused && !gameOver) {
if (knight.willHitTile()) {
knight.stayStill();
tilesMan.stayStill();
frameMan.stayStill();
}
frameMan.update();
tilesMan.update();
knight.updateSprite();
fireball.updateSprite();
if (showExplosion)
explosionPlayer.updateTick();
}
}
private void gameRender() {
if (boardImage == null){
boardImage = createImage(PWIDTH, PHEIGHT);
if (boardImage == null) {
System.out.println("boardImage is null");
return;
}
else
boardGraphics = boardImage.getGraphics();
}
boardGraphics.setColor(Color.white);
boardGraphics.fillRect(0, 0, PWIDTH, PHEIGHT);
frameMan.display(boardGraphics);
tilesMan.display(boardGraphics);
knight.drawSprite(boardGraphics);
fireball.drawSprite(boardGraphics);
if (showExplosion)
boardGraphics.drawImage(explosionPlayer.getCurrentImage(), > xExpl,
yExpl, null);
if (gameOver)
gameOverMessage(boardGraphics);
if (showTitleScreen) // draw the help at the very front (if switched on)
boardGraphics.drawImage(storyIm, (PWIDTH-storyIm.getWidth())/2, (PHEIGHT-storyIm.getHeight())/2, null);
}
private void paintScreen() {
Graphics g;
try {
g = this.getGraphics();
if ((g != null) && (boardImage != null))
g.drawImage(boardImage, 0, 0, null);
Toolkit.getDefaultToolkit().sync();
g.dispose();
} catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
}
}
我正在尝试制作类似于Mario的游戏,目前,当我加载游戏时,显示在屏幕上的第一件事是故事情节“ storyIm”。我试图制作一个单独的菜单类,其中的按钮可以确保导航更容易,并且尝试使其制作成这样,以便游戏在加载游戏时将用户直接带到菜单上,但是我的程序不会显示菜单,并且会而是加载故事情节。
任何人对我如何实现菜单并确保其优先于游戏中所有其他任务有任何想法吗?