2016-04-28 6 views
1

私はJavaでシンプルなボールとパドルマルチプレイヤーゲームを作っています。 MultiCastSocketを使用してデータを送受信します。ボールは、プレーヤー
のシステム上でのみ移動されます。1.ボールの位置は、ネットワーク上のすべてのプレーヤーによって送信されます。すべての選手はデータを受け取りますが、p1以外の選手だけがそれを読んでボールの位置を更新します。ここで問題となるのは、ボールはp1では滑らかに動いていますが、他のプレーヤのシステムでは連続動作していないことです。私のコードのネットワーキング部分のコードスニペットが表示されます: (ここでmyTagはプレーヤー番号です recはデータを受信し、受信したデータクラスのオブジェクトで、 dataJavaマルチプレイヤーゲームスムーズネットワーク機能

private class ScheduleTask extends TimerTask { 

    @Override 
    public void run() { 


     paddleArr[myTag].moveX(); 

     for(int i=0; i<4; i++){ 
      if(i != myTag){ 
       if(!others.contains(i)){ 
        Computer comPaddle = new Computer(paddleArr[i], ball); 
        if(paddleArr[i].isHorizontal()){comPaddle.moveSideways();} 
        else {comPaddle.move();} 
       } 
      } 
     } 
     if(myTag==0){ball.move();} 

     if(ball.getXdir()*ball.getXdir()+ball.getYdir()*ball.getYdir() >= 80){ 
      ball.setXdir(ball.getXdir()*0.67); 
      ball.setYdir(ball.getYdir()*0.67); 
     } 


     if(newgame){ 
      try { 
      socket = new MulticastSocket(4446); 
      group =InetAddress.getByName("228.6.7.8"); 
      socket.joinGroup(group); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 

      System.out.println("error"); 
     } 
      rec = new ReceiveData(socket, group, port, myTag); 
     newgame = false; 
     } 

     //System.out.println(rec.data); 

     if(bak > 10){ 
      setAllPos(rec.data.trim()); 
     } 
     bak++; 

     checkCollision(); 
     repaint(); 

     try { 
      socket = new MulticastSocket(4446); 
      group = InetAddress.getByName("228.6.7.8"); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     String str = myTag+" "+(ball.getMyX())+" "+(ball.getMyY())+" "+(ball.getXdir())+" "+(ball.getYdir())+" "+(paddleArr[myTag].getMyX())+" "+(paddleArr[myTag].getMyY()); 
     buf = str.getBytes(); 
     // Create a DatagramPacket 
     DatagramPacket packet = new DatagramPacket(buf, buf.length,group, 4446); 
     // Do a send. 
     try { 
      socket.send(packet); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      System.out.println("send failed"); 
     } 
     // And when we have finished sending data close the socket 
     socket.close(); 

    } 
} 

public void setAllPos(String s){ 
    //System.out.println(s); 
    String[] data = s.split(" "); 
    if(myTag != 0){ 
     if(data[0].equals("0")) 
     { 
      ball.setMyX(Double.parseDouble(data[1])); 
      ball.setMyY(Double.parseDouble(data[2])); 
      ball.setXdir(Double.parseDouble(data[3])); 
      ball.setYdir(Double.parseDouble(data[4])); 
      repaint(); 
      //ball.move(); 
      //paddleBottom.setMyX(Integer.parseInt(data[5])); 
      //content.udpPosition = data[5]; 
      //System.out.println("Ball pos set"); 
     } 
    } 

答えて

0

残念ながら、あなたはちょうどあなたがネットワーク経由で得た最新の位置を適用することにより、ネットワークゲームを行うことはできません。 (ネットワークパケットにはランダムな遅延があるため動きが不均一になるので)信頼性のない帯域幅は無駄です(各フレームに少なくとも1つのメッセージを送信する必要があります)。

あり、それを解決するには、2つの基本的なオプションがあり、彼らがより良い結果のために組み合わせることができます

1)で何が起こっているかの少し遅れたバージョンを表し、各クライアント上のボールの地元の「影」のコピーを保管してください他のマシン。その後、新しい位置にジャンプするのではなく、ネットワークの更新を受け取ったら、現在の位置と目標位置の間の補間を開始するので、短時間で到達することができます。その間に新しいアップデートを受け取ったら、新しい位置に向かって補間を開始してください。この方法では、わずかな一定の遅れ(それはかなり低いことがあります)を犠牲にして、奇妙なジャンプを認識しません。

2)ちょうど位置を送信する代わりに、速度を送信します(既に行っています)。位置の更新に基づいてではなく、それに基づいて各機械の動きのシミュレーションを実行します。すべてがスムーズになりますが、位置が同期していなくてもエラーはコンパイルされます

適切なソリューションは、両方のソリューションをコンパイルすることです。位置を補間し、受信した速度をシミュレーションします(必要に応じて時間補間することもできます)。

ここにいくつかの数学について読むことができます。 https://en.wikipedia.org/wiki/Dead_reckoning#Dead_reckoning_for_networked_games さらに詳しくは、ウェブで「推測航法」を参照してください。ガマシュトラのことについてはかなりの記事があるはずです。

ます。またquake3ネットワークプロトコルに http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking やその他のソースをチェックアウトする場合があります - それは非信頼性の高いネットワークを非常に効率的な方法で行うことができますどのように良い例です(そしてその間に暗黙的にhttps://en.wikipedia.org/wiki/Lamport_timestampsを紹介)

+0

ありがとうたくさんの男!それは今の魅力のように動作します:) – Sarvesh

関連する問題