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);

        }

 

 

 

C#坦克大战网络版代码_第1张图片

 

单机测试时 先运行服务端  再运行多个客户端就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);

        }

 

如果你发现有什么不合理的,需要改进的地方,邮件联系[email protected](qq常年不在线,邮件联系) 。相互交流 谢谢

 

 

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

 

 

 

 

你可能感兴趣的:(thread,String,网络,C#,byte)