《java游戏大作业设计》.docx

上传人:b****9 文档编号:23414781 上传时间:2023-05-16 格式:DOCX 页数:27 大小:1.10MB
下载 相关 举报
《java游戏大作业设计》.docx_第1页
第1页 / 共27页
《java游戏大作业设计》.docx_第2页
第2页 / 共27页
《java游戏大作业设计》.docx_第3页
第3页 / 共27页
《java游戏大作业设计》.docx_第4页
第4页 / 共27页
《java游戏大作业设计》.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

《java游戏大作业设计》.docx

《《java游戏大作业设计》.docx》由会员分享,可在线阅读,更多相关《《java游戏大作业设计》.docx(27页珍藏版)》请在冰豆网上搜索。

《java游戏大作业设计》.docx

《java游戏大作业设计》

Java游戏编程基础课程

大作业报告

课题:

吃豆人游戏的设计与实现

姓名:

黄子强

学号:

7

同组:

照、杜威

专业班级:

网工15102

指导教师:

何青

设计时间:

2018.6.18

评阅意见:

 

评定成绩:

指导老师签名:

年月日

 

 

一、课程设计目的

复习、领会、巩固和运用课堂上所学的JAVA游戏编程方面的技术知识,让学生掌握游戏设计的基本原理和游戏编程的基本方法,掌握游戏开发的一般步骤和相应文档的编制,能够设计、调试、运行一个完整的游戏项目;提高开发过程中的团队意识,锻炼学生书面和口头表达能力,为学生提供主动学习、积极探索与大胆创新的机会。

通过本次游戏设计,综合自己在校期间所学的理论知识,使自己熟悉应用系统的开发过程,培养独立思考能力,检验学习效果和动手能力,初步掌握软件工程的系统理论,进一步巩固和加强自身对java基础知识的理解,提高自己的编程水平,从而达到理论与实践相结合的目的。

二、需求分析

吃豆子游戏是一种古老而又有趣的游戏,游戏软件不计其数,网上就有好多关于实现的复杂算法和设计,其难度让一般初学者望而却步。

开发的出来的吃豆子游戏是一种容丰富,画面优美,益智类游的戏,并且不受网络的限制,让人们能够在任何时刻通过体验游戏,放松心情。

设计需求:

①游戏界面设计要能够彰显设计者的基本设计框架及思路;

②游戏界面布局要清晰整洁、层次明确;

③游戏的设计要使玩家能在短时间掌握游戏规则;

④玩家可以自由操控角色,玩家角色具有吃豆子的功能;

⑤吃到不同的豆子能有不同的效果(分数变化、角色状态的变化等等);

⑥怪物要能够自主运动,采用其特定的算法独立实现;

⑦游戏中怪物与玩家角色之间要有相应的事件(比如:

触碰到玩家角色时玩家生命减1);

⑧界面上要能有够显示出当前的得分情况以及当前的生命值;

⑨对于游戏的设计,在游戏结束时能够有相应的提示。

三、总体设计

3.1类的设计

图3-1

在吃豆人游戏的类设计中,首先要确立的是类的关联、划分主次。

整个游戏主要由两大部分组成,在这其中PacWorld类既是其中的一大组成部分也游戏一个重要的“舞台”,承载了其他的类方法,在这其中,设计者可以根据具体的游戏需要来加入相应的游戏元素、游戏规则,从而达到丰富游戏的目的。

World类又分为PacWorld和MyWorld两个类,其中PacWorld类是游戏场景元素的一个大集合。

作为一个舞台的大容器,它包括游戏区块(左中右三部分)的布局、边界(墙壁)的绘制、背景颜色、空白填充、位置信息显示、分数、大小豆子、怪物以及的位置生成、豆子的生成位置等元素,给游戏塑造出了一个整体框架。

而另一大组成部分Actor类则作为各种对象类的集合定义游戏中的各种方法。

其中包括Animal类、Writing类以及Object类。

Animal类中包含了两个重要的元素——PacMan类和Ghost类,分别实现吃豆人和怪物的运动、动画、触发事件等算法逻辑及调用方法。

Writing类包含主游戏框架面板上计分板、位置显示、空白填充以及生命计数器的方法类。

Object类中则是定义被吃的大小豆子。

所有的类在设计的时候保证了相互之间的联系性,类与类之间存在方法上的调用,对象方法的灵活运用是吃豆人游戏的一大主体。

3.2事件的设计

作为一个游戏,事件的设计必不可少。

在设计一个游戏时总是会在特定的游戏场景中抛出一个自定义事件,由相关的界面(可能是多个)去订阅这个事件,当接收到这个事件时,这些界面刷新显示数据,从而解除游戏逻辑层和界面显示层的耦合关系。

每一个游戏都有其自定义的游戏触发事件,本次设计的吃豆人游戏也有着其独到的自定义事件。

这次的设计中,吃豆人的事件主要分为两大类,它们分别是针对吃豆子和触碰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

{

for(intj=0;j

{

pacworld[i][j]=false;

}

}

接下来根据数组绘制地图DrawPath,将绘制的边界以特殊的信息保存到数组中。

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

for(intj=0;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;

}

4.2Animal类

在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-3

图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(direction=='u'&&checkD(direction)==true)y=-steps;

if(direction=='d'&&checkD(direction)==true)y=steps;

if(direction=='l'&&checkD(direction)==true)x=-steps;

if(direction=='r'&&checkD(direction)==true)x=steps;

this.setLocation(this.getX()+x,this.getY()+y);

}

4.3PacMan类

privateGreenfootImageMopen=newGreenfootImage("open.png");

privateGreenfootImageMclosed=newGreenfootImage("closed.png");

定义吃豆人运动的两种状态图:

开口和闭口,用于运动时变换显示。

privatevoidmovePic(){

if(mCounter>=mChange){

setImage(Mopen);

if(mCounter==2*mChange)mCounter=0;

}

elsesetImage(Mclosed);

}

在类中,还需要专门设置一个用于标记吃豆人运动时图片的变化显示的量:

privatechard='l';

定义初始运动向左,吃豆人的四个运动方向分别是:

上(Up:

u),下(Down:

d),左(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));

}

}

}

4.4Ghost类

在吃豆人游戏中,怪物是一个非常重要的存在,要让一个怪物实现在场景中移动就需要一个用于定义怪物随机移动的函数。

使用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){

case0:

d='u';o='d';break;

case1:

d='d';o='u';break;

case2:

d='l';o='r';break;

case3:

d='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

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

countR++;

if(countR==50){

countR=0;

this.setImage(uPic);

}

elsethis.setImage(gPic);

}

elseif(runCount==1000){

runCount=0;

run=false;

}

}

设置怪物由出生点出发(图4-6):

图4-6

protectedvoidleave(){

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-7

protectedvoidchangePic(){

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

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1