这是一篇关于JAVA的贪吃蛇游戏,源代码的部分在下面正文中介绍,图片和音频的部分都放在百度云盘,需要的自行下载。
开发环境
开发工具:eclipse2021-12
JDK版本:JDK15.0.1
一、下载方法
百度云盘
链接:https://pan.baidu.com/s/1P9bwYgXkoRVaKdOOuWvUng
提取码:fcfj
编码格式:GBK
二、运行效果展示
运行代码以后,进入登录页面,点击“进入游戏”。
进入游戏的画面。此时小蛇还没有移动。
游戏运行时的画面
游戏运行时:
点击屏幕上方区域,小蛇转向上方
点击屏幕下方区域,小蛇转向下方
点击屏幕左方区域,小蛇转向左方
点击屏幕右方区域,小蛇转向右方
三、项目结构以及主程序入口
1.项目结构
2.主程序入口
入口程序在Start.java类中。
四、代码部分
1.代码如下
代码如下(示例):
Start.java类
package snakeGame;
/* Test类的主要任务是设计程序运行后的界面,包括 程序启动的界面和游戏运行界面。
* 程序启动的界面包括背景图片和进入运行界面的Button,点击按钮之后程序关闭启动界面进入到运行界面,
* 运行界面设置在SnakeGame类中,Test类大体设置了运行界面的大小可见与否等。
*/
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Start extends JFrame implements ActionListener {
static JFrame frame = new JFrame( );
public static void main(String[] args) {
System.out.print("main");
new Start();
}
public Start(){ //设置启动界面
System.out.print("构造函数star");
frame.setUndecorated(true); //用于取消边框背景
frame.setLayout (null);
frame.setSize(1600,900);
frame.setLocation(300, 100);
frame.setLocationRelativeTo (null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
AddButton();
AddPicture();
}
//定义进入游戏按钮
public void AddButton() {
RButton enterButton =new RButton("进入游戏");
enterButton.setFont(new Font("华文行楷", Font.BOLD, 35));
enterButton.setForeground(Color.red);
enterButton.setBounds (700, 600 , 200, 100);
enterButton.setBackground(Color.white);
frame.add(enterButton);
enterButton.addActionListener(this);
//定义按键
}
//加入背景图片
public void AddPicture() {
ImageIcon img = new ImageIcon("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();
}
/*
* 游戏运行界面,实例化SnakeGame类,并加入到运行界面中
*/
class Frame2 extends JFrame {
JFrame frame1 = new JFrame(); //游戏图形界面
public Frame2() throws InterruptedException{
frame1.setUndecorated(true);
frame1.setBounds(200,70,1600,900);
// frame1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame1.setVisible(true);
SnakeGame sn = new SnakeGame();
frame1.add(sn);
sn.requestFocus();//布局的中间
}
}
}
SnakeNode.java类
package snakeGame;
/*
* 定义一个类,用来描述贪吃蛇游戏中的蛇,蛇身上的每一个点,通过建立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;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
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;
}
}
SnakeGame.java类
package snakeGame;
/*
* SnakeGame类来设计贪吃蛇小游戏的运行界面,运行界面是贪吃蛇游戏的主体部分, 界面主要包括两个方面的内容,
* 一方面是运行界面的内容,贪吃蛇长度显示,游戏说明,速度控制,游戏开始,暂停退出等按钮。
* 另一方面,主要包括贪吃蛇的形状和移动,贪吃蛇移动区域,随机点的定义
* 运行界面的过程是这样的:在开始姐爱你点击进入游戏按钮以后,程序运行到运行界面,开始播放背景音乐。
* 点击游戏说明按钮,弹出一个对话框,说明游戏运行的操作过程。点击开始按钮以后,
* 贪吃蛇开始向上移动,鼠标在向上区域点击,贪吃蛇向上,向左区域点击,贪吃蛇向左,依次赖推。
* 当贪吃蛇碰到草莓时,吃掉它,蛇身变长,并有背景音乐显示,长度显示加一,
* 点击暂停按钮游戏暂停,点击退出按钮后,退出游戏。
* 当贪吃蛇撞到自己或者墙体的时候,贪吃蛇会死亡,然后弹出一个界面,重启界面,用来决定游戏继续进行或者退出游戏。
* 贪吃蛇的形状和移动通过数组的形式实现,在界面中,定义一个x轴和y轴定义的坐标系,定义一个数组,数组的移动就是贪吃蛇的移动,
* 移动方式是贪吃蛇坐标的改变,可以通过鼠标控制或键盘控制来实现贪吃蛇的移动,
* 随机点产生是在坐标系中产生随机数来实现,
*/
import java.applet.AudioClip;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JApplet;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.Timer;
public class SnakeGame extends JPanel implements ActionListener {
private final int length = 15;//定义活动范围
private final int width = 25;//定义活动范围
private final int unit = 45;//定义单位长度
private final int GameLOCX=40;
private final int GameLOCY=40;
private final int GameWidth=width*unit;
private final int GameLength=length*unit;
//随机点坐标
int newY1 =0 ;
int newX1 = 0 ;
int mousex=1;
int mousey=1;
//播放背景音乐
AudioClip christmas = loadSound("src/Music/backgroundMusic.wav");
int direction = 1;//定义一个按下按钮后要去的方向
private ArrayList<SnakeNode> snake = new ArrayList<SnakeNode>();//定义蛇身的数组集合
private int Direction;//定义蛇头的方向
private int Length ;//定义蛇身的长度
private SnakeNode newNode = new SnakeNode(1,1,Color.BLACK);//定义随机点
boolean startFlag =false;
//定义按钮,速度控制,开始暂停退出按钮等
RButton SspeedButton , TspeedButton,FspeedButton,THspeedButton ,ShowButton;
RButton startButton , stopButton , quitButton ,reStartButton,closeButton;
//定义标签,长度显示,方向显示,按钮提示等
JLabel snakeScore, label1, label3,label4;
//初始速度控制
private static int Difficult_Degree=1;
//蛇的移动控制,利用线程来实现用鼠标控制,利用计时器来实现用键盘控制。
Thread tr= new Thread(new ThingsListener());
Timer time = new Timer(1000, new ThingsListener1());//定义一个定时器对象,这里我们还要创建一个ThingsListener事件
public SnakeGame() {//初始化区域
//循环播放背景音乐
christmas.loop ();
// time.start();
tr.start();
//定义按键
//在容器中添加按钮标签等的时候,需要说明布局管理为空,不然的话,加进去的按钮会按照一定的布局来实现,
this.setLayout (null);
//定义按钮
startButton = new RButton("开始游戏");
stopButton =new RButton("暂停游戏");
quitButton =new RButton("退出游戏");
FspeedButton =new RButton("速度一");
SspeedButton =new RButton("速度二");
TspeedButton=new RButton("速度三");
THspeedButton=new RButton("速度四");
ShowButton =new RButton("游戏指南");
//定义标签
snakeScore =new JLabel("3");
label1 =new JLabel("当前长度");
label3 =new JLabel("速度设置");
label4 =new JLabel( );
//设置字体
startButton.setFont(new Font("华文行楷", Font.BOLD, 35));
stopButton.setFont(new Font("华文行楷", Font.BOLD, 35));
quitButton.setFont(new Font("华文行楷", Font.BOLD, 35));
FspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
TspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
SspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
THspeedButton.setFont(new Font("华文行楷", Font.BOLD, 15));
ShowButton.setFont(new Font("华文行楷", Font.BOLD, 30));
label1.setFont(new Font("华文行楷", Font.BOLD, 35));
snakeScore.setFont(new Font("华文行楷", Font.BOLD, 50));
label3.setFont(new Font("华文行楷", Font.BOLD, 30));
label4.setFont(new Font("华文行楷", Font.BOLD, 35));
//定义按钮标签位置
startButton.setBounds (1390, 500 , 190, 90);
stopButton.setBounds (1390, 600 , 190, 90);
quitButton.setBounds (1390, 700 , 190, 90);
snakeScore.setBounds(1450, 70, 150, 90);
label1.setBounds(1390, 10, 190, 90);
ShowButton.setBounds(1390, 170, 190, 90);
label3.setBounds(1390, 270, 190, 90);
label4.setBounds(0, 0, 190, 90);
FspeedButton.setBounds (1390, 350 , 85, 60);
SspeedButton.setBounds (1500,350 , 85, 60);
TspeedButton.setBounds (1390, 420 , 85, 60);
THspeedButton.setBounds (1500, 420 , 85, 60);
THspeedButton.setBackground(Color.green);
SspeedButton.setBackground(Color.blue);
TspeedButton.setBackground(Color.red);
FspeedButton.setBackground(Color.red);
// 添加 按钮和标签,用this关键字指向当前容器
this.add(startButton);
this.add(stopButton);
this.add(quitButton);
this.add(FspeedButton);
this.add(SspeedButton);
this.add(TspeedButton);
this.add(THspeedButton);
this.add(label1);
this.add(snakeScore);
this.add( ShowButton);
this.add(label3);
this.add(label4);
// 添加三个按键的监听事件
startButton.addActionListener(this);
stopButton.addActionListener(this);
quitButton.addActionListener(this);
THspeedButton.addActionListener(this);
SspeedButton.addActionListener(this);
TspeedButton.addActionListener(this);
FspeedButton.addActionListener(this);
ShowButton.addActionListener(this);
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();//产生随机点
// CreateNode2();
/*//采用键盘控制的控制模式,利用键盘的上下左右键,来实现让·direction的变化,从而使贪吃蛇能够按照键盘的控制来实现移动
this.addKeyListener(new KeyAdapter() {//捕捉键盘的按键事件 设置监听器
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()) {
case KeyEvent.VK_UP://按下向上,返回1
direction = 1;
break;
case KeyEvent.VK_DOWN://按下向下,返回-1
direction = -1;
break;
case KeyEvent.VK_LEFT://按下相左,返回2
direction = 2;
break;
case KeyEvent.VK_RIGHT://按下向右,返回-2
direction = -2;
break;
default:
break;
}
if(direction + Direction !=0) {//不能反向运动
Direction = direction;
Move(direction);
repaint();
}
}
});
*/
//采用 鼠标控制的控制模式 通过监听鼠标在容器中的位置,点击上下左右区域,改变direction的值,即可实现贪吃蛇的移动,
this.addMouseListener(new MouseAdapter(){ //匿名内部类,鼠标事件
public void mousePressed(MouseEvent e){
int a=0;//鼠标完成点击事件
//e.getButton就会返回点鼠标的那个键,左键还是右健,3代表右键
mousex = e.getX(); //得到鼠标x坐标
mousey = e.getY(); //得到鼠标y坐标
double k=0.6; //直线斜率
double Y1=0.6*mousex;
double Y2=-0.6*mousex+810;
double X1=1.6*mousey;
double X2=-1.6*mousey+1350;
if(mousex > X1&&mousex<X2&&mousey>0&&mousey<405) { //第一象限 向上
label4.setText( "向上" );
a=1;
}
if(mousex>X2&&mousex<X1&&mousey>405&&mousey<810) { // 第二象限 向下
label4.setText( " 向下" );
a=2;
}
if(mousex>0&&mousex<675&&mousey>Y1&&mousey<Y2) { //第三象限 向左
label4.setText( " 向左" );
a=3;
}
if(mousex>675&&mousex<1350&&mousey>Y2&&mousey<Y1) { //第四象限 向右
label4.setText( " 向右" );
a=4;
}
switch( a) {
case 1://按下向上,返回1
direction = 1;
break;
case 2://按下向下,返回-1
direction = -1;
break;
case 3://按下相左,返回2
direction = 2;
break;
case 4://按下向右,返回-2
direction = -2;
break;
default:
break;
}
if(direction + Direction !=0) {//不能反向运动
Direction = direction;
Move(direction);
repaint();
}
}
});
}
/*定义蛇移动的方法
* 贪吃蛇的移动方法主要包括方向控制,碰到随机点,碰到自己,碰到边界以及设计贪吃蛇从前向后的移动
*
*/
public void Move(int direction) {
int FirstX = snake.get(0).getX(); //获取蛇第一个点的横坐标
int FirstY = snake.get(0).getY(); //获取蛇第一个点的纵坐标
if(!startFlag)
return ;
//方向控制
switch(direction) {
case 1:
FirstY--;
break;
case -1:
FirstY++;
break;
case 2:
FirstX--;
break;
case -2:
FirstX++;
break;
default:
break;
}
//当碰到随机点时
if(FirstX == newNode.getX()&&FirstY == newNode.getY()) {
new eatFoodMusic();
getNode();
return;
}
//当碰到蛇身自己时
for(int x = 0; x < Length; x++) {
if((FirstX==snake.get(x).getX())&&(FirstY == snake.get(x).getY())) {
startFlag=false;
new DeadMusic();
new Restart();
christmas.stop ();
}
}
//当贪吃蛇撞到边界
if(FirstX < 1 || FirstX >29 || FirstY < 1 || FirstY >18) {
startFlag=false;
new DeadMusic();
new Restart();
christmas.stop ();
// new Test();
}
//定义循环,使得贪吃蛇从前向后移动
for(int x = Length - 1; x > 0; x--) {
snake.get(x).setX(snake.get(x-1).getX());
snake.get(x).setY(snake.get(x-1).getY());
}
snake.get(0).setX(FirstX);
snake.get(0).setY(FirstY);
repaint();
}
//获取随机点
public void getNode() {
snake.add(new SnakeNode());
Length++;
for(int x = Length-1; x >0; x--) {
snake.get(x).setX(snake.get(x-1).getX());
snake.get(x).setY(snake.get(x-1).getY());
snake.get(x).setColor(snake.get(x-1).getColor());
}
snakeScore.setText( ""+( Length )); //定义蛇的长度
snake.get(0).setX(newNode.getX());
snake.get(0).setY(newNode.getY());
snake.get(0).setColor(newNode.getColor());
CreateNode1();//产生随机点
// CreateNode2();
repaint();
//当长度超过10的时候,产生鼓掌声
if(Length==10) {
new applauseMusic();
}
}
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);
}
/*
* 这里是自己新建一个事件处理,每隔Timer的时间间隔,就开始移动Directon的位置,
* 由因为Direction的位置是构造方法中定义好的,所以就会自动地移动方向。而每当玩家使用键盘时,Direction的值变化,之后每次自动移动的方向也随之变化。
*
*
*/
//定义内部类,贪吃蛇不断移动
public class ThingsListener1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
Move(direction);
}
}//
public AudioClip loadSound ( String filename )
{
URL url = null;
try
{
url = new URL ("file:" + filename);
}
catch (MalformedURLException e)
{}
return JApplet.newAudioClip (url);
}
/*
* 当startflag为真的时候,贪吃蛇在线程时间的脉冲下继续移动,这个过程包含在if语句块中,当程序启动时,每隔1.2s就有一个响应,
*上一个方法采用Timer, Timer的构造方法是Timer(int delay, ActionListner listener)通俗的说就是创建一个每 delay秒触发一次动作的计时器,
* 每隔特定的时间就会触发特定的事件。可以使用start方法启动计时器。
* 优点在于形式简单,缺点在于当采用速度控制的时候不易控制,而同样作为时间触发作用的线程控制可以实现这个目的,即通过控制时间来控制贪吃蛇的移动速度
* 之所以之前的设计有错误,在于while后面没有用if进行startflag的检验,即startflag只有在真的条件下才可以移动,时间脉冲触发下才可以移动。
*
*
*/
//定义线程类,使得贪吃蛇能够在线程的控制下不断移动
class ThingsListener implements Runnable {
@Override
public void run() {
// TODO 自动生成的方法存根
while( true) {
if(startFlag) {
Move(Direction);
repaint();
}
try {
Thread.sleep(1200/Difficult_Degree);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}//设置一个监听器事件,用来控制蛇的不断移动
}
//定义图像类,画出贪吃蛇移动的运行界面,如贪吃蛇的形状,背景图片,蛇头蛇尾等
//描述蛇函数的主体形状,随机点的形状和蛇的形状
protected void paintComponent(Graphics g) {
super.paintComponent(g);//加背景
Image im=Toolkit.getDefaultToolkit().getImage("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( "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( "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( "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( "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( "src/image/food.png");
g.drawImage(food,newNode.getX()*unit, newNode.getY()*unit, unit, unit,this);
Toolkit tool2 = this.getToolkit();
Image food1= tool2.getImage( "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( "src/image/body.png");
g.drawImage(headright,snake.get(x).getX()*unit, snake.get(x).getY()*unit, unit,unit,this);//利用循环,来绘制蛇的形状
}
}
//设置按钮的监听器事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
//按开始键
if(e.getSource() == startButton) {
new pushButtonMusic ();
startFlag = true;
startButton.setEnabled(false);
stopButton.setEnabled(true);
}//按暂停键
if(e.getSource() == stopButton) {
new pushButtonMusic ();
startFlag = false;
startButton.setEnabled(true);
stopButton.setEnabled(false);
}
// 退出程序
if(e.getSource() == quitButton) {
System.exit(0);
}//按游戏指南建
if(e.getSource() == ShowButton) {
new pushButtonMusic ();
JDialog frame = new JDialog();//构造一个新的JFrame,作为新窗口。
frame.setBounds( 600,300,815,515 );
JTextArea Myarea=new JTextArea(3,10);
Myarea.setText("嗨,你好,欢迎体验贪吃蛇小游戏!\n "
+"这个小游戏点击开始按钮后贪吃蛇开始移动,你身体的前后左右移动\n"+"会使贪吃蛇也前后左右移动。\n"
+ "你的任务是通过控制蛇的移动来吃掉小草莓,这样贪吃蛇就长大了。\n"
+"点击暂停游戏按钮可以使得贪吃蛇停止移动,"
+"点击退出游戏按钮自然游\n"+"戏就结束啦!\n"
+ "点击速度一,速度二等按钮就可以控制贪吃蛇的移动速度,以提高\n"+"康复效率!\n"
+"此游戏素材部分来源于网络,如果有侵犯到您的利益 \n"+"请立刻联系我们,任何单位或个人不准用于商业用途。");
frame.setLayout(null);
Myarea.setBounds( 10,10,815,350);
Myarea.setFont(new Font("华文行楷",Font.BOLD,25));
frame.add(Myarea);
frame.setModalityType(JDialog.ModalityType.APPLICATION_MODAL); // 设置模式类型。
frame.setVisible(true);
}//按速度一键
if(e.getSource() == FspeedButton) {
new speedButtonMusic ();
Difficult_Degree= 2;
}//按速度二键
if(e.getSource() == SspeedButton) {
new speedButtonMusic ();
Difficult_Degree= 3;
}//按速度三键
if(e.getSource() == TspeedButton) {
new speedButtonMusic ();
Difficult_Degree= 4;
}//按速度四键
if(e.getSource() == THspeedButton) {
new speedButtonMusic ();
Difficult_Degree= 5;
}
this.requestFocus();
}
}
Restart.java类
package snakeGame;
/*
* ReStart类的功能和start相类似,设计程序运行后的界面,包括程序重启界面和游戏运行界面。运行界面和start类运行的一样,
* 重启界面包括包括两个按钮和一个背景图片,点击重启游戏按钮游戏进入运行界面,点击退出按钮后结束游戏。
*/
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
class Restart extends JFrame implements ActionListener{
public static void main(String [] args) {
new Restart();
}
JFrame frame2=new JFrame();
JButton reStartButton=new JButton("重新开始");
JButton closeButton =new JButton("结束游戏");
//定义界面按钮等内容。
public Restart() {
frame2.setUndecorated(true); //用于取消边框背景
frame2.setSize(800,480);
frame2.setLocation(600,300);
//frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.setVisible(true);
frame2.setLayout(null);
//设置按钮颜色
Color color2=new Color(124,252,0);
reStartButton.setBackground(color2);
Color color1 = new Color(124,252,0 );
closeButton.setBackground(color1 );
//设置按钮大小和位置
reStartButton.setBounds(140, 364, 120, 110);
closeButton.setBounds(280,270,120,110);
//设置按钮颜色和字体
reStartButton.setFont(new Font("华文行楷", Font.BOLD, 20));
closeButton.setFont(new Font("华文行楷", Font.BOLD, 20));
//在容器中加入按钮
frame2.add(reStartButton);
frame2.add(closeButton);
addPicture();
reStartButton.addActionListener(this);
closeButton.addActionListener(this);
}
//设置背景图片
public void addPicture() { //游戏结束时弹出的界面的背景
ImageIcon deadPicture = new ImageIcon("src/image/restartPicture.jpg");
JLabel pictureLabel =new JLabel(deadPicture);
pictureLabel.setBounds(0, 0,deadPicture.getIconWidth(), deadPicture.getIconHeight());
frame2.getLayeredPane().add(pictureLabel,new Integer(Integer.MIN_VALUE));
JPanel jp1=(JPanel)frame2.getContentPane();
jp1.setOpaque(false);
}
//按钮加入监听器事件
@Override
public void actionPerformed(ActionEvent e) {
// TODO 自动生成的方法存根
if(e.getSource()==reStartButton) {
closeThis();
new Frame3();
}
if(e.getSource()==closeButton) {
System.exit(0);
}
}
private void closeThis() {
// TODO 自动生成的方法存根
frame2.dispose();
}
// 游戏运行界面,实例化SnakeGame类,并加入到运行界面中
class Frame3 extends JFrame {
JFrame frame1 = new JFrame(); //游戏图形界面
public Frame3(){
frame1.setUndecorated(true); //用于取消边框背景
frame1.setBounds(200,70,1600,900);
/// frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setVisible(true);
SnakeGame sn =new SnakeGame();
frame1.add(sn);
sn.requestFocus();//布局的中间
}
}
}
RButton.java类
package snakeGame;
/*在Java swing中的button无法设置圆角按钮,为了一定程度上完善游戏界面,故而设置了圆角按钮。
* 定义圆角按钮;
*/
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JButton;
public class RButton extends JButton {
private static final long serialVersionUID = 39082560987930759L;
public static final Color BUTTON_COLOR1 = new Color(205, 255, 205); //设置按钮的第一种颜色
public static final Color BUTTON_COLOR2 = new Color(51, 55, 47); //设置按钮的第二种颜色
// public static final Color BUTTON_COLOR1 = new Color(125, 161, 237);
// public static final Color BUTTON_COLOR2 = new Color(91, 118, 173);
public static final Color BUTTON_FOREGROUND_COLOR = Color.WHITE;
private boolean hover;
public RButton(String name) {
this.setText(name); //添加名字
setFont(new Font("system", Font.PLAIN, 12)); //设置字体
setBorderPainted(false); //设置边界可见否
setForeground(BUTTON_COLOR2); //设置前景色
setFocusPainted(false);
setContentAreaFilled(false);
//定义鼠标事件,即当鼠标进入到按钮界面时,按钮颜色会发生变化,鼠标离开按钮区域时也会发生变化
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
setForeground(BUTTON_FOREGROUND_COLOR);
hover = true;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
setForeground(BUTTON_COLOR2);
hover = false;
repaint();
}
});
}
//设置按钮圆角
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
int h = getHeight();
int w = getWidth();
float tran = 1F;
if (!hover) {
tran = 0.3F;
}
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint p1;
GradientPaint p2;
//当点击按钮之后,按钮颜色和字体会发生变化
if (getModel().isPressed()) {
p1 = new GradientPaint(0, 0, new Color(0, 0, 0), 0, h - 1,
new Color(100, 100, 100));
p2 = new GradientPaint(0, 1, new Color(0, 0, 0, 50), 0, h - 3,
new Color(255, 255, 255, 100));
} else {
p1 = new GradientPaint(0, 0, new Color(100, 100, 100), 0, h - 1,
new Color(0, 0, 0));
p2 = new GradientPaint(0, 1, new Color(255, 255, 255, 100), 0,
h - 3, new Color(0, 0, 0, 50));
}
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
tran));
RoundRectangle2D.Float r2d = new RoundRectangle2D.Float(0, 0, w - 1,
h - 1, 20, 20);
Shape clip = g2d.getClip();
g2d.clip(r2d);
GradientPaint gp = new GradientPaint(0.0F, 0.0F, BUTTON_COLOR1, 0.0F,
h, BUTTON_COLOR2, true);
g2d.setPaint(gp);
g2d.fillRect(0, 0, w, h);
g2d.setClip(clip);
g2d.setPaint(p1);
g2d.drawRoundRect(0, 0, w - 1, h - 1, 20, 20);
g2d.setPaint(p2);
g2d.drawRoundRect(1, 1, w - 3, h - 3, 18, 18);
g2d.dispose();
super.paintComponent(g);
}
}
applauseMusic.java类
package snakeGame;
/*
* 设置程序运行背景音乐,包括 点击按钮音乐,鼓励音,撞墙音乐,吃食物音乐等等,
* 音乐类的设置可以在snakeGame类中实现,由于音乐太多,故而集中到一起,可以在需要添加的地方实例化即可。
*/
import java.applet.AudioClip;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.JApplet;
//添加鼓励音
class applauseMusic
{
AudioClip christmas = loadSound("src/music/applauseMusic.wav");
public applauseMusic ()
{
christmas.play ();
}
public AudioClip loadSound ( String filename )
{
URL url = null;
try
{
url = new URL ("file:" + filename);
}
catch (MalformedURLException e)
{}
return JApplet.newAudioClip (url);
}
}
//添加吃到食物的音乐
class eatFoodMusic
{
AudioClip christmas = loadSound("src/music/eatFoodMusic.wav");
public eatFoodMusic ()
{
christmas.play ();
}
public AudioClip loadSound ( String filename )
{
URL url = null;
try
{
url = new URL ("file:" + filename);
}
catch (MalformedURLException e)
{}
return JApplet.newAudioClip (url);
}
}
//添加撞墙音乐
class DeadMusic
{
AudioClip christmas = loadSound("src/music/DeadMusic.wav");
public DeadMusic ()
{
christmas.play ();
}
public AudioClip loadSound ( String filename )
{
URL url = null;
try
{
url = new URL ("file:" + filename);
}
catch (MalformedURLException e)
{}
return JApplet.newAudioClip (url);
}
}
//添加 按键音乐
class pushButtonMusic
{
AudioClip christmas = loadSound("src/music/pushButtonMusic.wav");
public pushButtonMusic ()
{
christmas.play ();
}
public AudioClip loadSound ( String filename )
{
URL url = null;
try
{
url = new URL ("file:" + filename);
}
catch (MalformedURLException e)
{}
return JApplet.newAudioClip (url);
}
}
// 添加速度控制音乐
class speedButtonMusic{
AudioClip christmas = loadSound("src/music/encouragMusic.wav");
public speedButtonMusic()
{
christmas.play ();
}
public AudioClip loadSound ( String filename )
{
URL url = null;
try
{
url = new URL ("file:" + filename);
}
catch (MalformedURLException e)
{}
return JApplet.newAudioClip (url);
}
}
总结
游戏有声音,就是音频有点吓人,其他都还好,如果不喜欢,可以换成自己喜欢的音频。
附上百度云盘下载连接地址:
链接:https://pan.baidu.com/s/1P9bwYgXkoRVaKdOOuWvUng
提取码:fcfj
欢迎交流,共同进步。