Java坦克大战网络版

openkk 12年前

不足之处

Server不够高效....需要看更多书去学习
协议不够精细
TankNewMsg TankAreadyExistMsg
子弹打中坦克后可否只发送一个消息
tankId id 被打中的tankId
同步线程
坦克退出后的服务器端处理.....另起端口管理跟命令相关之处,命令与数据分开
一段时间没有接收到数据后的处理
更加精细的内存控制

TankServer

import java.io.DataInputStream;  import java.io.DataOutputStream;  import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetSocketAddress;  import java.net.ServerSocket;  import java.net.Socket;  import java.net.SocketException;  import java.util.ArrayList;  import java.util.List;
 public class TankServer {   private static int ID = 100;   public static final int TCP_PORT = 8888;   public static final int UDP_PORT = 6666;      List clients = new ArrayList();            public void start() {        new Thread(new UDPThread()).start();        ServerSocket ss = null;    try {     ss = new ServerSocket(TCP_PORT);    } catch (IOException e) {     e.printStackTrace();    }        while(true) {     Socket s = null;     try {      s = ss.accept();      DataInputStream dis = new DataInputStream(s.getInputStream());      String IP = s.getInetAddress().getHostAddress();      int udpPort = dis.readInt();      Client c = new Client(IP, udpPort);      clients.add(c);      DataOutputStream dos = new DataOutputStream(s.getOutputStream());      dos.writeInt(ID++);      //s.close();  System.out.println("A Client Connect! Addr- " + s.getInetAddress() + ":" + s.getPort() + "----UDP Port:" + udpPort);     } catch (IOException e) {      e.printStackTrace();     } finally {      if(s != null) {       try {        s.close();        s = null;       } catch (IOException e) {        e.printStackTrace();       }      }     }    }   }      public static void main(String[] args) {    new TankServer().start();   }      private class Client {    String IP;    int udpPort;        public Client(String IP, int udpPort) {     this.IP = IP;     this.udpPort = udpPort;    }   }      private class UDPThread implements Runnable {        byte[] buf = new byte[1024];        public void run() {     DatagramSocket ds = null;     try {      ds = new DatagramSocket(UDP_PORT);     } catch (SocketException e) {      e.printStackTrace();     }  System.out.println("UDP thread started at port :" + UDP_PORT);     while(ds != null){      DatagramPacket dp = new DatagramPacket(buf, buf.length);      try {       ds.receive(dp);       for(int i=0; i 
TankClient

import java.awt.Button;  import java.awt.Color;  import java.awt.Dialog;  import java.awt.FlowLayout;  import java.awt.Frame;  import java.awt.Graphics;  import java.awt.Image;  import java.awt.Label;  import java.awt.TextField;  import java.awt.event.ActionEvent;  import java.awt.event.ActionListener;  import java.awt.event.KeyAdapter;  import java.awt.event.KeyEvent;  import java.awt.event.WindowAdapter;  import java.awt.event.WindowEvent;  import java.util.ArrayList;  import java.util.List;    public class TankClient extends Frame {   public static final int GAME_WIDTH = 800;   public static final int GAME_HEIGHT = 600;      Tank myTank = new Tank(50, 50, true, Dir.STOP, this);      List missiles = new ArrayList();   List explodes = new ArrayList();   List tanks = new ArrayList();     Image offScreenImage = null;      NetClient nc = new NetClient(this);      ConnDialog dialog = new ConnDialog();       @Override   public void paint(Graphics g) {    g.drawString("missiles count:" + missiles.size(), 10, 50);    g.drawString("explodes count:" + explodes.size(), 10, 70);    g.drawString("tanks    count:" + tanks.size(), 10, 90);        for(int i=0; i 

NetClient

import java.io.ByteArrayInputStream;  import java.io.DataInputStream;  import java.io.DataOutputStream;  import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.Socket;  import java.net.SocketException;  import java.net.UnknownHostException;    public class NetClient {   TankClient tc;   private int udpPort;      String IP;  //server IP      DatagramSocket ds = null;      public NetClient(TankClient tc) {    this.tc = tc;       }     public void connect(String IP, int port) {    this.IP = IP;     try {     ds = new DatagramSocket(udpPort);    } catch (SocketException e) {     e.printStackTrace();    }        Socket s = null;    try {     s = new Socket(IP, port);     DataOutputStream dos = new DataOutputStream(s.getOutputStream());     dos.writeInt(udpPort);     DataInputStream dis = new DataInputStream(s.getInputStream());     int id = dis.readInt();     tc.myTank.id = id;          if(id%2 == 0) tc.myTank.good = false;     else tc.myTank.good = true;       System.out.println("Connected to server! and server give me a ID:" + id);    } catch (UnknownHostException e) {     e.printStackTrace();    } catch (IOException e) {     e.printStackTrace();    } finally {     if(s != null) {      try {       s.close();       s = null;      } catch (IOException e) {       e.printStackTrace();      }     }    }        TankNewMsg msg = new TankNewMsg(tc.myTank);    send(msg);        new Thread(new UDPRecvThread()).start();   }      public void send(Msg msg) {    msg.send(ds, IP, TankServer.UDP_PORT);   }      private class UDPRecvThread implements Runnable {        byte[] buf = new byte[1024];        public void run() {          while(ds != null){      DatagramPacket dp = new DatagramPacket(buf, buf.length);      try {       ds.receive(dp);       parse(dp);  System.out.println("a packet received from server!");      } catch (IOException e) {       e.printStackTrace();      }     }    }      private void parse(DatagramPacket dp) {     ByteArrayInputStream bais = new ByteArrayInputStream(buf, 0, dp.getLength());     DataInputStream dis = new DataInputStream(bais);     int msgType = 0;     try {      msgType = dis.readInt();     } catch (IOException e) {      e.printStackTrace();     }     Msg msg = null;     switch (msgType) {     case Msg.TANK_NEW_MSG:          msg = new TankNewMsg(NetClient.this.tc);      msg.parse(dis);      break;     case Msg.TANK_MOVE_MSG:      msg = new TankMoveMsg(NetClient.this.tc);      msg.parse(dis);      break;     case Msg.MISSILE_NEW_MSG:      msg = new MissileNewMsg(NetClient.this.tc);      msg.parse(dis);      break;     case Msg.TANK_DEAD_MSG:      msg = new TankDeadMsg(NetClient.this.tc);      msg.parse(dis);      break;     case Msg.MISSILE_DEAD_MSG:      msg = new MissileDeadMsg(NetClient.this.tc);      msg.parse(dis);      break;     }         }       }     public int getUdpPort() {    return udpPort;   }     public void setUdpPort(int udpPort) {    this.udpPort = udpPort;   }  }
Msg接口

import java.io.DataInputStream;  import java.net.DatagramSocket;      public interface Msg {   public static final int TANK_NEW_MSG = 1;   public static final int TANK_MOVE_MSG = 2;   public static final int MISSILE_NEW_MSG = 3;   public static final int TANK_DEAD_MSG = 4;   public static final int MISSILE_DEAD_MSG = 5;      public void send(DatagramSocket ds, String IP, int udpPort);   public void parse(DataInputStream dis);  }
TankNewMsg

import java.io.ByteArrayOutputStream;  import java.io.DataInputStream;  import java.io.DataOutputStream;  import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetSocketAddress;  import java.net.SocketException;      public class TankNewMsg implements Msg {   int msgType = Msg.TANK_NEW_MSG;      Tank tank;   TankClient tc;   public TankNewMsg(Tank tank) {    this.tank = tank;   }      public TankNewMsg(TankClient tc) {    this.tc = tc;   }      public void send(DatagramSocket ds, String IP, int udpPort) {    ByteArrayOutputStream baos = new ByteArrayOutputStream();    DataOutputStream dos = new DataOutputStream(baos);    try {     dos.writeInt(msgType);     dos.writeInt(tank.id);     dos.writeInt(tank.x);     dos.writeInt(tank.y);     dos.writeInt(tank.dir.ordinal());     dos.writeBoolean(tank.good);    } catch (IOException e) {     e.printStackTrace();    }    byte[] buf = baos.toByteArray();    try {     DatagramPacket dp = new DatagramPacket(buf, buf.length, new InetSocketAddress(IP, udpPort));     ds.send(dp);    } catch (SocketException e) {     e.printStackTrace();    } catch (IOException e) {     e.printStackTrace();    }       }     public void parse(DataInputStream dis) {    try {     int id = dis.readInt();     if(tc.myTank.id == id) {      return;     }                    int x = dis.readInt();     int y = dis.readInt();     Dir dir = Dir.values()[dis.readInt()];     boolean good = dis.readBoolean();  //System.out.println("id:" + id + "-x:" + x + "-y:" + y + "-dir:" + dir + "-good:" + good);     boolean exist = false;     for(int i=0; iTankMoveMsg    

import java.io.ByteArrayOutputStream;  import java.io.DataInputStream;  import java.io.DataOutputStream;  import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetSocketAddress;  import java.net.SocketException;      public class TankMoveMsg implements Msg {   int msgType = Msg.TANK_MOVE_MSG;   int x, y;   int id;   Dir ptDir;   Dir dir;   TankClient tc;      public TankMoveMsg(int id,int x, int y,  Dir dir, Dir ptDir) {    this.id = id;    this.x = x;    this.y = y;    this.dir = dir;    this.ptDir = ptDir;   }      public TankMoveMsg(TankClient tc) {    this.tc = tc;   }     public void parse(DataInputStream dis) {    try {     int id = dis.readInt();     if(tc.myTank.id == id) {      return;     }     int x = dis.readInt();     int y = dis.readInt();     Dir dir = Dir.values()[dis.readInt()];     Dir ptDir = Dir.values()[dis.readInt()];       //System.out.println("id:" + id + "-x:" + x + "-y:" + y + "-dir:" + dir + "-good:" + good);     boolean exist = false;     for(int i=0; iTankDeadMsg    

import java.io.ByteArrayOutputStream;  import java.io.DataInputStream;  import java.io.DataOutputStream;  import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetSocketAddress;  import java.net.SocketException;      public class TankDeadMsg implements Msg {   int msgType = Msg.TANK_DEAD_MSG;   TankClient tc;   int id;      public TankDeadMsg(int id) {    this.id = id;   }      public TankDeadMsg(TankClient tc) {    this.tc = tc;   }      public void parse(DataInputStream dis) {    try {     int id = dis.readInt();     if(tc.myTank.id == id) {      return;     }       //System.out.println("id:" + id + "-x:" + x + "-y:" + y + "-dir:" + dir + "-good:" + good);     for(int i=0; iTank    

import java.awt.Color;  import java.awt.Graphics;  import java.awt.Rectangle;  import java.awt.event.KeyEvent;  import java.util.Random;    public class Tank {   int id;      public static final int XSPEED = 5;   public static final int YSPEED = 5;      public static final int WIDTH = 30;   public static final int HEIGHT = 30;      boolean good;   int x, y;      private static Random r = new Random();      private boolean live = true;      private int step = r.nextInt(12) + 3;      TankClient tc;      boolean bL, bU, bR, bD;       Dir dir = Dir.STOP;   Dir ptDir = Dir.D;      public Tank(int x, int y, boolean good) {    this.x = x;    this.y = y;    this.good = good;   }      public Tank(int x, int y, boolean good, Dir dir, TankClient tc) {    this(x, y, good);    this.dir = dir;    this.tc = tc;   }      public void draw(Graphics g) {    if(!live) {     if(!good) {      tc.tanks.remove(this);     }     return;    }        Color c = g.getColor();    if(good) g.setColor(Color.RED);    else g.setColor(Color.BLUE);    g.fillOval(x, y, WIDTH, HEIGHT);    g.drawString("id:" + id, x, y-10);    g.setColor(c);        switch(ptDir) {    case L:      g.drawLine(x + WIDTH/2, y + HEIGHT/2, x, y + HEIGHT/2);     break;    case LU:     g.drawLine(x + WIDTH/2, y + HEIGHT/2, x, y);     break;    case U:     g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH/2, y);     break;    case RU:     g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH, y);     break;    case R:     g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH, y + HEIGHT/2);     break;    case RD:     g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH, y + HEIGHT);     break;    case D:     g.drawLine(x + WIDTH/2, y + HEIGHT/2, x + WIDTH/2, y + HEIGHT);     break;    case LD:     g.drawLine(x + WIDTH/2, y + HEIGHT/2, x, y + HEIGHT);     break;    }        move();   }     private void move() {    switch(dir) {    case L:     x -= XSPEED;     break;    case LU:     x -= XSPEED;     y -= YSPEED;     break;    case U:     y -= YSPEED;     break;    case RU:     x += XSPEED;     y -= YSPEED;     break;    case R:     x += XSPEED;     break;    case RD:     x += XSPEED;     y += YSPEED;     break;    case D:     y += YSPEED;     break;    case LD:     x -= XSPEED;     y += YSPEED;     break;    case STOP:     break;    }        if(dir != Dir.STOP) {     ptDir = dir;    }        if(x < 0) x = 0;    if(y < 30) y = 30;    if(x + WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - WIDTH;    if(y + HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - HEIGHT;        /*if(!good) {     if(step == 0) {      step = r.nextInt(12) + 3;      Dir[] dirs = Dir.values();      dir = dirs[r.nextInt(dirs.length)];     }     step --;     if(r.nextInt(40) > 38) this.fire();    }*/       }     public void keyPressed(KeyEvent e) {    int key = e.getKeyCode();    switch (key) {    case KeyEvent.VK_LEFT:     bL = true;     break;    case KeyEvent.VK_UP:     bU = true;     break;    case KeyEvent.VK_RIGHT:     bR = true;     break;    case KeyEvent.VK_DOWN:     bD = true;     break;    }    locateDirection();   }     private void locateDirection() {    Dir oldDir = this.dir;        if(bL && !bU && !bR && !bD) dir = Dir.L;    else if(bL && bU && !bR && !bD) dir = Dir.LU;    else if(!bL && bU && !bR && !bD) dir = Dir.U;    else if(!bL && bU && bR && !bD) dir = Dir.RU;    else if(!bL && !bU && bR && !bD) dir = Dir.R;    else if(!bL && !bU && bR && bD) dir = Dir.RD;    else if(!bL && !bU && !bR && bD) dir = Dir.D;    else if(bL && !bU && !bR && bD) dir = Dir.LD;    else if(!bL && !bU && !bR && !bD) dir = Dir.STOP;        if(dir != oldDir) {     TankMoveMsg msg = new TankMoveMsg(id, x, y, dir, ptDir);     tc.nc.send(msg);    }   }     public void keyReleased(KeyEvent e) {    int key = e.getKeyCode();    switch (key) {    case KeyEvent.VK_CONTROL:     fire();     break;    case KeyEvent.VK_LEFT:     bL = false;     break;    case KeyEvent.VK_UP:     bU = false;     break;    case KeyEvent.VK_RIGHT:     bR = false;     break;    case KeyEvent.VK_DOWN:     bD = false;     break;    }    locateDirection();   }      private Missile fire() {    if(!live)     return null;    int x = this.x + WIDTH/2 - Missile.WIDTH/2;    int y = this.y + HEIGHT/2 - Missile.HEIGHT/2;    Missile m = new Missile(id, x, y, this.good, this.ptDir, this.tc);    tc.missiles.add(m);        MissileNewMsg msg = new MissileNewMsg(m);    tc.nc.send(msg);        return m;   }      public Rectangle getRect() {    return new Rectangle(x, y, WIDTH, HEIGHT);   }     public boolean isLive() {    return live;   }     public void setLive(boolean live) {    this.live = live;   }  }
Missile

import java.awt.Color;  import java.awt.Graphics;  import java.awt.Rectangle;  import java.util.List;        public class Missile {   public static final int XSPEED = 10;   public static final int YSPEED = 10;      public static final int WIDTH = 10;   public static final int HEIGHT = 10;      private static int ID = 1;      TankClient tc;   int tankId;   int id;      int x, y;   Dir dir = Dir.R;   boolean live = true;   boolean good;      public Missile(int tankId, int x, int y, boolean good, Dir dir) {    this.tankId = tankId;    this.x = x;    this.y = y;    this.good = good;    this.dir = dir;    this.id = ID++;   }      public Missile(int tankId, int x, int y, boolean good, Dir dir, TankClient tc) {    this(tankId, x, y, good, dir);    this.tc = tc;   }      public void draw(Graphics g) {    if(!live) {     tc.missiles.remove(this);     return;    }        Color c = g.getColor();    g.setColor(Color.BLACK);    g.fillOval(x, y, WIDTH, HEIGHT);    g.setColor(c);        move();   }     private void move() {    switch(dir) {    case L:     x -= XSPEED;     break;    case LU:     x -= XSPEED;     y -= YSPEED;     break;    case U:     y -= YSPEED;     break;    case RU:     x += XSPEED;     y -= YSPEED;     break;    case R:     x += XSPEED;     break;    case RD:     x += XSPEED;     y += YSPEED;     break;    case D:     y += YSPEED;     break;    case LD:     x -= XSPEED;     y += YSPEED;     break;    case STOP:     break;    }        if(x < 0 || y < 0 || x > TankClient.GAME_WIDTH || y > TankClient.GAME_HEIGHT) {     live = false;    }   }      public Rectangle getRect() {    return new Rectangle(x, y, WIDTH, HEIGHT);   }      public boolean hitTank(Tank t) {    if(this.live && t.isLive() && this.good != t.good &&this.getRect().intersects(t.getRect())) {     this.live = false;     t.setLive(false);     tc.explodes.add(new Explode(x, y, tc));     return true;    }    return false;   }      public boolean hitTanks(List tanks) {    for(int i=0; iMissileNewMsg    

import java.io.ByteArrayOutputStream;  import java.io.DataInputStream;  import java.io.DataOutputStream;  import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetSocketAddress;  import java.net.SocketException;      public class MissileNewMsg implements Msg {   int msgType = Msg.MISSILE_NEW_MSG;   TankClient tc;   Missile m;      public MissileNewMsg(Missile m) {    this.m = m;   }      public MissileNewMsg(TankClient tc) {    this.tc = tc;   }      public void send(DatagramSocket ds, String IP, int udpPort) {        ByteArrayOutputStream baos = new ByteArrayOutputStream();    DataOutputStream dos = new DataOutputStream(baos);    try {     dos.writeInt(msgType);     dos.writeInt(m.tankId);     dos.writeInt(m.id);     dos.writeInt(m.x);     dos.writeInt(m.y);     dos.writeInt(m.dir.ordinal());     dos.writeBoolean(m.good);    } catch (IOException e) {     e.printStackTrace();    }    byte[] buf = baos.toByteArray();    try {     DatagramPacket dp = new DatagramPacket(buf, buf.length, new InetSocketAddress(IP, udpPort));     ds.send(dp);    } catch (SocketException e) {     e.printStackTrace();    } catch (IOException e) {     e.printStackTrace();    }   }     public void parse(DataInputStream dis) {    try {     int tankId = dis.readInt();      if(tankId == tc.myTank.id) {      return;     }     int id = dis.readInt();     int x = dis.readInt();     int y = dis.readInt();     Dir dir = Dir.values()[dis.readInt()];     boolean good = dis.readBoolean();       //System.out.println("id:" + id + "-x:" + x + "-y:" + y + "-dir:" + dir + "-good:" + good);     Missile m = new Missile(tankId, x, y, good, dir, tc);     m.id = id;     tc.missiles.add(m);    } catch (IOException e) {     e.printStackTrace();    }   }       }
MissileDeadMsg

import java.io.ByteArrayOutputStream;  import java.io.DataInputStream;  import java.io.DataOutputStream;  import java.io.IOException;  import java.net.DatagramPacket;  import java.net.DatagramSocket;  import java.net.InetSocketAddress;  import java.net.SocketException;      public class MissileDeadMsg implements Msg {   int msgType = Msg.MISSILE_DEAD_MSG;   TankClient tc;   int tankId;   int id;      public MissileDeadMsg(int tankId, int id) {    this.tankId = tankId;    this.id = id;   }      public MissileDeadMsg(TankClient tc) {    this.tc = tc;   }      public void parse(DataInputStream dis) {    try {     int tankId = dis.readInt();     int id = dis.readInt();       //System.out.println("id:" + id + "-x:" + x + "-y:" + y + "-dir:" + dir + "-good:" + good);     for(int i=0; iExplode    

import java.awt.Color;  import java.awt.Graphics;    public class Explode {   int x, y;   private int[] diameters = {4, 7, 12, 18, 26, 32, 49, 30, 14, 6};   private boolean live = true;      private TankClient tc;   int step = 0;      public Explode(int x, int y, TankClient tc) {    this.x = x;    this.y = y;    this.tc = tc;   }      public void draw(Graphics g) {    if(!live) {     tc.explodes.remove(this);     return;    }        Color c = g.getColor();    g.setColor(Color.ORANGE);    g.fillOval(x, y, diameters[step], diameters[step]);    g.setColor(c);        step ++;    if(step == diameters.length) {     live = false;       }   }  }
Dir

public enum Dir {   L, LU, U, RU, R, RD, D, LD, STOP  }
Java坦克大战网络版

Java坦克大战网络版

Java坦克大战网络版

Java坦克大战网络版

Java坦克大战网络版

Java坦克大战网络版

 转自:http://blog.csdn.net/slience_perseverance/article/details/7844993

 

</TC.MISSILES.SIZE();></pre></TANKS.SIZE();></tank></pre></TC.TANKS.SIZE();></pre></TC.TANKS.SIZE();></pre></TC.TANKS.SIZE();></pre>