引言:Java贪吃蛇小游戏是一款非常经典的小游戏,在总论中分析了我的贪吃蛇小游戏的运行过程,以及贪吃蛇的算法分析等等,对于贪吃蛇的移动原理,随机点的出现等有了一定的了解,那么,分论三篇将从我写的代码出发,分析贪食蛇小游戏的具体组成原理和代码实现,分论一主要说明贪吃蛇小游戏的界面设计,贪吃蛇的设计,和随机点出现等,分论二来分析贪吃蛇移动方式的分析,分论三主要介绍贪吃蛇小游戏辅助类,即圆角按钮和音乐类的实现。
(一)贪吃蛇小游戏界面分析
界面是贪吃蛇小游戏运行的地方,是游戏中最基础的元素,在Java中利用swing来界面设计,有三个界面,启动界面,运行界面,和重启界面,利用窗体JFrame来设计界面,为了让窗体比较好看,需要加入图片,图片的路径需要放在程序可引用的地方。如下面的代码就是在启动界面中加入图片。
//加入背景图片
public void AddPicture() {
ImageIcon img = new ImageIcon("F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\timg.jpg");//注意引用图片的路径。
JLabel Label= new JLabel(img);
Label.setBounds(0,0,img.getIconWidth(),img.getIconHeight()); //设置大小
frame.getLayeredPane().add(Label,new Integer(Integer.MIN_VALUE)); //设置图片底层和按钮在容器中的顺序
JPanel jp =(JPanel)frame.getContentPane();
jp.setOpaque(false); //设置透明与否
}
然后在窗体中加入各种组件,如按钮,文本框和标签等,需要给按钮加入监听器事件,不同的按钮有不同的作用,如进入游戏按钮点击以后进入运行界面,并关闭启动界面。
/*设置按钮的监听器事件
* 进入按钮的监听器事件的主要功能是当点击按钮以后,程序关掉启动界面,并转入运行界面。
* 主要实现原理是定义一个新界面的类,作为运行界面,然后定义一个关掉启动界面的方法,然后在监听器事件中,
* 调用关掉界面的方法,实例化运行界面
*/
@Override
public void actionPerformed(ActionEvent e) {
new pushButtonMusic ();
// TODO 自动生成的方法存根
closeThis(); //关掉新界面的方法
try {
new Frame2 (); //实例化运行界面
} catch (InterruptedException e1) {
// TODO 自动生成的 catch 块
e1.printStackTrace();
} //创建新的窗体,以达到切换窗体的效果
}
private void closeThis() {
// TODO 自动生成的方法存根
frame.dispose();//关闭启动界面的方法。
}
开始游戏或者暂停游戏的用来控制贪吃蛇的具体状态。
//设置按钮的监听器事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
//按开始键
if(e.getSource() == startButton) {
new pushButtonMusic ();
startFlag = true;
startButton.setEnabled(false);
stopButton.setEnabled(true);
将标签,按钮等放入窗体中,来实现程序和用户的人机交互功能,具体的关于SWing知识在Java基础片中说了很多,此外,在运行程序的时候,需要重新定义窗体的大小和位置, 因为不同电脑屏幕大小不同。窗体显示的位置也一样。
(二)贪吃蛇和随机点分析
贪吃蛇小游戏中最难设计的便是贪吃蛇和随机点,那么,如何设计贪吃蛇和随机点呢?我们已经知道贪吃蛇是以数组的形式来定义的,贪吃蛇包括两个部分,设计部分和实现移动,也就是说,如何让贪吃蛇出现在窗体中,怎么样实现移动。随机点在窗体中按照随机点坐标来实现。
(1)贪吃蛇的设计
它是由什么组成的?如何实现移动?我们可以把贪吃蛇的蛇身定义为一个数组,理解成一个集合,它有固定的起始元素,代表游戏一开始时的蛇身。当贪吃蛇吃到点时,集合就添加一个元素,蛇的长度就加一,然后随机点重新出现。
那么,集合中的元素是什么呢?要理解这个问题,首先得关注蛇身移动所处的环境。在JFrame窗体中,是由X、Y轴坐标对位置进行区分。贪吃蛇的蛇身可以看做是一个一个联系紧密的点,在坐标轴上显示出来。每当朝某个方向移动时,蛇的坐标就按照某个规律变化。例如,我们操控贪吃蛇向上移动时,蛇的全体坐标的Y轴就减一;如果蛇的第一个坐标与蛇身的某个坐标重合,就代表贪吃蛇碰到自己;如果蛇的第一个坐标碰到了边界,蛇就撞墙。这就是贪吃蛇的本质。
我们来建立建立蛇身上每一个点的对象,蛇身就是由一个一个这样的对象所组成的,那么定义一个类,用来返回贪吃蛇的每个点的坐标:
/*
* 定义一个类,用来描述贪吃蛇游戏中的蛇,蛇身上的每一个点,通过建立snakeNode的对象,指定不同的X轴和Y轴的值,就能组成一个蛇身。
* 同时可以获得蛇身上的x和y点坐标,和颜色
*/
import java.awt.Color;
public class SnakeNode { //定义蛇身集合中的各个元素点,x,y。以及颜色三个蛇的关键组成
private int x;
private int y;
private Color color;
public int setX=20;
public int setY=20;
public SnakeNode() {
super();
}
public SnakeNode(int x, int y, Color color) {
super();
this.x = x;
this.y = y;
this.color = color;
}
//定义和返回x坐标
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
//定义和返回y轴的坐标
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
//定义和返回颜色
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}
其次,贪吃蛇的定义,定义一个集合,来存储蛇身上的各个点。 一个变量,用来表示随机出现的点(贪吃蛇的目标),贪吃蛇单击开始按钮以后初始移动的方向,定义一个变量Length用来表示蛇的长度。
private ArrayList<SnakeNode> snake = new ArrayList<>();//定义蛇身的数组集合
private int Direction;//定义蛇头的方向
private int Length ;//定义蛇身的长度
private SnakeNode newNode = new SnakeNode(1,1,Color.BLACK);//定义随机点
将贪吃蛇加入窗体中,需要定义贪吃蛇在窗体位置,这样的话,运行程序在运行界面就会看到贪吃蛇。
snake.add(new SnakeNode(width/2,length/2 ,Color.red));
snake.add(new SnakeNode(width/2,length/2+1 ,Color.blue));
snake.add(new SnakeNode(width/2,length/2+2 ,Color.green));
Direction = 1;//定义初始方向为向上
Length = 3;//蛇身长度为3
CreateNode1();//产生随机点
贪吃蛇的移动需要在一个范围内,运行界面中有按钮等其他组件,故而将贪吃蛇的移动范围和组件区域分开也就是贪吃蛇撞到的墙体。变量width和length。我们将蛇身的移动范围限制在X轴上0—15,Y轴上0~25,至于变量unit,稍后再进行分析
private final int length = 15;//定义活动范围
private final int width = 25;//定义活动范围
private final int unit = 45;//定义单位长度
上面分析了贪吃蛇从设计到实现的整个过程,总体来说,将贪吃蛇看成一个数组集合,需要定义一个类,来获得贪吃蛇每一节身体的坐标,也就是数组的每一个数,因为贪吃蛇分为蛇头,蛇身和蛇尾,每一个部分的设计不一样。然后定义一些变量,用来存储贪吃蛇的坐标,初始方向和长度,然后将其加入到窗体中,这样运行程序的时候就可以看到贪吃蛇了,此外,将运行界面划分为两个区域,组件区用来放各种组件,贪吃蛇运行区就是贪吃蛇运行的区域,撞到边界即撞到墙体就会死亡。
(2)随机点设计
createNode()是创造随机点的方法,随机点是定义在窗体中随机的x和y坐标决定。创造随机点有哪些要求?首先,随机点的范围肯定不能超出限制,否则游戏将无法继续;其次,随机点不能出现在蛇身上,也就是随机点的坐标不能和蛇身体上的任意坐标相同,否则就会出现BUG。
public void CreateNode1() { //创造随机点的方法
Boolean flag = true;
while(flag) {
newY1 = new Random().nextInt(15)+1; //定义随机点的纵坐标
newX1= new Random().nextInt(25)+1; //定义随机点的横坐标
for(int x = 0; x < Length; x++) { // 不能出现在蛇身上,通过循环判断是否与蛇身的点重合来产生随机点
if(snake.get(x).getX() == newX1 && snake.get(x).getY() == newY1) {
flag = true;
break;
}
flag = false;
}
for(int i = 0; i < Length; i++) { //随机点不能超出面板 ,确定面板的上下左右边界,然后判断随机点是否超出边界。
if(snake.get(i).getX()> 5&& snake.get(i).getX()<newX1 &&snake.get(i).getY() > 5
&& snake.get(i).getY()<newY1) {
flag = true;
break;
}
flag= false;
}
}
Color color = new Color(new Random().nextInt(255),new Random().nextInt(255),new Random().nextInt(255));
newNode.setColor(color);
newNode.setX(newX1);
newNode.setY(newY1);
}
通过上面的分析,我们已经能够架构出贪吃蛇的基本框架,设计好界面,定义好贪吃蛇的形状和随机点,那么, 如何显示在界面上呢?swing图形界面设计有Graphics类,可用来画出自己想要的图形, 定义图像类,画出贪吃蛇移动的运行界面,如贪吃蛇的形状,背景图片,蛇头蛇尾等 。描述蛇函数的主体形状,随机点的形状和蛇的形状 。
//定义图像类,画出贪吃蛇移动的运行界面,如贪吃蛇的形状,背景图片,蛇头蛇尾等
//描述蛇函数的主体形状,随机点的形状和蛇的形状
protected void paintComponent(Graphics g) {
super.paintComponent(g);//加背景
Image im=Toolkit.getDefaultToolkit().getImage("F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\background1.jpg");//将图片存入相应的路径
g.drawImage(im, 0, 0, this.getWidth(), this.getHeight(), this);
//画出蛇头,贪吃蛇在上下左右移动的时候蛇头的方向也不一样,故监听贪吃蛇上下左右的移动,改变蛇头的图形。
if(direction ==1||Direction==1){ //贪吃蛇向上时
Toolkit toolup = this.getToolkit();
Image headup = toolup.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\up.png");
g.drawImage(headup,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}else if(direction ==-1){//贪吃蛇向下时
Toolkit tooldown = this.getToolkit();
Image headdown = tooldown.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\down.png");
g.drawImage(headdown,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}else if(direction ==2){//贪吃蛇向左时
Toolkit toolleft = this.getToolkit();
Image headleft = toolleft.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\left.png");
g.drawImage(headleft,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}else if(direction ==-2){ //贪吃蛇向右时
Toolkit toolright = this.getToolkit();
Image headright = toolright.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\right.png");
g.drawImage(headright,snake.get(0).getX()*unit, snake.get(0).getY()*unit, unit, unit,this);
}
//画出食物的形状
Toolkit tool1 = this.getToolkit();
Image food= tool1.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\food.png");
g.drawImage(food,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this);
Toolkit tool2 = this.getToolkit();
Image food1= tool2.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\food.png");
g.drawImage(food1,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this);
//绘制指定矩形的边框。矩形的左边和右边位于 x 和 x + width。顶边和底边位于 y 和 y + height。使用图形上下文的当前颜色绘制该矩形。
g.drawRect(40, 30, 1350, 810 );
for(int x = 1; x < Length-1; x++) { //利用循环,来绘制蛇身的形状
g.setColor(snake.get(x).getColor());
g.fillOval(snake.get(x).getX()*unit, snake.get(x).getY()*unit, unit, unit); //给蛇的每一个节点画椭圆
}
for(int x = Length-1; x < Length; x++) { // 来绘制蛇身的形状
Toolkit toolright = this.getToolkit();
Image headright = toolright.getImage( "F:\\MYJAVA\\Myprogram\\Snakeexample\\src\\image\\body.png");
g.drawImage(headright,snake.get(x).getX()*unit, snake.get(x).getY()*unit, unit,unit,this);//利用循环,来绘制蛇的形状
}
}