兴国安邦

C# 3.0, Linq, Linq To Sql

博客园 首页 新随笔 联系 订阅 管理
  33 Posts :: 0 Stories :: 528 Comments :: 51 Trackbacks
在上一节中,我们讲到了业务实体的设计。好多人可能都觉得,为什么没有在这些实体类中放置方法,不够oo. 这实际和项目整体的设计有关。在杀人游戏系列 之一 一节中,我们提到了,整个项目的架构是网络模式的。而网络模式势必有client和server端。那client和server之间的通信成为这个游戏逻辑的推动力。本节从wcf层面的设计讲起,看看游戏逻辑是如何驱动的。
1,client与server的消息体的设计
既然client和server之间的通信是不可避免的。那需要先定义通信消息的数据格式。第一个被定义的是登陆消息格式。如下:
    [DataContract]
    
public class LogonFormat
    
{
        [DataMember]
        
public string LogonPerson getset; }

        [DataMember]
        
public string IPPortServiceString getset; }
    }
这里只有用户的用户名和其ip地址。
第二个被定义的是交谈消息的格式。如下:

    [DataContract]
    
public class ChatFormat
    
{
        
//ID
        [DataMember]
        
public string Sender getset; }

        [DataMember]
        
public string MsgBody getset; }

        
//TODO:When chat one to one
        
//"" if this message is not to a given person
        [DataMember]
        
public string Receipter getset; }

        
//Time flag, indicate daytime or night
        [DataMember]
        
public TimeFlag TimeFlag getset; }

    }

做下简单的介绍,sender是发送者,msgbody是消息体。receipter是接收人。timeflag是白天还是黑天。在这里,为了继续简化游戏。我们认为规定了,server端只维持一个game。这个设计无疑是个败笔。但是时间紧迫,5天内会熟练使用wcf就已经不错了,别说把游戏的逻辑设计的完美无缺陷。如果server端只维持一个游戏,整个逻辑就简单了许多。所以,chatformat并没有game编号的定义。
最后一个被定义消息体是,voteforamt,如下:
    [DataContract]
    
public class VoteFormat
    
{
        [DataMember]
        
public string Voter getset; }

        [DataMember]
        
public string Condidate getset; }

        
//Time flag, indicate daytime or night
        [DataMember]
        
public TimeFlag TimeFlag getset; }

    }

无论是用户杀人还是投票,都可以需要向服务器端发送消息。我们把杀人和投票这两个行为需要的消息体进行了整合。用timeflog来区别他们。当是白天时,那就是投票,而黑夜时,就是杀人。

2,游戏逻辑从实体对象的转移
有了这些数据格式的定义,该做的就是通信方法的定义了。定义如下接口:
通信接口的定义
这个接口有三个方法。登陆,发送消息,和投票。在这里,游戏的逻辑继续被简化。首先,没有登陆游戏,也没有创建游戏,更没有开始游戏和退出游戏。那这些逻辑都在那里呢?这些逻辑在用户登陆server时,server自己判断。一旦人数超过了设定的人数,server自动创建一个游戏,并启动这个游戏。这里的简化和前面的设计有关,即server只维系一个game.这里依然将来需要做大的彻底更改的地方。
杀人游戏系列 之二 中,有游戏的逻辑图。在投票和杀人整合后,用户登陆以及启动游戏的地方再一次做了简化。刚才提到的投票和杀人的逻辑,事实是在DistribVoteMsg发放中完成的。而DistribChatMsg只负责单纯的交谈,并没有太多的游戏逻辑。写到这里,整个游戏设计思路就该明了了。游戏中出现的实体类,只是被驱动的对象,而不是游戏逻辑的载体。游戏逻辑被封装到了wcf层面的通信上了。 而与数据库的交互,被单独做成了静态的方法,独自行成一个类库。这些方法承载了部分的游戏逻辑。但又相互独立。在这个类库里,实体类依然只是传递数据,而不封装游戏逻辑。或许这与传统的oo方法有出入,但走linq To Sql这条路,这样的设计才能发挥其优势。

3,UI的设计
既然游戏的逻辑被简化,ui上也就不会有太多的麻烦。一个登陆框,加一个游戏的主界面。在这个游戏的主界面中,左边显示用户。中间是对话框,下面是消息输入框和杀人及投票的按钮。如图

如果,不简化游戏逻辑,还要增加游戏大厅里的对话框,以及创建game,加入game,开始game和退出game等。

4,一些新鲜设计或技术点
4.1 我们知道wcf只是一个类库,它实际上需要一个宿主来提供它的服务。我们在这里建立了一个console 的application来提供wcf的服务。但是,消息是单向的,只能是client从server请求,怎么样才能把消息从server端发到client端呢?这里,client也不得不启动一个wcf的服务,来接收从server的消息。这时,server是做为普通client端。
4.2 wcf的宿主还起到了另一个功能,初始化数据库。通常的数据库的项目。布置和配制数据库是相当的麻烦。这里,程序在启动服务时,先检查数据是否存在,如果数据库不存在,它讲初始化数据库。当然,这里也是人写好的。如下:
初始化数据库
4.3 wpf中的回调
在登陆界面后,需要显示主游戏界面。而此时,牵扯到wpf中的回调。如下:
wpf中的回调
在这里,ShowMainDailog函数体内,需要再一次调用ShowMainDailog函数。主要是因为!lstGame.CheckAccess()条件成立,即form是不可以访问的。当第二次调用时,就走else字句了。(说实话,这是wpf里的技术,我也晕着呢。)

5 结语
可能会让好多人失望,没有谈wpf和wcf技术。但是,谈游戏才是本篇的主题。技术是为这个主题服务的。在这里,游戏逻辑因为时间上的因素被简化依然让笔者心痛。这是个比赛,需要在第三天的时候,整个程序就能跑起来,剩下的2天调试排错。这无疑让我们不得忍痛割爱。在以后的日子里,如果时间允许的话,笔者还是会加上被砍掉的游戏逻辑。放出所有的代码,供参考。(大家需要注意的是,我和peter最近再做修改,希望能添加上被砍掉的部分,所以,代码和blog里有些出入。)

上一篇
杀人游戏系列 之二
杀人游戏系列 之一
其他:
Linq To Sql进阶系列 -目录导航
C# 3.0入门系列-目录导航
posted on 2007-10-25 20:43 Tom Song 阅读(2713) 评论(12)  编辑 收藏 所属分类: Linq To Sql

Feedback

#1楼 [楼主] 2007-10-25 20:47 Tom Song      
有可能会编译不过。我的版本比beta2要新。要是写一篇能告诉大家RTM版在linq to sql方面做了那些改动,就好了。
  回复  引用  查看    

#2楼  2007-10-25 20:51 姓名 [未注册用户]
嗯,非常不错
  回复  引用    

#3楼  2007-10-25 21:15 guohao0826 [未注册用户]
我是b2版本的。打不开哦。你的版本居然更加新。 咋样才能在b2版本里打开?
  回复  引用    

#4楼  2007-10-25 22:06 5207      
老大使用的2008?我这里打不开呀?
  回复  引用  查看    

#5楼  2007-10-26 09:06 tzhao [未注册用户]
这样实时的对数据库进行频繁操作,如果同时开10个,100个,,杀人房间做过测试吗?

客户端统一的时间器如何进行工作的呢? 如果每秒都以数据库服务器的时间为准,那么会有很多问题,而如果完全以客户端的时间为准,那么这样每个人的时间都会出现差异型,不知道你们是如何处理的, 我觉得这样的游戏的进行过程, 用数据库做每个时刻的数据支撑,效率非常差,并且可能这个游戏都无法进行下去,关键还是在服务器端的逻辑处理接口,及客户端的js处理,
  回复  引用    

#6楼  2007-10-26 09:44 静水≈深流      
好耶 认证学习,谢谢 各位辛苦啦
  回复  引用  查看    

#7楼  2007-10-26 09:48 静水≈深流      
对了 你上次说到 RTM版在linq to sql方面做了那些改动
能说一下做啦那些改动吗?
  回复  引用  查看    

#8楼 [楼主] 2007-10-26 10:39 Tom Song      
@tzhao
--引用--------------------------------------------------
tzhao: 这样实时的对数据库进行频繁操作,如果同时开10个,100个,,杀人房间做过测试吗?

客户端统一的时间器如何进行工作的呢? 如果每秒都以数据库服务器的时间为准,那么会有很多问题,而如果完全以客户端的时间为准,那么这样每个人的时间都会出现差异型,不知道你们是如何处理的, 我觉得这样的游戏的进行过程, 用数据库做每个时刻的数据支撑,效率非常差,并且可能这个游戏都无法进行下去,关键还是在服务器端的逻辑处理接口,及客户端的js处理,
--------------------------------------------------------
好问题。确实,我们并没有思考时间统一的问题,更没有考虑到是否断线的问题。最近在玩popo的游戏,经常断线,才想到这个问题。

用数据库来维持每个时刻的数据,确实这块的设计是有问题。我们在做修改。希望能把砍掉的东西添加上来,也希望能改变维持数据的方式。
  回复  引用  查看    

#9楼  2007-10-31 19:21 Boler Guo      
http://blogs.msdn.com/dinesh.kulkarni/archive/2007/10/09/linq-to-sql-breaking-changes-from-beta2-to-rtm-compiled-from-my-linq-forum-posts.aspx
  回复  引用  查看    

#10楼  2007-11-02 18:2