6.失败判定、积分系统
现在先把代码折叠起来,会发现一个惊人的一个相似之处。无论加什么人功能,都是做四件事情。
添加食物:设置一个食物坐标,把它画到面板上,监听食物
画蛇:蛇的初始坐标,把蛇画上去,监听蛇
第和键盘相关的放在键盘监听里面,和游戏相关的放在事件监听里面。
一、按照步骤加一个游戏失败的判断:
- 首先得有一个游戏失败的判定
- 画数据到面板上
- 键盘监听事件,就是获得键盘的时候,空格有双重作用,isStart 肯定就不行了,先判断如果是 isFail 就重新开始,否则的话,就让他去开始或者停止。isFail 时,需要取 false ,又重新开始,需要重新初始化 init();
- 键盘监听搞定,它还有事件,我们需要去搞定事件监听
1 package com.gui.snake; 2 3 import javax.swing.*; 4 import java.awt.*; 5 import java.awt.event.ActionEvent; 6 import java.awt.event.ActionListener; 7 import java.awt.event.KeyEvent; 8 import java.awt.event.KeyListener; 9 import java.util.Random; 10 11 //游戏的面板 12 public class GamePanel extends JPanel implements KeyListener, ActionListener { 13 14 //定义蛇的数据结构 15 int length; //蛇的长度 16 int[] snakeX = new int[600]; //蛇的x坐标 25*25 17 int[] snakeY = new int[500]; //蛇的Y坐标 25*25 18 String fx; 19 20 //食物的坐标 21 int foodx; 22 int foody; 23 Random random = new Random(); 24 25 //游戏当前的状态:开始、停止 26 boolean isStart = false; //默认是不开始 27 28 boolean isFail = false;//游戏失败状态 29 30 //定时器 以毫秒为单位 1000ms = 1s 31 Timer timer = new Timer(100, this);//100ms执行一次 32 33 //构造器 34 public GamePanel() { 35 init(); 36 //获得焦点和键盘事件 37 this.setFocusable(true);//获得焦点事件 38 this.addKeyListener(this);//获得键盘监听事件:写的当前这个类,所以是this如果是其他类的话,去new一个监听器 39 timer.start();//游戏一开始,就让定时器启动 40 } 41 42 //初始化方法 43 public void init() { 44 length = 3; 45 snakeX[0] = 100;snakeY[0] = 100;//脑袋的坐标 46 snakeX[1] = 75 ;snakeY[1] = 100;//第一个身体的坐标 47 snakeX[2] = 50 ;snakeY[2] = 100;//第二个身体的坐标 48 fx = "R";//初始方向向右 49 50 //把食物随机分配在界面上 51 foodx = 25 + 25 * random.nextInt(34); 52 foody = 75 + 25 * random.nextInt(24); 53 } 54 55 //绘制面板,我们游戏中的所有东西,都是用这个画笔来画。 Ctrl+O,画组件 56 @Override 57 protected void paintComponent(Graphics g) { 58 super.paintComponent(g);//清屏的作用,不用会闪烁 59 //绘制静态的面板 60 this.setBackground(Color.WHITE); 61 Data.header.paintIcon(this, g, 25, 11);//头部广告栏画上去 62 g.fillRect(25, 75, 850, 600);//默认游戏界面 63 64 //把小蛇画上去 65 if (fx.equals("R")) { 66 Data.right.paintIcon(this, g, snakeX[0], snakeY[0]);//蛇头初始化向右,需要通过方向来判断 67 } else if (fx.equals("L")) { 68 Data.left.paintIcon(this, g, snakeX[0], snakeY[0]); 69 } else if (fx.equals("U")) { 70 Data.up.paintIcon(this, g, snakeX[0], snakeY[0]); 71 } else if (fx.equals("D")) { 72 Data.down.paintIcon(this, g, snakeX[0], snakeY[0]); 73 } 74 75 for (int i = 1; i < length; i++) { 76 Data.body.paintIcon(this, g, snakeX[i], snakeY[i]);//蛇的身体 77 } 78 79 //画食物 80 Data.food.paintIcon(this,g,foodx,foody); 81 82 83 //游戏状态 84 if (isStart == false) { 85 g.setColor(Color.white); 86 g.setFont(new Font("楷体", Font.BOLD, 40)); 87 g.drawString("按下空格开始游戏", 300, 300); 88 } 89 90 if(isFail == true){ 91 g.setColor(Color.red); 92 g.setFont(new Font("楷体", Font.BOLD, 40)); 93 g.drawString("失败,按下空格重新开始", 300, 300); 94 } 95 } 96 97 98 //键盘监听事件 99 @Override 100 public void keyPressed(KeyEvent e) { 101 int keyCode = e.getKeyCode();//获得键盘按键是哪一个 102 if (keyCode == KeyEvent.VK_SPACE) {//如果按下的是空格键 103 if (isFail){ 104 //重新开始 105 isFail = false; 106 init(); 107 }else { 108 isStart = !isStart;//取反 109 } 110 repaint();//重新绘制,因为值已经变化了 111 } 112 //小蛇移动 113 if (keyCode == KeyEvent.VK_UP) { 114 fx = "U"; 115 } else if (keyCode == KeyEvent.VK_DOWN) { 116 fx = "D"; 117 } else if (keyCode == KeyEvent.VK_LEFT) { 118 fx = "L"; 119 } else if (keyCode == KeyEvent.VK_RIGHT) { 120 fx = "R"; 121 } 122 } 123 124 //事件监听---需要通过固定的时间来刷新,1s=10次 125 @Override 126 public void actionPerformed(ActionEvent e) { 127 if (isStart && isFail == false) {//如果游戏不处于失败状态,并且是开始状态,就让小蛇动起来! 128 129 //吃食物 130 if(snakeX[0] == foodx && snakeY[0] == foody){ 131 length++;//长度 + 1 132 //再次随机食物 133 foodx = 25 + 25 * random.nextInt(34); 134 foody = 75 + 25 * random.nextInt(24); 135 } 136 137 //移动 138 for (int i = length - 1; i > 0; i--) {//后一节移到前一节的位置 snake[1] = snake [0]; 139 snakeX[i] = snakeX[i - 1]; 140 snakeY[i] = snakeY[i - 1]; 141 } 142 143 //走向 144 if (fx.equals("R")) { 145 snakeX[0] = snakeX[0] + 25; 146 if (snakeX[0] > 850) { snakeX[0] = 25; }//边界判断 147 } else if (fx.equals("L")) { 148 snakeX[0] = snakeX[0] - 25; 149 if (snakeX[0] < 25) { snakeX[0] = 850; }//边界判断 150 } else if (fx.equals("U")) { 151 snakeY[0] = snakeY[0] - 25; 152 if (snakeY[0] < 75) { snakeY[0] = 650; }//边界判断 153 } else if (fx.equals("D")) { 154 snakeY[0] = snakeY[0] + 25; 155 if (snakeY[0] > 650) { snakeY[0] = 75; }//边界判断 156 } 157 158 //失败判定,撞到自己就算失败 159 for (int i = 1; i <length ; i++) { 160 if(snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]){ 161 isFail = true; 162 } 163 } 164 165 repaint();//重画页面 166 } 167 timer.start(); 168 } 169 170 @Override 171 public void keyReleased(KeyEvent e) { 172 } 173 174 @Override 175 public void keyTyped(KeyEvent e) { 176 } 177 }
测试游戏失败:
解决问题:
食物在身体上边的原因:代码顺序,把画食物的代码,放在在画小蛇前面,小蛇把食物吃掉就没了。
二、积分展示:
- 定义数据,放到初始化方法里面
- 画到面板上
- 吃食物的时候,每吃一个食物,分数加10
测试分数系统: