C#坦克大战网络版代码


   

简单C#坦克大战网络版代码





写完单机版 http://blog.csdn.net/xiaoxiao108/archive/2010/12/18/6084473.aspx游戏后

再写个网络版玩玩。

开发工具vs2008





网络版实现方法很简单

1.一个服务端,多个客户端

2.服务端开个端口监听,当一个客户端程序后连接到服务端后,服务端分配个编号给客户端作为他的坦克编号

3.当有新坦克创建,坦克移动,等操作时,客户端发送数据到服务端,服务端再把数据发送到所有的客户端来实现网络游戏的同步





具体实现代码

1.服务端开启服务代码

   public void Start()

   {

     //开启udp线程

     Thread t = new Thread(UDPThread);

     t.IsBackground = true;

     t.Start();

     //开启tcp服务

     TcpListener tl = new TcpListener(TCP_PORT);

     tl.Start();

     while (true)

     {

       TcpClient tc = tl.AcceptTcpClient();

       Stream ns = tc.GetStream();

       BinaryReader br = new BinaryReader(ns);

       int udpPort = br.ReadInt32();//br.Close();不能关闭br

       BinaryWriter bw = new BinaryWriter(ns);

       bw.Write(ID++);

       IPEndPoint rep = (IPEndPoint)tc.Client.RemoteEndPoint;

       Client c = new Client(rep.Address.ToString(), udpPort);

       clients.Add(c);

       Console.WriteLine("A Client TCP Connect! Addr- " + rep.Address.ToString() + ":" + rep.Port);

     }

   }

2.服务端udp数据接收转发代码

   private void UDPThread()

   {

     Console.WriteLine("UDP thread started at port :" + UDP_PORT);

     byte[] buf = new byte[1024];

     UdpClient uc = new UdpClient(UDP_PORT);//// 跟java有区别 如果这句话放到while外面 就不能接受第二个坦克连入

     IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);

     while (true)

     {

       buf = uc.Receive(ref ipep);

       Console.WriteLine("a udp packet received! from " + ipep.Address + ":" + ipep.Port);

       //把收到的数据转发给每一个客户端

       for (int i = 0; i < clients.Count; i++)

       {

         Client c = clients[i];

         UdpClient _uc = new UdpClient();

         _uc.Connect(c.ip, c.udpPort);

         _uc.Send(buf, buf.Length);

       }

     }

   }

3.客户端连接代码

   public void Connect(string ip, int port)

   {

     this.ip = ip;

     TcpClient client = new TcpClient();

     client.Connect(ip, port);

     Stream ns = client.GetStream();

     BinaryWriter bw = new BinaryWriter(ns);

     bw.Write(udpPort);

     BinaryReader br = new BinaryReader(ns);       //bw.Close();不能关闭bw

     //从服务器端取到服务器分配的坦克编号

     int id = br.ReadInt32();

     tc.myTank.ID = id;

     //编号为偶数的设置为坏蛋

     if (id % 2 == 0)

       tc.myTank.Good = false;

     else

       tc.myTank.Good = true;

     //可以在“输出窗口”看到下面的调试代码

     Debug.WriteLine("Connected to server! and server give me a ID:" + id);

     br.Close();

     ns.Close();

     client.Close();

     TankNewMsg msg = new TankNewMsg(tc.myTank);

     Send(msg);

     //开启接收线程

     Thread t = new Thread(UDPRecvThread);

     t.IsBackground = true;

     t.Start();

   }

4.坦克加入消息代码发送代码



   public void Send(UdpClient uc, string ip, int udpPort)

   {

     uc.Connect(ip, udpPort);

     //程序中用 | 来分割发送的内容

     string str = msgType + "|" + tank.ID + "|" + tank.x + "|" + tank.y + "|" + (int)tank.dir + "|" + tank.Good;

     uc.Send(Encoding.UTF32.GetBytes(str), Encoding.UTF32.GetBytes(str).Length);

   }

5.坦克加入消息解析代码

   public void Parse(byte[] b)

   {

     string str = Encoding.UTF32.GetString(b);

     string[] strs = str.Split('|');

     int id = Convert.ToInt32(strs[1]);

     //如果数据包里是自己的坦克不处理

     if (id == tc.myTank.ID)

     {

       return;

     }

     int x = Convert.ToInt32(strs[2]);

     int y = Convert.ToInt32(strs[3]);

     Direction dir = (Direction)Convert.ToInt32(strs[4]);

     bool good = Convert.ToBoolean(strs[5]);

     Boolean exist = false;

     for (int i = 0; i < tc.tanks.Count; i++)

     {

       Tank t = tc.tanks[i];

       if (t.ID == id)

       {

         exist = true;

         break;

       }

     }

     //如果坦克不存在就创建出来

     if (!exist)

     {

       TankNewMsg msg = new TankNewMsg(tc.myTank);

       tc.nc.Send(msg);

       //Tank t = new Tank(x, y, good, tc);//java中是这样写得Tank t = new Tank(x,y,good,dir,tc)

       Tank t = new Tank(x, y, good, dir, tc); //有可能是老坦克 给新坦克发包 所以要家dir参数

       t.ID = id;

       tc.tanks.Add(t);

     }

   }

6.坦克移动消息

   public void Send(UdpClient uc, string ip, int udpPort)

   {

     uc.Connect(ip, udpPort);

     //程序中用 | 来分割发送的内容

     string str = msgType + "|" + id + "|" + x + "|" + y + "|" + Convert.ToInt32(dir);

     uc.Send(Encoding.UTF32.GetBytes(str), Encoding.UTF32.GetBytes(str).Length);

   }



   public void Parse(byte[] b)

   {

     string str = Encoding.UTF32.GetString(b);

     string[] strs = str.Split('|');

     int id = Convert.ToInt32(strs[1]);

     //如果数据包里是自己的坦克不处理

     if (id == tc.myTank.ID)

     {

       return;

     }

     int x = Convert.ToInt32(strs[2]);

     int y = Convert.ToInt32(strs[3]);

     Direction dir = (Direction)Convert.ToInt32(strs[4]);

     for (int i = 0; i < tc.tanks.Count; i++)

     {

       Tank t = tc.tanks[i];

       if (t.ID == id)

       {

         t.dir = dir;

         t.x = x;

         t.y = y;

         break;

       }

     }

   }

7.子弹消息处理代码

   public void Send(UdpClient uc, string ip, int udpPort)

   {

     uc.Connect(ip, udpPort);

     //程序中用 | 来分割发送的内容

     string str = msgType + "|" + m.tankID + "|" + m.x + "|" + m.y + "|" + (int)m.dir + "|" + m.good;

     uc.Send(Encoding.UTF32.GetBytes(str), Encoding.UTF32.GetBytes(str).Length);

   }



   public void Parse(byte[] b)

   {

     string str = Encoding.UTF32.GetString(b);

     string[] strs = str.Split('|');

     int tankID = Convert.ToInt32(strs[1]);

     if (tankID == tc.myTank.ID)

     {

       return;

     }

     int x = Convert.ToInt32(strs[2]);

     int y = Convert.ToInt32(strs[3]);

     Direction dir = (Direction)Convert.ToInt32(strs[4]);

     bool good = Convert.ToBoolean(strs[5]);

     Missile m = new Missile(tankID, x, y, good, dir, tc);

     tc.missiles.Add(m);

   }







<img src="http://hi.csdn.net/attachment/201101/16/0_1295172842poHz.gif" alt="">



单机测试时 先运行服务端 再运行多个客户端就ok

多机联网游戏时修改下 nc.Connect("127.0.0.1", 8888);中的ip地址就可以在局域网内玩了

   private void Form1_Load(object sender, EventArgs e)

   {

     myTank = new Tank(50, 20, true, this);//放到前面 this不能用 //y轴比java的减少了30

     nc = new NetClient(this);

     nc.Connect("127.0.0.1", 8888);

     //nc.connect("192.168.1.168",8888);

     //nc.connect("10.10.10.1",8888);

   }



如果你发现有什么不合理的,需要改进的地方,<span style="font-family: 'lucida Grande',Verdana; font-size: 14px; line-height: 23px;">邮件联系[email protected](qq常年不在线,邮件联系)</span> 朱晓 (泰山学院)。相互交流 谢谢





下载地址 http://download.csdn.net/source/2986606









 

你可能感兴趣的:(java,工作,C#坦克大战网络版代码)