贪吃蛇游戏的设计步骤:
Part 1:
设计游戏图纸
画出900*700的白色窗口
在窗口上添加画布
在画布上添加标题
在画布上添加黑色游戏区
Part 2:
放置静态的蛇:一个头、两个身体
加上开始提示:按空格键开始游戏
让蛇动起来:监听Timer事件,平移数据
实现游戏暂停
实现转向功能
Part 3:
添加食物
吃掉食物
添加死亡条件
实现“重新开始”功能
添加分数和长度
游戏图纸如下:
蛇及游戏框的素材如下:
图片下载地址 链接:https://pan.baidu.com/s/1jH6xnXc 密码:hqze
Snake主类:
1 package snake; 2 3 import javax.swing.JFrame; 4 import javax.swing.JPanel; 5 6 public class Snake { 7 8 public static void main(String[] args) { 9 10 JFrame frame = new JFrame(); // 创建一个游戏界面的框架 11 frame.setBounds(10, 10, 900, 720); // 设置框架的大小 12 frame.setResizable(false); // 设置框架大小为不能改变 13 // 点击关闭按钮 关闭游戏界面 14 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 15 16 SnakePanel panel = new SnakePanel(); //添加画布 17 frame.add(panel); // 刚添加时画布是空的看不到 18 19 frame.setVisible(true); // 允许显示游戏界面 20 } 21 22 }
SnakePanel类:
1 package snake; 2 3 import java.awt.Color; 4 import java.awt.Font; 5 import java.awt.Graphics; 6 import java.awt.event.ActionEvent; 7 import java.awt.event.ActionListener; 8 import java.awt.event.KeyEvent; 9 import java.awt.event.KeyListener; 10 import java.util.Random; 11 12 import javax.swing.ImageIcon; 13 import javax.swing.JPanel; 14 import javax.swing.Timer; 15 16 public class SnakePanel extends JPanel implements KeyListener,ActionListener{ 17 18 // 定义七个图片变量,代表七张图片 19 ImageIcon up = new ImageIcon("up.png"); // 向上的蛇头 20 ImageIcon down = new ImageIcon("down.png"); // 向下的蛇头 21 ImageIcon left = new ImageIcon("left.png"); // 向左的蛇头 22 ImageIcon right = new ImageIcon("right.png"); // 向右的蛇头 23 ImageIcon food = new ImageIcon("food.png"); // 食物 24 ImageIcon body = new ImageIcon("body.png"); // 蛇的身体 25 ImageIcon title = new ImageIcon("title.jpg"); // 游戏界面的主题 26 27 // 蛇的每一部分 28 int[] snakex = new int [750]; 29 int[] snakey = new int [750]; 30 31 // 随机生成食物 32 Random rand = new Random(); 33 int foodx = rand.nextInt(34)*25+25; //此处的数值根据自己设计的游戏界面的大小来确定 34 int foody = rand.nextInt(24)*25+75; 35 36 // 设置游戏的默认属性 37 int len = 3; 38 int score = 0; 39 String direction = "R"; // U上 D下 L左 R右 40 41 boolean isStarted = false; // 判断游戏是否开始 42 boolean isFailed = false; // 判断游戏是否结束 43 44 Timer timer = new Timer(100,this); // 每100毫秒调用一次ActionPerformed 45 46 47 public SnakePanel() { // 建造画布的构造函数 48 this.setFocusable(true); // 获取焦点 49 this.addKeyListener(this); // 监听键盘事件 50 setup(); 51 timer.start(); 52 } 53 54 public void paint(Graphics g) { // Graphics 画笔 55 56 this.setBackground(Color.BLACK); // 设置画布背景颜色 57 title.paintIcon(this, g, 25, 11);// 放置主题图片 58 g.fillRect(25, 75, 850, 650); // 用画笔设置游戏方框 59 60 // 画蛇头(注意判断蛇头的方向) 61 if (direction.equals("R")) 62 right.paintIcon(this, g, snakex[0], snakey[0]); 63 else if (direction.equals("L")) 64 left.paintIcon(this, g, snakex[0], snakey[0]); 65 else if (direction.equals("U")) 66 up.paintIcon(this, g, snakex[0], snakey[0]); 67 else if (direction.equals("D")) 68 down.paintIcon(this, g, snakex[0], snakey[0]); 69 70 // 画蛇的身体 71 for(int i = 1; i < len; i ++) 72 body.paintIcon(this, g, snakex[i], snakey[i]); 73 74 // 判断如果游戏没开始显示。。。 75 if (!isStarted){ 76 g.setColor(Color.WHITE); 77 g.setFont(new Font("arial",Font.BOLD, 30)); 78 g.drawString("Press Space to start / pause", 200, 300); 79 } 80 81 // 判断如果游戏结束显示。。。 82 if (isFailed){ 83 g.setColor(Color.WHITE); 84 g.setFont(new Font("arial",Font.BOLD, 30)); 85 g.drawString("Game Over ! Press space to restart", 200, 300); 86 } 87 88 // 显示食物 89 food.paintIcon(this, g, foodx, foody); 90 91 // 设置分数和蛇的长度 92 g.setColor(Color.WHITE); 93 g.setFont(new Font("arial",Font.PLAIN,15)); 94 g.drawString("Score : "+score, 650, 37); 95 g.drawString("Len :"+len, 650, 57); 96 } 97 98 public void setup() { // 游戏初始化 99 isStarted = false; 100 isFailed = false; 101 len = 3; 102 score = 0; 103 snakex[0] = 100; snakex[1] = 75; snakex[2] = 50; 104 snakey[0] = 100; snakey[1] = 100; snakey[2] = 100; 105 } 106 107 @Override 108 public void keyPressed(KeyEvent e) { 109 110 //实现键盘响应 111 int KeyCode = e.getKeyCode(); 112 if (KeyCode == KeyEvent.VK_SPACE){ // 敲击空格现实/消除提示信息 113 if (isFailed){ 114 // isStarted = false; // 可以将这两行放入setup中 115 // isFailed = false; 116 setup(); 117 }else 118 isStarted = !isStarted; 119 } else if (KeyCode == KeyEvent.VK_UP && direction != "D") 120 direction = "U"; 121 else if (KeyCode == KeyEvent.VK_DOWN && direction != "U" ) 122 direction = "D"; 123 else if (KeyCode == KeyEvent.VK_RIGHT && direction != "L") 124 direction = "R"; 125 else if (KeyCode == KeyEvent.VK_LEFT && direction != "R") 126 direction = "L"; 127 } 128 129 @Override 130 public void actionPerformed(ActionEvent e) { 131 // 1. 再定义一个闹钟 132 timer.start(); 133 134 // 2. 移动数据 135 if (isStarted && !isFailed){ 136 // 移动身体 137 for (int i = len; i>0; i--){ 138 snakex[i] = snakex[i-1]; 139 snakey[i] = snakey[i-1]; 140 } 141 // 移动头 142 if (direction.equals("R")){ 143 snakex[0] = snakex[0] + 25; 144 if(snakex[0] > 850) snakex[0] = 25; 145 }else if (direction.equals("L")){ 146 snakex[0] = snakex[0] - 25; 147 if(snakex[0] < 25) snakex[0] = 850; 148 }else if (direction.equals("U")){ 149 snakey[0] = snakey[0] - 25; 150 if (snakey[0] < 75) snakey[0] = 650; 151 }else if (direction.equals("D")){ 152 snakey[0] = snakey[0] + 25; 153 if (snakey[0] > 650) snakey[0] = 75; 154 } 155 156 if (snakex[0] == foodx && snakey[0] == foody){ // 吃食物 157 len ++; 158 score ++; 159 foodx = rand.nextInt(34)*25+25; 160 foody = rand.nextInt(24)*25+75; 161 } 162 163 for (int i = 1; i < len; i ++){ // 如果蛇头碰到自己的身体游戏结束 164 if (snakex[0] == snakex[i] && snakey[0] == snakey[i]){ 165 isFailed = true; 166 } 167 } 168 169 } 170 // 3. repaint() 171 repaint(); 172 } 173 174 @Override 175 public void keyTyped(KeyEvent e) { 176 177 } 178 179 @Override 180 public void keyReleased(KeyEvent e) { 181 182 } 183 }