在项目之间有段“空项期”,上个项目刚刚完成,下个项目还没落实,时间比较充裕。去年9月份就经历了这么一次短暂的“空项期”,那时偶还是一名前端工作者,C#使用起来毫不含糊,还自己整过一个类SCSF的MVP框架AngelFrame(详见之前博客:http://www.VEVb.com/wgp13x/p/99c2adc52d8f0dff30a038841ac32872.html)。在那段“空项期”之前,有位朋友托我做个小游戏,偶也满口的答应,只可惜之前项目太忙没时间做,就一直耽搁了,正好有这段“空项期”,所以做了一下,现在回想起来,做这个小游戏的过程中还是学习到了不少东西的,因为做游戏跟做项目的常用技术不同,于是在这里总结一下,别把这么宝贵的经验给弄丢了。
这个小游戏的需求很简单,就是在局域网的环境里能够自组织一个飞行棋平台,多个玩家在里面你一步我一步的玩,看谁先飞完全程。在做这个游戏之前,偶连什么是飞行棋,飞行棋怎么玩的都不懂,就先在网上试玩了一小把,查了查飞行棋的规则。会玩儿了,就要想想怎么做了,规则实现肯定要有,用户交互是个问题。在网上搜索了一下现成的C#飞行棋实现例子,发现不是给自家女儿做的就是给自家儿子做的,单机版的,手机版的,就是没有局域网版的。好吧,只有看我来创造了。关键词:飞行棋, C#, 局域网, 多人对战摘要:很久之前就有个朋友托我做个游戏了,这个游戏的需求很简单,就是在局域网的环境里能够自组织一个飞行棋平台,多个玩家在里面你一步我一步的玩。游戏规则有了,实现的难点在于自建多人对战平台,C#飞行棋实现例子有很多,可就是没有局域网版的,下面就是我抽出时间写的一个局域网多人对战飞行棋,在这里总结一下。publicclassNetwork{PRivatestaticNetwork_instace;privateconstintPort=100;publicstaticUdpClientUdpClient;privatestaticEncodingencoding=Encoding.GetEncoding("gb2312");publicstaticstrinGhostName;publicstaticIPAddressIpAddress;privatestaticThreadlistener;publiceventEventHandler<GameMsg>ReceivedMsg;publicstaticNetworkInstance{get{if(_instace==null)_instace=newNetwork();return_instace;}}privateNetwork(){UdpClient=newUdpClient(Port);HostName=Dns.GetHostName();foreach(IPAddressipinDns.GetHostAddresses(HostName)){if(ip.AddressFamily==AddressFamily.InterNetwork){IpAddress=ip;break;}}}//局域网内广播,在上线时调用,通知其它Client有人上线了publicvoidBroadcast(GameMsgmsg){IPEndPointipEndPoint=newIPEndPoint(IPAddress.Broadcast,Port);byte[]bytes=Tools.Serialize(msg);UdpClient.Send(bytes,bytes.Length,ipEndPoint);}//接收消息线程入口,收到消息后触发各类事件publicvoidReceiveMsg(){IPEndPointipEndPoint=newIPEndPoint(IPAddress.Broadcast,Port);while(true){byte[]bytes=null;try{bytes=UdpClient.Receive(refipEndPoint);}catch(SocketExceptionex){return;}GameMsgmsg=(GameMsg)Tools.Deserialize(bytes);if(ReceivedMsg!=null&&!msg.IpAddress.Equals(IpAddress))ReceivedMsg(this,msg);}}//向某IP定向发送消息publicvoidSend(IPAddressip,GameMsgmsg){IPEndPointipEndPoint=newIPEndPoint(ip,Port);byte[]bytes=Tools.Serialize(msg);UdpClient.Send(bytes,bytes.Length,ipEndPoint);}//向一些IP定向发送消息publicvoidSend(IPAddress[]ips,GameMsgmsg){foreach(IPAddressipAddressinips){if(!ipAddress.Equals(IpAddress))Send(ipAddress,msg);}}} |
[Serializable]publicclassGameMsg:EventArgs{publicMsgTypeEnumMsgType;publicIPAddressIpAddress;publicobjectMsgContent;}[Serializable]publicclassLandGameMsg//OnlineReply,Hello{publicstringHostName;publicstringUserName;}[Serializable]publicclassCreateGameMsg{publicstringCreaterHostName;publicstringCreaterUserName;publicIPAddress[]SelectedIpAddresses;publicstring[]SelectedHostNames;}...... |
publicpartialclassMainForm:Form{publicstaticThreadListener=newThread(newThreadStart(Network.Instance.ReceiveMsg)){Name="receiveMsg",Priority=ThreadPriority.Highest};publicstaticCurrStatEnumCurrStat=CurrStatEnum.Idle;privatestaticreadonlyMsgTypeEnum[]interestMsgTypes=newMsgTypeEnum[]{MsgTypeEnum.QuitGame}; publicMainForm(){Listener.Start();Network.Instance.ReceivedMsg+=newEventHandler<GameMsg>(_network_ReceivedMsg);Network.Instance.Broadcast(newGameMsg(){MsgType=MsgTypeEnum.LandGame,IpAddress=Network.IpAddress,MsgContent=newLandGameMsg(){HostName=Network.HostName}});} privatedelegatevoidDelegate_ReceivedMsg(GameMsgmsg);void_network_ReceivedMsg(objectsender,GameMsge){Delegate_ReceivedMsgmyDelegate=newDelegate_ReceivedMsg(handleReceivedMsg);if(interestMsgTypes.Contains(e.MsgType))Invoke(myDelegate,e);}voidhandleReceivedMsg(GameMsgmsg){switch(msg.MsgType){caseMsgTypeEnum.QuitGame://收到某人退出游戏请求MessageBox.Show("有小伙伴要求退出游戏");ucUsersInGame_QuitGame(null,null);break;}}} |
publicpartialclassInviteOthers:Form{privatestaticreadonlyMsgTypeEnum[]interestMsgTypes=newMsgTypeEnum[]{MsgTypeEnum.OnlineReply};publicList<GameMsg>OnlineReplys=newList<GameMsg>(); void_network_ReceivedMsg(objectsender,GameMsgmsg){if(interestMsgTypes.Contains(msg.MsgType)){switch(msg.MsgType){caseMsgTypeEnum.OnlineReply: OnlineReplys.Add(msg);break;}}} } |
///监控鼠标和窗口位置privatevoidtimer1_Tick(objectsender,EventArgse){intmouse_x=Cursor.Position.X,mouse_y=Cursor.Position.Y;intwindow_x=this.Location.X,window_y=this.Location.Y;intwindow_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;}}///隐藏界面privatevoidtimer2_Tick(objectsender,EventArgse){intwindow_height=this.Size.Height;startY+=window_height/8;if(startY<window_height){this.Location=newPoint(this.Location.X,-startY);}else{this.Location=newPoint(this.Location.X,1-window_height);isHiding=true;timer2.Enabled=false;timer1.Enabled=true;}}///显示界面privatevoidtimer3_Tick(objectsender,EventArgse){intwindow_height=this.Size.Height;startY-=window_height/8;if(startY>0){this.Location=newPoint(this.Location.X,-startY);}else{this.Location=newPoint(this.Location.X,0);isHiding=false;timer3.Enabled=false;timer1.Enabled=true;}} |
新闻热点
疑难解答