本文介绍了如何利用WCF和callback机制开发一个简单的多人在线游戏模型。
运行过程如下:
当game service 启动之后,若干个客户端便会自动连接到服务器。当某个客户端点击join game时,所有客户端同时更新。
运行screenshot如下图所示:
WCF service screenshot
client1 screenshot:
client2 screenshot:
WCF service主要代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace GameService
{
public class PlayerEventAgrs : EventArgs
{
public Player player;
public GameDesk desk;
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
class GameService:IGameService
{
static List<Player> Players=new List<Player>();
public delegate void PlayerEventHandler(object sender, PlayerEventAgrs e);
public static event PlayerEventHandler OnJoinGame;
public static event PlayerEventHandler OnStartGame;
public IPlayerCallBack callback;
public GameService()
{
callback = System.ServiceModel.OperationContext.Current.GetCallbackChannel<IPlayerCallBack>();
OnJoinGame += new PlayerEventHandler(GameService_OnJoinGame);
OnStartGame += new PlayerEventHandler(GameService_OnStartGame);
}
public List<Player> GetPlayerList()
{
System.Threading.Thread.Sleep(4000);
return Players;
}
void GameService_OnJoinGame(object sender, PlayerEventAgrs e)
{
Console.WriteLine("{0} is joining the game on desk NO {1}", e.player.PlayerName, e.desk.DeskNo);
callback.OnJoin(e.player,e.desk);
}
void GameService_OnStartGame(object sender, PlayerEventAgrs e)
{
callback.OnStart(e.player);
}
public void BroadGameEvent(PlayerEventAgrs e, PlayerEventHandler temp)
{
if (OnJoinGame != null)
{
foreach (PlayerEventHandler handler in temp.GetInvocationList())
{
handler.BeginInvoke(this, e, null, null);
}
}
}
public void JoinToGame(Player player,GameDesk desk)
{
Players.Add(player);
PlayerEventAgrs e = new PlayerEventAgrs();
e.player = player;
e.player.PositionNO = desk;
e.desk = desk;
BroadGameEvent(e, OnJoinGame);
}
public void StartGame(Player player)
{
PlayerEventAgrs e = new PlayerEventAgrs();
e.player = player;
BroadGameEvent(e, OnStartGame);
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace GameService
{
public class PlayerEventAgrs : EventArgs
{
public Player player;
public GameDesk desk;
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
class GameService:IGameService
{
static List<Player> Players=new List<Player>();
public delegate void PlayerEventHandler(object sender, PlayerEventAgrs e);
public static event PlayerEventHandler OnJoinGame;
public static event PlayerEventHandler OnStartGame;
public IPlayerCallBack callback;
public GameService()
{
callback = System.ServiceModel.OperationContext.Current.GetCallbackChannel<IPlayerCallBack>();
OnJoinGame += new PlayerEventHandler(GameService_OnJoinGame);
OnStartGame += new PlayerEventHandler(GameService_OnStartGame);
}
public List<Player> GetPlayerList()
{
System.Threading.Thread.Sleep(4000);
return Players;
}
void GameService_OnJoinGame(object sender, PlayerEventAgrs e)
{
Console.WriteLine("{0} is joining the game on desk NO {1}", e.player.PlayerName, e.desk.DeskNo);
callback.OnJoin(e.player,e.desk);
}
void GameService_OnStartGame(object sender, PlayerEventAgrs e)
{
callback.OnStart(e.player);
}
public void BroadGameEvent(PlayerEventAgrs e, PlayerEventHandler temp)
{
if (OnJoinGame != null)
{
foreach (PlayerEventHandler handler in temp.GetInvocationList())
{
handler.BeginInvoke(this, e, null, null);
}
}
}
public void JoinToGame(Player player,GameDesk desk)
{
Players.Add(player);
PlayerEventAgrs e = new PlayerEventAgrs();
e.player = player;
e.player.PositionNO = desk;
e.desk = desk;
BroadGameEvent(e, OnJoinGame);
}
public void StartGame(Player player)
{
PlayerEventAgrs e = new PlayerEventAgrs();
e.player = player;
BroadGameEvent(e, OnStartGame);
}
}
}
callback interface如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace GameService
{
[ServiceContract]
public interface IPlayerCallBack
{
[OperationContract(IsOneWay = true)]
void OnJoin(Player player,GameDesk gamedesk);
[OperationContract(IsOneWay = true)]
void OnStart(Player player);
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace GameService
{
[ServiceContract]
public interface IPlayerCallBack
{
[OperationContract(IsOneWay = true)]
void OnJoin(Player player,GameDesk gamedesk);
[OperationContract(IsOneWay = true)]
void OnStart(Player player);
}
}
客户端callback implementation如下:
#region CallBack Implementation
public void OnJoin(GameService.Player player, GameService.GameDesk desk)
{
int deskNo = desk.DeskNo;
StringBuilder show = new StringBuilder();;
show.AppendFormat("Player Information\n");
show.AppendFormat("Player Name:{0}\n", player.PlayerName);
show.AppendFormat("Player Status: {0}\n",player.Action);
show.AppendFormat("Player Role: {0}\n", player.Role);
img_Desktop.Image = new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\active-desktop.bmp"));
switch (deskNo)
{
case 1:
lb_PlayerInfo1.Text = show.ToString();
lb_PlayerInfo1.Refresh();
pic_Player1.Image=new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\acvite-icon.bmp"));
break;
case 2:
lb_PlayerInfo2.Text = show.ToString();
pic_Player2.Image = new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\acvite-icon.bmp"));
break;
case 3:
lb_PlayerInfo3.Text = show.ToString();
pic_Player3.Image = new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\acvite-icon.bmp"));
break;
}
}
public void OnStart(GameService.Player player)
{
}
#endregion
public void OnJoin(GameService.Player player, GameService.GameDesk desk)
{
int deskNo = desk.DeskNo;
StringBuilder show = new StringBuilder();;
show.AppendFormat("Player Information\n");
show.AppendFormat("Player Name:{0}\n", player.PlayerName);
show.AppendFormat("Player Status: {0}\n",player.Action);
show.AppendFormat("Player Role: {0}\n", player.Role);
img_Desktop.Image = new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\active-desktop.bmp"));
switch (deskNo)
{
case 1:
lb_PlayerInfo1.Text = show.ToString();
lb_PlayerInfo1.Refresh();
pic_Player1.Image=new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\acvite-icon.bmp"));
break;
case 2:
lb_PlayerInfo2.Text = show.ToString();
pic_Player2.Image = new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\acvite-icon.bmp"));
break;
case 3:
lb_PlayerInfo3.Text = show.ToString();
pic_Player3.Image = new System.Drawing.Bitmap(System.Drawing.Image.FromFile(@"image\acvite-icon.bmp"));
break;
}
}
public void OnStart(GameService.Player player)
{
}
#endregion
有关本文完整源代码,请点击此处下载