游戏大厅 从基础开始(1)
——最简单的关系,用户与房间。
做游戏 就好像写一篇简单的记叙文
作为小学语文大纲要求 记叙文需要完整地叙述:
时间,地点,人物,事件
也就是 WHEN , WHERE, WHO, WHAT HAPPENED
猜猜哪个最重要?
我选WHO
WHO
没有WHO,没有了某个意识的主观活动影响客观环境,故事就是静止的。那就不叫故事,叫速写。
在一个网络游戏服务模型中,最基础的概念就是 WHO
有了WHO游戏才不是电影电视剧那样的直接灌输。
有了WHO电脑屏幕前的个体才能与别的个体有所区分
有了个体的区分 网络游戏才可以"互动"。
最最基础的用户的存在,至少要有一个唯一的数据库ID,一个登陆用的用户名,一个友好的名字
- 唯一的ID 让数据库认识你是WHO
- 唯一的登录名 让服务程序认识你是WHO
- 友好的名字 让别的WHO认识你是WHO
其次是
WHERE
WHERE的本质用途是 隔离WHO和资源。
试想有一座学校 ,没有分别的教室而只有一间大会堂,三十多名老师和校工 四百多个学生一起办公与学习,一边在唱着童年的歌谣,一边在笑人齿缺曰狗窦大开。
把学校换成服务器 把学生换成用户 这样的烂摊子你能收拾得了么?
我们需要教室!
最基本的User和Area的关系需求:
这里我们要着重分析一下房间与房间的关系
典型的例子:棋牌房间,劲x团,百战天虫,疯狂坦克,浩方,QQ聊天室
这种树形房间结构只有两种关系:父,子。实际上是在一个简单维度上的两个方向。一个房间有多个子房间,一般看成同一纬度上的若干不同的点。用户最基础的移动操作就是 上一层 下一层。
典型的例子:文字MUD
常常听说十字链表这个词语,我最早就是从文字mud的开发文档中接触的。
作为一个模拟真实的地图,大家把区域模拟成类似国际象棋那样的棋盘,彼此保留着邻居的结构,或者类的引用
interface IArea
property name as string ..
...
..
property Warea as Area
property Earea as Area
property Sarea as Area
property Narea as Area
end class
用这种链表 用户的身处环境就可以平滑有序的移动。
后来更复杂些的MUD和网络游戏 又增加了 UP和DOWN两个方向 比如xx地下城1层 2层,天空挑战赛1层2层
有些是真的实现了立体链表 有些使用更抽象的方式 在某个没有邻居的方向用二维十字链表模拟
- 多维关系和混合关系 (wow等等副本游戏 立体地图的部分游戏如孢子)
比如ro 两个地区间可能有2-3道门 每一条都可以进入目标区域相应的位置。 所以相邻的两个地区间 仅仅维护一个彼此的引用是远远不够的
有的区域进得去出不来
有的区域要满足xx条件才能出来
有的区域要找另外一条道路才能出来
回到最上层 回城
参考以上可能性 我建立了目前的 IPathWay 接口
IArea之间不再用链表而是使用IPathWay互相连接。IPathWay是单程的 是可以附加属性的(坐标,范围,条件)
IArea本身可以通过添加或者减少IPathWay来保证与其他Area的连接
Iuser可以选择直接移动 还是按照已经准备好的IPathWay 规则来移动。
每个IPathWay 都有自己的方向
对于父子树来说 之需要一个水平方向的x轴, 深层是正方向
对于二维十字地图链表 我们把地图映射到坐标系 东为x的正方向 北为Y轴正方向
对于三维 上为正
对于更多。。。。
对于完全没有道理但是一定会存在的那种特殊路径 在6维空间以下的坐标系 我们可以直接放在C轴
这就是最简单的房间与用户的交互
房间组织 -〉 用户进入 ——〉 用户移动
参考代码:
Code '-----------------------------' Wayne Wang ' 个人研究 ' 不是什么了不起的东西 ' 有错误的话还请告诉我' 努力奋斗' Yeah!'-----------------------------Namespace Common ''' <summary> ''' 基础“区域” ''' Basic Area ''' </summary> ''' <remarks> ''' 能够通过AreaLink和其他区域,或者与其他用户交互 Can interactive with other areas(by arealink) and users ''' </remarks> Public Interface IArea ''' <summary> ''' 区域名称 ''' Area Display Name ''' </summary> ''' <remarks>显示名称</remarks> ''' <value>"0000001|GameHall"</value> ReadOnly Property Name() As String ''' <summary> ''' 区域的唯一ID ''' Unique ID of Area ''' </summary> ''' <remarks> ''' 随机生成 临时的 或者被设置为特殊用途的特定值(AutoGen tempory or be set for special use.) ''' </remarks> ''' <value>{guid xxxxx-xxxxx-xxxx-xxxx}</value> ReadOnly Property ID() As String ''' <summary> ''' 用户列表 ''' </summary> ReadOnly Property Users() As IDictionary(Of String, Common.IUser) ''' <summary> ''' 本区域对外的通路 ''' </summary> ReadOnly Property PathWays(ByVal axis As IPathWay.PathWayAxis, ByVal direction As IPathWay.PathWayDirection) As System.Collections.Generic.IEnumerable(Of IPathWay) ReadOnly Property CreateTime() As Date ''' <summary> ''' 加入一个通路 ''' </summary> Sub PathMount(ByVal path As IPathWay) ''' <summary> ''' 去掉一个通路 ''' </summary> Sub PathDemount(ByVal path As IPathWay) ''' <summary> ''' 为两区域之间添加一条双向通路 也就是两条不同方向的通路 ''' </summary> ''' <remarks></remarks> Sub AreaCreatePairPathWay(ByVal targetArea As IArea, ByVal axis As IPathWay.PathWayAxis, ByVal targetDirection As IPathWay.PathWayDirection) ''' <summary> ''' 用户加入 ''' </summary> Sub UserJoin(ByVal user As Common.IUser) ''' <summary> ''' 用户离开 ''' </summary> Sub UserLeave(ByVal User As Common.IUser) End InterfaceEnd Namespace
Code '-----------------------------' Wayne Wang ' 个人研究 ' 不是什么了不起的东西 ' 有错误的话还请告诉我' 努力奋斗' Yeah!'-----------------------------Namespace Common ''' <summary> ''' PathWay: A Link From one area to another ''' 通路: 一条从一个区域到另一个区域的连接 ''' </summary> ''' <remarks> ''' ''' ''' 如果是一维父子关系 那么只存在x轴上的 -1up(上一层)和1down(下一层)的两种通路 ''' ''' 如果是2维的十字链表地图 则可以用x y两个轴。 ''' ''' ''' 通路的两个端点的属性 由 SourceProperties和TargetProperties 两个集合保存 ''' </remarks> Public Interface IPathWay ''' <summary> ''' 这个路径在当前纬度的方向。 ''' </summary> ReadOnly Property Direction() As PathWayDirection ''' <summary> ''' 路径终点的区域 ''' </summary> ReadOnly Property TargetArea() As IArea ''' <summary> ''' 路径终点的参数字典 ''' </summary> ReadOnly Property TargetProperties() As IDictionary(Of String, Object) ''' <summary> ''' 路径起点的参数字典 ''' </summary> ReadOnly Property SourceProperties() As System.Collections.Generic.IDictionary(Of String, Object) ''' <summary> ''' 表示这个路径在区域的轴上的上方还是下方 ''' </summary> Enum PathWayDirection ''' <summary> ''' 任意 ''' </summary> Any = Nothing ''' <summary> ''' 正方向 ''' </summary> Forward = 1 ''' <summary> ''' 负方向 ''' </summary> Backward = -1 End Enum ''' <summary> ''' 表示这个路径在区域的哪个轴 ''' </summary> Enum PathWayAxis ''' <summary> ''' 任意 ''' </summary> Any = Nothing ''' <summary> ''' 第1个轴 ''' </summary> x = 0 ''' <summary> ''' 第2个轴 ''' </summary> y = 1 ''' <summary> ''' 第3个轴 ''' </summary> z = 2 ''' <summary> ''' 第4个轴 ''' </summary> a = 3 ''' <summary> ''' 第5个轴 ''' </summary> b = 4 ''' <summary> ''' 第6个轴 ''' </summary> c = 5 End Enum End InterfaceEnd Namespace
Code '-----------------------------' Wayne Wang ' 个人研究 ' 不是什么了不起的东西 ' 有错误的话还请告诉我' 努力奋斗' Yeah!'-----------------------------Namespace Common ''' <summary> ''' Basic User ''' 基础用户 ''' </summary> ''' <remarks> ''' 登陆的基础单位 ''' 一个逻辑可操作的人 ''' </remarks> Public Interface IUser ''' <summary> ''' 用户的登陆名(小写) ''' </summary> ReadOnly Property UID() As String ''' <summary> ''' 用户在数据库中同样有效的行Key ''' </summary> ReadOnly Property DatabaseID() As Guid ''' <summary> ''' 用户的友好名 ''' </summary> Property NickName() As String ''' <summary> ''' 用户当前的位置 ''' </summary> ReadOnly Property CurrentArea() As IArea ''' <summary> ''' 用户的登陆时间 ''' </summary> Property LoginTime() As Date ''' <summary> ''' 用户的客户端连接 ''' </summary> ReadOnly Property ClientLink() As Communication.IClientLink ''' <summary> ''' 用户移动到另一个位置 ''' </summary> ''' <param name="targetArea">目标位置</param> Sub Move(ByVal targetArea As IArea) ''' <summary> ''' 用户顺着某一个路径移动到另一个位置 ''' </summary> ''' <param name="leadingPathWay">作为移动根据的路径</param> Sub Move(ByVal leadingPathWay As IPathWay) ''' <summary> ''' 用户移动到另一个用户的位置 ''' </summary> Sub Move(ByVal targetUser As IUser) ''' <summary> ''' 用户退出 ''' </summary> Sub Logoff() End InterfaceEnd Namespace