窗体主类:Yard.java
package com.weibo.r4p0.snack;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JOptionPane;
public class Yard extends Frame {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final int ROWS = 20;
public static final int COLUMNS = 20;
public static final int CELL_WEIGHT = 20;
public boolean flag = true;
public boolean pause = true;
private Runnable refreshRunnable = new YardRunnable();
private Canvas canvas = new YardCanvas();
private Snake snake = null;
private Egg egg = null;
public static void main(String[] args) {
new Yard().launch();
}
/**
* 启动窗口
*/
private void launch() {
this.setTitle("My Snake");
// 添加键盘监听
this.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
keyPress(e);
}
});
this.setResizable(false);
this.setLayout(new BorderLayout());
// 新建画布对象,用来控制实际尺寸
MenuBar bar = new MenuBar();
Menu menu = new Menu("Help");
MenuItem helpItem = new MenuItem("How to play");
helpItem.setActionCommand("help");
menu.add(helpItem);
MenuItem aboutItem = new MenuItem("About Snake");
aboutItem.setActionCommand("about");
menu.add(aboutItem);
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
actionPress(e);
}
};
aboutItem.addActionListener(actionListener);
helpItem.addActionListener(actionListener);
bar.add(menu);
this.setMenuBar(bar);
canvas = new YardCanvas();
this.add(canvas);
// 自动适配窗口大小
this.pack();
// 居中计算
int width = this.getWidth();
int height = this.getHeight();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screenSize.width - width) / 2;
int y = (screenSize.height - height) / 2;
this.setLocation(x, y);
// 添加关闭窗口监听
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
System.exit(0);
}
});
// 显示窗口
this.setVisible(true);
restart();
pause = true;
}
/**
* 键盘事件处理
*/
private void keyPress(KeyEvent e) {
Dir head = snake.head.dir;
Dir change = null;
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
if (head != Dir.DOWN) {
change = Dir.UP;
} else {
return;
}
break;
case KeyEvent.VK_DOWN:
if (head != Dir.UP) {
change = Dir.DOWN;
} else {
return;
}
break;
case KeyEvent.VK_LEFT:
if (head != Dir.RIGHT) {
change = Dir.LEFT;
} else {
return;
}
break;
case KeyEvent.VK_RIGHT:
if (head != Dir.LEFT) {
change = Dir.RIGHT;
} else {
return;
}
break;
case KeyEvent.VK_F2:
this.restart();
return;
case KeyEvent.VK_SPACE:
pause = !pause;
return;
default:
return;
}
if (change == head && !pause) {
} else {
snake.head.dir = change;
}
snake.move();
snake.eat(egg);
}
/**
* 重新开始游戏
*/
private void restart() {
snake = new Snake(this);
egg = new Egg(snake);
if (!flag || pause) {
pause = false;
flag = true;
new Thread(refreshRunnable).start();
}
}
/**
* 停止游戏
*/
public void stop() {
flag = false;
while (!flag) {
int result = JOptionPane.showConfirmDialog(canvas, "Restart",
"Game Over", JOptionPane.OK_CANCEL_OPTION);
if (result == 0) {
restart();
} else {
int exit = JOptionPane.showConfirmDialog(canvas, "Exit",
"Exit", JOptionPane.OK_CANCEL_OPTION);
if (exit == 0) {
System.exit(0);
}
}
}
}
/**
* 处理ActionListener的事件
*
@param e
*/
private void actionPress(ActionEvent e) {
MenuItem temp = (MenuItem) e.getSource();
String message = null, title = null;
if (temp.getActionCommand().equals("about")) {
message = "Author : Rain Yuan";
title = "About";
} else if (temp.getActionCommand().equals("help")) {
message = "Press direction key to move the snake\nPress F2 to restart\nPress spacebar to pause";
title = "Help";
}
JOptionPane.showMessageDialog(null, message, title,
JOptionPane.INFORMATION_MESSAGE);
}
/**
* 创建自定义画布类
*/
private class YardCanvas extends Canvas {
private static final long serialVersionUID = 1L;
private int width = COLUMNS * CELL_WEIGHT;;
private int height = ROWS * CELL_WEIGHT;;
private Image iBuffer;
private Graphics gBuffer;
/**
* 初始化画布
*/
public YardCanvas() {
this.setSize(width, height);
this.setBackground(Color.LIGHT_GRAY);
}
/**
* 绘制画布
*/
public void paint(Graphics g) {
Color c = g.getColor();
// 绘制网格
g.setColor(Color.BLACK);
for (int i = 1; i < ROWS; i++) {
g.drawLine(0, CELL_WEIGHT * i, width, CELL_WEIGHT * i);
}
for (int i = 1; i < COLUMNS; i++) {
g.drawLine(CELL_WEIGHT * i, 0, CELL_WEIGHT * i, height);
}
// 绘制蛇
snake.draw(g);
egg.draw(g);
snake.eat(egg);
g.setColor(c);
}
/**
* 用update方法实现图形双缓冲
*/
public void update(Graphics g) {
if (iBuffer == null) {
iBuffer = createImage(this.getWidth(), this.getHeight());
gBuffer = iBuffer.getGraphics();
}
gBuffer.setColor(getBackground());
gBuffer.fillRect(0, 0, this.getWidth(), this.getHeight());
paint(gBuffer);
g.drawImage(iBuffer, 0, 0, this);
}
}
/**
* 创建刷信用线程类
*/
private class YardRunnable implements Runnable {
private int updateFre = 1000 / 30;
public void run() {
while (flag) {
if (!pause) {
canvas.repaint();
}
try {
Thread.sleep(updateFre);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}