《java游戏大作业设计》_第1页
《java游戏大作业设计》_第2页
《java游戏大作业设计》_第3页
《java游戏大作业设计》_第4页
《java游戏大作业设计》_第5页
已阅读5页,还剩22页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JaVa游戏编程基础课程大作业报告课题: 吃豆人游戏的设计与实现 姓名: 黄子强 学号:_^7 同组姓名: 刘照、杜威 专业班级: 网工15102 扌旨导教师: 何青 设计时间: 2018618 评阅意见:评定成绩:目指录老师签名:课程设计目的需求分析.总体设计.3.1类的设计3.2事件的设计四、详细设计.PaCWOrId类 Animal类 7PaCMan类 9TOC\o"1-5"\h\zGhost 类 11Blank 类 14Position类 14Score 类 15Lives 类 16Object类 17COin类&Power_Pellet类 17\o"CurrentDocument"五、游戏测试 175.1游戏界面展示 175.2游戏效果测试 19总结 20课程设计目的复习、领会、巩固和运用课堂上所学的JAVA游戏编程方面的技术知识,让学生掌握游戏设计的基本原理和游戏编程的基本方法,掌握游戏开发的一般步骤和相应文档的编制,能够设计、调试、运行一个完整的游戏项目;提高开发过程中的团队意识,锻炼学生书面和口头表达能力,为学生提供主动学习、积极探索与大胆创新的机会。通过本次游戏设计,综合自己在校期间所学的理论知识,使自己熟悉应用系统的开发过程,培养独立思考能力,检验学习效果和动手能力,初步掌握软件工程的系统理论,进一步巩固和加强自身对java基础知识的理解,提高自己的编程水平,从而达到理论与实践相结合的目的。二、 需求分析吃豆子游戏是一种古老而又有趣的游戏,游戏软件不计其数,网上就有好多关于实现的复杂算法和设计,其难度让一般初学者望而却步。开发的出来的吃豆子游戏是一种内容丰富,画面优美,益智类游的戏,并且不受网络的限制,让人们能够在任何时刻通过体验游戏,放松心情。设计需求:游戏界面设计要能够彰显设计者的基本设计框架及思路;游戏界面布局要清晰整洁、层次明确;游戏的设计要使玩家能在短时间内掌握游戏规则;玩家可以自由操控角色,玩家角色具有吃豆子的功能;吃到不同的豆子能有不同的效果(分数变化、角色状态的变化等等);怪物要能够自主运动,采用其特定的算法独立实现;游戏中怪物与玩家角色之间要有相应的事件(比如:触碰到玩家角色时玩家生命减1);界面上要能有够显示出当前的得分情况以及当前的生命值;对于游戏的设计,在游戏结束时能够有相应的提示。三、 总体设计类的设计图3-1在吃豆人游戏的类设计中,首先要确立的是类的关联、划分主次。整个游戏主要由两大部分组成,在这其中PacWorld类既是其中的一大组成部分也游戏一个重要的“舞台”,承载了其他的类方法,在这其中,设计者可以根据具体的游戏需要来加入相应的游戏元素、游戏规则,从而达到丰富游戏的目的。World类又分为PaCWOrId和MyWOrId两个类,其中PaCWOrId类是游戏场景元素的一个大集合。作为一个舞台的大容器,它包括游戏区块(左中右三部分)的布局、边界(墙壁)的绘制、背景颜色、空白填充、位置信息显示、分数、大小豆子、怪物以及的位置生成、豆子的生成位置等元素,给游戏塑造出了一个整体框架。而另一大组成部分ACtOr类则作为各种对象类的集合定义游戏中的各种方法。其中包括AnimaI类、Writing类以及ObjeCt类。AnimaI类中包含了两个重要的元素——PaCMan类和GhOSt类,分别实现吃豆人和怪物的运动、动画、触发事件等算法逻辑及调用方法。Writing类包含主游戏框架面板上计分板、位置显示、空白填充以及生命计数器的方法类。ObjeCt类中则是定义被吃的大小豆子。所有的类在设计的时候保证了相互之间的联系性,类与类之间存在方法上的调用,对象方法的灵活运用是吃豆人游戏的一大主体。事件的设计作为一个游戏,事件的设计必不可少。在设计一个游戏时总是会在特定的游戏场景中抛出一个自定义事件,由相关的界面(可能是多个)去订阅这个事件,当接收到这个事件时,这些界面刷新显示数据,从而解除游戏逻辑层和界面显示层的耦合关系。每一个游戏都有其自定义的游戏触发事件,本次设计的吃豆人游戏也有着其独到的自定义事件这次的设计中,吃豆人的事件主要分为两大类,它们分别是针对吃豆子和触碰Ghost的触发事件。在吃豆子的事件中(如图3-3所示),当玩家操控吃豆人角色吃到小豆子(coin)时,分数加1(更新计分板)并移除小豆子。而当吃到大豆子(Power_Pellet)时,就需要在分数加5并移除大豆子的基础上更新Ghost状态(这里需要改变Ghost的图形,使玩家能在视觉上感受变化)。图3-2在触碰Ghost事件中(如图3-4所示),只有当Ghost处于特殊状态时,玩家角色才可以将其吞食消除,否则吃豆人将会失去一条生命并且重置回出生点,并在计分板上使其生命显示减1(同步计数器)。图3-3四、 详细设计4.1PacWorld类在游戏场景中,除了中央的游戏区域外,左右各有三块区域用于显示游戏信息,而其余部分则用Blank类方法填充空白。游戏中央的场景中绘制出地图(边界线/墙壁),留出通道,在其中的相应位置放入对应的怪物、大小豆子以及游戏的控制主体——吃豆人,左右放置对应的计分板和计数器,构成整个游戏的基本元素框架。图4-1先定义各元素信息:左右空白填充:BlankblankR=newBlank();BlankblankL=newBlank();生命显示:(左下角三个小吃豆人)Liveslife1=newLives(1);Liveslife2=newLives(2);Liveslife3=newLives(3)四种颜色的怪物:Inkyinky=newInky();Blinkyblinky=newBlinky();Clydeclyde=newClyde();Pinkypinky=newPinky();Ghost.speed=gSpeed;吃豆人:staticPacManpacman;pacman=newPacMan(pPoints,pLives);地图信息:首先,将整个地图存入到一个二维数组中:for(inti=0;i<pacworld.length;i++){for(intj=0;j<pacworld[i].length;j++){pacworld[i][j]=false;}}接下来根据数组绘制地图 DraWPath,将绘制的边界以特殊的信息保存到数组中

privatevoidDrawPath()部分代码)privatevoidDrawPath()部分代码){min=200;max=442;for(intx=min;x<=max;x++){pacworld[x][341]=true;}min=283;max=358;for(intx=min;x<=max;x++){pacworld[x][221]=true;pacworld[x][213]=true;pacworld[x][204]=true;}min=120;max=522;for(intx=min;x<=max;x++){pacworld[x][426]=true;pacworld[x][87]=true;}min=248;max=394;for(intx=min;x<=max;x++){pacworld[x][257]=true;pacworld[x][171]=true;} //为简明说明此处省略90%勺边界代码}图4-2绘制完成后就向其中加入实体:(计分板、空白填充、生命计数器、吃豆人、怪物)Positionposition=newPosition();ScorescorE=newScore();addObject(position,320,460);addObject(pacman,320,257);addObject(scorE,46,75);addObject(inky,283,210);addObject(blinky,320,171);addObject(pinky,320,217);addObject(clyde,358,210);addObject(blankL,75,214);addObject(blankR,575,214);addObject(life1,70,350);addObject(life2,45,350);addObject(life3,20,350);豆子的绘制(程序中放置在转角处)需要对通路进行统计,即CoinFill函数的square的计数:.在指定的区域放置大豆子,当吃到大豆子时所有的怪物立刻变为可以被吃掉的状态。注:在吃掉大豆子后吃豆人的标记run会变为true,意味着此时可以吃掉怪物,这个状态的持续时间定义为5秒。.在路口处放置小豆子.放置完豆子使其计数器加一publicvoidCoinFill(){coins=0;for(inti=0;i<pacworld.length;i++){for(intj=0;j<pacworld[i].length;j++){if(pacworld[i][j]==true){intsquare=1;if(pacworld[i+1][j]==true)square++;elseif(pacworld[i-1][j]==true)square++;if(pacworld[i][j+1]==true)square++;elseif(pacworld[i][j-1]==true)square++;:if(/*(i==320&&j==171)||*/(i==200&&j==87)||(i==442&&j==87)||(i==420&&j==341)||(i==224&&j==341)){addObject(newPower_Pellet(),i,j);coins++;}elseif(i>=283&&i<=358&&j>=172&&j<=221)coins=coins;elseif(square>2){addObject(newCoin(),i,j);coins++;}}}}c=coins;}Animal类在Animal类中定义了用于子类继承的抽象方法,如:方向的移动、方向移动的提前量判断等,在该类中还设置了角色的场景移动传送方法,用于对游戏场景中部特殊的通道移动的定义。对于Ghost而言,他们的移动的范围要求比吃豆人更广提高难度,当他们从地图中央两侧的通道进入时,将会从另一侧出现。这种突然出现在身边的GhOSt往往能提高玩家的紧张感,提升游戏性。ProteCtedvoidwarp(){POSitionX=this.getX();POSitionY=this.getY();if(positionX==94)SetLOCatiOn(550,213);elseif(positionX==556)SetLOCatiOn(104,213);例如:当Ghost从右侧通道走出游戏场景时将会从左侧的通道重新出现在玩家的面前(如图4-3、图4-4所示)图4-4在游戏中,总是会在一个方向上碰到无法继续前进的情况,这个时候就需要判断此时还能往哪个方向进行运动,时刻检查能否向四周运动,并根据这个方向来和键盘输入的方向键进行比较,来执行最终的动作方向。CheCkD用于检查你可以去往哪个方向PriVatebooleanCheCkD(CharS){intX=0,y=0;SWitCh(S){{case'u':y=-steps;break;case'd':y=steps;break;case'l':x=-steps;break;case'r':x=steps;break;}returnPacWorld.pacworld[getX()+x][getY()+y];}只有当判定可以往目标方向移动时,角色才可以进行移动protectedvoidmove(chardirection)intx=0,y=0;if(directiony=-steps;if(direction==if(directionx=-steps;intx=0,y=0;if(directiony=-steps;if(direction==if(directionx=-steps;if(direction===='u'&&checkD(direction)'d'&&checkD(direction)==true)=='l'&&checkD(direction)'r'&&checkD(direction)==true)==true)y=steps;==true)x=steps;this.setLocation(this.getX()+x,this.getY()+y);}PacMan类privateGreenfootImageMopen=newGreenfootImage("open.png");

privateGreenfootImageMclosednewprivateGreenfootImageMclosednewGreenfootImage("closed.png");定义吃豆人运动的两种状态图:开口和闭口,用于运动时变换显示。privatevoidmovePic(){if(mCounter>=mChange){setImage(Mopen);if(mCounter==2*mChange)mCounter=0;}elsesetImage(Mclosed);}在类中,还需要专门设置一个用于标记吃豆人运动时图片的变化显示的量:privatechard='l';定义初始运动向左,吃豆人的四个运动方向分别是: 上(Up:U),下(DOWnd),左(Left:l),右(Right:r)。如:(键盘点击方向键向上后,改变吃豆人的运动方向向上)if(GreenfOOt.isKeyDOWn("up")){setROtatiOn(90);d='u';}图4-5在获得了键盘输入的方向后,改变吃豆人的运动(位置、方向),这里还会对可能移动的方向先进行判断(判定是否可以朝目标方向移动)。(图4-5)privatevOidcOrner(charside){fOr(inti=-7;i<=7;i++){intx=0,y=0;switch(side){case'u':y=-1;x=i;break;case'd':y=1;x=i;break;case'l':x=-1;y=i;break;case'r':x=1;y=i;break;}if(PacWorld.pacworld[getX()+x][getY()+y]==true)setLocation(getX()+x,getY()+y);}}吃豆人在吃豆子时需要调用eat函数:当吃到小豆子时,移除当前接触到的小豆子并让分数加一;当吃到大豆子时,移除当前接触到的大豆子并让分数加五;当分数高于200且当前游戏中仍存有豆子时,怪物的速度提升(难度提升)。privatevoideat(){if(isTouching(Coin.class)){removeTouching(Coin.class);coinsCollected++;points++;}if(isTouching(Power_Pellet.class)){removeTouching(Power_Pellet.class);run=true;coinsCollected++;points+=5;}if(coinsCollected==PacWorld.coins&&PacWorld.coins!=0){if(points>200*Ghost.speed)Ghost.speed++;Greenfoot.setWorld(newPacWorld(l,points,Ghost.speed));}}在游戏中,吃豆人难免会出现触碰到怪物而死亡的情况,这个时候就需要死亡函数——在出生点重生,生命减一,并执行一次判断:当生命所剩为零时重置游戏。执行这个死亡函数的前提条件是吃豆人触碰到四个怪物中的任意一个(if语句)。privatevoiddie(){if(isTouching(Inky.class)||isTouching(Pinky.class)||isTouching(Blinky.class)||isTouching(Clyde.class)){l--;setLocation(320,257);if(l==0){points=0;Greenfoot.setWorld(newPacWorld(3,0,1));}}}}}}}}Ghost类在吃豆人游戏中,怪物是一个非常重要的存在,要让一个怪物实现在场景中移动就需要一个用于定义怪物随机移动的函数。使用random函数随机生成四个方向的移动,当怪物移动到一个方向的尽头时则执行下一个方向的运动判断。protectedvoidrandomWalk(){intsquare=1;if(PacWorld.pacworld[this.getX()+1][this.getY()] ==true)square++;elseif(PacWorld.pacworld[this.getX()-1][this.getY()]==true)square++;if(PacWorld.pacworld[this.getX()][this.getY()+1] ==true)square++;elseif(PacWorld.pacworld[this.getX()][this.getY()-1]==true)square++;if(square>2){do{intr=(int)(int)(Math.random()*4);switch(r){case0d='u';o='d';break;case1d='d';o='u';break;case2d='l';o='r';break;case3d='r';o='l';break;}bX=this.getX();bY=this.getY();move(d);aX=this.getX();aY=this.getY();move(o);}while(bX==aX&&bY==aY);}for(inti=0;i<speed;i++)move(d);if(this.getX()==320&&this.getY()>171&&this.getY()<221)this.setLocation(320,171);}protectedvoidrun(){if(run)runCount++;if(isTouching(PacMan.class)&&run==true){PacMan.points+=20;setLocation(320,213);this.start=true;elseif(800<runCount&&runCount<1000){countR++;if(countR==50){countR=0;this.setImage(uPic);}elsethis.setImage(gPic);}elseif(runCount==1000){runCount=0;run=false;}}设置怪物由出生点出发(图4-6):图4-6protectedvoidleave(){lCount++;if(lCount==100){this.order--;Count=0;if(this.position==false&&this.order!=1){if(this.getY()==204)this.d='d';elseif(this.getY()==221)this.d='u';move(this.d);}elseif(this.position==false&&this.order==1){if(this.getY()<213)move('d');elseif(this.getY()>213)move('u');elseif(this.getY()==213){if(this.getX()<320)move('r');elseif(this.getX()>320)move('l');else{this.position=true;}}}elseif(this.position==true){if(this.getY()>171)move('u');else{this.start=false;inta=(int)(Math.random()*2);if(a==0)this.d='r';}}}}elsethis.d='l';}}吃豆人有着其运动的样式,而怪物也同样有着四个方向运动的图案变化4-7):图4-7protectedvoidchangePic(){if(run==false){switch(this.d){case'u':this.setImage(this.uPic);break;case'd':this.setImage(this.dPic);break;case'r':this.setImage(this.rPic);break;case'l':this.setImage(this.lPic);break;}}elsethis.setImage(gPic);}Blank类Blank类用于填充空白部分(填充黑色单元块)publicclassBlankextendsWriting{publicBlank(){50,setImage(newGreenfootImage(" ",50,}}Color.BLACK,Color.BLACK));}}Position类不论是吃豆人还是怪物都需要动态标记、使用当前的位置,这样就需要一个能够被所有对象调用的Position类,这个类既定义了对象坐标也和PacWorld起定义了这些对象所能够运动的轨迹。publicclassPositionextendsWritingprivateintpX,pY;publicvoidact(){pX=PacMan.X;pY=PacMan.Y;//intpY).getRed();//intpY).getGreen();//intpY).getBlue();//intr=getWorld().getBackground().getColorAt(pX,//intpY).getRed();//intpY).getGreen();//intpY).getBlue();//intr=getWorld().getBackground().getColorAt(pX,g=getWorld().getBackground().getColorAt(pX,b=getWorld().getBackground().getColorAt(pX,a=getWorld().getBackground().getColorAt(pX,pY).getAlpha();setImage(newGreenfootImage("X:"+pX+"Y:"+pY,15,Color.WHITE,Color.BLACK));//setImage(newGreenfootImage("R:"+r+"G:"+g+"B:"+b+"A:"+a,15,Color.WHITE,Color.BLACK));}}运动轨迹为图中白色区域中的灰色直线(图4-8):图4-8同时在游戏过程中,我们也可以通过显示position来看到吃豆人所在的位置(图4-9):图4-9Score类分数信息显示在左上角,当分数为0时显示为000,个位数显示为00+对应数字,十位数显示为0+对应二位数字,三位数则直接显示数字(图4-10)。publicclassScoreextendsWriting{publicvoidact(){Stringnumber="00";if(PacMan.points<0)PacMan.points=0;elseif(PacMan.points>99)number="";elseif(PacMan.points>9)number="0";elsenumber="00";setImage(newGreenfootImage(number+PacMan.points,30,Color.WHITE,Color.BLACK));图4-10Lives类既然存在玩家角色和怪物,以及触碰的死亡事件,那么就必然有着对应的生命计数器(生命计分面板),用于显示玩家当前剩余的生命值。而这样就需要一个类用于计算玩家的生命信息。publicclassLivesextendsWriting{publicintN;publicLives(intn){N=n;}publicvoidact(){if(N-1==PacMan.l){getWorld().removeObject(this);PacMan.points-=20;}}}图4-11Object类Object类继承Actor类中的方法,同样,这其中的方法也传递给了两个子类。两种豆子的子类继承了Object类即Actor类的所有属性及方法。Coin类和Powe_Pellet类在PacWorld类中与吃豆人共同作用了一个事件,同时Powe_Pellet类对象还将对Ghost产生状态的影响。这两个类在PacWorld类中作为类对象被放置在容器中充实游戏整体,也为与 PaCMan类和GhOSt类的互动打下一个基础。图4-12Coin类&PowerPellet类两种豆子在这两个类中被分别定义声明,主要在PaCWOrId类中被调用五、游戏测试5.1游戏界面展示最初运行游戏时,玩家将会进入最初的静止的游戏界面:图5-1点击运行即可开始游戏:图5-2在游戏中,吃到小豆子时(分数、游戏效果变化)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论