Swing贪吃蛇游戏(一):基本功能实现
本文将提供一个Swing版本的贪吃蛇游戏,游戏包括最基本的功能:
1. 用Timer来管理贪吃蛇线程。
2. 实现按钮,键盘的事件响应。
3. 随机产生食物。
4. 游戏结束的判断:蛇头触碰到蛇身或者蛇头触碰到边界。
5. 实现游戏过程中的暂停以及贪吃蛇运行速度调整。
6. … …
程序界面如下:左边是贪吃蛇运行的范围,右边暂时只有分数信息,当蛇吃到食物的时候分数加10.
[img]http://dl2.iteye.com/upload/attachment/0087/3921/af342211-d283-3363-9d90-7f22e53804dd.jpg[/img]
暂停,调整蛇体运行速度界面如下:
[img]http://dl2.iteye.com/upload/attachment/0087/3919/98c451aa-554c-3297-87ba-092b51af86d9.jpg[/img]
主要的代码如下:
[img]http://dl2.iteye.com/upload/attachment/0087/3917/cbb14deb-6058-32e5-acbc-fb7714bc6ea0.jpg[/img]
package my.games.snake.model;
import java.awt.Color;import java.awt.Graphics2D;import java.awt.geom.Rectangle2D;import java.io.Serializable;import my.games.snake.contants.SnakeGameConstant;
/** * * 贪吃蛇游戏用到的格子类 * * @author Eric * */public class Grid implements Serializable {
private static final long serialVersionUID = 5105993927776028563L;
private int x; // x location
private int y; // y location
private Color color; // color for square
public Grid() { }
public Grid(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; }
/** * Draw Grid * * @param g2 */ public void draw(Graphics2D g2) { int clientX = SnakeGameConstant.SNAKE_GAME_PANEL_LEFT + x * SnakeGameConstant.GRID_SIZE; int clientY = SnakeGameConstant.SNAKE_GAME_PANEL_TOP + y * SnakeGameConstant.GRID_SIZE; Rectangle2D.Double rect = new Rectangle2D.Double(clientX, clientY, SnakeGameConstant.GRID_SIZE, SnakeGameConstant.GRID_SIZE); g2.setPaint(color); g2.fill(rect); g2.setPaint(Color.BLACK); g2.draw(rect); }
/** * @return the color */ public Color getColor() { return color; }
/** * @param color * the color to set */ public void setColor(Color color) { this.color = color; }
/** * @return the x */ public int getX() { return x; }
/** * @param x * the x to set */ public void setX(int x) { this.x = x; }
/** * @return the y */ public int getY() { return y; }
/** * @param y * the y to set */ public void setY(int y) { this.y = y; }
}
package my.games.snake.model;
import java.awt.Graphics2D;import java.io.Serializable;import java.util.LinkedList;import java.util.List;
import my.games.snake.contants.SnakeGameConstant;import my.games.snake.enums.Direction;
public class Snake implements Serializable {
private static final long serialVersionUID = -1064622816984550631L;
private List<Grid> list = null;
private Direction direction = Direction.RIGHT;
public Snake() { this.list = new LinkedList<Grid>(); }
public void changeDirection(Direction direction) { if (direction.isUpDirection()) { if (!this.direction.isUpDirection() && !this.direction.isDownDirection()) { this.direction = direction; } } else if (direction.isRightDirection()) { if (!this.direction.isRightDirection() && !this.direction.isLeftDirection()) { this.direction = direction; } } else if (direction.isDownDirection()) { if (!this.direction.isUpDirection() && !this.direction.isDownDirection()) { this.direction = direction; } } else if (direction.isLeftDirection()) { if (!this.direction.isRightDirection() && !this.direction.isLeftDirection()) { this.direction = direction; } } }
public void draw(Graphics2D g2) { for (Grid grid : list) { grid.draw(g2); } }
/** * @return the list */ public List<Grid> getList() { return list; }
/** * @param list * the list to set */ public void setList(List<Grid> list) { this.list = list; }
/** * @return the direction */ public Direction getDirection() { return direction; }
/** * @param direction * the direction to set */ public void setDirection(Direction direction) { this.direction = direction; }
public void move() { Grid currentHead = list.get(0); int headX = currentHead.getX(); int headY = currentHead.getY(); currentHead.setColor(SnakeGameConstant.SNAKE_BODY_COLOR);
if (direction.isDownDirection()) { list.add(0, new Grid(headX, headY + 1, SnakeGameConstant.SNAKE_HEADER_COLOR)); list.remove(list.size() - 1); } else if (direction.isUpDirection()) { list.add(0, new Grid(headX, headY - 1, SnakeGameConstant.SNAKE_HEADER_COLOR)); list.remove(list.size() - 1); } else if (direction.isRightDirection()) { list.add(0, new Grid(headX + 1, headY, SnakeGameConstant.SNAKE_HEADER_COLOR)); list.remove(list.size() - 1); } else if (direction.isLeftDirection()) { list.add(0, new Grid(headX - 1, headY, SnakeGameConstant.SNAKE_HEADER_COLOR)); list.remove(list.size() - 1); }
}
}
package my.games.snake.ui;
import java.awt.Container;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.ButtonGroup;import javax.swing.JFrame;import javax.swing.JMenu;import javax.swing.JMenuBar;import javax.swing.JMenuItem;import javax.swing.JOptionPane;import javax.swing.JRadioButtonMenuItem;import my.games.snake.contants.SnakeGameConstant;import my.games.snake.enums.GameState;
public class SnakeGameFrame extends JFrame {
private static final long serialVersionUID = 998014032682506026L;
private SnakeGamePanel panel;
private Container contentPane;
private JMenuItem startMI = new JMenuItem("Start");
private JMenuItem pauseMI = new JMenuItem("Pause");
private JMenu speedMenu = new JMenu("Speed");
private JMenuItem exitMI = new JMenuItem("Exit");
private JMenuItem aboutMI = new JMenuItem("About");
private JRadioButtonMenuItem speedMI1 = new JRadioButtonMenuItem("Speed1", true);
private JRadioButtonMenuItem speedMI2 = new JRadioButtonMenuItem("Speed2", false);
private JRadioButtonMenuItem speedMI3 = new JRadioButtonMenuItem("Speed3", false);
private JRadioButtonMenuItem speedMI4 = new JRadioButtonMenuItem("Speed4", false);
private JRadioButtonMenuItem speedMI5 = new JRadioButtonMenuItem("Speed5", false);
public int speedFlag = 1;
public SnakeGameFrame() { setTitle(SnakeGameConstant.SNAKE_GAME); setSize(SnakeGameConstant.SNAKE_GAME_FRAME_WIDTH, SnakeGameConstant.SNAKE_GAME_FRAME_HEIGHT); setResizable(false);
JMenuBar menuBar = new JMenuBar(); setJMenuBar(menuBar);
JMenu setMenu = new JMenu("Set"); JMenu helpMenu = new JMenu("Help");
setMenu.setMnemonic('s'); setMenu.setMnemonic('H');
menuBar.add(setMenu); menuBar.add(helpMenu);
setMenu.add(startMI); setMenu.add(pauseMI); setMenu.addSeparator();
setMenu.addSeparator(); setMenu.add(speedMenu); setMenu.addSeparator(); setMenu.add(exitMI);
ButtonGroup group = new ButtonGroup(); group.add(speedMI1); group.add(speedMI2); group.add(speedMI3); group.add(speedMI4); group.add(speedMI5);
speedMenu.add(speedMI1); speedMenu.add(speedMI2); speedMenu.add(speedMI3); speedMenu.add(speedMI4); speedMenu.add(speedMI5);
startMI.addActionListener(new StartAction()); pauseMI.addActionListener(new PauseAction()); exitMI.addActionListener(new ExitAction()); speedMI1.addActionListener(new SpeedAction()); speedMI2.addActionListener(new SpeedAction()); speedMI3.addActionListener(new SpeedAction()); speedMI4.addActionListener(new SpeedAction()); speedMI5.addActionListener(new SpeedAction());
helpMenu.add(aboutMI); aboutMI.addActionListener(new AboutAction());
contentPane = getContentPane(); panel = new SnakeGamePanel(this); contentPane.add(panel);
startMI.setEnabled(true); pauseMI.setEnabled(false);
// 设置游戏状态是初始化状态 panel.setGameState(GameState.INITIALIZE); }
private class StartAction implements ActionListener { public void actionPerformed(ActionEvent event) { startMI.setEnabled(false); pauseMI.setEnabled(true); panel.setGameState(GameState.RUN); panel.getTimer().start(); } }
private class PauseAction implements ActionListener { public void actionPerformed(ActionEvent event) { pauseMI.setEnabled(false); startMI.setEnabled(true); panel.setGameState(GameState.PAUSE); if (panel.getTimer().isRunning()) { panel.getTimer().stop(); }
} }
private class SpeedAction implements ActionListener { public void actionPerformed(ActionEvent event) { Object speed = event.getSource(); if (speed == speedMI1) { speedFlag = 1; } else if (speed == speedMI2) { speedFlag = 2; } else if (speed == speedMI3) { speedFlag = 3; } else if (speed == speedMI4) { speedFlag = 4; } else if (speed == speedMI5) { speedFlag = 5; }
panel.getTimer().setDelay(1000 - 200 * (speedFlag - 1)); } }
private class ExitAction implements ActionListener { public void actionPerformed(ActionEvent event) { int result = JOptionPane.showConfirmDialog(SnakeGameFrame.this, SnakeGameConstant.QUIT_GAME, SnakeGameConstant.SNAKE_GAME, JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { System.exit(0); } } }
private class AboutAction implements ActionListener { public void actionPerformed(ActionEvent event) { String string = SnakeGameConstant.KEYBOARDS_DESCRIPTION; JOptionPane.showMessageDialog(SnakeGameFrame.this, string); } }
}
package my.games.snake.ui;
import java.awt.Color;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.geom.Rectangle2D;import java.io.Serializable;import java.util.LinkedList;import java.util.List;import java.util.Random;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.Timer;import my.games.snake.contants.SnakeGameConstant;import my.games.snake.enums.Direction;import my.games.snake.enums.GameState;import my.games.snake.model.Grid;import my.games.snake.model.Snake;
public class SnakeGamePanel extends JPanel {
private static final long serialVersionUID = -4173775119881265176L;
private int flag[][] = new int[SnakeGameConstant.GRID_COLUMN_NUMBER][SnakeGameConstant.GRID_ROW_NUMBER];// 在一个20*30的界面中,设置每个方块的flag
private Color color[][] = new Color[SnakeGameConstant.GRID_COLUMN_NUMBER][SnakeGameConstant.GRID_ROW_NUMBER];// 在一个20*30的界面中,设置每个方块的颜色
private Snake snake;
private Grid food;
public TimerAction timerAction;
private int score;
private SnakeGameFrame frame;
private Timer timer;
private Grid grid;
private GameState gameState = GameState.INITIALIZE;
//private GameOverType gameOverType = GameOverType.TOUCH_EDGE;
private boolean needToGenerateFood = false;
public SnakeGamePanel(SnakeGameFrame frame) { for (int i = SnakeGameConstant.LEFT; i <= SnakeGameConstant.RIGHT; i++) { for (int j = SnakeGameConstant.UP; j <= SnakeGameConstant.DOWN; j++) { flag[i][j] = 0; } } addKeyListener(new KeyHandler()); setFocusable(true); init();
timerAction = new TimerAction(); timer = new Timer(1000, timerAction); score = 0; this.frame = frame; grid = new Grid(); }
private void init() { initSnake(); initFood(); }
private void initSnake() { snake = new Snake(); List<Grid> list = new LinkedList<Grid>(); list.add(new Grid(4, 1, SnakeGameConstant.SNAKE_BODY_COLOR)); list.add(0, new Grid(5, 1, SnakeGameConstant.SNAKE_HEADER_COLOR)); snake.setList(list); }
private void initFood() { food = new Grid(); needToGenerateFood = true; this.generateFoodByRandom(); }
public void setGameState(GameState state) { gameState = state; }
private void judgeGameOver() { if (isSnakeHeadTouchEdge() || isSnakeHeadTouchBody()) { gameState = GameState.OVER; int result = JOptionPane.showConfirmDialog(frame, SnakeGameConstant.GAME_OVER, SnakeGameConstant.SNAKE_GAME, JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) { for (int i = SnakeGameConstant.LEFT; i <= SnakeGameConstant.RIGHT; i++) { for (int j = SnakeGameConstant.UP; j <= SnakeGameConstant.DOWN; j++) { flag[i][j] = 0; } }
gameState = GameState.RUN; score = 0; init(); timer.start(); } else { System.exit(0); } } }
public void drawGameFrame(Graphics2D g2) {
}
public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g;
g2.draw(new Rectangle2D.Double(SnakeGameConstant.SNAKE_GAME_PANEL_LEFT, SnakeGameConstant.SNAKE_GAME_PANEL_TOP, SnakeGameConstant.SNAKE_GAME_PANEL_RIGHT, SnakeGameConstant.SNAKEGAME_PANEL_BOTTOM));
if (gameState.isInitializedState()) { return; }
draw(g2); drawScore(g); }
private void draw(Graphics2D g2) { drawSnake(g2); drawFood(g2); for (int i = SnakeGameConstant.LEFT; i <= SnakeGameConstant.RIGHT; i++) { for (int j = SnakeGameConstant.UP; j <= SnakeGameConstant.DOWN; j++) { if (flag[i][j] == 1) { grid.setX(i); grid.setY(j); grid.setColor(color[i][j]); grid.draw(g2); } } } }
private void drawScore(Graphics g) { g.drawString("Score: " + score, SnakeGameConstant.SNAKE_GAME_PANEL_RIGHT + 20, 200); }
private void drawSnake(Graphics2D g2) { snake.draw(g2); }
private void drawFood(Graphics2D g2) { food.draw(g2); }
private class KeyHandler implements KeyListener { public void keyPressed(KeyEvent event) { if (!gameState.isRunState()) { return; } int keyCode = event.getKeyCode(); switch (keyCode) { case KeyEvent.VK_LEFT: snake.changeDirection(Direction.LEFT); break;
case KeyEvent.VK_RIGHT: snake.changeDirection(Direction.RIGHT); break;
case KeyEvent.VK_UP: snake.changeDirection(Direction.UP); break;
case KeyEvent.VK_DOWN: snake.changeDirection(Direction.DOWN); break; default: break; } repaint(); }
public void keyReleased(KeyEvent event) { }
public void keyTyped(KeyEvent event) { } }
private class TimerAction implements ActionListener, Serializable {
private static final long serialVersionUID = 749074368549207272L;
public void actionPerformed(ActionEvent e) { if (!gameState.isRunState()) { return; }
generateFoodByRandom(); snake.move(); eatFood(); judgeGameOver();
repaint(); } }
private boolean isFoodAvailable(int x, int y) { for (Grid grid : snake.getList()) { if (x == grid.getX() && y == grid.getY()) { return false; } } return true; }
private void generateFoodByRandom() {
if (needToGenerateFood) { Random r = new Random(); int randomX = r.nextInt(SnakeGameConstant.GRID_COLUMN_NUMBER); int randomY = r.nextInt(SnakeGameConstant.GRID_ROW_NUMBER);
if (isFoodAvailable(randomX, randomX)) { food = new Grid(randomX, randomY, SnakeGameConstant.FOOD_COLOR);
needToGenerateFood = false; } else { generateFoodByRandom(); } } }
private boolean isSnakeHeadTouchEdge() { Grid head = this.snake.getList().get(0); if ((head.getX() >= SnakeGameConstant.GRID_COLUMN_NUMBER) || (head.getX() < 0)) { //this.gameOverType = GameOverType.TOUCH_EDGE; return true; } if ((head.getY() >= SnakeGameConstant.GRID_ROW_NUMBER) || (head.getY() < 0)) { //this.gameOverType = GameOverType.TOUCH_EDGE; return true; }
return false; }
private boolean isSnakeHeadTouchBody() { Grid head = this.snake.getList().get(0); int length = snake.getList().size();
for (int i = 1; i < length; i++) { if (head.getX() == snake.getList().get(i).getX() && head.getY() == snake.getList().get(i).getY()) { //this.gameOverType = GameOverType.TOUCH_BODY; return true; } }
return false; }
private boolean isFoodTouched() { Grid head = snake.getList().get(0); return head.getX() == food.getX() && head.getY() == food.getY(); }
private void eatFood() { if (isFoodTouched()) { Grid tail = snake.getList().get(snake.getList().size() - 1); snake.getList().add(tail); this.needToGenerateFood = true; this.score += 10;
} }
/** * @return the timer */ public Timer getTimer() { return timer; }
/** * @param timer * the timer to set */ public void setTimer(Timer timer) { this.timer = timer; }
}
完整的代码,请参考附件MySnakeGame.7z,有需要的朋友可以下载。
后续的博文将添加如下功能:
(二)添加随机障碍物。
(三)添加游戏进度的存储和读取
(四)完成游戏排行榜
... ...
Swing贪吃蛇游戏(一):基本功能实现相关推荐
- Swing贪吃蛇游戏(四):增加游戏得分排行榜功能
在上几篇博文中,介绍了 Swing贪吃蛇游戏(一):基本功能实现 >>> [url]http://mouselearnjava.iteye.com/blog/1913290[/url ...
- 基于FPGA的VGA显示对贪吃蛇游戏的设计
基于FPGA的VGA显示对贪吃蛇游戏的设计 摘要 目前,电子数码产品已经进入了人生活的方方面面,而大多数电子产品都依靠显示屏来传递信息,由此可见用电路对显示屏进行控制的研究有很大的实用价值和市场需求. ...
- 【使用java swing制作简易贪吃蛇游戏】软件实习项目二
一.项目准备 需求分析: 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后" ...
- Java项目:贪吃蛇游戏(java+swing)
源码获取:博客首页 "资源" 里下载! 功能简介: 贪吃蛇游戏 大嘴鱼洁面类.完成大嘴鱼的界面的绘制: /*** 大嘴鱼洁面类.完成大嘴鱼的界面的绘制.*/ public clas ...
- 实验二、贪吃蛇游戏开发
实验要求 实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子"以后"蛇" ...
- JAVA简易贪吃蛇游戏实现
JAVA简易贪吃蛇游戏实现 自学java不久,最近看了些GUI编程,就拿贪吃蛇练个手,很基础 刚学的 也是最简易的版本.纯粹就想通过博客记录来巩固自己的学习效果. 游戏介绍 玩家通过按键控制蛇身的移动 ...
- java从零开发贪吃蛇游戏全流程
java从零开始开发贪吃蛇 1.游戏介绍 贪吃蛇是一款经典的益智类小游戏,是最初的翻盖机里面最常见的小游戏之一,学过编程的你有没有想过自己尝试着制作一款自己的贪吃蛇呢. 接下来我将从零开始带着大家做一 ...
- 基于java的贪吃蛇游戏
贪吃蛇的游戏开发 实验内容: 1)实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右 控制"蛇"的移动,吃到"豆子"以后 ...
- JAVAJ2ME贪吃蛇游戏的设计
JAVAJ2ME贪吃蛇游戏的设计 1.包含源程序,数据库脚本.代码和数据库脚本都有详细注释. 2.课题设计仅供参考学习使用,可以在此基础上进行扩展完善 代码已经上传github,下载地址https:/ ...
最新文章
- Spring Boot整合Spring Data JPA操作数据
- Android高效加载大图、多图解决方案,有效避免程序OOM
- 用钉钉接收zabbix告警
- js 事件委托深入浅出
- 句法分析(syntactic parsing)在NLP领域的应用是怎样的
- java 线程组作用_Java线程组(ThreadGroup)使用
- RedHat gcc编译器版本升级到4.8.2支持C++11标准
- [神奇的问题啊,GetProcAddress一个不存在的API时,返回非空值,且指向另一个API]谜团解开,错不在GetProcAddress...
- hwui opengl VS skia opengl VS skia vulkan?
- 万豪联姻蚂蚁金服 结合优势打造共赢
- pycharm缩进对齐线_代码中的缩进线
- The More You Know: Using Knowledge Graphs for Image Classification 论文总结
- ME525做网络收音机和学外文用了……(安卓4.4.4系统,20190817更新)
- 油猴加idm不起作用了 油猴加idm下载百度云
- vivox50支持鸿蒙,vivo X50厚度刷新纪录:迄今为止最薄5G手机
- 关于GTP-4,这是14个被忽略的惊人细节!
- Android 实战项目汇总
- 使用Python相关技术实现对一本中文小说(自选)进行词频分析,字数不低于10万字,显示小说中出现率前50的中文词组,并用图表展示。
- python中init什么意思_python中init是什么
- inkscape制作向日葵