最后还剩下游戏入口部分,Silverlight是客户端插件,因此首选WCF作为它与服务器端数据库的桥接。撇去UI方面华丽的动态角色创建与选择不再多说,本节的重点便是在教程Demo的基础上整合进基于WCF的注册与登陆等操作,使之最终成为一款相对完整而五脏俱全的RPG作品。

依旧钟情于LINQ,因此LINQ to SQL成为我操作数据库的首选。强烈建议大家首先参考这篇文章:数据库LINQ TO SQLSilverlight中的应用(WCF) ,其中的所有细节都已阐述得相当详细。如果你的电脑中存有之前的Demo源码,那么接下来你可以按照下面的步骤跟着我一步步从零开始搭建游戏的登陆部分,真真切切的体会WCF技术在Silverlight中的常规应用。

第一步:依照游戏中角色注册、创建、相关信息及登录等需求设计数据库,并编写好相应可能会用到的增删改查等存储过程(本节Demo源码中附带了名为FS3.sql的数据库文件,表和存储过程都在其中)

第二步:在Silverlight的寄主Web项目中右键->添加新项目->LINQ to SQL映射类,这里我取名为L2S.dbml

第三步:打开VS视图中的服务器资源管理器,右键添加SQL连接到FS3(SQL版本最好2005以上)后将其中的表和存储过程等均拖到L2S.dbml的设计窗口中形成大家再熟悉不过的映射:

第四步:此时便可编写WCF操作类了,Silverlight的寄主Web项目中右键->添加WCF服务,取名为WCFService.svc

需要特别注意的是带返回类型的存储过程需要修改其相应属性为表实体,否则后面的逻辑查找不到:

第五步:编写具体操作逻辑,搞过WCF开发的朋友此处可完全忽略,超级简单;没搞过的也很容易看懂,具体就不多说啦,直接列代码:

    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode 
= AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(IncludeExceptionDetailInFaults 
= true)]
    
public class WCFService {
        [OperationContract]
        
public void DoWork() { }

        
/// <summary>
        
/// 添加新用户(添加过程中字符型超出限制长度则自动截取)
        
/// </summary>
        
/// <returns>新用户的ID,0则表示失败</returns>
        [OperationContract]
        
public long InsertUser(string userName, string password, string realName, string idCard, string eMail, string address) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return Convert.ToInt64(dc.p_InsertUser(userName, password, realName, idCard, eMail, address, """").ReturnValue);
            }
        }

        
/// <summary>
        
/// 用户资料验证
        
/// </summary>
        
/// <param name="userName">用户名</param>
        
/// <returns>0表示不存在</returns>
        [OperationContract]
        
public int CheckUserExist(string userName) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return dc.p_CheckUserExist(userName);
            }
        }

        
/// <summary>
        
/// 用户登陆验证
        
/// </summary>
        
/// <param name="userName">用户名</param>
        
/// <param name="password">密码</param>
        
/// <returns>0表示不匹配</returns>
        [OperationContract]
        
public int UserLogonValidate(string userName, string password) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return dc.p_CheckUserLogon(userName, password);
            }
        }

        
/// <summary>
        
/// 检查角色是否已存在
        
/// </summary>
        
/// <param name="name">角色名</param>
        
/// <returns>0表示不存在</returns>
        [OperationContract]
        
public int CheckRoleExist(string name) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return dc.p_CheckRoleExist(name);
            }
        }

        
/// <summary>
        
/// 检查用户创建的角色数量
        
/// </summary>
        
/// <param name="userName">用户名</param>
        
/// <returns>角色数</returns>
        [OperationContract]
        
public int GetUserRoleNum(string userName) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return dc.p_GetUserRoleNum(userName);
            }
        }

        
/// <summary>
        
/// 添加新角色
        
/// </summary>
        
/// <returns>新角色的ID,0则表示失败</returns>
        [OperationContract]
        
public long InsertRole(string userName, string name, byte avatar, byte sex, byte occupation, byte roleLevel, long experience, long mapID, string lastIP, string remarks) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return Convert.ToInt64(dc.p_InsertRole(userName, name, avatar, sex, occupation, roleLevel, experience, mapID, lastIP, "").ReturnValue);
            }
        }

        
/// <summary>
        
/// 根据用户名获取该用户的所有角色
        
/// </summary>
        
/// <param name="userName">用户名</param>
        
/// <returns>创建的所有角色</returns>
        [OperationContract]
        
public List<Role> GetRoleByUserName(string userName) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return dc.p_GetRoleByUserName(userName).ToList<Role>();
            }
        }

        
/// <summary>
        
/// 删除角色记录
        
/// </summary>
        
/// <param name="roleName">角色名</param>
        
/// <returns>失败0,成功1</returns>
        [OperationContract]
        
public int DeleteRole(string roleName) {
            
using (L2SDataContext dc = new L2SDataContext()) {
                
return dc.p_DeleteRole(roleName);
            }
        }

    }

第六步:也是最后一步,在RPGEffectsDemo项目中右键添加服务引用(Service References),然后检索到WCFService.svc完成即可。接着发布网站,并在服务器端配置好IIS,整个流程到此结束。

参照如上步骤搭建的WCF框架,如果服务器(IIS)或数据库相关数据参数发生变动则仅需修改以下两个文件:ServiceReferences.ClientConfigWeb.config,具体位置如下,参数很好理解,尤其是搞过这方面开发的朋友更无须多说:

一切OK后,以游戏登陆时输入用户名与密码的窗体为例,我们可通过类似以下的代码创建WCF连接以及处理相应逻辑:

                WCFServiceClient wcfServiceClient = new WCFServiceClient();
wcfServiceClient.UserLogonValidateAsync(userName.Text.Trim(), GlobalMethod.Encrypt(pwd.Password));
                wcfServiceClient.UserLogonValidateCompleted 
+= (wcfs1, wcfe1) => {
                    
if (wcfe1.Result != 0) {
                        LoginManager.UserName 
= userName.Text.Trim();
                        
if (Login != null) { Login(thisnull); }
                    } 
else {
                        LoginManager.loading.Hide();
                        LoginManager.loginTip.Show(GetLanguagePackContent(
11), LoginTipMode.TipOnly);
                    }
                    wcfServiceClient.CloseAsync();
                };

ASP.NET页面设计类似,游戏中比如语言选择、版本说明、登陆、注册、角色创建、角色选择、物品窗口、属性窗口等每个窗体我们都可以单独的控件类文件存在,并为它们内部的每个需要交互的按钮设置对应的事件以实现与其他对象的交互消灭耦合:

另外,Demo使用了动态多国语言设计,众所周知同一词汇在不同语言书写中存在长度差异,因此语言包中还应在需要的地方添加上OffsetFontSize参数以使得界面看上去更协调整洁:

Silverlight动态多国语言设计模式对于WebGame来说可轻松实现玩家跨国交互和竞技,可谓真正能实现网游国际化的RIA技术;这才是Silverlight页游即将为世界所缔造的网游领域新的蓝海!第四次游戏革命:网页网游全球一体化。试想不同民族、不同国籍的玩家在一款游戏中同场竞技或SNS中相互交流,尤其是亚洲,中、港、台、日、韩、越、泰等周边国家的游戏玩家齐聚一堂,共享世纪网游大作,那将是一件多么伟大而具有划时代意义的历史记忆!不远了,多少前辈曾经为了这个梦想而奋斗青春,当微软为了Silverlight能兼更强劲的GPU而收购NVIDIA,当Silverlight 5正式版浩瀚问世之时,那才是网游世界新的春天!

XNA已成为Silverlight.XNA,无可厚非Silverlight必将成为微软未来平台统一与兼容的首选~!兼具高开发效率、优秀用户体验及跨平台等诸多优势最具潜力的RIA技术,未来将与HTML5共舞,优势互补一统所有网络应用。

本系列源码请到目录中下载

在线演示地址:http://silverfuture.cn

posted on 2011-06-08 16:26  深蓝色右手  阅读(5776)  评论(26编辑  收藏  举报