在項目之間有段「空項期」,上個項目剛剛完成,下個項目還沒落實,時間比較充裕。去年9月份就經歷了這麼一次短暫的「空項期」,那時偶仍是一名前端工做者,C#使用起來絕不含糊,還本身整過一個類SCSF的MVP框架AngelFrame(詳見以前博客:http://www.cnblogs.com/wgp13x/p/99c2adc52d8f0dff30a038841ac32872.html)。在那段「空項期」以前,有位朋友託我作個小遊戲,偶也滿口的答應,只惋惜以前項目太忙沒時間作,就一直耽擱了,正好有這段「空項期」,因此作了一下,如今回想起來,作這個小遊戲的過程當中仍是學習到了很多東西的,由於作遊戲跟作項目的經常使用技術不一樣,因而在這裏總結一下,別把這麼寶貴的經驗給弄丟了。html
public class Network
{
private static Network _instace;
private const int Port = 100;
public static UdpClient UdpClient;
private static Encoding encoding = Encoding.GetEncoding("gb2312");
public static string HostName;
public static IPAddress IpAddress;
private static Thread listener;
public event EventHandler<GameMsg> ReceivedMsg;
public static Network Instance
{
get
{
if (_instace == null)
_instace = new Network();
return _instace;
}
}
private Network()
{
UdpClient = new UdpClient(Port);
HostName = Dns.GetHostName();
foreach (IPAddress ip in Dns.GetHostAddresses(HostName))
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
IpAddress = ip;
break;
}
}
}
//局域網內廣播,在上線時調用,通知其它Client有人上線了
public void Broadcast(GameMsg msg)
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Broadcast, Port);
byte[] bytes = Tools.Serialize(msg);
UdpClient.Send(bytes, bytes.Length, ipEndPoint);
}
//接收消息線程入口,收到消息後觸發各種事件
public void ReceiveMsg()
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Broadcast, Port);
while (true)
{
byte[] bytes = null;
try
{
bytes = UdpClient.Receive(ref ipEndPoint);
}
catch (SocketException ex)
{
return;
}
GameMsg msg = (GameMsg)Tools.Deserialize(bytes);
if (ReceivedMsg != null && !msg.IpAddress.Equals(IpAddress))
ReceivedMsg(this, msg);
}
}
//向某IP定向發送消息
public void Send(IPAddress ip, GameMsg msg)
{
IPEndPoint ipEndPoint = new IPEndPoint(ip, Port);
byte[] bytes = Tools.Serialize(msg);
UdpClient.Send(bytes, bytes.Length, ipEndPoint);
}
//向一些IP定向發送消息
public void Send(IPAddress[] ips, GameMsg msg)
{
foreach (IPAddress ipAddress in ips)
{
if (!ipAddress.Equals(IpAddress))
Send(ipAddress, msg);
}
}
}
|
[Serializable]
public class GameMsg : EventArgs
{
public MsgTypeEnum MsgType;
public IPAddress IpAddress;
public object MsgContent;
}
[Serializable]
public class LandGameMsg //OnlineReply, Hello
{
public string HostName;
public string UserName;
}
[Serializable]
public class CreateGameMsg
{
public string CreaterHostName;
public string CreaterUserName;
public IPAddress[] SelectedIpAddresses;
public string[] SelectedHostNames;
}
......
|
public partial class MainForm : Form
{
public static Thread Listener = new Thread(new ThreadStart(Network.Instance.ReceiveMsg)) { Name = "receiveMsg", Priority = ThreadPriority.Highest };
public static CurrStatEnum CurrStat = CurrStatEnum.Idle;
private static readonly MsgTypeEnum[] interestMsgTypes = new MsgTypeEnum[] { MsgTypeEnum.QuitGame };
public
MainForm()
{
Listener.Start();
Network.Instance.ReceivedMsg += new EventHandler<GameMsg>(_network_ReceivedMsg);
Network.Instance.Broadcast(new GameMsg() { MsgType = MsgTypeEnum.LandGame, IpAddress = Network.IpAddress, MsgContent = new LandGameMsg() { HostName = Network.HostName } });
}
private
delegate
void
Delegate_ReceivedMsg(GameMsg msg);
void _network_ReceivedMsg(object sender, GameMsg e)
{
Delegate_ReceivedMsg myDelegate = new Delegate_ReceivedMsg(handleReceivedMsg);
if (interestMsgTypes.Contains(e.MsgType))
Invoke(myDelegate, e);
}
void handleReceivedMsg(GameMsg msg)
{
switch (msg.MsgType)
{
case MsgTypeEnum.QuitGame: //收到某人退出遊戲請求
MessageBox.Show("有小夥伴要求退出遊戲");
ucUsersInGame_QuitGame(null, null);
break;
}
}
}
|
public partial class InviteOthers : Form
{
private static readonly MsgTypeEnum[] interestMsgTypes = new MsgTypeEnum[] { MsgTypeEnum.OnlineReply };
public List<GameMsg> OnlineReplys = new List<GameMsg>();
void
_network_ReceivedMsg(
object
sender, GameMsg msg)
{
if (interestMsgTypes.Contains(msg.MsgType))
{
switch (msg.MsgType)
{
case MsgTypeEnum.OnlineReply:
OnlineReplys.Add(msg);
break;
}
}
}
}
|
/// 監控鼠標和窗口位置
private void timer1_Tick(object sender, EventArgs e)
{
int mouse_x = Cursor.Position.X, mouse_y = Cursor.Position.Y;
int window_x = this.Location.X, window_y = this.Location.Y;
int window_width = this.Size.Width, window_height = this.Size.Height;
if (isHiding == false && window_y == 0)
{
if (window_x - mouse_x > 10 || mouse_x - window_x - window_width > 10
|| mouse_y - window_y - window_height > 10)
{
timer1.Enabled = false;
timer2.Enabled = true;
}
}
if (isHiding == true && mouse_y <= 1 && mouse_x > window_x &&
mouse_x < window_x + window_width)
{
timer1.Enabled = false;
timer3.Enabled = true;
}
}
/// 隱藏界面
private void timer2_Tick(object sender, EventArgs e)
{
int window_height = this.Size.Height;
startY += window_height / 8;
if (startY < window_height)
{
this.Location = new Point(this.Location.X, -startY);
}
else
{
this.Location = new Point(this.Location.X, 1 - window_height);
isHiding = true;
timer2.Enabled = false;
timer1.Enabled = true;
}
}
/// 顯示界面
private void timer3_Tick(object sender, EventArgs e)
{
int window_height = this.Size.Height;
startY -= window_height / 8;
if (startY > 0)
{
this.Location = new Point(this.Location.X, -startY);
}
else
{
this.Location = new Point(this.Location.X, 0);
isHiding = false;
timer3.Enabled = false;
timer1.Enabled = true;
}
}
|