本文主要是介绍Java期末项目 大鱼吃小鱼(改进版-期末95分以上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
项目名称:大鱼吃小鱼
目录
1 基本信息
1.1 系统名称
1.2 开发运行环境
1.3 使用的核心类
2.系统需求分析
2.1系统可行性分析
2.2系统需求分析
3.系统功能设计
3.1系统总体设计
3.2系统模块详细设计
3.3 其他分析
4.系统整体及功能模块展示与实现
5.总结体会
1 基本信息
1.1 系统名称
大鱼吃小鱼
1.2 开发运行环境
JDK1.8、Eclipse、photoshop、Windows操作系统
1.3 使用的核心类
1.GWindow类:窗口的绘制,继承JFrame类,其主要设置的内容有:
窗口的相关信息:宽度、高度、窗体是否可见、窗体居中,添加组件等等。
相关事件:鼠标事件、键盘事件
相关方法:logic()方法用来实现鱼类的不断创建,reGame()方法用来实现游戏的重新开始,paint()方法用来实现图像的绘制,使用线程sleep()方法调用repaint()方法。
游戏状态:5种,0—未开始 1—游戏中 2—通关失败 3—通关成功 4—暂停,通过switch语句定义状态。
2.GUtils类:工具类,存放的内容有:
游戏的相关信息:游戏背景图,关卡等级,鱼类图片等。
方法:drawWord()方法用来绘制窗体中文字的大小、颜色、位置等。
3.Bg类:背景图的实体类,用来绘制不同游戏状态下的背景,在状态0(未开始)下背景上出现开始,状态1(游戏中)下会出现积分、难度、等级,状态2(通关失败)下会出现积分、难度、等级、失败,状态3(通关成功)下会出现积分、难度、等级、成功,状态4(暂停)下会出现积分、难度、等级、游戏暂停。
4.EnamyFish类:敌方鱼类,存放的内容有:
定义相关信息:物体坐标、体型大小、移动速度、移动方向、分值等。
方法:paintSelf()实现绘制自身的方法,getrRec()是获取自身矩形的方法,用于碰撞检测。
5.MyFish类:我方 鱼类,存放的内容有:
定义相关信息:物体坐标、体型大小、移动速度、等级等等。
方法:paintSelf()实现绘制自身的方法,getrRec()是获取自身矩形的方法,用于碰撞检测,logic()是返回我方鱼类的方法,添加对键盘的控制。
6.Music类:实现播放背景音乐的类,主要内容有:
run()方法中调用play()方法,play()方法用于实现字节流的读入,并通过玩家播放音乐。
2.系统需求分析
2.1系统可行性分析
1.项目概况
《大鱼吃小鱼》是一款休闲类游戏,于2011年发行。该游戏把玩家带进一个神秘的海底世界,游戏中每一关卡都有玩法提示和海洋鱼类知识学习。在看似风平浪静的大海里,却隐藏着与人类世界相同的危机,海底生物在弱肉强食的竞争下,不但得觅食以填饱肚子,更重要的是学会保护自己。
2.项目当前发展情况
此类游戏在现在的手机上基本都可安装此游戏。虽然版本有所不同,但是游戏玩法和以前没什么区别,值得一提的是操作的设计越来越人性化。
3.项目实现所需条件
《大鱼吃小鱼》的核心算法是实现移动和捕食,我们需要实现《大鱼吃小鱼》的基本功能的方向移动以及捕食后体积增长。
4.项目实施总结
本次项目设计主要运用Java语言来完成。Java语言是一种跨平台,适应于分布式计算环境的面向对象编程语言,用Java编写的应用程序可以不经过大幅度修改就可在不同的软硬件平台上运行,更加简便高效。
2.2系统需求分析
本次项目设计主要是完成游戏的基本操作,需要满足以下几点要求:
1.对游戏中所需类进行设计。
2.写出源程序文件,对游戏进行调试和分析,使程序能够成功运行。
3.系统功能设计
3.1系统总体设计
见文档
3.2系统模块详细设计
部分内容如下:
3.2.1启动封面功能模块
启动封面模块时,首先需要了解一件事,就是游戏的五种游戏状态:
//游戏状态 0—未开始 1—游戏中 2—通关失败 3—通关成功 4—暂停
static int state=0;//游戏默认状态
//在paint()方法中利用switch语句定义游戏状态
public void paint(Graphics g) {g.drawImage(offScreenImage, 0, 0, null);switch (state) {case 0:g.drawImage(GUtils.image, 0, 0, null);// 启动页面背景图break;case 1:break;case 2:break;case 3:break;case 4:break;default:}}
3.2.2 启动页面的点击事件功能模块
启动页面是在游戏最开始的时候显示,此时游戏的状态为0。当鼠标左键点击启动窗口后,用if判断鼠标可否点击,游戏进入运行状态,游戏状态为1,启动页面文字消失,在launch()方法中,为页面添加鼠标事件。
// 鼠标事件this.addMouseListener(new MouseAdapter() {// 使用MouseAdapter()可直接重写某个需要的方法@Overridepublic void mouseClicked(MouseEvent e) {super.mouseClicked(e);// 用if判断鼠标可否点击,并进入游戏运行状态if (e.getButton() == 1 && state == 0) {// 鼠标点击了左键时,e.getButton()==1,进入游戏中修改state=1state = 1;// repaint()可再次调用paint方法,将改变后的窗口绘制出来repaint();}}});
3.2.3 游戏开始的背景添加功能模块
首先新建一个背景图的实体类Bg。过程如下:
1.编写绘制背景的方法,定义所需参数。
//绘制背景的方法paintSelf()
public void paintSelf(Graphics g,int fishgrade) {//定义所需参数g.drawImage(GUtils.image, 0, 0, null);}
2.在窗体类中获取背景类的对象。
//获取背景类Bg的对象Bg bg=new Bg();
3.将背景绘制自身的方法,放到游戏状态为1的语句下。
public void paint(Graphics g) {g.drawImage(offScreenImage, 0, 0, null);switch (state) {case 0:g.drawImage(GUtils.image, 0, 0, null);// 启动页面背景图g.setColor(Color.pink);//将画笔颜色改为粉色g.setFont(new Font("仿宋",Font.BOLD,60));//设置字体样式g.drawString("开始", 700, 500);//为启动页面添加文字break;case 1:bg.paintSelf(g);break;case 2:break;case 3:break;case 4:break;default:}}
4.在launch()方法中添加一个while循环,每间隔40毫秒调用一次repaint方法。
while (true) {repaint();try {Thread.sleep(40);} catch (InterruptedException e) {e.printStackTrace();}
3.2.4 双缓存解决闪屏问题功能模块
在游戏开始的背景添加功能模块中,在launch()方法中添加一个while循环后,会发现启动页的文字有闪动现象,使用缓存的方式解决闪动问题。思路为:重新创建一个空的图片,把所有的组件先绘制到空的图片上,然后把绘制好的图片一次性绘制到主窗口中。过程如下:
1.在主窗口中定义一个成员变量
Image offScreenImage;
2.在paint()方法中懒加载模式初始化对象
public void paint(Graphics g) {offScreenImage = createImage(width, height);Graphics gImage = offScreenImage.getGraphics();// 获取图片对应的画笔对象,把组件绘制到新的图片中g.drawImage(offScreenImage, 0, 0, null);switch (state) {case 0: // 已在Bg类中定义gImage.drawImage(GUtils.image, 0, 0, null);//启动页面背景图gImage.setColor(Color.pink);//将画笔颜色改为粉色gImage.setFont(new Font("仿宋",Font.BOLD,60));//设置字体样式gImage.drawString("开始", 700, 500);//为启动页面添加文字break;case 1:bg.paintSelf(gImage);break;case 2:break;case 3:break;case 4:break;default:}}
3.把内存当中绘制好的新图片一次性绘制到主窗口中。
g.drawImage(offScreenImage, 0, 0, null);
3.2.5敌方鱼的随机生成功能模块
1.在工具类(GUtils)中,创建一个所有敌方鱼物体的集合。
//敌方鱼类集合
public static List<EnamyFish> EnamyList=new ArrayList<>();
2.创建敌方鱼类(EnamyFish),添加敌方鱼类,编写敌方鱼的父类,定义变量。实现右鱼继承左鱼,左鱼继承敌方鱼父类。
Image img; //定义图片int x; int y; //定义物体坐标int width; int height;int speed; //定义移动速度int dir=1; //定义方向:敌方鱼的移动方向,从左向右—1,从右向左— -1int type; //定义敌方鱼的类型int count; //定义分值public void paintSelf(Graphics g){g.drawImage(img, x, y, width, height, null);} //绘制自身的方法//获取自身矩形的方法,用于碰撞检测public Rectangle getrRec(){return new Rectangle(x,y,width,height);}
3.在窗口类创建一个方法,用于批量添加敌方鱼类,将敌方小鱼添加到敌方鱼的集合中。
//敌方鱼EnamyFish enamy;public void logic(){enamy=new Enamy_1_L();GUtils.EnamyList.add(enamy);}
4.因为鱼的生成速度过快,因此要在所创造的方法中,控制敌方鱼的生成,定义一个变量,记录游戏的重绘次数 即paint调用次数,在while中进行自增。
int time=0;while (true) {repaint();time++;try {Thread.sleep(40);//调用sleep()方法} catch (InterruptedException e) {e.printStackTrace();}}
5.在敌方鱼的代码中添加判断语句,定义一个随机数double random,每调用20次paint方法生成一条鱼,在paint方法游戏状态为1的代码块中,循环遍历敌方鱼的生成。
if(time%20 ==0){if(random>0.5){ enamy =new Enamy_1_L();//将小鱼添加到集合中}GUtils.EnamyList.add(enamy);}// 循环遍历敌方鱼的生成, 绘制敌方鱼for (EnamyFish enamy : GUtils.EnamyList) {enamy.paintSelf(gImage);}
6.在所创造的方法中用for each循环定义地方鱼移动方向。
//foreach循环定义鱼类移动方向for(EnamyFish enamy : GUtils.EnamyList){enamy.x += enamy.dir*enamy.speed;}
3.2.6键盘控制我方鱼的移动功能模块
添加我方鱼类并实现键盘控制。过程如下:
1.首先在工具类中添加我方鱼图。
//我方鱼类public static Image myfish_l=new ImageIcon("images/myfish/myfish_left.gif").getImage();public static Image myfish_r=new ImageIcon("images/myfish/myfish_right.gif").getImage();
2.创建我方鱼类(MyFish),定义物体变量。过程同敌方鱼类(EnamyFish)。
3.在工具类中添加方向判定,用于控制我方鱼移动的方向。
4.在MyFish类中定义logic()方法,并在paintSelf()中画出对键盘的控
3.2.7鱼的碰撞检测功能模块
1.通过获取鱼类自身矩形的方法,用于检测不同矩形之间是否相交了来判断鱼类碰撞。为每个鱼类生成一个可以返回Rectangle类的对象的方法。之后再通过Java中的intersects()方法去比较两个返回的Rectangle对象是否相交就可以判断出鱼类间是否碰撞了。
2.我方鱼的体积增加时,碰撞检测时的体积也应该增加。
public Rectangle getRec(){return new Rectangle(x,y,width+GUtils.count,height+GUtils.count);}
3.2.8 游戏积分的实现功能模块
1.工具类中定义分数
//定义分值public static int count=0;
2.我方鱼和敌方鱼碰撞检测完成后积分加1,在窗口类中实现我方鱼吃掉敌方鱼的所得积分。
if(myFish.getRec().intersects(enamy.getrRec())){System.out.println("碰撞了");enamy.x=-200;enamy.y=-200;//碰撞了,积分加碰撞的敌方鱼数GUtils.count=GUtils.count+enamy.count; }
3.在窗口类paint方法,游戏状态为1的代码块中,打印所得积分。
gImage.setColor(Color.pink);//将画笔颜色改为粉色gImage.setFont(new Font("仿宋",Font.BOLD,60));//设置字体样式gImage.drawString("积分", 200, 120);//为启动页面添加文字
3.2.9关卡的设置功能模块
根据积分实现关卡的设置,如果达到目标积分则过关,并增加等级。
1.在工具类中定义关卡等级grade。并在窗口类logic()方法中设置关卡难度,在paint()方法中state=3的情况下实现。
static int grade=0;//关卡难度if(GUtils.count<10){.grade=0; MyFish.grade=1;}else if(GUtils.count<=50){ GUtils.grade=1; }else if(GUtils.count<=100){ GUtils.grade=2; MyFish.grade=2;}else if(GUtils.count<=150){ GUtils.grade=3; MyFish.grade=3; }else if(GUtils.count<=200){ GUtils.grade=4; MyFish.grade=3; }else if(GUtils.count>200){ state=3; }//在paint()方法中state=3的情况下实现case 3:myFish.paintSelf(gImage);gImage.setColor(Color.pink);//将画笔颜色改为粉色gImage.setFont(new Font("仿宋",Font.BOLD,60));//设置字体样式gImage.drawString("积分", 200, 120);//为启动页面添加文字gImage.drawString("胜利", 400, 500);//为启动页面添加文字break;
3.2.10 boss鱼的出现功能模块
3.2.11 暂停和重新开始功能模块
3.2.12 背景音乐功能模块
为了增加游戏的功能,创建一个Music类继承Thread类,为游戏添加背景音乐。
需要重写run方法。并将音乐读入,在主类中创建Music对象。
public void play() throws FileNotFoundException, JavaLayerException { //通过字符缓冲流读入FileInputStream fis=new FileInputStream(music);BufferedInputStream buffer = new BufferedInputStream(fis);player = new Player(buffer);player.play();}//重写Thread类中的run方法public void run() {try {play();//调用play方法,并抛出异常} catch (FileNotFoundException |JavaLayerException e) {// TODO Auto-generated catch blocke.printStackTrace();}}new Music("Relax.mp3").start();
3.3 其他分析
我利用所学的专业知识应用到这个项目中,内容如下:
1.引入第三方jar包:若Java程序想要实现背景音乐功能,就需要下载一个jar包,即在本程序中引入第三方jar包。可以从网站下载我们所需要的jar包。导入jar包的步骤:
在java项目中新建一个文件夹,并将需要导入的jar包复制到新建文件夹中→→选中新建文件夹中的jar包,右键依次点击【Build Path】→【Add to Build Path】即可。
2. Photoshop技术
通过Photoshop我设计出游戏中鱼类的图片,主要实现的是:
a.设置动态鱼类,格式为gif。
b.用Photoshop将gif图片背景变透明。
步骤为:打开一张gif图→→点击窗口的时间轴→→选中第一张图片,让其图层为可见,选择魔棒工具,点击图片背景,点击Delete键将背景删除→依次选中后面图层,并将其背景删除→→时间轴处点击下面小箭头可以设置延迟时间,点击播放可以看动态效果→→完成后将图片存储为web所用格式→→选择格式为gif。
4.系统整体及功能模块展示与实现
5.总结体会
这篇关于Java期末项目 大鱼吃小鱼(改进版-期末95分以上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!