目录
(一)效果图
(二)代码实现
(1)将图片加载到程序中
(2)创建窗体
(3)创建面板
(4)绘制静态的小蛇
(5) 加入监听事件
(6)让蛇动起来
(7)绘制食物和吃食物
(8)把游戏打包
💴哈喽,大家好丫,你们的小郭子又来啦 ~
🌞今天我们用java来写一个简单的小项目——【贪吃蛇】,嘿嘿,是不是DNA动了呀🌞🌞
🌞话不多说,直接上干货,
(一)效果图
(二)代码实现
(1)将图片加载到程序中
现在本程序中创建一个Images包,包中保存需要使用的照片,如图所示
/*** Images这个类,专门用来获取游戏中所涉及的图片*/
public class Images {/*现在是面向对象的语言,面向对象的思维--》将图片进行封装 ,封装为一个对象,这样在程序中才可以通过操纵这个对象来操纵图片。*///将图片的路径封装为一个对象:public static URL bodyURL = Images.class.getResource("/images/body.png");//将图片封装为程序中一个对象: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);
}
class TestURL {//这是一个main方法,是程序的入口:public static void main(String[] args) {URL url = Images.class.getResource("/");// /指代的就是相对路径,相对/D:/IDEA_workspace/TestJavaSE/out/production/TestSnakeGame/System.out.println(url);}
}
(2)创建窗体
public class StartGame {public static void main(String[] args) {//创建一个窗体:JFrame jf = new JFrame();//给窗体设置一个标题:jf.setTitle("贪吃蛇 by jayden");//设置窗体弹出的坐标,对应窗体的宽高:int width = Toolkit.getDefaultToolkit().getScreenSize().width;int height = Toolkit.getDefaultToolkit().getScreenSize().height;jf.setBounds((width-800)/2,(height-800)/2,800,800);//设置窗体大小不可调节:jf.setResizable(false);//关闭窗口的同时 程序随之关闭:jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//默认情况下窗体是隐藏效果,必须将窗体进行显现:细节--》这个显现方法最好放在最后jf.setVisible(true);}
}
(3)创建面板
public class StartGame {public static void main(String[] args) {//创建一个窗体:JFrame jf = new JFrame();//给窗体设置一个标题:jf.setTitle("贪吃蛇 by jayden");//设置窗体弹出的坐标,对应窗体的宽高:int width = Toolkit.getDefaultToolkit().getScreenSize().width;int height = Toolkit.getDefaultToolkit().getScreenSize().height;jf.setBounds((width-800)/2,(height-800)/2,800,800);//设置窗体大小不可调节:jf.setResizable(false);//关闭窗口的同时 程序随之关闭:jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//默认情况下窗体是隐藏效果,必须将窗体进行显现:细节--》这个显现方法最好放在最后jf.setVisible(true);}
}
(4)绘制静态的小蛇
/*** @author : jayden* GamePanel继承了JPanel以后,才具备面板的功能,才成为一个面板*/
public class GamePanel extends JPanel {//定义两个数组//蛇的长度:int length;//一个数组,专门存储蛇的x轴坐标int[] snakeX = new int[200];//一个数组,专门存储蛇的y轴坐标int[] snakeY = new int[200];//定义蛇的行走方向: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}public GamePanel(){init();}/*paintComponent这个方法比较特殊,这个方法就属于图形版的main方法自动调用*/@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);//填充背景颜色:this.setBackground(new Color(208, 221, 227));//画头部图片:/*paintIcon四个参数:this指的是当前面板 g:指的是使用的画笔 x,y对应的坐标*/Images.headerImg.paintIcon(this,g,-10,10);//调解画笔颜色:g.setColor(new Color(219, 226, 219));//画一个矩形:g.fillRect(10,70,770,685);//画小蛇://画蛇头: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) 加入监听事件
/*** @author : jayden* GamePanel继承了JPanel以后,才具备面板的功能,才成为一个面板*/
public class GamePanel extends JPanel {//定义两个数组//蛇的长度:int length;//一个数组,专门存储蛇的x轴坐标int[] snakeX = new int[200];//一个数组,专门存储蛇的y轴坐标int[] snakeY = new int[200];//游戏只有两个状态,开始,暂停:boolean isStart = false;//默认游戏是暂停效果//定义蛇的行走方向: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}public GamePanel(){init();//将焦点定位在当前操作的面板上:this.setFocusable(true);//加入监听:this.addKeyListener(new KeyAdapter(){@Overridepublic void keyPressed(KeyEvent e) {//监听键盘按键的按下操作super.keyPressed(e);int keyCode = e.getKeyCode();System.out.println(keyCode);if(keyCode == 32){isStart = !isStart;//监听到空格以后,游戏开始的就变成暂停的,暂停的就变成开始的repaint();//重绘动作,重新调用paintComponent()方法}}});}/*paintComponent这个方法比较特殊,这个方法就属于图形版的main方法自动调用*/@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);//填充背景颜色:this.setBackground(new Color(208, 221, 227));//画头部图片:/*paintIcon四个参数:this指的是当前面板 g:指的是使用的画笔 x,y对应的坐标*/Images.headerImg.paintIcon(this,g,-10,10);//调解画笔颜色:g.setColor(new Color(219, 226, 219));//画一个矩形:g.fillRect(10,70,770,685);//画小蛇://画蛇头: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]);}//如果游戏暂停的,界面中间就应该有一句提示语:if(isStart == false){//画一个文字:g.setColor(new Color(114, 98, 255));//三个参数:字体,加粗,字号g.setFont(new Font("微软雅黑",Font.BOLD,40));//画文字:三个参数:文字内容,x轴坐标,y轴坐标g.drawString("点击空格开始游戏",250,330);}}
}
(6)让蛇动起来
public class GamePanel extends JPanel {//定义两个数组//蛇的长度:int length;//一个数组,专门存储蛇的x轴坐标int[] snakeX = new int[200];//一个数组,专门存储蛇的y轴坐标int[] snakeY = new int[200];//游戏只有两个状态,开始,暂停:boolean isStart = false;//默认游戏是暂停效果//加入一个定时器:Timer timer;//定义蛇的行走方向: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}public GamePanel(){init();//将焦点定位在当前操作的面板上:this.setFocusable(true);//加入监听:this.addKeyListener(new KeyAdapter(){@Overridepublic void keyPressed(KeyEvent e) {//监听键盘按键的按下操作super.keyPressed(e);int keyCode = e.getKeyCode();System.out.println(keyCode);if(keyCode == 32){isStart = !isStart;//监听到空格以后,游戏开始的就变成暂停的,暂停的就变成开始的repaint();//重绘动作,重新调用paintComponent()方法}}});//对定时器进行初始化动作:timer = new Timer(150, new ActionListener() {/*ActionListener是 事件监听相当于每100ms监听一下你是否发生了一个动作具体的动作放入actionPerformed*/@Overridepublic 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();}/*paintComponent这个方法比较特殊,这个方法就属于图形版的main方法自动调用*/@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);//填充背景颜色:this.setBackground(new Color(208, 221, 227));//画头部图片:/*paintIcon四个参数:this指的是当前面板 g:指的是使用的画笔 x,y对应的坐标*/Images.headerImg.paintIcon(this,g,-10,10);//调解画笔颜色:g.setColor(new Color(219, 226, 219));//画一个矩形:g.fillRect(10,70,770,685);//画小蛇://画蛇头: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]);}//如果游戏暂停的,界面中间就应该有一句提示语:if(isStart == false){//画一个文字:g.setColor(new Color(114, 98, 255));//三个参数:字体,加粗,字号g.setFont(new Font("微软雅黑",Font.BOLD,40));//画文字:三个参数:文字内容,x轴坐标,y轴坐标g.drawString("点击空格开始游戏",250,330);}}
}
(7)绘制食物和吃食物
public class GamePanel extends JPanel {//定义两个数组//蛇的长度:int length;//一个数组,专门存储蛇的x轴坐标int[] snakeX = new int[200];//一个数组,专门存储蛇的y轴坐标int[] snakeY = new int[200];//游戏只有两个状态,开始,暂停:boolean isStart = false;//默认游戏是暂停效果//加入一个定时器:Timer timer;//定义蛇的行走方向:String direction ;//定义食物的x,y轴坐标:int foodX;int 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;//初始化食物的坐标:foodX = 300;foodY = 200;//初始化蛇头的方向:direction = "R"; // U D L R}public GamePanel(){init();//将焦点定位在当前操作的面板上:this.setFocusable(true);//加入监听:this.addKeyListener(new KeyAdapter(){@Overridepublic void keyPressed(KeyEvent e) {//监听键盘按键的按下操作super.keyPressed(e);int keyCode = e.getKeyCode();System.out.println(keyCode);if(keyCode == 32){
// isStart = !isStart;//监听到空格以后,游戏开始的就变成暂停的,暂停的就变成开始的
// repaint();//重绘动作,重新调用paintComponent()方法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";}}});//对定时器进行初始化动作:timer = new Timer(150, new ActionListener() {/*ActionListener是 事件监听相当于每100ms监听一下你是否发生了一个动作具体的动作放入actionPerformed*/@Overridepublic 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]>750){snakeX[0] = 25;}if(snakeX[0]<25){snakeX[0] = 750;}if(snakeY[0]<100){snakeY[0] = 725;}if(snakeY[0]>725){snakeY[0] = 100;}//防止蛇超出边界:if(snakeX[0]>750){snakeX[0] = 25;}//检测碰撞的动作://食物的坐标和蛇头的坐标一样的时候,才是碰撞了if(snakeX[0] == foodX&&snakeY[0] == foodY){//蛇长度加1:length++;//吃上食物以后 积分加10分:score += 10;//食物坐标改变:随机生成坐标 --》细节:坐标必须是25的倍数/*[25,750] -> [1,30]*25[1,30]Math.random() -> [0.0,1.0)Math.random()*30 -> [0.0,30.0)(int)(Math.random()*30) -> [0,29](int)(Math.random()*30)+1 -> [1,30]*/foodX = ((int)(Math.random()*30)+1)*25;//[25,750]/*[100,725] -> [4,29]*25[4,29]->[0,25]+4[0,25]new Random().nextInt(26) -> [0,26) ->[0,25]*/foodY = (new Random().nextInt(26)+4)*25;//[100,725]}//死亡判定:蛇头和任意一节身子碰撞都是死亡:for(int i = 1;i<length;i++){if(snakeX[0]==snakeX[i]&&snakeY[0]==snakeY[i]){//将死亡 状态改为:trueisDie = true;}}repaint();//重绘}}});//定时器必须要启动:timer.start();}/*paintComponent这个方法比较特殊,这个方法就属于图形版的main方法自动调用*/@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);//填充背景颜色:this.setBackground(new Color(208, 221, 227));//画头部图片:/*paintIcon四个参数:this指的是当前面板 g:指的是使用的画笔 x,y对应的坐标*/Images.headerImg.paintIcon(this,g,-10,10);//调解画笔颜色:g.setColor(new Color(219, 226, 219));//画一个矩形:g.fillRect(10,70,770,685);//画小蛇://画蛇头: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]);}//如果游戏暂停的,界面中间就应该有一句提示语:if(isStart == false){//画一个文字:g.setColor(new Color(114, 98, 255));//三个参数:字体,加粗,字号g.setFont(new Font("微软雅黑",Font.BOLD,40));//画文字:三个参数:文字内容,x轴坐标,y轴坐标g.drawString("点击空格开始游戏",250,330);}//画食物:Images.foodImg.paintIcon(this,g,foodX,foodY);//画积分:g.setColor(new Color(255, 248, 248));g.setFont(new Font("微软雅黑",Font.BOLD,20));g.drawString("积分:"+score,670,45);//画入死亡状态:if(isDie){g.setColor(new Color(255, 82, 68));g.setFont(new Font("微软雅黑",Font.BOLD,20));g.drawString("小蛇死亡,游戏停止,按下空格重新开始游戏",200,330);}}
}
(8)把游戏打包
好啦,今天的分享到这里就结束啦 ~🌞🌞
觉得我分享的文章不错的话,可以关注一下哦,嘻嘻嘻🌞🌞