疯狂java实战演义-第4章 桌面弹球

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第4章桌面弹球第4章桌面弹球4.1桌面弹球概述桌面弹球是游戏中常见的游戏,从以前的掌上游戏机到如今的手机游戏,都是一个十分经典的游戏。玩家控制一个可以左右移动的挡板去改变运动中小球的移动方向,目的是用小球消除游戏屏幕中的所有障碍物到达下一关,在障碍物被消除的过程中,可能会产生一些能改变挡板或者小球状态的物品,例如:挡板变长、变短,小球威力加强等等。本章主要介绍如何实现一个简单的弹球游戏,让读者了解“动画”的实现原理。在本章中,将介绍与使用Java的绘图功能,使用到JPanel的paint(Graphicsg)方法去绘图,绘图主要是依靠这个方法中的Graphics类型的参数,将使用Java中的Timer去重复绘图,产生动画效果,桌面弹球游戏的效果如图4.1所示。图4.1桌面弹球4.1.1动画原理简单地来说,动画是利用人的视觉暂留的生理特性,实现出来的一种假象,只要每隔一段时间(这个时间少于人的视频暂留时间)就重新绘制一幅状态改变的图片,就能造成这种“动”的假象。我们在第4章桌面弹球·2·程序中不断的进行绘画(使用repaint方法),对程序来讲,只需要在短时间内进行多次的绘画,并且每次绘画都需要改变绘画的相关值,就可以达到“动画”的效果。4.1.2小球反弹的方向在本章实现的过程中,我们会设置小球于对称的方式,并出现少许偏移的方式反弹,如图4.2所示。让小球反弹出现少许编移是为了让游戏增加点不确定性,增加游戏的趣味性。我们需要在编写游戏前确定这些小细节,这样在开发的过程中,我们就可以按照这些小细节去逐步实现我们的程序。图4.2小球的反弹4.2流程描述玩家使用左右方向键开始游戏与控制挡板,在未消除完所有的障碍物或者挡板没有档住向下移动的小球之前,会一直处于游戏状态,在这个状态中,小球会一直处于直线运动或者改变方向,当小球消除掉障碍物的时候,有机率产生一些物品,产生的物品会直线向下移动,用挡板接住物品后,物品的特殊效果会生效。如果消除了所有的障碍物,就判断玩家为赢,如果挡板没有接住向下移动的小球,就判断玩家为输。具体的游戏流程如图4.3所示。图4.3游戏流程游戏中并不涉及复杂的流程,只需要处理游戏的输赢即可,因此在实现的过程中,关键是如何确定游戏输赢的标准(挡栏没有挡住小球)。第4章桌面弹球·3·4.3创建游戏对象在这个游戏中,有挡板,小球,砖块(障碍物),道具等物品,这些物品都有共同的特性,有属于自己的x与y坐标属性,有图片属性,有速度属性,所以,在这时在,设计一个基类BallComponent包含这些属性与相关的方法,让其子类继承。继承此类的子类有Stick类(用于定义挡板的行为于属性),Ball类(控制小球的移动与其它动作),Brick类(砖块类),Magic类(道具抽像类,此类中有一个用于使道具功能实现的抽象方法,供其子类实现)。道具类的子类有LongMagic与ShortMagic,作用是使Stick的长度变长或者变短。在平时的开发中,如果发现多个对象之间有一些共同的特性或者行为,并且觉得可以使用这些特性或者行为构成一个对象,那么可以建立一个新的对象作为这些对象的父类。如果该父类中某些方法并不需要由父类实现,我们可以将父类做成抽象类,并将这些方法变成抽象的。确定了我们游戏中的所涉及的对象后,我们还需要一个BallFrame类去创建一个画板,用于绘制图片,此类还完成界面的初始化,监听用户的键盘,而与游戏相关的业务逻辑(判断输赢或者球的运动),我们放到BallService类中去处理,本章类的关系如图4.4所示。图4.4桌面弹球类图笔者在这里提供了本章的类图,是为了让读者可以更清晰的了解本章程序的结构,但在实现开发的过程中,我们可以根据实际情况,加入或者改变各个类的关系或者程序的结构,但最终都是为降低程序的耦合、提高内聚、编写出优秀的代码。第4章桌面弹球·4·4.3.1基类BallComponentBallComponent,做为Brick(砖块)类、Magic(道具)类、Stick(挡板)类、Ball(小球)类的父类,定义了这些子类共有的属性与方法,属性有:x坐标,初始值为-1;y坐标,初始值为-1;图片image,初始值为null;速度speed,初始值为5。根据不同的需要,提供以下三个构造方法:BallComponent(Stringpath),path是图片的路径,用图片的路径来构造一个BallComponent,在此构造方法中,将根据路径去读取图片,再设置对象中image属性。BallComponent(intpanelWidth,intpanelHeight,Stringpath),以panelWidth,panelHeight,与path去构造一个Component。BallComponent(Stringpath,intx,inty),以x坐标,y坐标和path去构造一个BallComponet。除去这些构造方法,此类提供了这些属性的setter与getter方法,用于获取对象的坐标与图片,或者改变对象的坐标位置与图片属性。如果我们在编码的过程中发现有一些共同的属性或者方法,我们可以将这些放到这个基类中。创建BallComponent的时候,我们可以将这个类变成抽象类,即使它没有任何的抽象方法,这样做的目的是,在我们的桌面弹球游戏中,该类并不是具体存在的某一个对象,而是我们将一些公用的属性或者方法存放到该类中,因此它在游戏中并不代表某个具体的对象。将该类创建为抽象类,我们就可以提供(如果需要的话)一些抽象方法让子类去实现,并且可以在父类中调用这些抽象方法。4.3.2砖块类(Brick)此类是BallComponet的一个子类,提供一个Brick(Stringpath,inttype,intx,inty)构造器,其中pah、x与y参数用于调用父类的构造器,type是代表砖块的类型:1代表此砖块里面有LongMagic类型的道具;2代表此砖块里面有ShortMagic类型的道具;其它代表此砖块里面没有道具。另外,本类增加了magic与disable属性,magic代表此砖块中所包含的道具,初始值为null,disable是用来标志Brick的状态,如果diable为true,则表明此砖块已经不可用,不会再显示。并提供这两个属性相关的以下方法:voidsetMagic(Magicmagic),设置道具。MagicgetMagic(),获取道具。booleanisDisable(),用来判断此类是否有效。voidsetDisable(booleandisable),停用或者启用此类,disable的值为true或者false。确定了一个砖块由一个Brick对象来表示后,在界面中,我们可以提供一个Brick的二维数组,来表示界面中所有的砖块,实现原理与控制台五子棋中的棋盘一样,但是在本章中,二维数组的每一个元素并不是字符串,而是具体的某个Brick对象,在以后的章节中,当遇到需要在界面中绘画某些图片的时候,我们都可以建立一个二维数组,将相应的对象放置到该数组中,当界面进行绘画的时候,就可以将这个二维数组“画”出来。4.3.3道具类及其子类(Magic)Magic类是一个道具类,在游戏中表现包含在砖块中,是BallComponet的一个抽象子类,此类提供一个Magic(Stringpath,intx,inty)构造器去调用父类的构造器,并提供一个抽象的方法magicDo(Stickstick),此抽象方法是实现道具的效果功能,用于给其子类实现,现在实现的子类的LongMagic类和ShortMagic类,两个子类的magicDo方法中分别实现使挡板变长与变短的功能。abstractvoidmagicDo(Stickstick),道具的功能,给其子类实现。在本例中,挡板是可以变长或者变短的,而使挡板变长或者变短的方式是通过道具来实现,因此可以将道具抽象成变长的道具或者变短的道具,而它们都需要做同一件是,就是改变挡板的展现形式。为第4章桌面弹球·5·了程序的可扩展性,我们在这里将一个道具变为一个抽象类(Magic),当我们需要有其他形式的道具的时候,就可以为该类添加子类,并提供不同的实现。当然,这里只提供一个Stick的参数可能并不够,如果以后游戏中出现另外一种道具,会改变球的速度(变快或者变慢),那么我们就需要为该抽象类提供更多的参数。4.3.4挡板类(Stick)同样,Stick类也是BallComponet的子类,用来代表游戏中的挡板,由于挡板只有左右移动的,所以,此类中只定义了挡板x方向的移动速度SPEED,还有定义挡板的初始长度preWidth,并提供此方法的setter与getter方法,如下:voidsetPreWidth(intpreWidth),设置初始长度。intgetPreWidth(),获取初始长度。由于该类继承于BallComponet类,因此只需要提供一个构造器即可。在本例中,挡板是可以变长或者变短的,并且在建立道具抽象类的时候,已经定义了一个magicDo的方法,该方法的参数就是一个挡板对象,所以挡板类必须包括长度的属性,这样,在实现道具类的时候,就可以通过改变挡板类的长度来实现本例中所需要实现的长短挡板功能。在Stick类中并不需要关心挡板的图片、位置与大小,这些属性已经在BallComponet中体现。4.3.5小球类(Ball)Ball类也是BallComponet的子类,由于小球在游戏面板中运动的时候除了横竖方向,还有各种角度的斜方向,所以我们把小球的速度分解成横向速度与竖向速度(speedX与speedY),游戏未开始前,小球是处于静止状态,所以用一个started属性来标志小球是否已经开始运动。游戏结束后,小球也是处于静止状态,但不能再移动,同样,用一个stop属性来标志小球是否能再移动。除了定义这些属性,还为这些属性提供相应的setter与getter方法,如下:setSpeedX(intspeed),设置小球的横向速度。setSpeedY(intspeed),设置小球的竖向速度。booleanisStarted(),小球是否已经在运动。voidsetStarted(booleanb),把小球状态设置为运动或者静止。intgetSpeedX(),获取小球的横向速度。intgetSpeedY(),获取小球的竖向速度。在本例中,小球对象只保存一些相关的属性,例如横向速度与纵向速度(图片、位置与大小在父类中体现),如果需要改变小球的速度,可以调用相关的setter方法来进行,但是我们需要知道由哪些对象来改变小球的相关属性,我们在前面的章节中提到,提供一个业务类进负责处理游戏的相关逻辑,因此,业务类就需要维护一个小球的对象,来控制小球的运动或者其他行为。在这里,小球对象可以单纯的看作一个简单的对象,并不负责处理任何的行为,这可以看作我们一般所说的贫血模式,对象并不负责处理任何的业务逻辑。如果需要将该小球对象编写成为充血模式,可以为小球对象提供一些与之相关的行为,例如小球会运动,我们可以为Ball类加入一个run的方法,表示球的运动,例如小球会停止运动(在游戏结束或者开始时),我们就可以为Ball类添加一个stopRun的方法,总之,如果需要做到充血模式,可以将所有与小球相关的方法加入到Ball中。4.3.6业务处理类(BallService)BallService处理了这个游戏中的大部分业务功能,包括开始游戏、小球移动、道具移动、挡板移动、测试小球与挡板是否有碰撞或者挡板和其它元素有碰撞、设置挡板的长度、判断用户是否通关、初第4章桌面弹球·6·始化砖块的排列与道具、画图等功能。这些功能的实现都有对应的方法,如下:voidrun(),小球进行运动。voidsetStickPos(KeyEventke),改变挡板的坐标位置。setBallPos(),改变小球的坐标位置。booleanisHitBrick(Brickbrick),测试小球与砖

1 / 23
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功