小游戏——贪吃蛇案例
一、案例目的
1、实现贪吃蛇游戏基本功能,屏幕上随机出现一个“食物”,称为豆子,上下左右控制“蛇”的移动,吃到“豆子”以后“蛇”的身体加长一点。
2、“蛇”碰到边界或蛇头与蛇身相撞,蛇死亡,游戏结束。
3、为游戏设计友好的交互界面;例如欢迎界面,游戏界面,游戏结束界面。要有开始键、暂停键和停止退出的选项。
4、对蛇吃到豆子进行分值计算,可以设置游戏速度,游戏音乐等拓展元素。
二、案例1、一张地图,四周有墙体。
2、一条蛇,由蛇身和蛇头组成。
3、食物,蛇吃到食物后身体变长,并且重新生成一个食物。
4、蛇需要移动,这是难实现的一个部分。
5、蛇撞到墙或者自己的身体就会死亡
6、需要能用键盘控制蛇的运动方向。
1、新建一个贪吃蛇项目,在此项目下面新建两个包,一个包存放代码,另一个包存放素材图片。
2、先用Java代码的swing框架绘制出游戏界面。
3、再在游戏界面上,绘制出游戏区域,并把两块区域调好配色。
4、找绘制蛇头、蛇身以及食物的素材,导入到素材图片的包里面,方便后面的调用。
5、利用循环语句,控制蛇身体的增长。
6、设置键盘监听,可以用键盘控制开始以及蛇上下左右的移动。
7、设置限制条件,蛇碰到自己身体和墙就会死。
8、设置计分程序。
StartGame类代码:
package li.fox; import javax.swing.*; public class StartGames { public static void main(String[] args){ JFrame frame = new JFrame("李飒宇-贪吃小狐狸"); //绘制一个静态窗口 frame.setBounds(10 , 10 , 900 , 720); //设置界面大小 frame.setResizable(false); //窗口大小不可以改变 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭事件,使得游戏可以关闭 frame.add(new GamePanel()); //游戏界面 frame.setVisible(true); //让窗口可以显示出来 } }
GamePanel类代码:
package li.fox; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Objects; import java.util.Random; public class GamePanel extends JPanel implements KeyListener, ActionListener { int length; //狐狸的长度 int[] foxX = new int[600]; //狐狸的X坐标 int[] foxY = new int[500]; //狐狸的Y坐标 String direction = "R"; boolean isStart = false; //游戏是否开始 Timer timer = new Timer(170, this); //定时器:第一个参数,就是定时执行时间 int foodx; //定义食物的坐标 int foody; Random random = new Random(); boolean isFail = false; //游戏是否结束 int score; //游戏分数 //构造器 public GamePanel() { init(); this.setFocusable(true); //获取焦点事件 this.addKeyListener(this); //键盘监听事件 timer.start(); } //初始化 public void init() { length = 3; foxX[0] = 100; foxY[0] = 100; //头部坐标 foxX[1] = 75; foxY[1] = 100; //第一节身体坐标 foxX[2] = 50; foxY[2] = 100; //第二节身体坐标 foodx = 25 + 25 * random.nextInt(34); //初始化食物数据 foody = 25 + 25 * random.nextInt(25); score = 0; //初始化游戏分数 } @Override protected void paintComponent(Graphics g) { //Graphics :画笔 super.paintComponent(g); //清屏 this.setBackground(Color.white); //设置背景的颜色 g.fillRect(18, 25, 850, 625); //绘制游戏区域 this.setForeground(Color.DARK_GRAY); //绘制狐狸的头 if (direction.equals("R")) { Data.right.paintIcon(this, g, foxX[0], foxY[0]); } else if (direction.equals("L")) { Data.left.paintIcon(this, g, foxX[0], foxY[0]); } else if (direction.equals("U")) { Data.up.paintIcon(this, g, foxX[0], foxY[0]); } else if (direction.equals("D")) { Data.down.paintIcon(this, g, foxX[0], foxY[0]); } for (int i = 1; i < length; i++) { //狐狸的身体长度通过length来控制 Data.body.paintIcon(this, g, foxX[i], foxY[i]); } //画食物 Data.food.paintIcon(this, g, foodx, foody); g.setColor(Color.red); g.setFont(new Font("微软雅黑", Font.BOLD, 18)); g.drawString("长度" + length, 750, 18); g.drawString("分数" + score, 650, 18); //游戏提示 if (isStart == false) { g.setColor(Color.white); //设置画笔的颜色 g.setFont(new Font("微软雅黑", Font.BOLD, 40)); //设置字体 g.drawString("按下空格键开始游戏!", 265, 300); } //失败判断 if (isFail) { g.setColor(Color.RED); g.setFont(new Font("微软雅黑", Font.BOLD, 40)); g.drawString("失败, 按下空格重新开始!", 235, 300); } } @Override public void keyTyped(KeyEvent e) { //键盘按下、弹起 } //键盘监听事件 @Override public void keyPressed(KeyEvent e) { //键盘按下,未释放 int keyCode = e.getKeyCode(); //获取按下的键盘是哪个键 if (keyCode == KeyEvent.VK_SPACE) { //如果是空格 if (isFail) { //如果游戏失败,从头再来! isFail = false; init(); //重新初始化 } else { //否则,暂停游戏 isStart = !isStart; } repaint(); //重新刷新界面 } //键盘控制走向 if (keyCode == KeyEvent.VK_LEFT && !Objects.equals(direction, "R")) { direction = "L"; } else if (keyCode == KeyEvent.VK_RIGHT && !Objects.equals(direction, "L")) { direction = "R"; } else if (keyCode == KeyEvent.VK_UP && !Objects.equals(direction, "D")) { direction = "U"; } else if (keyCode == KeyEvent.VK_DOWN && !Objects.equals(direction, "U")) { direction = "D"; } } @Override public void keyReleased(KeyEvent e) { //键盘释放 } //执行定时的操作 @Override public void actionPerformed(ActionEvent e) { //如果游戏处于开始状态,并且没有结束,则小蛇可以移动 if (isStart && isFail == false){ //右移:即让后一个移到前一个的位置即可 ! for (int i = length - 1; i > 0; i--) { //除了脑袋都往前移:身体移动 foxX[i] = foxX[i-1]; //即第i节(后一节)的位置变为(i-1:前一节)节的位置! foxY[i] = foxY[i-1]; } //通过方向控制,头部移动 if (direction.equals("R")){ foxX[0] = foxX[0] + 25; if (foxX[0] >= 850) { isFail = true; } } else if (direction.equals("L")){ foxX[0] = foxX[0] - 25; if (foxX[0] <= 18) { isFail = true; } } else if (direction.equals("U")){ foxY[0] = foxY[0] - 25; if (foxY[0] <= 25) { isFail = true; } } else if (direction.equals("D")){ foxY[0] = foxY[0] + 25; if (foxY[0] >= 625) { isFail = true; } } //吃食物:当蛇的头和食物一样时,算吃到食物! if (foxX[0] == foodx && foxY[0] == foody){ //长度加一 length++; //每吃一个食物,增加积分 score = score + 10; //2.重新生成食物 foodx = 25 + 25 * random.nextInt(34); foody = 25 + 25 * random.nextInt(25); } //结束判断,头和身体撞到了 for (int i = 1; i < length; i++) { //如果头和身体碰撞,那就说明游戏失败 if (foxX[i] == foxX[0] && foxY[i] == foxY[0] ){ isFail = true; } } repaint(); //需要不断的更新页面实现动画 } timer.start();//让时间动起来! } }
Data类代码:
package li.fox; import javax.swing.*; import java.net.URL; public class Data { public static URL upurl = Data.class.getResource("/statics/up.png"); //头部(向上)定位图片的地址 public static ImageIcon up = new ImageIcon(upurl); public static URL downurl = Data.class.getResource("/statics/down.png"); //头部(向下)定位图片的地址 public static ImageIcon down = new ImageIcon(downurl); public static URL lefturl = Data.class.getResource("/statics/left.png"); //头部(向左)定位图片的地址 public static ImageIcon left = new ImageIcon(lefturl); public static URL righturl = Data.class.getResource("/statics/right.png"); //头部(向右)定位图片的地址 public static ImageIcon right = new ImageIcon(righturl); public static URL bodyurl = Data.class.getResource("/statics/body.png"); //身体定位图片的地址 public static ImageIcon body = new ImageIcon(bodyurl); public static URL foodurl = Data.class.getResource("/statics/food.png"); //头部(向右)定位图片的地址 public static ImageIcon food = new ImageIcon(foodurl); }