【问题标题】:Java: client, client, (threaded) server, streams client info, JPanel created but messages(?) block start of gameJava:客户端,客户端,(线程)服务器,流客户端信息,JPanel 创建但消息(?)阻止游戏开始
【发布时间】:2012-05-09 10:41:13
【问题描述】:

我正在开发一个小规模的client1/ client2, server (threaded) TCP game。在尝试处理延迟问题时,我意识到我的transmitState() 存在缺陷。它迫使不必要的信息在通信流中产生迟缓,将汽车留在 JPanel 的不同位置,这基本上是错误的。所以我把它拿出来了。

但在这样做的过程中,尽管所有通信、协议、线程、“信使”和一切正常,但在我的逻辑中,我已经通过不允许repaint() 停止游戏的开始, transmitState()receiveState() 按逻辑顺序完成工作。

我真的看不出我哪里出错了。有什么建议吗?

注意:if keyPressed case 语句中的条件测试让精灵在左右旋转 360 度等,而 vel 是速度,因此不能超过 100。carRem = 汽车远程客户端。我知道有很多代码,但我过去(正确地)被告知没有包含足够的代码,所以我认为所有这些都显示了需要显示的内容(如果我错了请告诉我:)) .

传输状态:

public void transmitState(String s)
    {
        try
        {
            outputStream.writeBytes(s + "\n");
        }
        catch(IOException e)
        {
            System.err.println(e);
        }
    }

接收状态:

    public void receiveState()
    {
        try
        {
            messageIn = inputStream.readLine();
        }
        catch(IOException e)
        {
            System.err.println(e);
        }
        testState(messageIn);
    }

测试状态:

public void testState(String s)
{
if (s.equals("l") || s.equals("r") || s.equals("u") || s.equals("d"))
{
  c = s.charAt(0);
  this.i2 = i2;
  this.vel2 = vel2;
  this.carRem = carRem;

  switch (c)
  {
    case 'l':
      if (i2 == 0)
      {
        i2 = 15;
      }
      else
      {
        i2--;
      }
      carRem.setCurrentImage(i2);
      break;
    case 'r':
      if (i2 == 15)
      {
        i2 = 0;
      }
      else
      {
        i2++;
      }
      carRem.setCurrentImage(i2);
      break;
    case 'u':
      if (vel2 == 100)
      {

      }
      else
      {
        vel2 = vel2 + 10;
        carRem.setVel(vel2);
      }
      break;
    case 'd':
      if (vel2 == 0)
      {

      }
      else
      {
        vel2 = vel2 - 10;
        carRem.setVel(vel2);
      }
      break;
  }
}
}

JPANEL(具有大多数客户端功能):

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class UIPanel extends JPanel implements ActionListener, KeyListener
{       
    //sprite creation stuff, works fine (excluded here)
    private Timer timer;
    private CarLocal carLoc;
    private CarRemote carRem;
    private String carLocColour;

    private ClientMessenger cliMess = null;

    public UIPanel(CarLocal carLoc, CarRemote carRem, ClientMessenger cliMess)
    {
        this.carLoc = carLoc;
        this.carRem = carRem;
        this.cliMess = cliMess;

        images1 = new ImageIcon[TOTAL_IMAGES];
        images2 = new ImageIcon[TOTAL_IMAGES];

        carLocColour = carLoc.getColour();
            //setting sprites and testing order  (works fine and excluded here)

        this.addKeyListener(this);
        this.setFocusable(true);

       timer = new Timer(80, this);
        timer.start();
    }

    public void keyTyped(KeyEvent e) 
    {

    }

   public void keyPressed(KeyEvent e) 
    {
        int i1 = carLoc.getCurrentImage();
        int i2 = carRem.getCurrentImage();
        int vel1 = carLoc.getVel();
        int vel2 = carRem.getVel();
        switch (e.getKeyCode()) 
        {
        case KeyEvent.VK_LEFT:
                if(i1 == 0)
                {
                    i1 = 15;
                }
                else
                {
                    i1--;
                }
                carLoc.setCurrentImage(i1);
                cliMess.transmitState("l");
                break;
            case KeyEvent.VK_RIGHT:
                if(i1 == 15)
                {
                    i1 = 0;
                }
                else
                {
                    i1++;
                }
                carLoc.setCurrentImage(i1);
                cliMess.transmitState("r");
                break;
        case KeyEvent.VK_UP:
                if(vel1 == 100)
                {

                }
                else
                {
                    vel1 = vel1 + 10;
                    carLoc.setVel(vel1);
                    cliMess.transmitState("u");
                }
                break;
        case KeyEvent.VK_DOWN:
                if(vel1 == 0)
                {

                }
                else
                {
                    vel1 = vel1 - 10;
                    carLoc.setVel(vel1);
                    cliMess.transmitState("d");
                }
                break;
        }

        carLoc.setCurrentImage(i1);
        carLoc.setVel(vel1);;
   }

   public void keyReleased(KeyEvent e) 
    {

   }

    public void actionPerformed(ActionEvent e)
    {
        repaint();
        cliMess.receiveState();
    }

    public void paintComponent(Graphics g)
    {
        for(int iVel1 = carLoc.getVel(); iVel1 > 0; iVel1 = iVel1 - 10)
        {
            carLoc.forwardCalc(); 
        }
        for(int iVel2 = carRem.getVel(); iVel2 > 0; iVel2 = iVel2 - 10)
        {
            carRem.forwardCalc();
        }

        super.paintComponent(g);
        int i1X = carLoc.getCarX();
        int i1Y = carLoc.getCarY();
        int i2X = carRem.getCarX();
        int i2Y = carRem.getCarY();
        int currentImage1 = carLoc.getCurrentImage();
        int currentImage2 = carRem.getCurrentImage();
        Color c0 = Color.black;
        //includes some graphics stuff, works fine, excluded here

        images1[currentImage1].paintIcon( this, g, i1X, i1Y);
        images2[currentImage2].paintIcon( this, g, i2X, i2Y);
    }
}

【问题讨论】:

  • 我应该指出,一旦服务器被取消(在 cmd 提示符下按 CTRL + C),汽车就会开始按原样移动本地

标签: java multithreading stream jpanel


【解决方案1】:

根据您计划发送的数据量,您可能需要调用flush() 以确保发送数据而不需要内部缓冲区已满。

【讨论】:

  • 好的,谢谢,我会试试看。如果这是来自客户端将数据发送到服务器以线程并反弹回来,或者由线程服务器刷新并反弹数据,您会建议吗?或者这没有什么区别?它正在发送连续的字符串流。
  • 嗯,到目前为止这并没有太大的不同,但我很欣赏这个建议:)
  • 你应该在每条你想立即收到的消息后刷新,不管方向和发件人。
  • 好的,这可能会有所帮助,但它并没有帮助我仍然坚持的部分问题。不过还是谢谢。
猜你喜欢
  • 2015-03-24
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
相关资源
最近更新 更多