правильный анализ и обработка полученных сообщений в java udp

#java #udp

Вопрос:

в моей многопользовательской танковой игре есть проблема. резервуары на стороне клиента нарисованы неправильно. последний, отправленный с сервера, хорош. но остальные моргают. я нашел проблему в клиенте. при разборе сообщений он получает координаты и направление танков x, y с правильной очередью. но когда я отправляю их в метод рисования, он получает последний. когда я пишу координаты x,y в методе рисования, подавляющее большинство координат x и y принадлежат последнему танку. так что последний танк не мигает, но остальные мигают. вот мой код;

  public void run() {
    byte[] data= new byte[1024];
    while(true) {
    try { 
         DatagramPacket packetreceived = new DatagramPacket(data, data.length);
    soket.receive(packetreceived); 
    messagereceived=new String(packetreceived.getData(),0,packetreceived.getLength());
    
    setmesaj(messagereceived);
    
    parsemessage(messagereceived);
    
    
    
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    //soket.close();
}}
public String incomingmessage() {
    return messagereceived;
}
public void setmesaj(String messagereceived) {
    this.messagereceived=messagereceived;
}

public void senddata(byte[] data) {
    
    try {DatagramPacket packet = new DatagramPacket(data, data.length,host,port );
        soket.send(packet);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}


public void parsemessage(String messagereceived) {
    
    String[] msg= messagereceived.split(",");    
    if(msg[0].equalsIgnoreCase("playtank")) {
        
        
        
        tankno=Integer.parseInt(msg[1]);
        setTankno(Integer.parseInt(msg[1]));
        switch(tankno) {
        default:
        x=Integer.parseInt(msg[2]);
        y=Integer.parseInt(msg[3]);
        direction=Integer.parseInt(msg[4]);
        }
        
    }
    if(msg[0].equalsIgnoreCase("addnewtanks")) {
        this.tankno=Integer.parseInt(msg[1]);
        this.x=Integer.parseInt(msg[2]);
        this.y=Integer.parseInt(msg[3]);
        this.direction=Integer.parseInt(msg[4]);
        this.health=Integer.parseInt(msg[5]);
        this.say=Integer.parseInt(msg[6]);
        this.tip=Integer.parseInt(msg[7]);
    }
    System.out.println(this.x "     " this.y "     " this.tankno);
** when i write these values, it is written properly to console everything is ok**
}

public int getX() {
    return x;
}

public void setX(int x) {
    this.x = x;
}

public int getY() {
    return y;
}

public void setY(int y) {
    this.y = y;
}

public int getdir() {
    return direction;
}

public void setdir(int direction) {
    this.direction = direction;
}

public int getTankno() {
    return tankno;
}

public void setTankno(int tankno) {
    this.tankno = tankno;
}

public void draw(Graphics g,Bufferedimagex bf1) {
    //System.out.println(this.x "  " this.y "   " this.tankno);
**when the values are written here most of the written value on the console is the third one (there are 0,1,2,3 tanks).**
    g.drawImage(bf1.sprite(this.getdir()*32-32, this.tip*16), this.getX(), this.getY(), 48, 48,null); 
    
}
 

Ответ №1:

У вас есть отдельные объекты для каждого танка? По — видимому, это не так. Мне кажется, что у вас есть один run цикл для чтения сообщений для всех 4 танков, и все танки используют одни и те же поля объектов класса. Если это так, то вы, вероятно, постоянно перезаписываете поля участника, когда приходит другой пакет.

Вероятно, вам следует подумать о создании отдельного класса танков.

напр..,

 class Tank
{
    int x;
    int y;
    int direction;
}
 

Затем создайте массив, список или карту танков.

 Tank[] tanks = new Tank[4];
for(int i=0;i<tanks.length;i  )
{
    tanks[i] = new Tank();
}
 

Когда вы получите сообщение, вам нужно будет выбрать, какой резервуар обновить. Вот пример использования массива.

 String[] msg= messagereceived.split(",");    
if(msg[0].equalsIgnoreCase("playtank")) {
    tankno=Integer.parseInt(msg[1]);
    // Choose which tank to update
    Tank tank = tanks[tankno];
    tank.x=Integer.parseInt(msg[2]);
    etc...
 

Создавая отдельный объект для каждого резервуара, вы будете изолировать данные каждого резервуара от других, и у вас не возникнет проблем с перезаписью данных.

Комментарии:

1. спасибо, Джейми. да, у меня есть отдельный класс танков. я добавил танки в список arraylist. затем инициализируйте танки в игровой панели. но результат был тот же. поэтому я добавил метод рисования в клиентский класс, чтобы достичь всех значений. последнее выше, но оно не работает. я вижу танки на экране, но последний хорошо виден, а остальные появляются в кадре и быстро исчезают. они двигаются по кругу. их координаты меняются.

2. Ваш parsemessage метод не создает впечатления сохранения данных в отдельных объектах… он просто записывает данные в себя: x=Integer.parseInt(msg[2]); . Где он выбирает объект резервуара для обновления?