1、武汉理工大学华夏学院信息工程系课 程 设 计 任 务 书 三、 课程设计目的与任务 本课程的设计的目的是通过实践使同学们经历智能手机软件开发的全过程和受到一次综合训练,以便能较全面地理解、掌握和综合运用所学的智能手机开发的知识。结合具体的开发案例捕鱼达人,理解并初步掌握智能手机开发的主要环节和步骤以及智能手机游戏开发的知识。二、课程设计的内容与基本要求1、课程设计题目 捕鱼达人2、课程设计内容 要求学生根据所学的软件工程的理念,利用所学的Android 手机开发的知识,开发一个智能手机游戏捕鱼达人,并针对该手机游戏软件进行需求分析,总体设计、详细设计、编码、测试。 游戏操作 鼠标移动/键盘方向
2、键控制炮台射击方向,点击鼠标左键/按空格键射击撒网抓鱼,点击下方的红色+号和-号按钮/数字键1-8键/方向键键/滑动鼠标滑轮切换炮台游戏背景音乐设计游戏背景动画设计游戏界面设计游戏关卡设计游戏积分榜的设计三、课程设计步骤及时间进度和场地安排本课程设计将安排在第18周, 教育技术中心。具体安排如下:第一天,系统开发平台搭建及主流开发工具安装第二天,游戏界面的设计第三天,游戏业务的设计第四天,游戏关卡的设计 第五天,系统调试 测试 打包和验收周次星期一星期二星期三星期四星期五第18周第1-8节第1-8节第1-8节第1-8节第1-8节地点现教221现教221现教221现教221现教221四、课程设计
3、考核及评分标准课程设计考核将综合考虑学生考勤和参与度,系统设计方案正确性,系统设计和开发效果以及课程设计报告书的质量。具体评分标准如下:设置六个评分点(1)设计方案正确,具有可行性、创新性; 25分(2)系统开发效果较好; 25分(3)态度认真、刻苦钻研、遵守纪律; 10分(4)设计报告规范、课程设计报告质量高、参考文献充分 20分(5)课程设计答辩概念清晰,内容正确 10分(6)课程设计期间的课堂考勤、答疑与统筹考虑。 10分 按上述六项分别记分后求和,总分按五级记分法记载最后成绩。优秀(10090分),良好(8089分),中等(7079分),及格(6069分),不及格(059分)1设计题目
4、12开发环境13需求分析13.1设计目的13.2、设计要求14.概要设计24.1设计原理及其分析24.2本游戏的模块图25.详细设计45.1游戏欢迎界面的设计45.2 游戏背景的设计55.3游戏中鱼的设计65.4 渔网的设计85.5游戏的平衡设计96测试与运行116.1进行游戏测试116.2体力值为零的时弹出对话框。116.3游戏结束后进行选择127心得体会138.参考文献13附录:141设计题目捕鱼达人2开发环境Eclipse软件开发环境,PC机一台,windows操作系统。3需求分析3.1设计目的 捕鱼达人这个项目是一个娱乐性的游戏开发,该游戏可以给人们带来娱乐的同时还可以给人感官上的享受
5、,所以很受人们的欢迎。本次游戏的程序设计包含,java swing组件的合理运用,还有图像的变动达到一个动态的动画效果,线程的运用,游戏的异常处理,等方面的知识。培养学生运用所学知识的基础理论、基本知识和基本技能,分析解决实际问题能力的一个重要环节。它与课堂教学环节彼此配合,相辅相成,在某种程度上是课堂学习的继续、深化和检验。它的实践性和综合性是其它教学环节所不能代替的。课程设计能使学生受到必需的综合训练,在不同程度上提高各种能力。通过课程设计,使学生熟练掌握Java语言课程中所学的理论知识,通过综合Java语言的基本知识来解决实际问题,加强学生分析和解决问题的能力。3.2、设计要求框架:2个
6、场景,WelcomePanel,FishGame。流程:1)WelcomePanel :该场景是专门用来做一个欢迎动画的。 2)FishGame :用来运行游戏的载体窗口。与用户交流的界面,鱼儿在该window窗体上游动,玩家在上面捕鱼,然后计分等等。 4.概要设计4.1设计原理及其分析1.初始化界面需要800*500大小,需要一个游戏开始欢迎界面,游戏框上显示“欢迎捕鱼达人游戏”,3秒之后进入游戏界面,命名为“捕鱼达人”2.在程序中,我们需要对每一条鱼进行操作(移动,游动,捕鱼,死亡,复活),所以每条鱼我们将它定义为一个对象的线程,便于对鱼的完美操作与控制,游戏中我们定义了7种小鱼和4种大鱼
7、,每条鱼都有两条,所以鱼池中有22条鱼,鱼的数量达到了一定的饱和。3.鱼的每次移动,它的水平坐标改变了,所以我们需要将它移动之后的状态重画(repaint()方法)出来,从而达到鱼是在移动的。4.捕鱼的效果,我们被网赋一个能量值,可以改变网的大小,来改变网的能量的大小,而鱼就需要有一个血量值(大鱼的血量高,小鱼血量低),当网在鱼的范围之内的时候,点击鼠标左键让鱼扣除相应的血量值,鼠标右键控制网的大小,点击一下改变一下网的大小,当鱼的血量小于0的时候,鱼就会弹跳几下然后消失,达到捕鱼成功。 5.每个游戏都是需要平衡的,所以我们不能一直捕鱼下去。体力值,计分,捕鱼条数,等数据来平衡游戏。当体力值小
8、于0 的时候就结束游戏,而捕一条鱼,加上相应鱼的分数,而捕鱼条数上就加1,体力值也相应的回复一部分,不同的鱼分数不同,回复体力值也不同,基本上大鱼分数高,小于分数低。最后判定输赢就是看分数的高低。4.2本游戏的模块图分别有:鱼的模块,网的模块,鱼池的模块,游戏的模块,每一个模块相当于一个类,鱼模块:主要实现鱼图片的加载,鱼游动效果,鱼游动,还有鱼的一些基本属性, 比如鱼的坐标,大小,还有血量值。一些基本方法,鱼的构造方法。网模块:主要实现渔网图片的加载,渔网的属性有坐标,大小的宽和高,还有渔网的powe r值,渔网中还有一个改变渔网大小的方法。鱼池模块:将鱼类的对象,网类的对象都在本类中进行调
9、用,并将相应对象的图片显示出来,并将游戏的背景画出来。 欢迎模块:将欢迎的图片加载进来。游戏模块 欢迎模块鱼池模块网模块鱼模块 图4.1系统模块图 图4.2 系统类图5.详细设计5.1游戏欢迎界面的设计创建游戏的运行界面的框架,带有main()函数的类,FishGame.java类,专门用来承载游戏的运行,在主函数中创建JFram类的一个对象,即创建window视窗,然后设置大小,默认居中显示,大小不可以改变等功能,具体代码如下:final JFrame welcome =new JFrame(欢迎光临);welcome.setSize(643,435);welcome.setLocation
10、RelativeTo(null);welcome.setResizable(false);welcome.setVisible(true); 图5.1游戏运行的框架 创建WelcomePanel.java类,专门用来创建画笔(即paint()方法),画出要显示出来的欢迎界面,既然是开始界面,我们还要去掉边框,还要等待几秒钟后才能进入游戏界面。所以王某要创建一个Timer类的一个对象,来合理分配时间上的任务。实现代码如下:在WelcomePanel类中:public class WelcomPanel extends JPanelBufferedImage bg;public WelcomPan
11、el()try bg=ImageIO.read(new File(images/welcome.jpg);/加载本地的图片 catch (IOException e) e.printStackTrace(); public void paint(Graphics g) /g相当于是画笔g.drawImage(bg,0,0,null); /画图片 然后在FishGame类中的main()函数中创建WelcomPanel类的一个对象,将画出来的动画在创建好的JFrame框架上显示出来。具体代码如下:welcome.setUndecorated(true);/隐藏框架,大小不可变WelcomPane
12、l wel=new WelcomPanel();welcome.add(wel);welcome.setVisible(true); /显示显示效果如下: 图5.2欢迎图画显示5.2 游戏背景的设计 创建的Pool.java类要继承JPanel类,用paint()的方法画出游戏运行的效果出来,首先画出游戏的背景出来。具体画出的过程如WelcomPanel类的方法类似。然后再在FishGame.java类中的main()添加如下代码:final JFrame win = new JFrame(捕鱼达人游戏);win.setSize(800,500);win.setLocationRelative
13、To(null);win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);Pool buyu=new Pool();win.add(buyu);Timer timer = new Timer(); timer.schedule(new TimerTask() public void run() /3秒之后,欢迎界面关闭,游戏窗口打开welcome.setVisible(false); win.setVisible(true);, 3000); buyu.action(); /调用Pool类对象buyu的action()方法 运行后的游戏背景如下图:
14、 图5.3游戏运行背景5.3游戏中鱼的设计创建Fish.java类。在这个类之中,我们要创建鱼的对象,但是为了方便启动每一条鱼,我们将Fish.java的类继承了Thread类,这样,每一条鱼就相当于一个线程,每一个线程我们就可以对它分别进行控制,比如移动,速度,血量,当然还有鱼游动的效果。在玩家所看见鱼儿游动的效果其实就是鱼儿游动的一张张图片在不停的变换。我们所做的鱼儿素材只有静态的图片。根据研究,只要换的图片帧数达到23张每秒我们就会认为图片就是动的 。所以在鱼儿游动的时候我们还要调用Tread.sleep(1000/60)相当于1秒钟换了60张图片。速度上已经相当快了。这里我们在构造方法
15、里面写出BufferedImage类的一个数组对象,将鱼游动的不同图片用缓冲技术将图片加载到游戏中去,加快游戏运行速度,当然由于鱼的类型不同,所以需要写出两个变量出来s1和s2,s1代表不同种类的鱼类,s2代表同一种鱼的不同的游动的样子。将代码写入Fish.javaL类的构造方法中,如下:for(int i=0;i10;i+)imagesi=ImageIO.read(new File(images/fish+s1+_+s2+.png); 该构造函数是一个带参数的构造函数,s1就是传过来的参数,鱼的种类有19种,加上大于2种共11种鱼。鱼的移动,鱼有几个属性如下:x,y代表鱼的左上角的坐标,wi
16、dth,height代表当前鱼的图片的一个宽和高。我们就对这次的实验做一个简单的要求。所有的鱼儿都是从最右边开始的。用一个Random 的随机函数随机出鱼出场的位置:x=random.nextInt(780+width)-width;y=random.nextInt(470+height)-height; speed=random.nextInt(4)+3;/36 这几句代码的意思是随机出鱼出场的位置在右边,且高度不能超过游戏界面的高度,而随机出来的速度,可以使鱼儿游的快与慢。不至于所有的鱼儿以相同频率游动。再写一个step()方法,每Thread.sleep(1000/10)秒,鱼儿就左移一
17、次:x-=speed;图片也相应的换一次image=imagesi+%10; 这里与10取余的意思是我们每一种鱼都有10张游动的图片。当然鱼游出界的时候,鱼儿就重新随机出新的位置来具体实现代码如下:public void run() int i=0;while(true)x-=speed;image=imagesi+%10;/鱼儿每游动一下换一帧图片if(x-width)/如果鱼过了左边界,就出场 getOut();/该方法是用来对鱼的出场处理,给鱼重新随机出新的位置 try Thread.sleep(1000/10); catch (InterruptedException e) e.pri
18、ntStackTrace(); 鱼的类王某已经创建完毕,所以王某接下来就是要在Pool类的piant()方法中画出鱼,在此游戏中,王某把每一条鱼都创建了两次,使得鱼池中的鱼不至于嫌少, 代码如下:for (int i = 0; i fishes.length; i+) Fish f = fishesi;g.drawImage(f.image, f.x, f.y, null); 以上代码中,g相当于是paint方法中的一个画笔,用循环的方法将各种鱼画出来,fishes22数组代表的是22条鱼,即Fish类的一个数组对象(或者线程)。在画板中画出鱼后,王某还要启动该鱼的线程:用for循环将每条鱼的
19、线程启动:fishesi.start(),i取值022。其实这样的话鱼已经可以移动了,但是,在运行出来以后,其实鱼还没动,这是因为,画面定格了,所以我们需要调用系统的repaint()方法,将鱼游动之后的样子画出来,通过不停的重画,使鱼儿游动起来。在Pool类中添加action()方法,用一个死循环,不停的重画,然后线程停顿一下Tread.sleep(1000/10)。最后在FishGame.java中的main()方法中用Pool的对象调用action()方法即可。运行效果如下: 图5.4 在游戏中画出鱼5.4 渔网的设计 创建Net.java类。与创建鱼的方法类似。渔网有x,y,表示渔网左
20、上角的坐标,width,height表示渔网的款和高,power,代表渔网的能量值,渔网的网号鱼大,power值越大。渔网有7中图片,用BufferedImage 的数组将本地的7个渔网图片都加载进来,在构造方法中写如下主要代码:for (int i = 0; i 7; i+)imagesi = ImageIO.read(new File(images/net_ + (i + 1)+ .png); 同样的道理,在Pool类中的piant()方法中画出渔网,if (net.show) g.drawImage(net.image, net.x - net.width / 2, net.y - ne
21、t.height/ 2, null);show是渔网的一个boolean属性,当他为true时,显示渔网,否则不显示,这是因为当我们鼠标出去游戏界面的时候,不需要显示渔网。而且在游戏中,王某的渔网是跟着鼠标动的,鼠标在哪,我们的渔网就在哪,所以我们用鼠标监听来处理该事件,鼠标右键点击一下,我们就换一下网,同样的网的power值也将改变。具体代码在Pool类中写:public void initMouseAdapter() MouseAdapter m = new MouseAdapter() / 监听鼠标移动的方法public void mouseMoved(MouseEvent e) /渔网
22、的位置等于鼠标的位置int x = e.getX();int y = e.getY();net.x = x;net.y = y;public void mousePressed(MouseEvent e) /鼠标右键触发来改变渔网的大小/ 点击左键捕鱼,右键改变网的大小int n = e.getModifiers(); / 获得鼠标的左右位置System.out.println(n);if (n = 4) net.power+;net.changeThePower(net.power);public void mouseEntered(MouseEvent e) /鼠标进入,渔网显示 net.
23、show = true;public void mouseExited(MouseEvent e) /鼠标出来,渔网不显示net.show = false;this.addMouseListener(m); /添加鼠标事件监听this.addMouseMotionListener(m);5.5游戏的平衡设计 这个游戏的基本元素都已经设计出来了。鱼池,鱼,网等都已经实现了,但毕竟这是一个游戏,所以我们还在本游戏中添加了一些游戏的分数,鱼的条数,体力值,还有血量。大体的就是在我们有限的体力值内,可以改变渔网的大小(鼠标右键点击,点一下,渔网变大一下,当渔网的编号大于6时,渔网编号重新变为0),来扣
24、除鱼的血量。当网的中心位置在鱼的图片范围之内是,鼠标左键点击一下就扣除鱼的血量值,具体扣多少要看当前渔网的power值。而鱼的血量是根据鱼的大小来设定的,大于血量厚,小鱼血量薄,当鱼死之后,鱼就会翻身弹跳几下,实现过程是在鱼死之后根据以上鱼儿游动的效果一样,换上几张鱼被捕之后的图片即可实现。而当鱼死后,会加上相应的分数,和回复一定的体力值。当体力值为0的时候,游戏就结束,判断输赢就根据分数来判断。在Fish.java定义属性有:int blood; /鱼的血量 static int count; /捕鱼条数的计数,静态的属性实现累加 static int score; /捕鱼后得到的分数 再在
25、该类中添加如下方法,使鱼在死之后进行翻身,达到更好的捕鱼体验,鱼死后就会count+代表又捕到了一条鱼,而分数根据鱼的种类(index属性)的5倍。private void turnOver() for(int j=0;j3;j+) for(int i=0;icatchFish.length;i+)image=catchFishi;try Thread.sleep(1000/15); catch (InterruptedException e) / TODO Auto-generated catch blocke.printStackTrace();count+; score+=index*5
26、;在Pool.java类中我们添加static int physics_power;属性,用来记录当前的用户体力值。该游戏的主要操作是靠鼠标来操作的,所以添加了鼠标监听,然后通过n = e.getModifiers()这句代码获得鼠标的左右位置,左边点击时n=4,代表我们捕鱼的动作。点击鼠标右边,n=16,代表我们可以变换渔网的大小,在鼠标左击之后,鱼儿扣血,相应的体力值减少,然后判断,体力值是否小于零,如果小于零就弹出对话框,问用户是否结束。具体实现的代码如下:public void initMouseAdapter() public void mousePressed(MouseEvent
27、 e) int n = e.getModifiers();/ 获得鼠标的左右位置if (n = 4) net.power+;if (net.power = 8) net.power = 1;if(physics_powernet.power)net.power-;net.changeThePower(net.power);if (n = 16) /捕鱼if(physics_power=0)JOptionPane.showMessageDialog(getRootPane(), 游戏结束了);int m=JOptionPane.showConfirmDialog(getRootPane(), 是
28、否进行下一局);if(m=JOptionPane.YES_OPTION)System.out.println(下一局); newPool();/该方法是将所有数据清零,然后重新开始游戏else if(m=JOptionPane.NO_OPTION)System.out.println(游戏结束);System.exit(0);elsefor(int i=0;ifishes.length;i+)net.catchThe(fishesi);/网捕鱼physics_power-=net.power;if(physics_powernet.power&physics_power!=0)net.powe
29、r=physics_power;net.changeThePower(net.power);为了提高用户的体验度,我们将以上的属性都在页面上显示出来,有如下属性:当前的网的大小或者所当前渔网的power值,还有当前的体力值,还有捕鱼的条数,分数,所以我们需要在Pool.java类中的piant()方法中添加如下代码:g.setColor(Color.yellow);Font font = new Font(宋体, Font.BOLD, 25);g.setFont(font);g.drawString(当前的能量大小为: + net.power, 0, 30);g.drawString(体力值为
30、+physics_power, 400,30 );g.setColor(Color.red);Font font1 = new Font(宋体, Font.BOLD, 15);g.setFont(font1);g.drawString(点击右键改变网的大小, 0, 50);g.drawString(当前的条数为+Fish.count,0 ,70);g.drawString(得分为:+Fish.score, 0, 90);6测试与运行 6.1进行游戏测试 图6.1捕鱼过程6.2体力值为零的时弹出对话框。 图6.2 游戏结束6.3游戏结束后进行选择点击确定按钮后,再度提示,增加游戏体验度。点击是就
31、会重新开始一局游戏,所有数据清零,点击否就会结束游戏,而点击取消不做任何操作。 图6.3 游戏结束后选择 经过以上的测试与运行,游戏的效果已经很好了,至于其他的问题暂时还没有找到。7心得体会 这一个新星期的课程设计我相信我学到了很多。通过老师给我们带入门,我们终于看到了游戏编程的过程。一个星期,5天的时间,我们经过老师的悉心教导,我们完成了2048,捕鱼达人,FlappyBird等三个游戏,其进度不可谓不快。在学习的过程中,我们充分利用了所学的知识,将之融汇,贯通,最后得到这样的成品出来,心中不免有点小激动。在试验过程中我们对与java的swing组建的应用更是如鱼得水,游戏的各个板块都与之相
32、关,比如JFrame类创建游戏运行的视窗也是相当于画板,将游戏的效果显示出来,Pannel类画出背景,鱼,网等。还有,我对于面向对象的理念更加的清晰,以前对于面向过程,面向对象的概念还不是很懂,如今明白,面向对象,简而言之是万物皆对象,在我编程的过程中,鱼是一个对象,渔网也是一个对象,还有里面的鱼池也是一个对象,甚至是游戏运行的视窗也是JFrame的一个对象。每个对象都有自己的属性,方法,单斐然还有构造器,对对象进行初始化。在我的程序设计过程中,我充分的体会到了“实践出真知”这一点,书本上的知识是不够的,只有把理论与实践相结合才能够真正的学到知识。一个游戏的设计,不可能一步到位,还需要不断的完
33、善和补充。同时,游戏中还存在许多问题,有待在日后的使用中发现和解决。编程前的深思熟虑是减少程序调试工作量的重要方法,只有进行充分考虑,才会减少调试过程中的工作量。虽然在开始写程序之前我们做了多的准备工作,但在真正的写程序时仍然发现许多问题,有些问题是分析时的疏漏,有些则是如果不做无论如何也想不到的。8.参考文献1徐迎晓.JAVA语法及网络应用设计M.清华大学出版社.2李尊朝 苏军.JAVA语言程序设计(第二版)M.北京:中国铁道出版社,2007.103李明 袁晓君.Java计算机语言函数应用M.北京:科学出版社,20004黄晓东.JAVA课程设计案例精编(第二版)M.北京:中国水利水电出版社,
34、2007 附录:游戏运行类:package com.lhc.fishgame;import java.util.Timer;import java.util.TimerTask;import javax.swing.JFrame;public class FishGame public static void main(String args) final JFrame welcome =new JFrame(欢迎光临);welcome.setSize(643,435);welcome.setLocationRelativeTo(null);welcome.setResizable(false
35、);welcome.setUndecorated(true);/隐藏框架,大小不可变WelcomPanel wel=new WelcomPanel();welcome.add(wel);welcome.setVisible(true); /显示游戏界面final JFrame win = new JFrame(捕鱼达人游戏);win.setSize(800,500);win.setLocationRelativeTo(null);win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);Pool buyu=new Pool(); win.add(bu
36、yu);Timer timer = new Timer(); timer.schedule(new TimerTask() public void run() welcome.setVisible(false);win.setVisible(true);, 3000); buyu.action();鱼类:package com.lhc.fishgame;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.ut
37、il.Random;import javax.imageio.ImageIO;import javax.swing.JPanel;public class Fish extends ThreadBufferedImage image;BufferedImage images=new BufferedImage10;BufferedImage catchFish; int speed;/鱼的游动速度int x;int y;int height;int width;int blood;int index;/鱼的下标static int count;static int score;Random r
38、andom=new Random();/随机函数生成器public Fish(int index)this.index=index;if(index8)catchFish=new BufferedImage2;elsecatchFish=new BufferedImage4;String s1=(index10?0:)+index;String s2;try /image=ImageIO.read(new File(images/fish+s1+_01.png);for(int i=0;i10;i+)s2=(i=9?:0)+(i+1); imagesi=ImageIO.read(new Fil
39、e(images/fish+s1+_+s2+.png); for(int j=0;jcatchFish.length;j+)catchFishj=ImageIO.read(new File(images/fish+s1+_catch_0+(j+1)+.png); catch (IOException e) / TODO Auto-generated catch blocke.printStackTrace();/设置图片的长宽高width=images0.getWidth();height=images0.getHeight();/设置图片的显示范围x=random.nextInt(780+w
40、idth)-width;y=random.nextInt(470+height)-height;speed=random.nextInt(4)+3;/36blood=index*3;public void run() int i=0;while(true)x-=speed;image=imagesi+%10;if(x-width)/如果鱼过了左边界,就出场 getOut();if(blood=0)turnOver();getOut();blood=index*3; try Thread.sleep(1000/10); catch (InterruptedException e) / TODO
41、Auto-generated catch blocke.printStackTrace();/死鱼翻身private void turnOver() for(int j=0;j3;j+) for(int i=0;icatchFish.length;i+)image=catchFishi;try Thread.sleep(1000/15); catch (InterruptedException e) / TODO Auto-generated catch blocke.printStackTrace(); count+; score+=index*5;/*鱼出场地 方法*/private void getOut() / TODO Auto-generated method stubx=800;y=random.nextInt(470+height)-height;speed=random.nextInt(4)+3;/36渔网类:package com.lhc.fishgame;import java.awt.image.BufferedImage;import java.io.File;import j