贪吃蛇课设项目解析

今天来具体说说我的课设项目,是使用swing完成的贪吃蛇大作战,在这个项目中遇到了一些困难,最终全部解决。

首先我们要定义一个蛇类,用来绘出蛇的形状和基本的逻辑处理


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;


public class Food {
private Point food;// 食物坐标
private Random rand;// 随机数
private Color color = Color.CYAN;// 食物颜色


public Food() {
rand = new Random();
food = new Point();// 初始化食物坐标
changeColor();// 随机颜色
food.setLocation(randomPoint());// 随机坐标
}


// 产生一个食物
public void createFood(Snake snake) {
Point temPoint = randomPoint();// 随机坐标,tempPoint为食物坐标
for (Point p : snake.getSnakeBody()) {// 判断食物是否与蛇重叠
if (p.equals(temPoint)) {
temPoint = randomPoint();// 重叠后重新产生坐标
}
}
food.setLocation(temPoint);// 设置食物坐标
}


// 画出食物
public void drawFood(Graphics g) {
g.setColor(color);// 设置颜色
g.fill3DRect(food.x * SizeConstants.SIZE, food.y * SizeConstants.SIZE, SizeConstants.SIZE, SizeConstants.SIZE,
true);
}


// 得到食物位置
public Point getFood() {
return food;
}


// 改变颜色
public void changeColor() {
color = randomColor();
}


public Color getColor() {
return color;
}


// 随机坐标
private Point randomPoint() {
int x = rand.nextInt(SizeConstants.WIDTH - 1) + 1;
int y = rand.nextInt(SizeConstants.HEIGHT - 1) + 1;
return new Point(x, y);
}


// 随机颜色
private Color randomColor() {
int r = rand.nextInt(255);
int g = rand.nextInt(255);
int b = rand.nextInt(235);
return new Color(r, g, b);
}


}


接下来我们要定义一个食物类:


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;


public class Food {
private Point food;// 食物坐标
private Random rand;// 随机数
private Color color = Color.CYAN;// 食物颜色


public Food() {
rand = new Random();
food = new Point();// 初始化食物坐标
changeColor();// 随机颜色
food.setLocation(randomPoint());// 随机坐标
}


// 产生一个食物
public void createFood(Snake snake) {
Point temPoint = randomPoint();// 随机坐标,tempPoint为食物坐标
for (Point p : snake.getSnakeBody()) {// 判断食物是否与蛇重叠
if (p.equals(temPoint)) {
temPoint = randomPoint();// 重叠后重新产生坐标
}
}
food.setLocation(temPoint);// 设置食物坐标
}


// 画出食物
public void drawFood(Graphics g) {
g.setColor(color);// 设置颜色
g.fill3DRect(food.x * SizeConstants.SIZE, food.y * SizeConstants.SIZE, SizeConstants.SIZE, SizeConstants.SIZE,
true);
}


// 得到食物位置
public Point getFood() {
return food;
}


// 改变颜色
public void changeColor() {
color = randomColor();
}


public Color getColor() {
return color;
}


// 随机坐标
private Point randomPoint() {
int x = rand.nextInt(SizeConstants.WIDTH - 1) + 1;
int y = rand.nextInt(SizeConstants.HEIGHT - 1) + 1;
return new Point(x, y);
}


// 随机颜色
private Color randomColor() {
int r = rand.nextInt(255);
int g = rand.nextInt(255);
int b = rand.nextInt(235);
return new Color(r, g, b);
}


}


这里定义了食物的基本信息,包括食物的产生,状态,位置,颜色等


本来到此javabean就结束了,但是我总感觉太单调。内容不够丰富,于是我又加上了一个挑战模式(齿轮),下面是齿轮的javabean

public final class SizeConstants {


public static final int SIZE = 15;
public static final int WIDTH = 35;
public static final int HEIGHT = 35 ;


private SizeConstants() {
}
}


import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.IOException;


public class Game extends JFrame {
private static final Image bgImage = Toolkit.getDefaultToolkit().getImage("src/images/贪吃蛇.jpg");//加载背景图片
private static final int WIDTH = 800;//
private static final int HEIGHT = 450;
private static final int MENU_X_START = 337;
private static final int MENU_X_END = 460;
private static final int START_Y_START = 262;
private static final int START_Y_END = 299;
private static final int ABOUT_Y_START = 323;
private static final int ABOUT_Y_END = 362;
private static final int EXIT_Y_START = 388;
private static final int EXIT_Y_END = 425;
private static final int MUSIC_X_START = 8;
private static final int MUSIC_X_END = 68;
private static final int MUSIC_Y_START = 387;
private static final int MUSIC_Y_END = 437;


private final Sound sound = new Sound();


public Game() {
initGUI();
}


private void initGUI() {
setTitle("贪吃蛇");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setUndecorated(true);
setLocationRelativeTo(null);
setResizable(false);


try {
sound.playBgMusic();
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}


setVisible(true);


addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent event) {//鼠标点击事件
handleMouseClick(event);//处理鼠标点击事件,点击开始游戏,关于,退出游戏
}
});


addMouseMotionListener(new MouseMotionAdapter() {//鼠标移动事件
@Override
public void mouseMoved(MouseEvent event) {
handleMouseMove(event);
}
});
}


private void handleMouseClick(MouseEvent event) {
int x = event.getX();
int y = event.getY();


if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, START_Y_START, START_Y_END)) {
dispose();
new GameFrame();
} else if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, ABOUT_Y_START, ABOUT_Y_END)) {
new AboutDialog();
} else if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, EXIT_Y_START, EXIT_Y_END)) {
int num = JOptionPane.showConfirmDialog(this, "确认退出游戏吗", "退出提示", JOptionPane.CANCEL_OPTION);
if (num == 0) {
System.exit(0);
}
} else if (isWithinBounds(x, y, MUSIC_X_START, MUSIC_X_END, MUSIC_Y_START, MUSIC_Y_END)) {
toggleMusic();
}
}


private void handleMouseMove(MouseEvent event) {
int x = event.getX();
int y = event.getY();


if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, START_Y_START, START_Y_END) ||
isWithinBounds(x, y, MENU_X_START, MENU_X_END, ABOUT_Y_START, ABOUT_Y_END) ||
isWithinBounds(x, y, MENU_X_START, MENU_X_END, EXIT_Y_START, EXIT_Y_END) ||
isWithinBounds(x, y, MUSIC_X_START, MUSIC_X_END, MUSIC_Y_START, MUSIC_Y_END)) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else {
setCursor(Cursor.getDefaultCursor());
}
}


private boolean isWithinBounds(int x, int y, int xStart, int xEnd, int yStart, int yEnd) {
return x >= xStart && x <= xEnd && y >= yStart && y <= yEnd;
}


private void toggleMusic() {
if (sound.getBgSoundClip() != null) {
sound.stop();
} else {
try {
sound.playBgMusic();
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}
}
}


@Override
public void paint(Graphics g) {
g.drawImage(bgImage, 0, 0, this);
}


public static void main(String[] args) {
new Game();
}

三个javabean到此结束,接下来绘制地图

public final class SizeConstants {


public static final int SIZE = 15;
public static final int WIDTH = 35;
public static final int HEIGHT = 35 ;


private SizeConstants() {
}
}


import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.IOException;


public class Game extends JFrame {
private static final Image bgImage = Toolkit.getDefaultToolkit().getImage("src/images/贪吃蛇.jpg");//加载背景图片
private static final int WIDTH = 800;//
private static final int HEIGHT = 450;
private static final int MENU_X_START = 337;
private static final int MENU_X_END = 460;
private static final int START_Y_START = 262;
private static final int START_Y_END = 299;
private static final int ABOUT_Y_START = 323;
private static final int ABOUT_Y_END = 362;
private static final int EXIT_Y_START = 388;
private static final int EXIT_Y_END = 425;
private static final int MUSIC_X_START = 8;
private static final int MUSIC_X_END = 68;
private static final int MUSIC_Y_START = 387;
private static final int MUSIC_Y_END = 437;


private final Sound sound = new Sound();


public Game() {
initGUI();
}


private void initGUI() {
setTitle("贪吃蛇");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setUndecorated(true);
setLocationRelativeTo(null);
setResizable(false);


try {
sound.playBgMusic();
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}


setVisible(true);


addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent event) {//鼠标点击事件
handleMouseClick(event);//处理鼠标点击事件,点击开始游戏,关于,退出游戏
}
});


addMouseMotionListener(new MouseMotionAdapter() {//鼠标移动事件
@Override
public void mouseMoved(MouseEvent event) {
handleMouseMove(event);
}
});
}


private void handleMouseClick(MouseEvent event) {
int x = event.getX();
int y = event.getY();


if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, START_Y_START, START_Y_END)) {
dispose();
new GameFrame();
} else if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, ABOUT_Y_START, ABOUT_Y_END)) {
new AboutDialog();
} else if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, EXIT_Y_START, EXIT_Y_END)) {
int num = JOptionPane.showConfirmDialog(this, "确认退出游戏吗", "退出提示", JOptionPane.CANCEL_OPTION);
if (num == 0) {
System.exit(0);
}
} else if (isWithinBounds(x, y, MUSIC_X_START, MUSIC_X_END, MUSIC_Y_START, MUSIC_Y_END)) {
toggleMusic();
}
}


private void handleMouseMove(MouseEvent event) {
int x = event.getX();
int y = event.getY();


if (isWithinBounds(x, y, MENU_X_START, MENU_X_END, START_Y_START, START_Y_END) ||
isWithinBounds(x, y, MENU_X_START, MENU_X_END, ABOUT_Y_START, ABOUT_Y_END) ||
isWithinBounds(x, y, MENU_X_START, MENU_X_END, EXIT_Y_START, EXIT_Y_END) ||
isWithinBounds(x, y, MUSIC_X_START, MUSIC_X_END, MUSIC_Y_START, MUSIC_Y_END)) {
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
} else {
setCursor(Cursor.getDefaultCursor());
}
}


private boolean isWithinBounds(int x, int y, int xStart, int xEnd, int yStart, int yEnd) {
return x >= xStart && x <= xEnd && y >= yStart && y <= yEnd;
}


private void toggleMusic() {
if (sound.getBgSoundClip() != null) {
sound.stop();
} else {
try {
sound.playBgMusic();
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException e) {
e.printStackTrace();
}
}
}


@Override
public void paint(Graphics g) {
g.drawImage(bgImage, 0, 0, this);
}


public static void main(String[] args) {
new Game();
}

下面是业务逻辑代码

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;


public class GameFrame extends JFrame {
// 游戏区域的宽度和高度
private static final int GAME_WIDTH = 535;
private static final int GAME_HEIGHT = 565;


private GamePanel gPanel; // 游戏面板
private JMenuBar jBar; // 菜单栏
private JMenuItem[] jItems; // 菜单项
private JLabel scoreLabel; // 用于显示得分的标签
private boolean isTwoPlayerMode = false; // 双人模式标志
private boolean isChallengeMode = false; // 挑战模式标志
private Gear gear; // 齿轮
public GameFrame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
setSize(GAME_WIDTH, GAME_HEIGHT);
setLayout(null);
setLocationRelativeTo(null); // 窗口居中显示
setUndecorated(true); // 去掉窗口的边框


jBar = new JMenuBar(); // 创建菜单栏
JMenu difficultyMenu = new JMenu("难度"); // 创建难度菜单
JMenu modeMenu = new JMenu("模式"); // 创建模式菜单


jItems = new JMenuItem[9]; // 创建菜单项数组


jItems[0] = new JMenuItem("重新开始");
jItems[0].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); // 设置快捷键
jItems[1] = new JMenuItem("暂停/开始");
jItems[1].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0)); // 设置快捷键
jItems[2] = new JRadioButtonMenuItem("低");
jItems[3] = new JRadioButtonMenuItem("中");
jItems[4] = new JRadioButtonMenuItem("高");
jItems[5] = new JMenuItem("退出");
jItems[5].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0));
jItems[6] = new JRadioButtonMenuItem("单人模式");
jItems[7] = new JRadioButtonMenuItem("双人模式");
jItems[8] = new JMenuItem("挑战");


// 设置菜单项的首选大小和最大大小
jItems[0].setPreferredSize(new Dimension(215, 40)); // 开始
jItems[1].setPreferredSize(new Dimension(215, 40)); // 暂停/开始
jItems[2].setPreferredSize(new Dimension(75, 40)); // 低
jItems[3].setPreferredSize(new Dimension(75, 40)); // 中
jItems[4].setPreferredSize(new Dimension(75, 40)); // 高
jItems[5].setPreferredSize(new Dimension(160, 40)); // 退出
jItems[6].setPreferredSize(new Dimension(160, 40)); // 单人模式
jItems[7].setPreferredSize(new Dimension(160, 40)); // 双人模式
jItems[8].setPreferredSize(new Dimension(110, 40)); // 挑战
// 默认选中“低”菜单项
jItems[2].setSelected(true);
// 默认选中“单人模式”菜单项
jItems[6].setSelected(true);


// 创建并添加难度菜单项
ButtonGroup difficultyGroup = new ButtonGroup();
difficultyGroup.add(jItems[2]);
difficultyGroup.add(jItems[3]);
difficultyGroup.add(jItems[4]);


difficultyMenu.add(jItems[2]);
difficultyMenu.add(jItems[3]);
difficultyMenu.add(jItems[4]);


// 创建并添加模式菜单项
ButtonGroup modeGroup = new ButtonGroup(); // 创建模式按钮组
modeGroup.add(jItems[6]);
modeGroup.add(jItems[7]);


modeMenu.add(jItems[6]);
modeMenu.add(jItems[7]);


jBar.add(jItems[0]); // jItems[0]是开始游戏的菜单项
jBar.add(jItems[1]); // jItems[1]是暂停/开始游戏的菜单项
jBar.add(difficultyMenu);
jBar.add(modeMenu); // 添加模式菜单
jBar.add(jItems[8]); // 添加挑战菜单项
jBar.add(jItems[5]); // jItems[5]是退出游戏的菜单项


for (int i = 0; i < jItems.length; i++) {
jItems[i].addActionListener(new MyAction()); // 为所有菜单项添加事件监听器,处理菜单项的单击事件
}


// 创建并添加用于显示得分的标签
scoreLabel = new JLabel("得分: 0"); // 创建得分标签
scoreLabel.setHorizontalAlignment(SwingConstants.RIGHT); // 设置标签中的文本右对齐
jBar.add(Box.createHorizontalGlue()); // 添加弹性空间以将得分标签推到右侧
jBar.add(scoreLabel); // 添加得分标签


setJMenuBar(jBar); // 设置菜单栏


gPanel = new GamePanel(this);
gPanel.setBounds(0, 0, GAME_WIDTH, GAME_HEIGHT); // 设置游戏面板的位置和大小
add(gPanel);
addWindowListener(new WindowAdapter() { // 为窗口添加窗口事件监听器
@Override
public void windowClosing(WindowEvent e) {
// 弹出对话框,询问用户是否退出游戏
int result = JOptionPane.showConfirmDialog(null, "是否退出游戏?", "退出游戏", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
});
setVisible(true);
gPanel.requestFocus();
showScore();
}


private void showScore() {
Timer timer = new Timer(100, e -> {
scoreLabel.setText("得分: " + gPanel.getScore() + " 长度: " + gPanel.getLength() + " 速度: " + (300 - gPanel.getSpeed()));
});
timer.start();
}


private class MyAction implements ActionListener { // 菜单项的事件监听器
@Override
public void actionPerformed(ActionEvent e) { // 处理菜单项的单击事件
String s = e.getActionCommand(); // 获取事件源的名称
switch (s) {
case "重新开始":
gPanel.againStart();
break;
case "暂停/开始":
gPanel.stop();
break;
case "低":
gPanel.setSpeed(200);
break;
case "中":
gPanel.setSpeed(150);
break;
case "高":
gPanel.setSpeed(100);
break;
case "挑战":
//暂停
gPanel.superStop();
//先判断是否已经是挑战模式,如果是,询问是否退出挑战模式
if (isChallengeMode) {
int result = JOptionPane.showConfirmDialog(null, "是否退出挑战模式?", "退出挑战", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
isChallengeMode = false;
gPanel.setSpeed(200);
gear=null;
//重新开始
gPanel.againStart();
// gPanel.stop();
}
break;
}
int result = JOptionPane.showConfirmDialog(null, "是否挑战?", "挑战", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
isChallengeMode = true;
gPanel.setSpeed(100);
gPanel.stop();
}
// isChallengeMode = true;
// gPanel.setSpeed(110);
break;
case "退出":
//暂停
gPanel.superStop();
// 弹出对话框,询问用户是否退出游戏
result = JOptionPane.showConfirmDialog(null, "是否退出游戏?", "退出游戏", JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION)
System.exit(0);
else {
//继续
gPanel.stop();
}
break;
case "单人模式":
isTwoPlayerMode = false; // 设置为单人模式
break;
case "双人模式":
isTwoPlayerMode = true; // 设置为双人模式
break;
default:
break;
}
}
}


public boolean isTwoPlayerMode() {
return isTwoPlayerMode;
}


public boolean isChallengeMode() {
return isChallengeMode;
}
}

这里完成了游戏的基本逻辑,下面是数据访问(也就是细节实现):

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;


public class GamePanel extends JPanel {


private static final long serialVersionUID = 1L;
private Snake snake;
private Food food;
private Gear gear;
private Timer timer;
private int score; // 分数
private int length = 3; // 蛇身长度
private int speed; // 速度
private GameFrame gameFrame; // 引用 GameFrame 实例
private int gearMoveCounter = 0; // 齿轮移动计数器


public GamePanel(GameFrame gameFrame) {
this.gameFrame = gameFrame;
snake = new Snake();
food = new Food();
speed = 200;
timer = new Timer(speed, new SnakeRunListener()); // 设置定时器,控制蛇移动,速度,吃食物,碰撞检测


setSize(SizeConstants.WIDTH * SizeConstants.SIZE, SizeConstants.HEIGHT * SizeConstants.SIZE); // 设置面板大小
addKeyListener(new KeyControl()); // 添加键盘监听,控制蛇移动
}


// 开始游戏
public void startGame() {
score = 0;
length = snake.getSnakeBody().size();
if (gameFrame.isChallengeMode()) {
gear = new Gear(); // 仅在挑战模式下初始化齿轮
gear.randomGear(); // 随机生成齿轮
} else {
gear = null; // 非挑战模式下齿轮为空
}
timer.start(); // 启动定时器,蛇开始移动
}


// 暂停
public void stop() {
if (timer.isRunning()) { // 判断是否在运行,如果isRunning为true,则暂停
timer.stop(); // 暂停
} else {
timer.start();
}
}
public void superStop() {
timer.stop();
}


// 重新开始
public void againStart() {
setSpeed(200);
repaint();
snake.againStart();
startGame();
}


// 当吃到食物后产生新食物
public void eatFood() {
if (snake.isEatFood(food)) {
addSpeed();
timer.setDelay(speed);
countScore();
countLength();
snake.eatFood();
snake.setColor(food.getColor());
food.changeColor();
food.createFood(snake);
}
}


// 游戏结束后的选择
public void gameEnd() {
if (!snake.getLife()) {
int option = JOptionPane.showConfirmDialog(null, "是否继续?", "游戏已结束", JOptionPane.YES_NO_OPTION);
if (option == JOptionPane.YES_OPTION) {
setSpeed(200);
timer.setDelay(speed);
againStart();
} else {
System.exit(0);
}
}
}


// 速度增长比例
public void addSpeed() {
// 判断延迟是否大于25
if (speed > 25) {
speed = speed - 5;
}
}


// 分数计算
public void countScore() {
score = score + 2 * (length - 2);
}


// 长度计算
public void countLength() {
length++;
}


public int getScore() {
return score;
}


public int getLength() {
return length;
}


public int getSpeed() {
return speed;
}


public void setSpeed(int speed) {
this.speed = speed;
}


@Override
public void paintComponent(Graphics g) {
super.paintComponent(g); //双缓冲技术,防止闪烁
for (int x = 0; x < SizeConstants.WIDTH; x++) {
for (int y = 0; y < SizeConstants.HEIGHT; y++) {
// 设置单元格填充颜色为白色
g.setColor(new Color(242, 242, 242));
// 绘制单元格
g.fillRect(x * SizeConstants.SIZE, y * SizeConstants.SIZE, SizeConstants.SIZE, SizeConstants.SIZE);


// 设置边框颜色为灰白色
g.setColor(Color.white);
// 绘制单元格边框
g.drawRect(x * SizeConstants.SIZE, y * SizeConstants.SIZE, SizeConstants.SIZE, SizeConstants.SIZE);
}
}


// 如果是挑战模式,绘制齿轮
if (gameFrame.isChallengeMode() && gear != null) {
g.drawImage(new ImageIcon("src/images/齿轮.jpg").getImage(), gear.getX() * SizeConstants.SIZE, gear.getY() * SizeConstants.SIZE, this);
}


// 绘制蛇和食物
snake.drawSnake(g);
food.drawFood(g);
eatFood();
}


private class SnakeRunListener implements ActionListener { // 定时器监听,控制蛇移动
@Override
public void actionPerformed(ActionEvent e) {
if (snake.getLife()) { // 判断蛇是否存活
snake.snakeMove();
if (gear != null) {
gearMoveCounter++;
if (gearMoveCounter >= 5) { // 每5次移动一次齿轮
gear.move(); // 更新齿轮位置
gearMoveCounter = 0;
}
if (snake.isMeetGear(gear)) { // 判断是否碰到齿轮
System.out.println("碰到齿轮");
snake.setLife(false); // 结束游戏
}
}
gameEnd();
repaint();
}
}
}


private class KeyControl extends KeyAdapter { // 键盘监听
@Override
public void keyPressed(KeyEvent e) { // 键盘按下事件
int key = e.getKeyCode(); // 获取按下的键值
if (gameFrame.isTwoPlayerMode()) {
switch (key) {
case KeyEvent.VK_UP:
snake.changeDeriction(snake.UP);
break;
case KeyEvent.VK_DOWN:
snake.changeDeriction(snake.DOWN);
break;
// 'a'键
case KeyEvent.VK_A:
snake.changeDeriction(snake.LEFT);
break;
// 'd'键
case KeyEvent.VK_D:
snake.changeDeriction(snake.RIGHT);
break;
}
} else {
switch (key) {
// 加上‘w','a','s','d'键控制
case KeyEvent.VK_UP:
case KeyEvent.VK_W:
snake.changeDeriction(snake.UP);
break;
case KeyEvent.VK_DOWN:
case KeyEvent.VK_S:
snake.changeDeriction(snake.DOWN);
break;
case KeyEvent.VK_LEFT:
case KeyEvent.VK_A:
snake.changeDeriction(snake.LEFT);
break;
case KeyEvent.VK_RIGHT:
case KeyEvent.VK_D:
snake.changeDeriction(snake.RIGHT);
break;
}
}
}
}
}

到此,游戏的所有逻辑已经完成,下面我们加上声音和游戏开始界面
声音相关代码:

import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;


/**
* 音乐播放器类
*/
public class Sound {
private static File bgSoundFile; // 背景音乐文件
private static File missileSoundFile; // 撞击音效文件
private Clip missileSoundClip; // 撞击音效播放器
private Clip bgSoundClip; // 背景音乐播放器
private static File eatileSoundFile; // 吃食物音效文件
private Clip eatileSoundClip; // 吃食物音效播放器


// 加载声音文件
static {
// 指定音频文件路径
bgSoundFile = new File("src/audio/贪吃蛇.wav");
// 指定音频文件路径
missileSoundFile = new File("src/audio/PenZ.wav");
// 指定音频文件路径
eatileSoundFile = new File("src/audio/Eat.wav");
}


public Clip getBgSoundClip() {
return this.bgSoundClip;
}


/**
* 获得背景音乐播放器对象
*
* @return
* @throws UnsupportedAudioFileException
* @throws IOException
* @throws LineUnavailableException
*/
public void playBgMusic() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
// 获取音频输入流
AudioInputStream bgSoundStream = AudioSystem.getAudioInputStream(bgSoundFile);


// 获取Clip对象
this.bgSoundClip = AudioSystem.getClip();
// 开发音乐流
this.bgSoundClip.open(bgSoundStream);
// 开始播放音乐
this.bgSoundClip.start();
// 循环播放
this.bgSoundClip.loop(-1);
}


/**
* 播放撞击音效
*
* @return
*/
public void playMissileSound() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
// 获取音频输入流
AudioInputStream missileSoundStream = AudioSystem.getAudioInputStream(missileSoundFile);


// 获取Clip对象
this.missileSoundClip = AudioSystem.getClip();
// 开发音乐流
this.missileSoundClip.open(missileSoundStream);
// 开始播放音乐
this.missileSoundClip.start();
}


/**
* 播放吃食物音效
*
* @return
*/
public void playEatileSound() throws UnsupportedAudioFileException, IOException, LineUnavailableException {
// 获取音频输入流
AudioInputStream eatileSoundStream = AudioSystem.getAudioInputStream(eatileSoundFile);


// 获取Clip对象
this.eatileSoundClip = AudioSystem.getClip();
// 开发音乐流
this.eatileSoundClip.open(eatileSoundStream);
// 开始播放音效
this.eatileSoundClip.start();
}


/**
* 停止背景音乐播放
*/
public void stop() {
if (this.bgSoundClip != null) {
this.bgSoundClip.stop();
this.bgSoundClip = null;
}
}


/**
* 停止吃食物音效播放
*/
public void stopEatileSound() {
if (this.eatileSoundClip != null) {
this.eatileSoundClip.stop();
this.eatileSoundClip = null;
}
}


}


上面就是所有的相关代码,以下是源代码地址:

https://gitee.com/nkion/untitled5

下面是界面截图:

1.以下是项目图片 

开始游戏界面

 

挑战模式

 

普通界面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nkion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值