上一节我们讲到登陆时通过WCF,把用户信息传递到远程服务器,并用一个全局泛型字典变量来保存用户列表。
登陆后我们转向了房间页面。这节,我们要通过点击房间上的座位进入主页面(Index.xaml)。
既然要点击房间座位才能进入,我们就得为那房间的座位添加鼠标点击事件了。
我们回到GameRoom.cs找到创建房间的代码,找到Draw函数里,创建红蓝黑三个房间座位的代码,其实就是那三个矩形框Rectangle。
我们在它们被添加到房间之前,添加几个事件:
//
添加三个房间点击事件
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);
三个房间座位产生的事件函数:
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蓝]
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
);
}
红色位置:和黑色位置一样的判断方法
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]:
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方法了。
说明写的够仔细了,小看一会就明白了,其实就是改变房间状态了。还有一些事件通知,我们后面再实现。
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方法,同样的也是改变房间的状态:
public
void
OutRoom(Player player,
int
roomID)
{
if
(roomID
>
)
{
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
意思就是当用户从不同的房间切换,就是进入或退出房间。
以下四行代码、四行说明结束函数。
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页面了。
///
<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
=
;
MessageBox.Show(
"
房间已有人!
"
);
}
}
我们运行F5一下,看看效果:
起动正常,输入上面的昵称后登陆
看到房间列表,我们随便点一下进去
看到一片空白,说明我们已进入到房间里面去了。
至此,本小结结束,下节,我们来实现房间的通知更新。
原文链接: http://www.cnblogs.com/cyq1162/archive/2010/07/16/1778711.html