新人任务二:基于Java Swing 的吃食蛇小游戏
自己设计的蛇和食物,有些丑,请勿见怪,哈哈!
前言
这是我的第二个小项目,原本想继续用VS的MFC实现的,奈何自己太菜,MFC不太会用,于是“转移战场”改用Java Swing去做了!
前期准备
我用的是Eclipse ,为了使用Swing,使游戏最终可以窗口的形式运行,在开始做小项目之前,需要去Elipse Marketplace 安装一下 WindowBuilder!
1、Java Swing的基本介绍
Swing 是一个为Java设计的GUI工具包,是JAVA基础类的一部分。
Swing包括了图形用户界面(GUI)器件如:文本框,按钮,分隔窗格和表。
转载JavaSwing的一些介绍
2、需求分析:
实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子,上下左右控制“蛇”的移动,吃到“豆子”以后“蛇”的身体加长一点,得分增加,“蛇”碰到边界或,蛇头与蛇身相撞,蛇死亡,游戏结束。为游戏设计初始欢迎界面,游戏界面,游戏结束界面。
设计思路
1.窗口设计
(1)设计思路:
利用Java swing 中的JFrame 窗口创建一个Snake Class,可以运行后弹出的窗口,之后创建一个SnakePenal Class ,并添加到窗口上画布,我们后面所有的操作在SnakePenal(画布)上进行
(2)参数设置:
frame.setBounds(200, 150, 600, 510);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SnakePanel panel = new SnakePanel();
frame.add(panel);
frame.setVisible(true);
}
}
2.蛇模块
(1)设计蛇的身体、头、标题以及整个活动范围等元素并导入Snake Class所在的项目路径下
//加载图片
ImageIcon up = new ImageIcon("up.png");
ImageIcon down = new ImageIcon("down.png");
ImageIcon left = new ImageIcon("left.png");
ImageIcon right = new ImageIcon("right.png");
ImageIcon title = new ImageIcon("title.png");
ImageIcon food = new ImageIcon("food.png");
ImageIcon body = new ImageIcon("body.png");
(2)蛇的数据结构设计
//蛇的数据结构
int[] snakex = new int[400];
int[] snakey = new int[400];
int len = 3;
String direction = "R";
(3)初始化蛇
//初始化蛇
public void initSnake() {
isOver = false;
isStarted = true;
len = 3;
direction = "R";
snakex[0]=100;
snakey[0]=100;
snakex[1]=75;
snakey[1]=100;
snakex[2]=50;
snakey[2]=100;
}
3.食物模块
(1)食物的设计
(2)食物的数据结构
//食物的数据结构
Random random = new Random();
int foodx = random.nextInt(22)*25+25;
int foody = random.nextInt(16)*25+75;
(3)初始化食物
随机生成,无需初始化
具体实现
(1)画布部分
package xch.snake;
import javax.swing.JFrame;
public class Snake {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setBounds(200, 150, 600, 510);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SnakePanel panel = new SnakePanel();
frame.add(panel);
frame.setVisible(true);
}
}
...
(2)蛇部分
1)初始化蛇
//初始化蛇
public void initSnake() {
isOver = false;
isStarted = true;
len = 3;
direction = "R";
snakex[0]=100;
snakey[0]=100;
snakex[1]=75;
snakey[1]=100;
snakex[2]=50;
snakey[2]=100;
}
2)画蛇头的蛇身体
//画蛇头
if(direction.equals("R")) {
right.paintIcon(this, g, snakex[0], snakey[0]);
}
else if(direction.equals("L")) {
left.paintIcon(this, g, snakex[0], snakey[0]);
}
else if(direction.equals("U")) {
up.paintIcon(this, g, snakex[0], snakey[0]);
}
else if(direction.equals("D")) {
down.paintIcon(this, g, snakex[0], snakey[0]);
}
//画蛇的身体
for(int i=1;i<len;i++) {
body.paintIcon(this, g, snakex[i], snakey[i]);
}
3)蛇的移动判断和实现
//判断蛇的移动按键
}else if(keyCode == KeyEvent.VK_UP && !direction.equals("D")) {
direction="U";
}else if(keyCode == KeyEvent.VK_DOWN && !direction.equals("U")) {
direction="D";
}else if(keyCode == KeyEvent.VK_LEFT && !direction.equals("R")) {
direction="L";
}else if(keyCode == KeyEvent.VK_RIGHT && !direction.equals("L")) {
direction="R";
}
}
//蛇的移动
timer.start();
if(isStarted && !isOver) {
for(int i=len;i>.0;i--) {
snakex[i] = snakex[i-1];
snakey[i] = snakey[i-1];
}
if(direction.equals("R")) {
snakex[0] = snakex[0] + 25;
if(snakex[0] >550) {
snakex[0] = 25;
}
}else if(direction.equals("L")) {
snakex[0] = snakex[0] - 25;
if(snakex[0] <25) {
snakex[0] = 550;
}
}else if(direction.equals("U")) {
snakey[0] = snakey[0] - 25;
if(snakey[0] <75) {
snakey[0] = 400;
}
}else if(direction.equals("D")) {
snakey[0] = snakey[0] + 25;
if(snakey[0] >400) {
snakey[0] = 75;
}
}
4)蛇吃食物
/蛇吃食物的逻辑
if(snakex[0] == foodx && snakey[0] == foody) {
len++;
foodx = random.nextInt(22)*25+25;
foody = random.nextInt(16)*25+75;
5)蛇的死亡游戏结束
//游戏结束逻辑(碰到身体)
for(int i=1;i<len;i++) {
if(snakex[0] == snakex[i] && snakey[0] == snakey[i]) {
isOver=true;
}
(3)食物部分
//画食物
food.paintIcon(this, g, foodx, foody);
(4)判断键盘输入部分
1)定义判断键盘输入部分KeyListener
public class SnakePanel extends JPanel implements KeyListener{
}
2)实现
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
//判断游戏开始按键
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_SPACE) {
if(isOver) {
initSnake();
}else
isStarted = !isStarted;
//repaint();
//判断蛇的移动按键
}else if(keyCode == KeyEvent.VK_UP && !direction.equals("D")) {
direction="U";
}else if(keyCode == KeyEvent.VK_DOWN && !direction.equals("U")) {
direction="D";
}else if(keyCode == KeyEvent.VK_LEFT && !direction.equals("R")) {
direction="L";
}else if(keyCode == KeyEvent.VK_RIGHT && !direction.equals("L")) {
direction="R";
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
(5)执行ActionListener部分
1)定义
public class SnakePanel extends JPanel implements KeyListener, ActionListener{
}
2)实现
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
//蛇的移动
timer.start();
if(isStarted && !isOver) {
for(int i=len;i>.0;i--) {
snakex[i] = snakex[i-1];
snakey[i] = snakey[i-1];
}
if(direction.equals("R")) {
snakex[0] = snakex[0] + 25;
if(snakex[0] >550) {
snakex[0] = 25;
}
}else if(direction.equals("L")) {
snakex[0] = snakex[0] - 25;
if(snakex[0] <25) {
snakex[0] = 550;
}
}else if(direction.equals("U")) {
snakey[0] = snakey[0] - 25;
if(snakey[0] <75) {
snakey[0] = 400;
}
}else if(direction.equals("D")) {
snakey[0] = snakey[0] + 25;
if(snakey[0] >400) {
snakey[0] = 75;
}
}
//蛇吃食物的逻辑
if(snakex[0] == foodx && snakey[0] == foody) {
len++;
foodx = random.nextInt(22)*25+25;
foody = random.nextInt(16)*25+75;
}
//游戏结束逻辑(碰到身体)
for(int i=1;i<len;i++) {
if(snakex[0] == snakex[i] && snakey[0] == snakey[i]) {
isOver=true;
}
}
}
repaint();
}
}
(6)游戏开始与结束
1)定义开始与结束
//游戏开始
boolean isStarted=false;
//游戏结束
boolean isOver=false;
Timer timer = new Timer(150,this);
public SnakePanel() {
this.setFocusable(true);
initSnake();
this.addKeyListener(this);
timer.start();
}
2)实现
//画游戏开始提示语
if(!isStarted) {
g.setColor(Color.WHITE);
g.setFont(new Font("arial",Font.BOLD,20));
g.drawString("Press Space to Start or Pause", 150, 250);
}
//画游戏结束提示语
if(isOver) {
g.setColor(Color.WHITE);
g.setFont(new Font("arial",Font.BOLD,20));
g.drawString("Game Over,Press Space to Restart", 150, 250);
}
总结
1、结果展示
总的来说,相对一一次写项目思路会更清晰一点,虽然说还是有很多BUG,但好在自己坚持下来了,继续努力吧,新人!