admin管理员组文章数量:1794759
用java写一个贪吃蛇小游戏(源码在最后)
一、引入
涉及技能:
GUI中的组件: 7.1 窗口 7.2 弹窗 7.3 面板 7.4 文本框 7.5 列表框 7.6 按钮 7.7 图片 7.8 交互的事件:监听事件(鼠标事件,键盘事件)
GUI技术,不流行了!!!界面太简单粗糙!!
已经被淘汰了,为什么还学?
注意: 学的是 思想!!!
二、原理图小蛇素材图像素为25*25,因此在对应xy轴上的数值也以25为步长。
三、进入正题1.打开IDEA工具,新建一个模块module。 2.选择java,点next。 3.取一个名字叫TestSnake,然后点击finish。 4.打开新建好的TestSnake,在src下新建一个文件夹,取名为images。 5.将所有的素材图片复制到images文件夹下。
四、将图片加载到程序中1.在src下再新建一个文件夹com.game,在这个文件夹下新建一个类Images,用于获取图片。 2.打开Images类,将以下代码写入,封装图片,后续使用时只要类名+图片即可。
import javax.swing.*; import java.URL; /*用来获取游戏中所有涉及的图片*/ public class Images { /*面向对象思想:将图片进行封装,封装为一个对象,在程序中通过操纵这个对象来操纵图片*/ /*将图片的路径封装为一个对象:*/ // class获取字节码 // getResource获取图片路径 // 在菜单Build下选中第二个Build Module,重写构建一下,生成对应的字节码信 // 在out文件夹下找图片路径 // '/'指代相对路径,相对file:/C:/Users/ASUS/Desktop/贪吃蛇小游戏/out/production/TestSnake/而言 public static URL bodyURL=Images.class.getResource("/images/body.png"); /*将图片封装为程序中一个对象:*/ // ImageIcon构造器,可以直接把url传进去 public static ImageIcon bodyImg=new ImageIcon(bodyURL); /*同理,将剩下的图片都封装:*/ public static URL downURL=Images.class.getResource("/images/down.png"); public static ImageIcon downImg=new ImageIcon(downURL); public static URL foodURL=Images.class.getResource("/images/food.png"); public static ImageIcon foodImg=new ImageIcon(foodURL); public static URL headerURL=Images.class.getResource("/images/header.png"); public static ImageIcon headerImg=new ImageIcon(headerURL); public static URL leftURL=Images.class.getResource("/images/left.png"); public static ImageIcon leftImg=new ImageIcon(leftURL); public static URL rightURL=Images.class.getResource("/images/right.png"); public static ImageIcon rightImg=new ImageIcon(rightURL); public static URL upURL=Images.class.getResource("/images/up.png"); public static ImageIcon upImg=new ImageIcon(upURL); }3.关于代码注释中的“在菜单Build下选中第二个Build Module,重写构建一下,生成对应的字节码信”、“ 在out文件夹下找图片路径”的操作,具体步骤如下:
五、创建窗体1.在com.game文件夹下新建一个类,叫StartGame。 2.将以下代码写入StartGame类中。
package com.game; import javax.swing.*; import java.awt.*; public class StartGame { public static void main(String[] args) { /*1.创建一个窗体:*/ JFrame jf=new JFrame(); /*2.给窗体设置一个标题:*/ jf.setTitle("贪吃蛇小游戏 by:cym"); /*3.设置窗体弹出的坐标,对应窗体的宽和高:*/ // 获取屏幕的宽、高 int width = Toolkit.getDefaultToolkit().getScreenSize().width; int height = Toolkit.getDefaultToolkit().getScreenSize().height; jf.setBounds((width-800)/2,(height-800)/2,800,800); /*4.设置窗体大小不可调:*/ jf.setResizable(false); /*5.关闭窗口的同时,程序随之关闭:*/ jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); /*默认情况下窗体隐藏,需要进行显现(最好放在最后):*/ jf.setVisible(true); } }3.计算窗体在屏幕居中的方法如下:
六、创建面板1.新建一个类GamePanel。 2.将以下代码写入GamePanel类中。
package com.game; import javax.swing.*; import java.awt.*; /*面板*/ //继承JPanel才具备面板的功能,才成为一个面板 public class GamePanel extends JPanel { /*此方法特殊,就相当于图形版的main方法,自动调用*/ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); /*1.填充背景颜色:*/ // 颜色由rgb(red green blue)组成 // 可通过点击左边行号旁的色块进行颜色修改 this.setBackground(new Color(243, 239, 190, 255)); /*2.画头部的图片header.png:*/ // Images.headerImg:调用图片类中的header.png图片 // paintIcon()方法将图片在面板中绘制出来 // this:当前面板 // g:使用的画笔 // x、y:对应坐标轴 Images.headerImg.paintIcon(this, g, 15, 10); /*3.画一个矩形:*/ // 先调节画笔颜色: g.setColor(new Color(195, 205, 246)); // fillRect填充矩形 g.fillRect(15, 70, 750, 670); } }3.在StartGame类中添加第6 步创建面板,将面板添加到窗体中。
package com.game; import javax.swing.*; import java.awt.*; /*窗体*/ public class StartGame { public static void main(String[] args) { /*1.创建一个窗体:*/ JFrame jf = new JFrame(); /*2.给窗体设置一个标题:*/ jf.setTitle("贪吃蛇小游戏 by:cym"); /*3.设置窗体弹出的坐标,对应窗体的宽和高:*/ // 获取屏幕的宽、高 int width = Toolkit.getDefaultToolkit().getScreenSize().width; int height = Toolkit.getDefaultToolkit().getScreenSize().height; jf.setBounds((width - 800) / 2, (height - 800) / 2, 800, 800); /*4.设置窗体大小不可调:*/ jf.setResizable(false); /*5.关闭窗口的同时,程序随之关闭:*/ jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); /*6.创建面板:*/ GamePanel gp=new GamePanel(); // 将面板放入窗体中: jf.add(gp); /*默认情况下窗体隐藏,需要进行显现(最好放在最后):*/ jf.setVisible(true); } } 七、画静态小蛇1.以这个图为例,做为一个默认小蛇,一个头,两节身子。 2.在面板类中的paintComponent()方法外部,写入以下代码。
/*定义两个数组: * 一个数组,专门存储蛇的x轴坐标 * 一个数组,专门存储蛇的y轴坐标 * */ int[] snakeX=new int[200]; int[] snakeY=new int[200]; /*定义蛇的长度:*/ int length; /*自定义一个初始化方法,初始化小蛇的坐标:*/ public void init(){ /*初始化蛇的长度:*/ length=3; /*初始化蛇头坐标:*/ snakeX[0]=175; snakeY[0]=275; /*初始化第一节身子坐标:*/ snakeX[1]=150; snakeY[1]=275; /*初始化第二节身子坐标:*/ snakeX[2]=125; snakeY[2]=275; } /*构造器,调用一下小蛇默认方法init(),进行面板初始化的时候就默认了蛇的位置:*/ public GamePanel(){ init(); }3.在面板类中的paintComponent()方法内部,写第4步画小蛇,详见以下代码。
/*4.画小蛇:*/ // 画蛇头: Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]); 画第一节身子: // Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]); 画第二节身子: // Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]); // 用循环来画蛇身子: for(int i=1;i<length;i++){ Images.bodyImg.paintIcon(this,g,snakeX[i],snakeY[i]); } 八、将蛇头按照行走方向改变1.定义蛇头的方向,代码如下。
/*定义两个数组: * 一个数组,专门存储蛇的x轴坐标 * 一个数组,专门存储蛇的y轴坐标 * */ int[] snakeX=new int[200]; int[] snakeY=new int[200]; /*定义蛇的长度:*/ int length; /*定义蛇的行走方向:*/ String direction; /*自定义一个初始化方法,初始化小蛇的坐标:*/ public void init(){ /*初始化蛇的长度:*/ length=3; /*初始化蛇头坐标:*/ snakeX[0]=175; snakeY[0]=275; /*初始化第一节身子坐标:*/ snakeX[1]=150; snakeY[1]=275; /*初始化第二节身子坐标:*/ snakeX[2]=125; snakeY[2]=275; /*初始化蛇头的方向为右:*/ direction="R";//上U 下D 左L 右R }2.根据不同方向画蛇头,代码如下。
/*4.画小蛇:*/ // 画蛇头: if("R".equals(direction)){ Images.rightImg.paintIcon(this,g,snakeX[0],snakeY[0]); } if("L".equals(direction)){ Images.leftImg.paintIcon(this,g,snakeX[0],snakeY[0]); } if("U".equals(direction)){ Images.upImg.paintIcon(this,g,snakeX[0],snakeY[0]); } if("D".equals(direction)){ Images.downImg.paintIcon(this,g,snakeX[0],snakeY[0]); } 九、加入监听,空格来控制游戏是否开始具体代码如下:
/*游戏只有两个状态:开始、暂停*/ boolean isStart=false;//默认游戏为暂停状态 /*构造器,调用一下小蛇默认方法init(),进行面板初始化的时候就默认了蛇的位置:*/ public GamePanel(){ init(); // 将焦点定位在当前操作的面板上 this.setFocusable(true); // 加入监听: // addKeyListener表示加入键盘监听 this.addKeyListener(new KeyAdapter() {//涉及到适配器模式 // 监听键盘按下操作 @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); int keyCode = e.getKeyCode(); // System.out.println(keyCode);//空格对应32 if (keyCode==32){ // System.out.println("点击了空格"); isStart=!isStart;//点击了空格,将isStart变成相反的状态 repaint();//重绘,调用paintComponent方法 } } }); } /*5.如果游戏是暂停的,界面中间有一个提示语*/ if(isStart==false){ /*画一个文字:*/ // 画笔设置颜色 g.setColor(new Color(250, 3, 3)); // 设置文字的字体、加粗、大小 g.setFont(new Font("微软雅黑",Font.BOLD,40)); // 画文字: // drawString()方法,画字符串 // 文字内容、xy轴坐标 g.drawString("点击空格开始游戏",250,330); } 十、小蛇向右动起来具体代码如下:
/*加入一个定时器:*/ Timer timer; /*构造器,调用一下小蛇默认方法init(),进行面板初始化的时候就默认了蛇的位置:*/ public GamePanel(){ init(); // 将焦点定位在当前操作的面板上 this.setFocusable(true); // 加入监听: // addKeyListener表示加入键盘监听 this.addKeyListener(new KeyAdapter() {//涉及到适配器模式 // 监听键盘按下操作 @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); int keyCode = e.getKeyCode(); // System.out.println(keyCode);//空格对应32 if (keyCode==32){ // System.out.println("点击了空格"); isStart=!isStart;//点击了空格,将isStart变成相反的状态 repaint();//重绘,调用paintComponent方法 } } }); /*对定时器做初始化:*/ // 延迟毫秒数、一个ActionListener类对象 timer=new Timer(100, new ActionListener() {//创建ActionListener对象,一个匿名内部类 // ActionListener是 事件监听 // 相当于每100ms监听你是否发生一个动作 // 具体动作放入actionPerformed中 @Override public void actionPerformed(ActionEvent e) { if(isStart){//游戏开始状态下才动 // 由最后一节身子往前一节身子上动 for(int i=length-1;i>0;i--){ snakeX[i]=snakeX[i-1]; snakeY[i]=snakeY[i-1]; } // 动头的位置 snakeX[0]+=25; // 防止蛇超出边界: if(snakeX[0]>750){ snakeX[0]=25; } repaint();//重绘,根据新的蛇头蛇身的位置画 } } }); // 启动计时器 timer.start(); } 十一、小蛇上下左右动起来代码如下:
/*构造器,调用一下小蛇默认方法init(),进行面板初始化的时候就默认了蛇的位置:*/ public GamePanel(){ init(); // 将焦点定位在当前操作的面板上 this.setFocusable(true); // 加入监听: // addKeyListener表示加入键盘监听 this.addKeyListener(new KeyAdapter() {//涉及到适配器模式 // 监听键盘按下操作 @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); int keyCode = e.getKeyCode(); // System.out.println(keyCode);//空格对应32 /*监听空格:*/ if (keyCode==KeyEvent.VK_SPACE){//将空格32封装起来 // System.out.println("点击了空格"); isStart=!isStart;//点击了空格,将isStart变成相反的状态 repaint();//重绘,调用paintComponent方法 } /*监听向上箭头:*/ if (keyCode==KeyEvent.VK_UP){ direction="U"; } /*监听向下箭头:*/ if (keyCode==KeyEvent.VK_DOWN){ direction="D"; } /*监听向左箭头:*/ if (keyCode==KeyEvent.VK_LEFT){ direction="L"; } /*监听向右箭头:*/ if (keyCode==KeyEvent.VK_RIGHT){ direction="R"; } } }); /*对定时器做初始化:*/ // 延迟毫秒数、一个ActionListener类对象 timer=new Timer(100, new ActionListener() {//创建ActionListener对象,一个匿名内部类 // ActionListener是 事件监听 // 相当于每100ms监听你是否发生一个动作 // 具体动作放入actionPerformed中 @Override public void actionPerformed(ActionEvent e) { if(isStart){//游戏开始状态下才动 // 由最后一节身子往前一节身子上动 for(int i=length-1;i>0;i--){ snakeX[i]=snakeX[i-1]; snakeY[i]=snakeY[i-1]; } // 动头的位置 if("R".equals(direction)){ snakeX[0]+=25; } if("L".equals(direction)){ snakeX[0]-=25; } if("U".equals(direction)){ snakeY[0]-=25; } if("D".equals(direction)){ snakeY[0]+=25; } // 防止蛇超出边界: if(snakeX[0]>745){ snakeX[0]=25; } if (snakeX[0]<25) { snakeX[0]=745; } if(snakeY[0]<70){ snakeY[0]=700; } if(snakeY[0]>700){ snakeY[0]=70; } repaint();//重绘,根据新的蛇头蛇身的位置画 } } }); // 启动计时器 timer.start(); } 十二、画食物、吃食物1.画食物代码:
/*定义食物的xy轴坐标*/ int foodX,foodY; /*自定义一个初始化方法,初始化小蛇的坐标:*/ public void init(){ /*初始化蛇的长度:*/ length=3; /*初始化蛇头坐标:*/ snakeX[0]=175; snakeY[0]=275; /*初始化第一节身子坐标:*/ snakeX[1]=150; snakeY[1]=275; /*初始化第二节身子坐标:*/ snakeX[2]=125; snakeY[2]=275; /*初始化蛇头的方向为右:*/ direction="R";//上U 下D 左L 右R /*初始化食物的坐标:*/ foodX=300; foodY=200; } /*6.画食物:*/ Images.foodImg.paintIcon(this,g,foodX,foodY);2.吃食物代码:
/*对定时器做初始化:*/ // 延迟毫秒数、一个ActionListener类对象 timer=new Timer(100, new ActionListener() {//创建ActionListener对象,一个匿名内部类 // ActionListener是 事件监听 // 相当于每100ms监听你是否发生一个动作 // 具体动作放入actionPerformed中 @Override public void actionPerformed(ActionEvent e) { if(isStart){//游戏开始状态下才动 // 由最后一节身子往前一节身子上动 for(int i=length-1;i>0;i--){ snakeX[i]=snakeX[i-1]; snakeY[i]=snakeY[i-1]; } // 动头的位置 if("R".equals(direction)){ snakeX[0]+=25; } if("L".equals(direction)){ snakeX[0]-=25; } if("U".equals(direction)){ snakeY[0]-=25; } if("D".equals(direction)){ snakeY[0]+=25; } // 防止蛇超出边界: if(snakeX[0]>725){ snakeX[0]=25; } if (snakeX[0]<25) { snakeX[0]=725; } if(snakeY[0]<75){ snakeY[0]=700; } if(snakeY[0]>700){ snakeY[0]=75; } /*监测碰撞的动作,也就是吃食物的动作:*/ // 如果蛇头坐标与食物坐标一样时,即吃到食物 if (snakeX[0]==foodX&&snakeY[0]==foodY) { // 蛇长度加一 length++; // 食物坐标改变,随机生成坐标,随机数必须是25的倍数,x轴【25,725】,y轴【75,700】 // 方法一: // math.random()-->[0.0,1.0) // math.random()*29-->[0.0,29.0) // (int)(math.random()*29)-->[0,28] // (int)(math.random()*29)+1-->[1,29] foodX=((int)(Math.random()*29)+1)*25;//[1,29]*25=[25,725] // 方法二: // [75,700]-->[3,28]*25 // [3,28]-->[0,25]+3 // [0,25] // new Random().nextInt(26)-->[0,26)-->[0,25] foodY=((new Random().nextInt(26))+3)*25;//[3,28]*25=[75,700] } repaint();//重绘,根据新的蛇头蛇身的位置画 } } }); // 启动计时器 timer.start(); } 十三、画积分代码如下:
/*定义一个积分:*/ int score; /*自定义一个初始化方法,初始化小蛇的坐标:*/ public void init(){ /*初始化蛇的长度:*/ length=3; /*初始化蛇头坐标:*/ snakeX[0]=175; snakeY[0]=275; /*初始化第一节身子坐标:*/ snakeX[1]=150; snakeY[1]=275; /*初始化第二节身子坐标:*/ snakeX[2]=125; snakeY[2]=275; /*初始化蛇头的方向为右:*/ direction="R";//上U 下D 左L 右R /*初始化食物的坐标:*/ foodX=300; foodY=200; /*初始化积分:*/ score=0; } /*监测碰撞的动作,也就是吃食物的动作:*/ // 如果蛇头坐标与食物坐标一样时,即吃到食物 if (snakeX[0]==foodX&&snakeY[0]==foodY) { // 蛇长度加一 length++; // 食物坐标改变,随机生成坐标,随机数必须是25的倍数,x轴【25,725】,y轴【75,700】 // 方法一: // math.random()-->[0.0,1.0) // math.random()*29-->[0.0,29.0) // (int)(math.random()*29)-->[0,28] // (int)(math.random()*29)+1-->[1,29] foodX=((int)(Math.random()*29)+1)*25;//[1,29]*25=[25,725] // 方法二: // [75,700]-->[3,28]*25 // [3,28]-->[0,25]+3 // [0,25] // new Random().nextInt(26)-->[0,26)-->[0,25] foodY=((new Random().nextInt(26))+3)*25;//[3,28]*25=[75,700] /*每吃到一次食物,积分加10*/ score+=10; } repaint();//重绘,根据新的蛇头蛇身的位置画 } } }); /*7.画积分(画文字):*/ g.setColor(new Color(246, 245, 245)); g.setFont(new Font("微软雅黑",Font.BOLD,20)); g.drawString("积分:"+score,280,40); 十四、死亡判定 /*初始化积分:*/ score=0; @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); int keyCode = e.getKeyCode(); // System.out.println(keyCode);//空格对应32 /*监听空格:*/ if (keyCode==KeyEvent.VK_SPACE){//将空格32封装起来 if(isDie){ // 全部恢复到初始化状态 init(); isDie=false; }else{ isStart=!isStart; repaint();//重绘 } } @Override public void actionPerformed(ActionEvent e) { if(isStart&&isDie==false){//游戏开始状态、小蛇活着的状态下才动 // 由最后一节身子往前一节身子上动 for(int i=length-1;i>0;i--){ snakeX[i]=snakeX[i-1]; snakeY[i]=snakeY[i-1]; } /*死亡判定:*/ for(int i=1;i<length;i++){ // 如果蛇头的坐标和身子的任意一节坐标一样 if (snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]) { // 判定为死亡状态 isDie=true; } /*8.画死亡状态:*/ if(isDie){ g.setColor(new Color(246, 11, 11)); g.setFont(new Font("微软雅黑",Font.BOLD,35)); g.drawString("小蛇死亡!游戏停止,按下空格重新开始游戏",50,330); 十五、游戏打包在对方电脑有jre的情况下,可以将程序打包发给对方。 1.选择File菜单下的项目结构Project Structure 2.点击Artifacts,再点击左上角的“+”号,JAR包下选择from modules with dependencies从项目中将所有依赖选上 3.在Main Class中选择游戏进入的入口,即main方法所在的类。 4.此时已经生成了一个jar文件,点击Apply运行,再OK即可。 5.在菜单栏Build下选择Build Artifacts,再点击Build,就会生成jar包。 6.生成好的jar包,可以在out文件夹下,找到刚生成好的jar包,右击选择Show inExplorer,就可以打开jar包所在位置 7.直接双击jar包,即可运行。
源代码Images类:
package com.game; import javax.swing.*; import java.URL; /*用来获取游戏中所有涉及的图片*/ public class Images { /*面向对象思想:将图片进行封装,封装为一个对象,在程序中通过操纵这个对象来操纵图片*/ /*将图片的路径封装为一个对象:*/ // class获取字节码 // getResource获取图片路径 // 在菜单Build下选中第二个Build Module,重写构建一下,生成对应的字节码信 // 在out文件夹下找图片路径 // '/'指代相对路径,相对file:/C:/Users/ASUS/Desktop/贪吃蛇小游戏/out/production/TestSnake/而言 public static URL bodyURL=Images.class.getResource("/images/body.png"); /*将图片封装为程序中一个对象:*/ // ImageIcon构造器,可以直接把url传进去 public static ImageIcon bodyImg=new ImageIcon(bodyURL); /*同理,将剩下的图片都封装:*/ public static URL downURL=Images.class.getResource("/images/down.png"); public static ImageIcon downImg=new ImageIcon(downURL); public static URL foodURL=Images.class.getResource("/images/food.png"); public static ImageIcon foodImg=new ImageIcon(foodURL); public static URL headerURL=Images.class.getResource("/images/header.png"); public static ImageIcon headerImg=new ImageIcon(headerURL); public static URL leftURL=Images.class.getResource("/images/left.png"); public static ImageIcon leftImg=new ImageIcon(leftURL); public static URL rightURL=Images.class.getResource("/images/right.png"); public static ImageIcon rightImg=new ImageIcon(rightURL); public static URL upURL=Images.class.getResource("/images/up.png"); public static ImageIcon upImg=new ImageIcon(upURL); }StartGame类:
package com.game; import javax.swing.*; import java.awt.*; public class StartGame { public static void main(String[] args) { /*1.创建一个窗体:*/ JFrame jf = new JFrame(); /*2.给窗体设置一个标题:*/ jf.setTitle("贪吃蛇小游戏 by:cym"); /*3.设置窗体弹出的坐标,对应窗体的宽和高:*/ // 获取屏幕的宽、高 int width = Toolkit.getDefaultToolkit().getScreenSize().width; int height = Toolkit.getDefaultToolkit().getScreenSize().height; jf.setBounds((width - 800) / 2, (height - 800) / 2, 800, 800); /*4.设置窗体大小不可调:*/ jf.setResizable(false); /*5.关闭窗口的同时,程序随之关闭:*/ jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); /*6.创建面板:*/ GamePanel gp = new GamePanel(); // 将面板放入窗体中: jf.add(gp); /*默认情况下窗体隐藏,需要进行显现(最好放在最后):*/ jf.setVisible(true); } }GamePanel类:
package com.game; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.util.Random; /*面板*/ //继承JPanel才具备面板的功能,才成为一个面板 public class GamePanel extends JPanel { /*定义两个数组: * 一个数组,专门存储蛇的x轴坐标 * 一个数组,专门存储蛇的y轴坐标 * */ int[] snakeX = new int[200]; int[] snakeY = new int[200]; /*定义蛇的长度:*/ int length; /*定义蛇的行走方向:*/ String direction; /*游戏只有两个状态:开始、暂停*/ boolean isStart = false;//默认游戏为暂停状态 /*加入一个定时器:*/ Timer timer; /*定义食物的xy轴坐标*/ int foodX, foodY; /*定义一个积分:*/ int score; /*加入一个变量,判断小蛇生死状态:*/ boolean isDie = false;//默认小蛇为活着的状态 /*自定义一个初始化方法,初始化小蛇的坐标:*/ public void init() { /*初始化蛇的长度:*/ length = 3; /*初始化蛇头坐标:*/ snakeX[0] = 175; snakeY[0] = 275; /*初始化第一节身子坐标:*/ snakeX[1] = 150; snakeY[1] = 275; /*初始化第二节身子坐标:*/ snakeX[2] = 125; snakeY[2] = 275; /*初始化蛇头的方向为右:*/ direction = "R";//上U 下D 左L 右R /*初始化食物的坐标:*/ foodX = 300; foodY = 200; /*初始化积分:*/ score = 0; } /*构造器,调用一下小蛇默认方法init(),进行面板初始化的时候就默认了蛇的位置:*/ public GamePanel() { init(); // 将焦点定位在当前操作的面板上 this.setFocusable(true); // 加入监听: // addKeyListener表示加入键盘监听 this.addKeyListener(new KeyAdapter() {//涉及到适配器模式 // 监听键盘按下操作 @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); int keyCode = e.getKeyCode(); // System.out.println(keyCode);//空格对应32 /*监听空格:*/ if (keyCode == KeyEvent.VK_SPACE) {//将空格32封装起来 if (isDie) { // 全部恢复到初始化状态 init(); isDie = false; } else { isStart = !isStart; repaint();//重绘 } } /*监听向上箭头:*/ if (keyCode == KeyEvent.VK_UP) { direction = "U"; } /*监听向下箭头:*/ if (keyCode == KeyEvent.VK_DOWN) { direction = "D"; } /*监听向左箭头:*/ if (keyCode == KeyEvent.VK_LEFT) { direction = "L"; } /*监听向右箭头:*/ if (keyCode == KeyEvent.VK_RIGHT) { direction = "R"; } } }); /*对定时器做初始化:*/ // 延迟毫秒数、一个ActionListener类对象 timer = new Timer(100, new ActionListener() {//创建ActionListener对象,一个匿名内部类 // ActionListener是 事件监听 // 相当于每100ms监听你是否发生一个动作 // 具体动作放入actionPerformed中 @Override public void actionPerformed(ActionEvent e) { if (isStart && isDie == false) {//游戏开始状态、小蛇活着的状态下才动 // 由最后一节身子往前一节身子上动 for (int i = length - 1; i > 0; i--) { snakeX[i] = snakeX[i - 1]; snakeY[i] = snakeY[i - 1]; } // 动头的位置 if ("R".equals(direction)) { snakeX[0] += 25; } if ("L".equals(direction)) { snakeX[0] -= 25; } if ("U".equals(direction)) { snakeY[0] -= 25; } if ("D".equals(direction)) { snakeY[0] += 25; } // 防止蛇超出边界: if (snakeX[0] > 725) { snakeX[0] = 25; } if (snakeX[0] < 25) { snakeX[0] = 725; } if (snakeY[0] < 75) { snakeY[0] = 700; } if (snakeY[0] > 700) { snakeY[0] = 75; } /*监测碰撞的动作,也就是吃食物的动作:*/ // 如果蛇头坐标与食物坐标一样时,即吃到食物 if (snakeX[0] == foodX && snakeY[0] == foodY) { // 蛇长度加一 length++; // 食物坐标改变,随机生成坐标,随机数必须是25的倍数,x轴【25,725】,y轴【75,700】 // 方法一: // math.random()-->[0.0,1.0) // math.random()*29-->[0.0,29.0) // (int)(math.random()*29)-->[0,28] // (int)(math.random()*29)+1-->[1,29] foodX = ((int) (Math.random() * 29) + 1) * 25;//[1,29]*25=[25,725] // 方法二: // [75,700]-->[3,28]*25 // [3,28]-->[0,25]+3 // [0,25] // new Random().nextInt(26)-->[0,26)-->[0,25] foodY = ((new Random().nextInt(26)) + 3) * 25;//[3,28]*25=[75,700] /*每吃到一次食物,积分加10*/ score += 10; } /*死亡判定:*/ for (int i = 1; i < length; i++) { // 如果蛇头的坐标和身子的任意一节坐标一样 if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) { // 判定为死亡状态 isDie = true; } } repaint();//重绘,根据新的蛇头蛇身的位置画 } } }); // 启动计时器 timer.start(); } /*此方法特殊,就相当于图形版的main方法,自动调用*/ @Override protected void paintComponent(Graphics g) { super.paintComponent(g); /*1.填充背景颜色:*/ // 颜色由rgb(red green blue)组成 // 可通过点击左边行号旁的色块进行颜色修改 this.setBackground(new Color(243, 239, 190, 255)); /*2.画头部的图片header.png:*/ // Images.headerImg:调用图片类中的header.png图片 // paintIcon()方法将图片在面板中绘制出来 // this:当前面板 // g:使用的画笔 // x、y:对应坐标轴 Images.headerImg.paintIcon(this, g, 15, 10); /*3.画一个矩形:*/ // 先调节画笔颜色: g.setColor(new Color(205, 228, 246)); // fillRect填充矩形 g.fillRect(15, 70, 750, 670); /*4.画小蛇:*/ // 画蛇头: if ("R".equals(direction)) { Images.rightImg.paintIcon(this, g, snakeX[0], snakeY[0]); } if ("L".equals(direction)) { Images.leftImg.paintIcon(this, g, snakeX[0], snakeY[0]); } if ("U".equals(direction)) { Images.upImg.paintIcon(this, g, snakeX[0], snakeY[0]); } if ("D".equals(direction)) { Images.downImg.paintIcon(this, g, snakeX[0], snakeY[0]); } 画第一节身子: // Images.bodyImg.paintIcon(this,g,snakeX[1],snakeY[1]); 画第二节身子: // Images.bodyImg.paintIcon(this,g,snakeX[2],snakeY[2]); // 用循环来画蛇身子: for (int i = 1; i < length; i++) { Images.bodyImg.paintIcon(this, g, snakeX[i], snakeY[i]); } /*5.如果游戏是暂停的,界面中间有一个提示语*/ if (isStart == false) { /*画一个文字:*/ // 画笔设置颜色 g.setColor(new Color(222, 13, 245)); // 设置文字的字体、加粗、大小 g.setFont(new Font("微软雅黑", Font.BOLD, 40)); // 画文字: // drawString()方法,画字符串 // 文字内容、xy轴坐标 g.drawString("点击空格开始游戏", 250, 330); } /*6.画食物:*/ Images.foodImg.paintIcon(this, g, foodX, foodY); /*7.画积分(画文字):*/ g.setColor(new Color(246, 245, 245)); g.setFont(new Font("微软雅黑", Font.BOLD, 20)); g.drawString("积分:" + score, 280, 40); /*8.画死亡状态:*/ if (isDie) { g.setColor(new Color(246, 11, 11)); g.setFont(new Font("微软雅黑", Font.BOLD, 35)); g.drawString("小蛇死亡!游戏停止,按下空格重新开始游戏", 50, 330); } } }贪吃蛇小游戏b站原视频: www.bilibili/video/BV1w5411g73U?share_source=copy_web
贪吃蛇图片素材: 链接:pan.baidu/s/1B5aIR-luqF94Y-8Lhwck0g?pwd=5gj9 提取码:5gj9 解压缩密码:456654
我的jar包: 链接:pan.baidu/s/1Zk31sOPTr_WCidZUd2Jl9A?pwd=4h7d 提取码:4h7d
若双击jar包不能够直接运行的解决办法: 指路我的博客:t.csdn/1QALL
版权声明:本文标题:用java写一个贪吃蛇小游戏(源码在最后) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686866532a112255.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论