`
wangxiaohigh
  • 浏览: 1429422 次
文章分类
社区版块
存档分类
最新评论

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

}

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

}

如果你发现有什么不合理的,需要改进的地方,邮件联系328452421@qq.com(qq常年不在线,邮件联系) 朱晓 (泰山学院)。相互交流 谢谢

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics