时间:2022-07-18 05:39:32
摘 要: 棋类游戏程序的编写本身并不复杂,但是如何写能提高效率,能更合理却成很多程序员要回答的问题。通过自己动手编写的一个黑白棋游戏,简单介绍一下该类游戏的架构设计,类设计,事件传送机制,并且给出具体的代码实现。
关键词: 棋类游戏;架构;类;事件
中图分类号:TP311.11 文献标志码:A 文章编号:1671-7597(2012)0210065-03
0 引言
由于棋类游戏设计简单,占内存小且娱乐性很强的,所以一直以来都非常有市场。但是一直以来,并没有一种设计规范。每个人,每个公司都用着自己的设计方案。
笔者通过一段时间的实验,用ActionScript3.0语言先后写了黑白棋,五子棋等程序,并且在FDT平台上运行成功,从中得到了一些编写此类程序的经验,现通过黑白棋程序简单介绍下自己的设计方法,希望可以抛砖引玉,也希望能让读者有所收获。
1 系统架构的建立
1.1 建立文档类
首先我们来建立我们的文档类,从ActionScript 3.0[1]开始,Adobe为Flash CS 3引入了文档类的概念,关于文档类,简单来说也就是Flash Player根显示容器所绑定的类,是整个flash影片的入口类。文档的使用可以使
这里的DocumentClass类继承于Sprite,所以也是一种显示容器,在创建游戏对象时通过this参数传递,也就是说Game对象是生成在这个显示容器上的。这样做的好处是,如果日后要开发另一个游戏,比如五子棋,泡泡龙等,直接写好Game类就行了,原有的显示容器类DocumentClass可以拿来直接使用。
1.2 游戏类的编写
接下来正式进入游戏类的编写,由于ActionScript 3.0已经真正实现了面向对象编程[2],所以编程之前我们必须考虑清楚,在这个游戏中我们会有哪些主要对象,这些对象又需要做些什么?
Game:游戏本身就是一个抽象的对象,和现实一样一个游戏本身就会有自己的游戏方式(方法)和游戏内容(属性)。
方法:开始游戏,结束游戏,暂停等。
属性:游戏工具(棋盘,棋子),规则,游戏参与者。
制作游戏的第一步我们要先把游戏工具确定下来。既然我们做的是棋类游戏,棋盘棋子是必不可少的。
ChessBoard:棋盘类,主要功能:显示棋盘,规划棋格(放上或去除棋子)。
Chessman:棋子类,主要功能:显示棋子,记录必要属性。
//首先我们用_rootmc=传入的容器,作为整个游戏根容器
_rootmc = rootmc;
//调整容器的位置为屏幕中心,在整个游戏的每个拥有显示容器的类中,我加入了对齐的概念,并预留了其他对齐方式的接口,像现在主容器的位置在屏幕中心,因为ALIGN==Enum_MCALIGN.Center;
}
//创建棋盘对象并传入游戏根目录容器对象,在ChessBoard的构造类我们可以看到,ChessBoard会自己构造一个容器加载到游戏根容器中,这个是这个游戏我所使用的显示对象自己管理显示类的方式。这样的优点是使对象和
//枚举类型对齐方式,使用枚举类型更易于发现字面错误。如果枚举名输入错误,ActionScript编译器会生成一个错误。如果使用字面值,存在拼写错误使用了错误数字时,编译器不会报错,而造成令人头疼的bug。[3]
Public class Enum_MCALIGN
{
public static const LEFTTOP : Enum_MCALIGN = new Enum_MCALIGN();
mc Sprite;
//棋盘行列数,因为将来可能出现不同长度的棋
//盘,所以使用变量
private var _chessLowLenght : Number = 8;
private var _chessRowLenght : Number = 8;
//棋子管理数组,记录棋盘中所有棋子对象
private var _chessmanArr : Array;
//棋盘左上角点
private var _startX : Number;
private var _startY : Number;
public function ChessBoard(Pmc : Sprite)
{
//创建棋盘容器,并加入父显示容器
_mc = new Sprite();
Pmc.addChild(_mc);
//center align,由于前边已经介绍过对齐方式,此
//处和前边相同,在这里不再重复。
…………………
//初始化棋子,为棋盘的的每一个格子初始化一//个看不见的棋子,其实我们的棋子chessman类//不光是棋子,还附加了棋盘上的一个“空格子”//概念,一个chessman对象一开始以一个“空格//子”的状态生成在棋盘上,这样做可以为以后//添加响应鼠标事件形成方便。
private function initChessman() : void
{
Chessman***************
import flash.display.Sprite;
import game.blackwhite.Enum.Enum_MCALIGN;
//载入枚举类型棋子状态
import game.blackwhite.Enum.Enum_ChessmanState;
public static const RADIUS :Number = 15;
public static const EMPTYCOLOR :int = =0xEEEEEE;//空棋子颜色;
public static const BLACKCOLOR :int = =0x000000;//黑棋子颜色;
public static const WHITECOLOR :int = =0xFFFFFF;//白棋子颜色;
//棋子显示容器
private var _mc : Sprite;
private var _i : int;
private var _j : int;
private var _x : Number;
private var _state : Enum_ChessmanState;
public function Chessman(Pmc : Sprite,i : int,j : int,x : Number,y : Number){
_mc = new Sprite();
Pmc.addChild(_mc);
_state = Enum_ ChessmanState.EMPTY;
//根据棋子不同的状态,用不同的颜色显示棋子
paint(_state);
}
private function paint(state:Enum_Chessman) : void
{
_mc.graghic.clear();
//center align,根据对齐方式,确定棋子显示位置,在此不再重复
…………………………
//设置空棋子,白棋子和黑棋子的绘制方式,不是本文讨论重点,略过。
…………………………
//在这个地方要特别指出的是,为什么要用2个set函数,并再set函数中即设定了该类的属性x/y,还设定了mc的x/y值。这就是我提到的逻辑类和显示类要分开的概念,也就是说这个棋子类是可以抛开其_mc容器而独立运行的,容器_mc只是这个棋子类的一个表现,可以有也可以没有。这样设计的好处是可以更方便且节约资源的在后台
枚举类Enum_ChessmanState的设计与前边的枚举类设计相似,在此不做重复。
到目前为止,我们已经简单的把整个游戏结构搭建起来了,已经可以看到棋盘和“空”棋子都已经显示出来了。而整个游戏的架构是Game控制ChessBoard,ChessBoard控制Chessman的方式。
2 取得鼠标事件
之前我们已经把棋盘和棋子显示出来了,接下来应该做的就是怎么让玩家通过鼠标事件来下棋。
其实在之前系统架构中我们已经为这个功能做了准备,在棋盘初始化的时候就放上了“空”的棋子,所以只要为每个“空”棋子加上事件响应就可以获得玩家在该格子的鼠标事件。
棋子对象可以通过paint函数来改变自己的颜色,达到下棋的效果。但究竟要下什么颜色的棋子,是否可以下,是否吃子等等的判断,棋子类是没办法判断的,我们也不应该让单个棋子参加到下棋规则的逻辑,棋子的工作就是Game作为游戏的控制类,接受棋盘的棋子点击事件,并作出响应后,再调用下棋函数进行下棋。
在以后的编程中,可以加入具体的游戏逻辑判定是否可以下棋,是否吃棋等,在游戏架构的设计中暂时不介绍。
到目前为止我们就可以在棋盘上下棋了,当然还只是能下黑子,在这部分中使用了一种拟人化的思想来架构我们的程序结构,并且使用了自下向上“报告”的方法。
3 结论
从上文中,我们可以看到棋类游戏分为以下步骤:
3.1 设计架构
1)设计文档类;2)编写游戏类。
3.2 取得鼠标事件
按以上步骤设计棋类游戏,不仅可以提高效率,而且可以提高程序的可读性。
参考文献:
[1]蒋国强、岳元亚,ActionScript 3.0从入门到精通,机械工业出版社,2011.
[2]李方捷,ActionScript 3.0开发技术大全,清华大学出版社,2004.
[3](美)Steve McConnell,代码大全,电子工业出版社,2006.
作者简介:
韩永亮(1988-),男,河南省新乡人,上海海事大学在读硕士,研究方向:分布式数据库。