整体架构图
Test类
package snake;
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Snake snake = new Snake();
int zz=snake.music;
Music audioPlayWave = new Music("1rjsrl-hytdo.wav");
audioPlayWave.start();
@SuppressWarnings("unused")
int musicOpenLab = 1;
//背景音乐启动
/* Music audioPlayWave = new Music("rjsrl-hytdo.wav");
audioPlayWave.start();
@SuppressWarnings("unused")
int musicOpenLab = 1; */
//GamePanel game = new GamePanel(0,0);
// Scanner s = new Scanner (System.in);
//snake.nandu=s.nextInt();
System.out.println(zz);
snake.myJFrame();
}
}
package snake;
import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Music extends Thread
{
private String fileName;
private final int EXTERNAL_BUFFER_SIZE = 524288;
public Music(String wavFile)
{
this.fileName = wavFile;
}
@SuppressWarnings("unused")
public void run()
{
File soundFile = new File(fileName); // 播放音乐的文件名
if (!soundFile.exists())
{
System.err.println("Wave file not found:" + fileName);
return;
}
while (true)
{ // 设置循环播放
AudioInputStream audioInputStream = null; // 创建音频输入流对象
try
{
audioInputStream = AudioSystem.getAudioInputStream(soundFile); // 创建音频对象
}
catch (UnsupportedAudioFileException e1)
{
e1.printStackTrace();
return;
}
catch (IOException e1)
{
e1.printStackTrace();
return;
}
AudioFormat format = audioInputStream.getFormat(); // 音频格式
SourceDataLine auline = null; // 源数据线
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try
{
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
}
catch (LineUnavailableException e)
{
e.printStackTrace();
return;
}
catch (Exception e)
{
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN))
{
FloatControl pan = (FloatControl) auline.getControl(FloatControl.Type.PAN);
}
auline.start();
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
try
{
while (nBytesRead != -1)
{
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0)
auline.write(abData, 0, nBytesRead);
}
}
catch (IOException e)
{
e.printStackTrace();
return;
}
finally
{
auline.drain();
// auline.close();
}
}
}
}
Snake类
package snake;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import javax.sound.sampled.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.awt.Toolkit;
import java.awt.event.*;
public class Snake extends JFrame implements KeyListener, ActionListener, MouseListener
{
//图片双缓冲防闪烁
Image offScreenImage = null;
int score=1;//分数
int slong = 2;//蛇当前长度
//蛇坐标
int[] Snakex = new int[100];
int[] Snakey = new int[100];
int fx = 1;//蛇的方向 0-左 1-右 2-上 3-下
int nandu =0;//传递输入流
//难度对应
Timer timer = new Timer(160, this);//设置定时器,x毫秒一次,即蛇运动速度
Timer timer1 = new Timer(140, this);
Timer timer2 = new Timer(130, this);
Timer timer3 = new Timer(120, this);
Timer timer4 = new Timer(115, this);
//食物位置
int foodx;
int foody;
int bombx,bomby;
Random random = new Random();//随机数,随机位置生成食物
//游戏信息 -1-选择界面 0-未开始 1-开始 2-结束 3-暂停 4-通关 5-无尽模式
int started = -1;
int guan=1;//关卡
int superfoodx,superfoody;//超级食物坐标
int music=0;
int doorx=0,doory=0;
JMenuBar menubar = new JMenuBar();
//JFrame a=new JFrame();
JMenu menu1 = new JMenu("开始");
JMenuItem item1 = new JMenuItem("游玩");
JMenuItem item2 = new JMenuItem("暂停");
JMenuItem item3 = new JMenuItem("保存");
//---------------------------------------------------------------------------------------------------------------------
//窗体
public void myJFrame() {
this.add(item1);
this.add(item2);
this.add(item3);
this.add(menu1);
item1.addActionListener(new kaishi()); //注册监听器
item2.addActionListener(new zanting()); //注册监听器
item3.addActionListener(new baocun()); //注册监听器.
this.setTitle("贪吃蛇"); //标题
this.setSize(800, 600); //窗口大小
this.setResizable(false); //窗口是否可以改变大小=否
this.setDefaultCloseOperation(Snake.EXIT_ON_CLOSE); //窗口关闭方式为关闭窗口同时结束程序
int width = Toolkit.getDefaultToolkit().getScreenSize().width; //获取屏幕宽度
int height = Toolkit.getDefaultToolkit().getScreenSize().height; //获取屏幕高度
// System.out.println("宽度:"+width);//测试
// System.out.println("高度:"+height);//测试
this.setLocation((width - 800) / 2, (height - 600) / 2); //设置窗口默认位置以屏幕居中
this.setFocusable(true);
this.addKeyListener(this);
this.setVisible(true); //窗口是否显示=是
// 蛇的初识位置
Snakex[0] = 260;
Snakey[0] = 300;
Snakex[1] = 240;
Snakey[1] = 300;
// 随机食物的初识位置
foodx = random.nextInt(39);
foody = random.nextInt(22);
foodx = foodx * 20;
foody = foody * 20 + 80;
System.out.println(foodx + "," + foody);//输出每次食物坐标
}
class kaishi implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
JOptionPane.showMessageDialog(null,"开始游戏");
}
}
class zanting implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
MenuListener m=new MenuListener();
m.guan=100;
JOptionPane.showMessageDialog(null,"已暂停");
System.out.println(m.guan);
}
}
class baocun implements ActionListener
{
@Override
public void actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
JOptionPane.showMessageDialog(null,"已保存");
}
}
//---------------------------------------------------------------------------------------------------------------------
//覆写paint方法,绘制界面
public void paint(Graphics g)
{
//初始化双缓存图片
if(offScreenImage==null)
{
offScreenImage=this.createImage(800, 600);
}
//获取图片对应的graphics对象
Graphics gImage = offScreenImage.getGraphics();
// 绘制背景
gImage.setColor(new Color(187,222,214));//文字背景
gImage.fillRect(0, 0, 800, 600);
//绘制游戏区域
switch(guan)
{
case 1:gImage.setColor(new Color(250,227,217));//文字背景
gImage.fillRect(0, 80, 800, 520);break;
case 2:gImage.setColor(new Color(247,239,214));//文字背景
gImage.fillRect(0, 80, 800, 520);break;
case 3:gImage.setColor(new Color(255,240,245));//文字背景
gImage.fillRect(0, 80, 800, 520);break;
case 4:gImage.setColor(new Color(0,128,128));//文字背景
gImage.fillRect(0, 80, 800, 520);break;
case 5:gImage.setColor(new Color(255,255,255));//文字背景
gImage.fillRect(0, 80, 800, 520);break;
}
//绘制蛇
for (int i = 0; i < slong; i++)
{
gImage.setColor(new Color(255,182,185));
gImage.fillRect(Snakex[i], Snakey[i], 20, 20);
}
// 绘制食物
gImage.setColor(new Color(138,198,209));
gImage.fillOval(foodx, foody, 20, 20);
// 超级食物
gImage.setColor(new Color(194,91,86));
gImage.fillOval(superfoodx, superfoody, 20, 20);
//炸弹食物
gImage.setColor(new Color(0,0,0));
gImage.fillOval(bombx, bomby, 20, 20);
//传送门
gImage.setColor(new Color(128,0,128));
gImage.fillOval(doorx, doory, 20, 20);
if (started == 0)
{
gImage.setColor(Color.BLACK);//设置画笔颜色
gImage.setFont(new Font("微软雅黑",Font.BOLD,25)); //设置字体
gImage.drawString("按下“空格键”开始游戏", 240, 65); //绘制字符
} else if (started == 1)
{
gImage.setColor(Color.BLACK);//设置画笔颜色
gImage.setFont(new Font("微软雅黑",Font.BOLD,25)); //设置字体
gImage.drawString("分数", 320, 65); //绘制字符
gImage.drawString(String.valueOf(slong - 2), 380, 65); //绘制字符
gImage.drawString("长度", 420, 65);
gImage.drawString(String.valueOf(slong), 480, 65);
gImage.drawString("关卡", 220, 65);
gImage.drawString(String.valueOf(guan), 280, 65);
}
else if (started == 4)
{
gImage.setColor(Color.BLACK);//设置画笔颜色
gImage.setFont(new Font("微软雅黑",Font.BOLD,25)); //设置字体
gImage.drawString("游戏结束 ——", 220, 65); //绘制字符
gImage.drawString("最终分数为:", 400, 65); //绘制字符
gImage.drawString(String.valueOf(slong - 2), 550, 65); //绘制字符
//死亡归零
bombx=0;
bomby=0;
superfoodx = 0;
superfoody = 0;
slong=2;
score=1;
}
else if (started ==3)
{
gImage.setColor(Color.BLACK);//设置画笔颜色
gImage.setFont(new Font("微软雅黑",Font.BOLD,25)); //设置字体
gImage.drawString("游戏已暂停,按下“空格键”开始游戏", 180, 65); //绘制字符
//gImage.drawString("最终分数为:", 400, 65); //绘制字符
}
else if(started==2)
{
gImage.setColor(new Color(76,88,112));//设置画笔颜色
gImage.setFont(new Font("微软雅黑",Font.BOLD,25)); //设置字体
gImage.drawString("恭喜您已通关,按下“空格键”进入下一关", 150, 70); //绘制字符
if(guan==5)
{
gImage.drawString("接下来将是隐藏无尽模式,你的长度和分数都会一直持续下去", 45, 120); //绘制字符
gImage.drawString("进入紫色传送门可直接进入下一关", 200, 150);
}
}
if(started==-1)
{
gImage.setColor(new Color(255,255,255));
gImage.fillRect(0, 0, 800, 600);
gImage.setColor(new Color(0,51,153));//设置画笔颜色
gImage.setFont(new Font("微软雅黑",Font.BOLD,60));
gImage.drawString("贪吃蛇", 300, 140);
gImage.setColor(new Color(51,153,255));
gImage.setFont(new Font("微软雅黑",Font.BOLD,25)); //设置字体
gImage.drawString("关卡选择", 335, 320);
gImage.drawString("关卡1", 150, 370); //绘制字符
gImage.drawString("关卡2", 250, 370);
gImage.drawString("关卡3", 350, 370);
gImage.drawString("关卡4", 450, 370);
gImage.drawString("关卡5", 550, 370);
gImage.drawString("按下空格键开始游戏", 280, 500);
//对应选择
switch(nandu)
{
case 1:gImage.setColor(new Color(51,102,204));
gImage.fillOval(170, 390, 20, 20);break;
case 2:gImage.setColor(new Color(51,102,204));
gImage.fillOval(270, 390, 20, 20);break;
case 3:gImage.setColor(new Color(51,102,204));
gImage.fillOval(370, 390, 20, 20);break;
case 4:gImage.setColor(new Color(51,102,204));
gImage.fillOval(470, 390, 20, 20);break;
case 5:gImage.setColor(new Color(51,102,204));
gImage.fillOval(570, 390, 20, 20);break;
}
gImage.drawString("歌曲选择", 335, 200);
//gImage.drawString("歌曲1", 250, 250);
gImage.drawString("歌曲1", 350, 250);
// gImage.drawString("歌曲3", 450, 250);
//对应选择
switch(music)
{
case 1:gImage.setColor(new Color(51,102,204));
gImage.fillOval(270, 270, 20, 20);break;
case 2:gImage.setColor(new Color(51,102,204));
gImage.fillOval(370, 270, 20, 20);break;
case 3:gImage.setColor(new Color(51,102,204));
gImage.fillOval(470, 270, 20, 20);break;
}
//刷新
repaint();
}
//双缓冲结尾
g.drawImage(offScreenImage,0,0,null);
}
// 操作监听——控制蛇的不断移动
@Override
public void actionPerformed(ActionEvent e)
{
// 判断游戏是否开始
if (started == 1)
{
// 通过循环控制蛇移动
for (int i = slong - 1; i > 0; i--)
{
Snakex[i] = Snakex[i - 1];
Snakey[i] = Snakey[i - 1];
}
// 判断蛇移动的方向
if (fx == 0)
{
Snakex[0] = Snakex[0] - 20;
}
else if (fx == 1)
{
Snakex[0] = Snakex[0] + 20;
}
else if (fx == 2)
{
Snakey[0] = Snakey[0] - 20;
}
else if (fx == 3)
{
Snakey[0] = Snakey[0] + 20;
}
// 判断蛇是否撞到墙外
if (Snakex[0] < 0 || Snakex[0] > 780 || Snakey[0] < 80 || Snakey[0] > 580)
{
started = 4;
}
// 判断蛇是否吃到了普通食物
if (Snakex[0] == foodx && Snakey[0] == foody)
{
slong++;
score++;
//特判超级食物
if(score%6==0&&guan>1)
{
superfoodx = random.nextInt(39);
superfoody = random.nextInt(22);
superfoodx = superfoodx * 20;
superfoody = superfoody * 20 + 80;
}
//特判炸弹食物
if(slong%6==0&&guan>2)
{
bombx=random.nextInt(39);
bomby = random.nextInt(22);
bombx = bombx * 20;
bomby = bomby * 20 + 80;
}
if(guan==6&&slong>random.nextInt(40)) {
doorx=random.nextInt(39);
doory = random.nextInt(22);
doorx = doorx * 20;
doory = doory * 20 + 80;
}
foodx = random.nextInt(39);
foody = random.nextInt(22);
foodx = foodx * 20;
foody = foody * 20 + 80;
System.out.println(foodx + "," + foody);//输出下个食物坐标
}
//超级食物判断
if (Snakex[0] == superfoodx && Snakey[0] == superfoody)
{
slong+=4;
score+=3;
//超级食物清零
superfoodx = 0;
superfoody = 0;
superfoodx = 0;
superfoody = 0;
//System.out.println(foodx + "," + foody);//输出下个食物坐标
}
//炸弹食物判断
if (Snakex[0] == bombx && Snakey[0] == bomby)
{
started=4;
//System.out.println(foodx + "," + foody);//输出下个食物坐标
}
if (Snakex[0] == doorx && Snakey[0] == doory)
{
score+=3;
//传送门清零
doorx = 0;
doory = 0;
started=2;
//System.out.println(foodx + "," + foody);//输出下个食物坐标
}
// 判断是否吃到了自己
for (int i = 1; i < slong; i++)
{
if (Snakex[0] == Snakex[i] && Snakey[0] == Snakey[i]) {
started = 4;
}
}
// 判断食物是否随机在了蛇身上
for (int i = 0; i < slong; i++)
{
if (foodx == Snakex[i] && foody == Snakey[i])
{
// 随机食物的初识位置
foodx = random.nextInt(39);
foody = random.nextInt(22);
foodx = foodx * 20;
foody = foody * 20 + 80;
System.out.println(foodx + "," + foody);
}
}
//刷新
repaint();
}
//通关判断
if(score>1) {
started=2;
}
}
// 键盘输入
@Override
public void keyTyped(KeyEvent e) {
}
// 键盘按下——控制游戏的开始以及蛇的移动方向
@Override
public void keyPressed(KeyEvent e) {
// 获取从键盘输入的键
int key = e.getKeyCode();
// 判断是否为空格
if (key == KeyEvent.VK_SPACE)
{
if (started == 0)
{
guan=nandu;
started = 1;
}
else if (started == 1)
{
started = 3;
}
else if (started == 4)
{
started = 0;
slong = 2;//蛇当前长度
// 蛇的初识位置
Snakex[0] = 260;
Snakey[0] = 300;
Snakex[1] = 240;
Snakey[1] = 300;
// 随机食物的初识位置
foodx = random.nextInt(39);
foody = random.nextInt(22);
foodx = foodx * 20;
foody = foody * 20 + 80;
// 初始化方向
fx = 1;
}
else if (started==3)
{
started=1;
}
else if(started==2)
{
started = 1;
if(guan<6) {
guan++;
score=1;
slong = 2;
// 蛇的初识位置
Snakex[0] = 260;
Snakey[0] = 300;
Snakex[1] = 240;
Snakey[1] = 300;
}else {
guan++;
slong+=2;
}
// 随机食物的初识位置
foodx = random.nextInt(39);
foody = random.nextInt(22);
foodx = foodx * 20;
foody = foody * 20 + 80;
}else if (started==-1)
{
started=0;
}
switch(guan)
{
case 1: timer.start();break;
case 2: timer1.start();break;
case 3: timer2.start();break;
case 4: timer3.start();break;
default: timer4.start();break;
}
//timer.start();
repaint();
// 左
} else if (key == KeyEvent.VK_LEFT||key == KeyEvent.VK_A)
{
if (fx != 1)
{
fx = 0;
}
// 右
} else if (key == KeyEvent.VK_RIGHT||key == KeyEvent.VK_D)
{
if (fx != 0)
{
fx = 1;
}
// 上
} else if (key == KeyEvent.VK_UP||key == KeyEvent.VK_W)
{
if (fx != 3)
{
fx = 2;
}
//下
} else if (key == KeyEvent.VK_DOWN||key == KeyEvent.VK_S)
{
if (fx != 2)
{
fx = 3;
}
}
else if (key == KeyEvent.VK_1)
{
nandu=1;
}
else if (key == KeyEvent.VK_2)
{
nandu=2;
}
else if (key == KeyEvent.VK_3)
{
nandu=3;
}
else if (key == KeyEvent.VK_4)
{
nandu=4;
}
else if (key == KeyEvent.VK_5)
{
nandu=5;
}
else if(key==KeyEvent.VK_6) {
music=1;
}else if(key==KeyEvent.VK_7) {
music=2;
}else if(key==KeyEvent.VK_8) {
music=3;
}
}
// 弹起
@Override
public void keyReleased(KeyEvent e) {
}
// 点击
@Override
public void mouseClicked(MouseEvent e) {
}
// 按下
@Override
public void mousePressed(MouseEvent e) {
}
// 抬起
@Override
public void mouseReleased(MouseEvent e) {
}
// 进入
@Override
public void mouseEntered(MouseEvent e) {
}
// 离开
@Override
public void mouseExited(MouseEvent e) {
}
}
有较多未实现功能,代码冗余太多,改日重构。