JAVA程序设计(16)----- 贪食蛇游戏制作 LinkedList 初级应用
2014-11-17 23:37
381 查看
主要是LinkedList应用,JFrame,HAS-A的组合关系,Timer应用,键盘监听器(适配器)应用,方法的重写 等练习
原始制作顺序为:
面板 1.SnakeFrame -------> 可动的点 2.Snake ------> 然后在Snake上加入方向3. Dirction --------> Snake 加入LinkedList 做成连续的蛇 并制作单节蛇 4. SnakeNode------------>制作可以吃的5.Egg ,将游戏中硬代码提出 写成6.SnakeContext 。
1.SnakeFrame部分
2.Snake部分
3.Dirction方向枚举
4.
5.Egg 可以吃的蛋蛋 呵呵
6.硬代码的去除
到此为止游戏制作完成,而且能够完美运行。不过尚有一个小BUG 手速快的朋友找找看 呵呵~~O(∩_∩)O~
原始制作顺序为:
面板 1.SnakeFrame -------> 可动的点 2.Snake ------> 然后在Snake上加入方向3. Dirction --------> Snake 加入LinkedList 做成连续的蛇 并制作单节蛇 4. SnakeNode------------>制作可以吃的5.Egg ,将游戏中硬代码提出 写成6.SnakeContext 。
1.SnakeFrame部分
package com.lovo.snake; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.Timer; /** * 类:贪食蛇 面板 * @author Abe */ @SuppressWarnings("serial") public class SnakeFrame extends JFrame { private Timer timer; private Image offImage = new BufferedImage(SnakeContext.GAME_SIZE, SnakeContext.GAME_SIZE, 1); private Snake snake = new Snake(); private Egg egg = new Egg(); private int counter = 0; private JLabel jl; private int level = 0; private boolean gameOver = false; /** * 构造器 初始化 */ public SnakeFrame() { this.setSize(SnakeContext.GAME_SIZE, SnakeContext.GAME_SIZE); this.setResizable(false); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setLayout(null); jl = new JLabel("分数:" + counter + "分"); jl.setBounds(50, 0, 400, 25); this.add(jl); /** * 键盘监听器 */ this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { Direction newDir = snake.getDir(); switch (e.getKeyCode()) { case KeyEvent.VK_W: case KeyEvent.VK_UP: newDir = Direction.UP; break; case KeyEvent.VK_S: case KeyEvent.VK_DOWN: newDir = Direction.DOWN; break; case KeyEvent.VK_A: case KeyEvent.VK_LEFT: newDir = Direction.LEFT; break; case KeyEvent.VK_D: case KeyEvent.VK_RIGHT: newDir = Direction.RIGHT; break; } if (snake.getDir() != newDir) { snake.changeDir(newDir); } } }); /** * F2 重置游戏键盘监听器(可写在上面一起)单独好看点 */ this.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { int obj = e.getKeyCode(); if (obj == KeyEvent.VK_F2) { for (int i = 0; i < snake.getLength(); i++) { snake.remove(); } snake = new Snake(); counter = 0; timer.start(); repaint(); gameOver = false; } } }); /** * Timer */ timer = new Timer(SnakeContext.INTERVAL, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Object obj = e.getSource(); if (obj == timer && gameOver == false) { snake.move(); SnakeNode tempHead = snake.getHead(); if (!snake.eatEgg(egg)) { snake.remove(); jl.setText("分数:" + counter + "分"+ " 按F2可刷新游戏"); } else { counter += 100; do { egg = new Egg(); } while (isRepeat(0,egg.getX(), egg.getY())); if (counter % 100 == 0) { if (level < 200) { level += 20; } timer.setDelay(SnakeContext.INTERVAL); } } repaint(); /** * 死亡判定,撞墙 撞自己 */ int x = tempHead.getX(); int y = tempHead.getY(); if ((x < SnakeContext.WALL_X) || (x > SnakeContext.WALL_X + SnakeContext.SQUARE_SIZE - SnakeContext.SNAKE_SIZE) || (y < SnakeContext.WALL_Y) || (y > SnakeContext.WALL_Y + SnakeContext.SQUARE_SIZE - SnakeContext.SNAKE_SIZE)) { timer.stop(); gameOver = true; } else if (isRepeat(1,x, y)) { timer.stop(); gameOver = true; } } } }); timer.start(); } /** * 方法:输入坐标筛查重复 */ public boolean isRepeat(int firstIndex,int x, int y) { for (int i = firstIndex; i < snake.getList().size(); i++) { SnakeNode temp = snake.getList().get(i); if (temp.getX() == x && temp.getY() == y) { return true; } } return false; } /** * 重写:绘图方法 */ @Override public void paint(Graphics g) { Graphics offG = offImage.getGraphics(); // 所有的画笔换成offG super.paint(offG); Graphics2D g2d = (Graphics2D) offG; offG.setColor(Color.black); g2d.setStroke(new BasicStroke(5)); offG.drawRect(SnakeContext.WALL_X, SnakeContext.WALL_Y, SnakeContext.SQUARE_SIZE, SnakeContext.SQUARE_SIZE); g2d.setStroke(new BasicStroke(1)); snake.draw(offG); egg.draw(offG); g.drawImage(offImage, 0, 0, null); } /** * main方法 窗口可见 * @param args */ public static void main(String[] args) { new SnakeFrame().setVisible(true); } }
2.Snake部分
package com.lovo.snake; import java.awt.Graphics; import java.util.LinkedList; /** * 类:蛇 * @author Abe 属性:X Y 坐标 */ public class Snake { private Direction dir = Direction.RIGHT; private LinkedList<SnakeNode> list = new LinkedList<SnakeNode>(); /** * 构造器 */ public Snake(){ for (int i = 0; i < SnakeContext.SNAKE_LENGTH; i++) { list.add(new SnakeNode(SnakeContext.SNAKE_X , SnakeContext.SNAKE_Y + i * SnakeContext.SNAKE_SIZE)); } } /** * 方法:改变方向 * @param newDir */ public void changeDir(Direction newDir) { if (!((dir == Direction.LEFT && newDir == Direction.RIGHT) || (dir == Direction.RIGHT && newDir == Direction.LEFT) || (dir == Direction.UP && newDir == Direction.DOWN) || (dir == Direction.DOWN && newDir == Direction.UP))) { dir = newDir; } } /** * 方法:获得现在方向 * @return */ public Direction getDir() { return dir; } /** * 获得蛇头 */ public SnakeNode getHead(){ return list.get(0); } /** * 获得长度 * @return */ public int getLength(){ return list.size(); } /** * 方法:移动 */ public void move() { SnakeNode head = getHead(); int x = head.getX(); int y = head.getY(); switch(dir){ case UP: y -= SnakeContext.SPEED;break; case DOWN: y += SnakeContext.SPEED;break; case LEFT: x -= SnakeContext.SPEED;break; case RIGHT: x += SnakeContext.SPEED;break; } list.addFirst(new SnakeNode(x, y)); } /** * 方法:移出最后一个 */ public void remove(){ list.removeLast(); } /** * 方法:绘制蛇身上有节点 */ public void draw(Graphics g){ for(SnakeNode tempNode : list){ tempNode.draw(g); } } /** * 吃蛋 * @return */ public boolean eatEgg(Egg egg){ SnakeNode head = getHead(); return head.getX() == egg.getX() && head.getY() == egg.getY(); } public LinkedList<SnakeNode> getList() { return list; } }
3.Dirction方向枚举
package com.lovo.snake; /** * 枚举:上下左右 * @author Abe */ public enum Direction { UP,DOWN,LEFT,RIGHT }
4.
package com.lovo.snake; import java.awt.Color; import java.awt.Graphics; /** * 类:单节的蛇 * @author Abe * */ public class SnakeNode { private int x; private int y; private int size = SnakeContext.SNAKE_SIZE; /** * 构造器 * @param x * @param y */ public SnakeNode(int x, int y) { this.x = x; this.y = y; } /** * 获得蛇 节点横纵坐标 * * @return */ public int getX() { return x; } public int getY() { return y; } /** * 方法:绘制蛇身上有节点 */ public void draw(Graphics g) { g.setColor(Color.green); g.fillRect(x, y, size, size); g.setColor(Color.black); g.drawRect(x, y, size, size); } }
5.Egg 可以吃的蛋蛋 呵呵
package com.lovo.snake; import java.awt.Color; import java.awt.Graphics; /** * 蛋 * @author Abe */ public class Egg { private int x, y; private int size = SnakeContext.EGG_SIZE; /** * 构造器:将中间的游戏进行面板等分,在节点上随机位置出现Egg */ public Egg() { x = ((int) (Math.random() * (SnakeContext.SQUARE_SIZE / SnakeContext.SNAKE_SIZE)) * SnakeContext.SNAKE_SIZE + (SnakeContext.WALL_X)); y = ((int) (Math.random() * (SnakeContext.SQUARE_SIZE / SnakeContext.SNAKE_SIZE)) * SnakeContext.SNAKE_SIZE + (SnakeContext.WALL_Y)); } /** * 绘制蛋蛋 * @param g */ public void draw(Graphics g) { g.setColor(Color.orange); g.fillOval(x, y, size, size); } /** * 获得蛋蛋的横纵坐标 * @return */ public int getX() { return x; } public int getY() { return y; } }
6.硬代码的去除
package com.lovo.snake; /** * 类:硬代码数据提出专门编写一类 方便修改 * @author Abe * */ public class SnakeContext { /** * 蛇的大小 */ public static final int SNAKE_SIZE = 25; /** * 蛋的大小 */ public static final int EGG_SIZE = SNAKE_SIZE; /** * 蛇的长度 */ public static final int SNAKE_LENGTH = 5; /** * 蛇的初始位置 * 要人为计算好初始位置,处于节点上,不然没法吃蛋。 * 如果愿意,也可以将XY坐标通过运算强制转到节点上,这只是数学问题了,懒得做了。 * 具体还是: X / 单份长度 * 单份长度 + 初始位置 */ public static final int SNAKE_X = 250; public static final int SNAKE_Y = 250; /** * 蛇的初始速度 */ public static final int SPEED = SNAKE_SIZE; /** * 游戏窗口大小 */ public static final int GAME_SIZE = 600; /** * 游戏场地大小 */ public static final int SQUARE_SIZE = 500; /** * 刷新周期 */ pub a170 lic static final int INTERVAL = 300; /** * 围墙起点坐标 */ public static final int WALL_X = 50; public static final int WALL_Y = 50; }
到此为止游戏制作完成,而且能够完美运行。不过尚有一个小BUG 手速快的朋友找找看 呵呵~~O(∩_∩)O~
相关文章推荐
- JAVA程序设计(08)-----数组初级应用 排序
- JAVA程序设计(12.2)---- 多态、监听器初级应用:在窗口中绘制图形,可以选择圆形 正方形 线条
- 新手上路:JDBC初级应用实例(一)
- DirectDraw6的初级编程应用 —— 配合实例讲解,让你迅速入门
- skin的初级应用[制作skin][应用skin][编程使用skin]
- Apache Axis初级教程---安装、应用
- JDBC初级应用实例(二)
- ajax初级应用
- 新手上路:JDBC初级应用实例(二)
- Javascript初级应用之一
- GridView初级自定义应用
- 最初级的MS SQL Server DTS应用示例。
- JDBC初级应用实例(一)
- AJAX初级应用-RSS无刷新聚合器的代码与下载第1/3页
- Windows Gdi入门初级应用
- JDBC初级应用实例(二)
- 原创]Windows Gdi入门初级应用(VC SDK)
- XML初级应用ABC
- 新手上路:JDBC初级应用实例(一)
- JDBC初级应用实例(一)