文章目录

  • 一丶游戏效果
  • 二、游戏架构
  • 三、代码设计
    • 1.窗体架构
    • 2.游戏嵌板
    • 3.图像绘制与显示
    • 4.视窗刷新与按键监听
    • 5.食物刷新与小蛇死亡判断
    • 6.游戏暂停与重新开始

一丶游戏效果

二、游戏架构

一个Java项目可以有多种设计模式,MVC,工厂,单例等等。
但在本次项目中,我们将介绍最基础的知识,在后续项目中逐步升级。
贪吃蛇项目的基本架构是窗体为主体,在面板中执行游戏操作,并在面板中绘制贪吃蛇图像和显示用户操作

三、代码设计

1.窗体架构

public class StartGame {public static void main(String[] args) {JFrame jFrame =new JFrame();jFrame .setTitle("贪吃豆");int width= Toolkit.getDefaultToolkit().getScreenSize().width;int height=Toolkit.getDefaultToolkit().getScreenSize().height;jFrame .setBounds((width-700)/2,(height-700)/2,700,700);jFrame .setResizable(false);jFrame .setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);GamePanel gamePanel= new GamePanel();jFrame.add(gamePanel);jFrame .setVisible(true);}
}

窗体方面我们利用Java中的JFrame创建一个窗体,并利用Toolkit获取屏幕大小,使的窗体能够正常显示在电脑中央
同时,这个main方法也是程序的入口,可以看出,我们在StartGame中加入了gamePanel这个对象,而我们的图像显示和游戏逻辑全部封装在GamePanel这个类中

2.游戏嵌板

Panel ,中文意思为“嵌板”。这个嵌板相当于窗体上的一个区域,我们可以根据自己的需求放置嵌板,并在对应的嵌板中设计我们的功能。这个项目只有一个嵌板。

package com.Karthus.game;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;public class GamePanel extends JPanel {int[] snakeX=new int[200];int[] snakeY=new int[200];int length;String direction;boolean isStart;boolean isDie;boolean isHungry;int foodX=200;int foodY=200;Timer timer;public GamePanel(){init();this.setFocusable(true);this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {super.keyPressed(e);int keyCode=e.getKeyCode();if(keyCode==KeyEvent.VK_SPACE){if(isDie){init();repaint();}else{isStart=!isStart;repaint();}}if (keyCode==KeyEvent.VK_UP){direction="u";}if (keyCode==KeyEvent.VK_DOWN){direction="d";}if (keyCode==KeyEvent.VK_RIGHT){direction="r";}if (keyCode==KeyEvent.VK_LEFT){direction="l";}}});timer =new Timer(100, new ActionListener() {@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];}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]>700){snakeX[0]=0;}if(snakeX[0]<0){snakeX[0]=675;}if(snakeY[0]>700){snakeY[0]=0;}if(snakeY[0]<0){snakeY[0]=675;}if(snakeX[0]==foodX&&snakeY[0]==foodY){length++;foodX=new Random().nextInt(27)*25;foodY=(new Random().nextInt(26)+1)*25;isHungry=false;}for(int i=length-1;i>0;i--){if(snakeX[i]==snakeX[0]&&snakeY[i]==snakeY[0]){isDie=true;isStart=false;}}repaint();}}});timer.start();}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";isStart=false;isDie=false;isHungry=true;}@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);this.setBackground(new Color(231, 214, 214));g.setColor(new Color(252, 252, 252));g.fillRect(0,0,700,700);if(isDie){g.setColor(new Color(65, 193, 193));g.setFont(new Font("微软雅黑",Font.BOLD,30));g.drawString("游戏死亡,按空格键重新开始",200,300);}switch (direction){case "r":Images.right.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "l":Images.left.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "u":Images.up.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "d":Images.down.paintIcon(this,g,snakeX[0],snakeY[0]);break;}if(isHungry) {for (int i = 1; i < length; i++) {Images.body.paintIcon(this, g, snakeX[i], snakeY[i]);isHungry=false;}}else {for (int i = 1; i < length-1; i++) {Images.body.paintIcon(this, g, snakeX[i], snakeY[i]);}}Images.food.paintIcon(this,g,foodX,foodY);if(!isStart&&!isDie){g.setColor(new Color(65, 193, 193));g.setFont(new Font("微软雅黑",Font.BOLD,30));g.drawString("点击空格开始游戏",200,300);}}
}

以上是GamePanel嵌板的全部内容。由于程序较简单,我们将蛇的属性放置于该嵌板中。下面会详细介绍嵌板中的内容。

3.图像绘制与显示

想要绘制图像,首先得拿到图片资源
程序中获取图片的方法有很多种,这里我们将所有图片文件放入images文件夹中


点击Build,选择reBuild project


会生成一个out文件,这些文件时JVM运行的文件,也就是JAVA虚拟机,图片的路径将保存在这个文件中

新建一个images类,将需要的图片数据放入这个类中

public class Images {public static URL upUrl =Images.class.getResource("/images/head_up.png");public static URL rightUrl =Images.class.getResource("/images/head_right.png");public static URL leftUrl =Images.class.getResource("/images/head_left.png");public static URL downUrl =Images.class.getResource("/images/head_down.png");public static URL bodyUrl =Images.class.getResource("/images/body.png");public static URL barUrl =Images.class.getResource("/images/topBar.png");public static URL foodUrl=Images.class.getResource("/images/food.png");public static ImageIcon up =new ImageIcon(upUrl);public static ImageIcon right =new ImageIcon(rightUrl);public static ImageIcon left =new ImageIcon(leftUrl);public static ImageIcon down =new ImageIcon(downUrl);public static ImageIcon body =new ImageIcon(bodyUrl);public static ImageIcon bar=new ImageIcon(barUrl);public static ImageIcon food=new ImageIcon(foodUrl);
}

收集到图片资源后就可以开始绘制了
在GamePanel中有一个绘制方法

 @Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);this.setBackground(new Color(231, 214, 214));}

g就相当于画笔,而每次生成一个嵌板对象时,都将自动调用该方法
对于整个嵌板就相当于一个坐标系,一张图片,我们想要放在嵌板中的某个地方,我们要考虑的问题,这个图片展多大空间,在嵌板的那个位置?

因此我们在GamePanel定义了蛇的二维坐标,并定义了蛇头位置朝向
下面给出蛇的画法

 switch (direction){case "r":Images.right.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "l":Images.left.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "u":Images.up.paintIcon(this,g,snakeX[0],snakeY[0]);break;case "d":Images.down.paintIcon(this,g,snakeX[0],snakeY[0]);break;}for(int i=1;i<length;i++)Images.body.paintIcon(this, g, snakeX[i], snakeY[i]);

4.视窗刷新与按键监听

游戏必须得要动起来才是游戏,贪吃蛇也要能够自己动起来,并且能够监听键盘的方向键
首先在GamePanel类中加入监听方法

    this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {super.keyPressed(e);int keyCode=e.getKeyCode();if(keyCode==KeyEvent.VK_SPACE){if(isDie){init();repaint();}else{isStart=!isStart;repaint();}}if (keyCode==KeyEvent.VK_UP){direction="u";}if (keyCode==KeyEvent.VK_DOWN){direction="d";}if (keyCode==KeyEvent.VK_RIGHT){direction="r";}if (keyCode==KeyEvent.VK_LEFT){direction="l";}}}

监听按键利用适配器模式

我们知道游戏刷新的本质是视图的刷新,也就是说我们要不断重复执行嵌板中的画图方法,我们定义一个Timer计时器让他计时刷新

即让是刷新我们还要弄清楚小蛇每次移动的算法,那么小蛇每次移动都是由后一节向前一节传递,而头部的刷新是由小蛇运动的方向决定的,刷新代码如下

  timer =new Timer(100, new ActionListener() {@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];}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]>700){snakeX[0]=0;}if(snakeX[0]<0){snakeX[0]=675;}if(snakeY[0]>700){snakeY[0]=0;}if(snakeY[0]<0){snakeY[0]=675;}if(snakeX[0]==foodX&&snakeY[0]==foodY){length++;foodX=new Random().nextInt(27)*25;foodY=(new Random().nextInt(26)+1)*25;isHungry=false;}for(int i=length-1;i>0;i--){if(snakeX[i]==snakeX[0]&&snakeY[i]==snakeY[0]){isDie=true;isStart=false;}}repaint();}}});timer.start();}

repaint将会重新执行paintComponent方法

5.食物刷新与小蛇死亡判断

每次吃完一个食物后将有新事物刷新,同时蛇身变长

 if(snakeX[0]==foodX&&snakeY[0]==foodY){length++;foodX=new Random().nextInt(27)*25;foodY=(new Random().nextInt(26)+1)*25;isHungry=false;}

小蛇死亡的判断则是判断蛇头与蛇身的坐标是否重合

   for(int i=length-1;i>0;i--){if(snakeX[i]==snakeX[0]&&snakeY[i]==snakeY[0]){isDie=true;isStart=false;}}

6.游戏暂停与重新开始

在游戏过程中如果要暂停或者游戏死亡后要重新开始,这就需要控制嵌板的画图计时,因此加入了isStart判定
空格监听

  if(keyCode==KeyEvent.VK_SPACE){if(isDie){init();repaint();}else{isStart=!isStart;repaint();}}

【Java游戏开发项目-01贪吃蛇】强烈推荐Java小白练手!!!相关推荐

  1. 【11款最全最新】Java游戏开发项目合集_Java项目实战_Java练手项目

    黄金矿工.俄罗斯方块.飞机大战.超级玛丽.坦克大战.飞翔的小鸟.扫雷.王者荣耀.推箱子.贪吃蛇.大鱼吃小鱼这些经典小游戏相信很多人都玩过.那大家有没有想过亲自制作出这些小游戏呢? 下面就给大家分享这1 ...

  2. 【11款最全最新】Java游戏开发项目合集(上)_Java项目实战_Java练手项目

    黄金矿工.俄罗斯方块.飞机大战.超级玛丽.坦克大战.飞翔的小鸟等等经典小游戏相信很多人都玩过.大家有没有想过亲自制作出这些小游戏呢? 今天给大家分享11款经典小游戏的Java开发教程,快来戳下方视频学 ...

  3. JAVA基于J2ME的手机游戏开发和实现——贪吃蛇

    随着通信技术的发展和手机的普及,手机游戏的开发技术越来越为人们所关注.以J2ME为开发平台,利用Java提供强大工具,不但可以在手机上实现静态HTML技术所无法实现的计算处理.数据存储.与服务器的通信 ...

  4. java 游戏开发项目教程 赛尔号

    现在我们来写一个游戏 这个游戏类似于 赛尔号 或者是 洛克王国的那种双方人物 都有 4个技能 一个普通攻击 每个人物的技能都有所不同 使用技能需要指定的蓝量 普通攻击就是简答的攻击 打出的伤害值是角色 ...

  5. Java游戏开发前景

    Java游戏开发前景如何?Java游戏开发曾经伴随着诺基亚的辉煌,Java游戏开发行业也是如火如荼,如日中天.但是现在随着诺基亚的地位一去不复返,Java游戏开发行业的曾经的火热也一去不复返,很多从事 ...

  6. 【Java游戏开发】坦克大战(附源码+课件+资料)

    本课程讲解了一个坦克大战游戏的详细编写流程,即使你是刚入门java的新手,只要你简单掌握了该游戏所需要的javase基础知识,便可以跟随教程视频完成属于你自己的坦克大战游戏!同时还可以加深和巩固你对面 ...

  7. 【源码+教程】Java课设项目_12款最热最新Java游戏项目_Java游戏开发_Java小游戏_飞翔的小鸟_王者荣耀_超级玛丽_推箱子_黄金矿工_贪吃蛇

    马上就要期末了,同学们课设做的如何了呢?本篇为大家带来了12款热门Java小游戏项目的源码和教程,助力大家顺利迎接暑假![源码+教程]Java课设项目_12款最热最新Java游戏项目_Java游戏开发 ...

  8. Java游戏开发——贪吃蛇

    最近在重构代码,思路和制作过程都有不少变化,为了避免混淆,我将之前的博客内容移到了我的有道云笔记里,通过链接可以查看历史文章. 旧版:http://note.youdao.com/noteshare? ...

  9. 【C语言项目】贪吃蛇游戏(上)

    00. 目录 文章目录 00. 目录 01. 开发背景 02. 功能介绍 03. 欢迎界面设计 3.1 常用终端控制函数 3.2 设置文本颜色函数 3.3 设置光标位置函数 3.4 绘制字符画(蛇) ...

最新文章

  1. mysql数据库忘记密码
  2. Permission is only granted to system app
  3. 在CentOS7上编译GreenPlum5.3.0
  4. 用户创建自定义的参数ID
  5. 深入浅出在NIO技术中,如何理解直接缓冲区要比非直接缓冲区效率高?
  6. CodeForces - 1354E Graph Coloring(dfs判断二分图+dp)
  7. 全国计算机等级考试收费不一样,2018年北京全国计算机等级考试收费标准
  8. Ruby中require,load,和include的区别
  9. [机器学习]LightGBM分布式使用完全手册
  10. 在 ASP.NET Core 中使用托管服务实现后台任务
  11. 自定义类加载器(ClassLoader + URLClassLoader)
  12. mysql binlog日志查看及解码
  13. 协议簇:TCP 解析: 连接断开
  14. 宿主机挂载虚拟机磁盘文件guestmount
  15. JavaScript 数组 array.at() 获取数组中最后一个元素
  16. 我是 Spring 菜鸟 -- 初始化方法 TODO
  17. 单手撸了个springboot+mybatis+druid 1
  18. 在 .NET Framework Data Provider for Microsoft SQL Server Compact 3.5 中发生错误
  19. java串口rxtx的若干坑
  20. Java 8 新增函数式接口到底是什么?

热门文章

  1. 这个夏天,我在网上学日语
  2. Python输出田字格
  3. 公布HP TC4400 安装WIN7全驱动全功能攻略
  4. GTY's math problem (BestCoder Round #29 A)
  5. R语言笔记-R语言数据挖掘方法及应用--1
  6. 三星SAMSUNG SCX-3205 驱动
  7. 炫界 (302) -(查动简)_家居照明之埃克苏Line系列吊灯:简直主义,把极简几何设计发挥得淋漓尽致...
  8. 葬爱家族时代已远,音乐交友游戏重获新生只是梦一场?
  9. get新方法:一个歌曲分享链接提取歌曲文件
  10. Inconsistent use of tabs and spaces in indentation等问题的解决