Silverlight+WCF 新手实例 象棋 回归WCF通讯应用-进入房间(十九)

简介:

上一节我们讲到登陆时通过WCF,把用户信息传递到远程服务器,并用一个全局泛型字典变量来保存用户列表。

登陆后我们转向了房间页面。这节,我们要通过点击房间上的座位进入主页面(Index.xaml)。

既然要点击房间座位才能进入,我们就得为那房间的座位添加鼠标点击事件了。

我们回到GameRoom.cs找到创建房间的代码,找到Draw函数里,创建红蓝黑三个房间座位的代码,其实就是那三个矩形框Rectangle。

我们在它们被添加到房间之前,添加几个事件:

 

复制代码
ExpandedBlockStart.gif
  // 添加三个房间点击事件
            redChair.MouseLeftButtonDown  +=   new  MouseButtonEventHandler(redChair_MouseLeftButtonDown);
            spectatorChair.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(spectatorChair_MouseLeftButtonDown);
            blackChair.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(blackChair_MouseLeftButtonDown);
            
// 下面就是添加房间了,之前就有的代码
            room.Children.Add(redChair);
            room.Children.Add(blackChair);
            room.Children.Add(spectatorChair);
            room.Children.Add(text);
            container.Children.Add(room);
复制代码

 

三个房间座位产生的事件函数:

复制代码
ExpandedBlockStart.gif
void  blackChair_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
        {
            
// 待实现
        }
        
void  spectatorChair_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
        {
            
// 待实现
        }
        
void  redChair_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
        {
            
// 待实现
        }
复制代码

 

OK,在点击的时候,我们都要产生同一个动作,就是“进入”房间了。简单逻辑思维告诉我们要添加一个公共的"Enter"方法

void  Enter( int  colorValue)
{
 
// 待实现
}

 

有了Enter方法,我们可以写鼠标点击事件了:

黑色位置点击:判断黑色房间是否有人,没人的话就设置一下有人,并改变一下房间背景色,然后调用Enter进入。

重提一下颜色值是:[1红2黑3蓝]

复制代码
ExpandedBlockStart.gif
void  blackChair_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
        {
            
if  ( ! BlackPlayerInChair)
            {
                BlackPlayerInChair 
=   true ;
                blackChair.Fill 
=   new  RadialGradientBrush(Colors.Blue , Colors.White);
                    
// new SolidColorBrush(Colors.Blue);
                Enter( 2 );
            }
            
else
            {
                MessageBox.Show(
" 黑色玩家已有人! " );
            }
        }
复制代码

 

旁观者位置:一点进去了,当然了,如果以后要增加房间人数上限,还是要加判断的

void  spectatorChair_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
        {
            Enter(
3 );
        }

 

红色位置:和黑色位置一样的判断方法

复制代码
ExpandedBlockStart.gif
void  redChair_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
        {
            
if  ( ! RedPlayerInChair)
            {
                RedPlayerInChair 
=   true ;
                redChair.Fill 
=   new  RadialGradientBrush(Colors.Blue, Colors.White);
                    
// new SolidColorBrush(Colors.Blue);
                Enter( 1 );
            }
            
else
            {
                MessageBox.Show(
" 红色玩家已有人! " );
            }
        }
复制代码

 

三个座位的点击事件都完成了,接下来要完成Enter方法了:

于由进入房间时,需要用WCF通讯告知服务端,所以要先转入WCF,添加服务端EnterRoom事件

回到GameService项目的IService.cs里,添加两个接口,进入房间和退出房间:

接口的参数都是一样的,一个玩家,和一个玩家要进入/退出的房间号。

[OperationContract]
bool  EnterRoom(Player player, int  roomID);

[OperationContract(IsOneWay 
=   true )]
void  OutRoom(Player player,  int  roomID);

 

接下来就是到到IService.svc.cs里实现接口了:

 

接着,我们要定义一个全局变量,有来保存所有发生变化的房间列表:

什么叫发生变化?就是房间默认是没人坐上去,如果有人进入房间,房间状态就发生变化了,这时我们就要记录下来,同时,要更新到

所有在线玩家的房间里去。

///   <summary>
///  所有变化的房间列表
///   </summary>
private   static  Dictionary < int , Room >  roomList  =   new  Dictionary < int , Room > ();

 

看到一个Room没有,既然要保存房间列表,所以我们得创建一个和Player一样的[契约数据]实体用于传递Room

我们对着文件夹DataContract右键->添加类->输入:Room.cs

为房间实体类添加几个属性:

ID:房间号

Count:房间人数

RedInChair:红色座位是否有人

BlackInChair:黑色座位是否有人

就四个属性,相当的简洁吧,接下来实现,这里一样去掉了文件夹的命名空间[.DataContract]:

复制代码
ExpandedBlockStart.gif
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  System.Runtime.Serialization;

namespace  GameService
{
    [DataContract]
    
public   class  Room
    {
        
///   <summary>
        
///  房间ID
        
///   </summary>
        [DataMember]
        
public   int  ID
        {
            
get ;
            
set ;
        }
        
///   <summary>
        
///  房间人数
        
///   </summary>
        [DataMember]
        
public   int  Count
        {
            
get ;
            
set ;
        }
        
///   <summary>
        
///  红色座位是否有人
        
///   </summary>
        [DataMember]
        
public   bool  RedInChair
        {
            
get ;
            
set ;
        }
        
///   <summary>
        
///  黑色座位是否有人
        
///   </summary>
        [DataMember]
        
public   bool  BlackInChair
        {
            
get ;
            
set ;
        }
    }
}
复制代码

同时呢,我们要为Player[契约数据]实体增加一个属性:颜色值,就是当前用户的进入房间后,自身的颜色就生变化了。

复制代码
  ///   <summary>
       
///  玩家颜色[0无色,1红,2黑色,3蓝色]
       
///   </summary>
       [DataMember]
       
public   int  ColorValue
       {
           
get ;
           
set ;
       }
复制代码

 

 

好了,玩家增加了一个颜色属性,房间实体也有了,全局的房间列表变量也加了。接下来要实现进入房间EnterRoom方法了。

说明写的够仔细了,小看一会就明白了,其实就是改变房间状态了。还有一些事件通知,我们后面再实现。

复制代码
ExpandedBlockStart.gif
  public   bool  EnterRoom(Player player,  int  roomID)
        {
            
bool  roomInDic  =  roomList.ContainsKey(roomID); // 房间列表里有没有
            Room room  =  roomInDic  ?  roomList[roomID] :  new  Room(); // 有就直接拿了,没有就直接New一个新的
             if  ( ! room.RedInChair) // 房间的红色座位有没有人
            {
                room.RedInChair 
=  player.ColorValue  ==   1 ;
            }
            
if  ( ! room.BlackInChair) // 房间的黑色座位有没有人
            {
                room.BlackInChair 
=  player.ColorValue  ==   2 ;
            }
            
if  ( ! roomInDic) // 房间列表里没有,添加到房间列表中
            {
                room.ID 
=  roomID;
                roomList.Add(roomID, room);
            }
            
            
// ChangeRoom(player, roomID);改变玩家的房间标记,待会实现

            
// 以下是我们以后要实现的。
            
// Notify.Room(true, playerList, room, player); // 提示房间内:有玩家进入
            
// if (room.RedInChair && room.BlackInChair) // 如果房间红和黑色都有人了。
            
// {
            
//     Notify.Game(playerList, player, GameType.Start); // 提示对方可以开始游戏。
            
// }
             return   true ;
        }
复制代码

 

接下来实现退出房间OutRoom方法,同样的也是改变房间的状态:

复制代码
ExpandedBlockStart.gif
public   void  OutRoom(Player player,  int  roomID)
        {
            
if  (roomID  >   0 )
            {
                Room room 
=  roomList[roomID];
                
if  (player.ColorValue  ==   1 ) // 如果退出玩家是红色座位
                {
                    room.RedInChair 
=   false ;
                }
                
if  (player.ColorValue  ==   2 ) // 如果退出玩家是红色黑色座位
                {
                    room.BlackInChair 
=   false ;
                }
               
//  ChangeRoom(player, 0);改变玩家的房间标记,待会实现
                
// Notify.Room(false, playerList, room, player); // 提示房间内:有玩家退出

            }
        }
复制代码

 

OK,接下来我们来完成一个共同的方法叫:ChangeRoom

意思就是当用户从不同的房间切换,就是进入或退出房间。

以下四行代码、四行说明结束函数。

复制代码
ExpandedBlockStart.gif
  public   static   void  ChangeRoom(Player player,  int  roomID)
 {
    RemovePlayer(player);
// 在全局列表中移除原有的用户
    AddPlayer(player, roomID); // 在新的房间增加新用户
    roomList[player.RoomID].Count  =  playerList[player.RoomID].Count; // 原来房间人数变化
    roomList[roomID].Count  =  playerList[roomID].Count; // 新加入的房间人数变化
}
复制代码

 

方法有了,上面的EnterRoom和OutRoom的两行ChangeRoom的注释可以去掉了,成了:

ChangeRoom(player, roomID);//改变玩家的房间标记,待会实现,这是进入房间的注释

ChangeRoom(player, 0);//改变玩家的房间标记,待会实现,这里退出房间的注释

 

OK,现在可以编绎一下代码,编绎后我们要在客户端更新一下服务引用。

&

 

由于在进入房间后,我们要进入Index页面,所以我们要新建一个Index.xaml了:

Silverlight项目右键->添加新建项->Silverlight用户控件->输入:Index.xaml[新建的控件目前是一片空白的]。

原来的MainPage.xaml我们把它删了吧,使命完成了,该回家吃饭了。

 

接着我们回到GameRoom.cs代码里,去实现我们的Enter方法:

代码相当的简单,就是调用WCF服务的EnterRoom,完成后转向Index页面了。

 

复制代码
ExpandedBlockStart.gif
  ///   <summary>
        
///  进入房间
        
///   </summary>
        
///   <param name="colorValue"> 颜色[0无色,1红,2黑色,3蓝] </param>
         void  Enter( int  colorValue)
        {
            App.player.ColorValue 
=  colorValue;
            App.client.EnterRoomCompleted 
+=   new  EventHandler < GameService.EnterRoomCompletedEventArgs > (client_EnterRoomCompleted);
            App.client.EnterRoomAsync(App.player, RoomID, RoomID);
        }

        
void  client_EnterRoomCompleted( object  sender, GameService.EnterRoomCompletedEventArgs e)
        {
            
if  (e.Result)
            {
                App.player.RoomID 
= RoomID;
                ((App)Application.Current).RedirectTo(
new  Index());
            }
            
else
            {
                App.player.ColorValue 
=   0 ;
                MessageBox.Show(
" 房间已有人! " );
            }
        }
复制代码

 

 我们运行F5一下,看看效果:

起动正常,输入上面的昵称后登陆

看到房间列表,我们随便点一下进去

看到一片空白,说明我们已进入到房间里面去了。

至此,本小结结束,下节,我们来实现房间的通知更新。

版权声明:本文原创发表于博客园,作者为路过秋天,原文链接:

http://www.cnblogs.com/cyq1162/archive/2010/07/16/1778711.html

相关文章
wcf双工通讯
首先说一个服务引用不成功的解决办法: 需要把服务端配置文件中的Binding换成: 或: 下面是一个wcf的简单示例: 服务契约代码: using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace WcfService { // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IUser”。
954 0
|
.NET 开发框架 数据安全/隐私保护
|
数据库 测试技术 安全
使用Entity Framework和WCF Ria Services开发SilverLight之2:POCO
在上一篇中《使用Entity Framework和WCF Ria Services开发SilverLight之1:简单模型》我们提出这类简单模型的几个问题: 1:实体模型被紧耦合在EDM中,同时它不能项目(模块)使用。
1206 0
|
SQL 监控 NoSQL
Wcf通讯基础框架方案(六)解决方案说明以及源代码
源代码见 http://wcfextension.codeplex.com/ 注意: 1) 本来没打算这么早开源,这只是一个比较原始的实现,请勿直接在商业环境使用 2) 请注意本框架的授权条款Apache License 2.
669 0
|
监控 NoSQL
Wcf通讯基础框架方案(一)——基本结构
由于希望使用Wcf作为公司内的通讯框架,因此基于Wcf进行了一些扩展,主要的目的有以下几个方面: 1) 希望减少客户端调用的复杂度,调用方式简化为WcfServiceLocator.Create().Add(1,2)。
770 0