逻辑服务器设计
服务器结构设计
逻辑服务器主要是处理玩家和玩家,玩家和服务器之间的瞬时事件。因此,整个服务器的对象可以分为2个大的类型,玩家和城市。
从需求分析里可以知道目前的游戏瞬时事件都还只是玩家和服务器之间的互相操作事件。因此,根据分析得到一个游戏消息的基本处理流程:
城市类的设计
设计思路
整个游戏世界是由多个城市组成的,每个城市之间是互相独立的,每个城市都有各自的属性,同时,在游戏进行的时候,玩家的一些动作,都只是针对某一个城市进行的,因此我们把游戏里的城市抽象为一个城市类(CCity),玩家也抽象出一个玩家类(CPlayerSession)。当玩家需要进行某些动作的时候,通过这个城市的接口函数( DoMsg() )获得玩家及玩家的动作类型,然后进行相应的数据处理。
在需求分析里,玩家的动作,都可以分解到城市里的5类场景(码头,船厂,交易所,银行,酒馆)因此,在城市类里,我们由针对这5类场景,分别设计了5个类。码头类(CShipside),船厂类(CBoatyard),交易所类(CBouse),银行类(CBank),酒馆类(CTaproom)
在这5类场景里,都存在着公共的部分:进入场景和退出场景,其中退出场景的动作每个建筑物都差不出(在进行基本的验证后,向地图服务器发出退出场景确认消息),而进入场景则个有不同,因为不同的场景在玩家进入后要根据其场景的类型,把场景内一些特定的场景信息发送给玩家。
数据结构设计:
在城市类里,需要保存一些有关城市的信息,其中包括有:城市的名字,城市的编号,城市对应的地图编号,城市在公海的地图编号,城市在公海的位置等与游戏相关的基本信息。
TKind identifier; // 城市编号和名称
int cityMapID; //对应的城市map
int seaMapID; //港口公海map编号
iPoint seaMapLocation; //港口公海Map中图元左上角的X , Y
与码头相关的信息有:单位补给的价格
int supplyPrice;
与船厂相关的数据有:修理单位船只的价格,船厂可出售船只的列表。其中船只列表用一个TShip 类型的数组newShip保存,数组的大小是所有船只,但是在一个船厂不会出售游戏里设定的所有船只,它能出售只是游戏设定里的一小部分而已,因此,在这里还定义有一个变量discount用于确定当前船厂能够出售多少条船。并且在进行处理的时候只读取船只数组[0~discount)区间的船只信息。
int basicRepairPrice; // 修理价格
int discount;
TShip newShip[BOATYARD_MAX_SHIP];
与码头相关的数据:交易所可以出售货物列表,交易所收购货物列表。因为这两个列表都采用数组的方式进行保存,在服务器实际应用的时候并不会完全使用完整个数据的空间,所以,我们在出售货物和收购货物的数组外还定义了交易所能够出售和能够收购货物的数量。
TGoods sellGoods[200]; // 可以卖给交易所的货物
int sellGoodsNum;
TGoods buyGoods[10]; // 可以从交易所购买的货物
int buyGoodsNum;
与酒吧相关的变量:雇佣水手的价格
int employCost;
与银行相关的数据:无
玩家类设计
玩家类是存放一个玩家在游戏里的各种属性的类,具有一定的动作,这些动作仅仅相对相对自身的动作,而游戏的动作时从城市类里再调用玩家自身动作来完成的。例如游戏里一个玩家购买货物的动作,分解到玩家这里,就是2个动作:1。增加货物,2。减少现金。
玩家类的数据结构设计
因为玩家类表示一个玩家,它是由玩家的基本信息,玩家的船只信息,玩家的货物信息,以及玩家的状态等信息组成。
其中人物的基本信息由玩家的名字,性别,国籍,现金组成,并封装在一个CPlayer类里。除了封装在CPlayer类里的基本数据以为,玩家的存款存放在TBank的数据结构里,改数据结构是为了将来扩展银行业务而设计的。
int sex;
int money;
TKind identifier; // 玩家的编号和名称
TKind nationality; // 国籍
void Init(CIniSet &ini);
玩家的船只分做2个部分,一个是玩家当前使用的船只,另外一个是玩家存放在船坞里备用的船只。虽然目前玩家只能够使用一条船,但是考虑到今后玩家的可以操作的船只数量会很多,所以,为了以后扩展方便,这里把当前使用船只和船坞船只都定义为TShip类型的数组。
玩家货物的货物信息用一个CPlayerGoods类型的数组保存,改类型继承自TGoods,它比TGoods多了两个属性,一个是数量,用来记录玩家当前购买了多少数量的货物,另外一个是货物的编号,虽然在TGoods里也保存有货物的编号,但是为了方便计算,这里就把货物的编号提取出来。
玩家的状态信息有:玩家编号,玩家当前出于的城市,玩家当前在的地图编号,玩家的状态信息(这个状态是指玩家是否出于下列场景:海上,城市,各类建筑物等)
int userID;
int cityID; // 城市编号,用于确定玩家所在城市的编号,如果编号在0一下,则视为在公海
int mapID; // 地图编号,玩家所处于那块地图
int state; // 状态:海上、城市、建筑物内
CPlayer baseInfo; // 人物基本属性
CPlayerGoods goods[PLAYER_MAX_GOODS];
TShip ship[PLAYER_MAX_SHIP]; // 船只的属性
TShip bsShip[PLAYER_MAX_SHIPSIDESHIP]; // 船坞船只信息,存储是从1开始
TBank bank; // 银行业务:当前只有存款
各个模块的设计:
城市场景通用接口设计:
在城市的5个场景里都存在着3个接口函数:DoMsg(),OnEnter(),OnExit()
DoMsg 的作用是根据玩家发送过来的游戏消息进行判断,并根据游戏消息选择相应的处理模块进行处理,其内部结构就是一个对消息进行判断的switch结构
OnEnter 的作用是由地图服务器传过来玩家进入场景的消息后,通过该函数返回场景内的信息给客户端,不同的场景会返回不同的信息
场景返回的消息:
1. 码头
a) 单位补给价格
2. 船厂
a) 可出售船只列表
3. 交易所
a) 玩家的货物类表
b) 交易所可出售货物列表
4. 酒吧
a) 雇佣单位水手的价格
5. 银行
a) 玩家在银行的存款
OnExit 的作用是在玩家发出退出场景消息后,对退出场景这个动作进行验证,验证通过后把玩家退出建筑物的消息发送给地图服务器。
码头设计:
码头的基本功能:
1. 补给
2. 更换船只
3. 出海
补给流程图:
更换船只流程图:
出海流程图:
船厂设计
基本功能:
1. 修理船只
2. 购买船只
3. 出售船只
修理船只流程图:
购买船只流程图:
出售船只流程图:
交易所设计:
基本功能
1. 购买货物
2. 出售货物
购买货物流程图:
出售货物流程图:
酒吧设计
基本功能
1. 雇佣水手
雇佣水手流程图:
银行设计
基本功能
1. 存款
2. 取款
存款流程图:
取款流程图:
玩家的基本功能:
1. 购买补给
2. 更换船只
3. 购买船只
4. 出售船只
5. 购买货物
6. 添加货物到货物列表
7. 出售货物
8. 从货物列表里删除货物
9. 雇佣水手
10. 存款
11. 取款
购买补给流程图:
更换船只流程图:
购买船只流程图:
出售船只流程图:
购买货物流程图:
添加货物到货物列表的流程图:
出售货物流程图:
从货物列表里删除货物流程图:
雇佣水手流程图:
存款流程图:
取款流程图