JavaScriptでソケットioを使用してマルチプレイヤーゲームを作成しています。クライアントの補間を除いて、現時点ではゲームは完全に機能します。現在、サーバーからパケットを受け取ったら、クライアントの位置をサーバーから送信された位置に設定するだけです。これが私がやろうとしたことです:
getServerInfo(packet) {
var otherPlayer = players[packet.id]; // GET PLAYER
otherPlayer.setTarget(packet.x, packet.y); // SET TARGET TO MOVE TO
...
}
プレイヤーの目標位置を設定しました。そして、Players Updateメソッドで、私はこれを単に行いました:
var update = function(delta) {
if (x != target.x || y != target.y){
var direction = Math.atan2((target.y - y), (target.x - x));
x += (delta* speed) * Math.cos(direction);
y += (delta* speed) * Math.sin(direction);
var dist = Math.sqrt((x - target.x) * (x - target.x) + (y - target.y)
* (y - target.y));
if (dist < treshhold){
x = target.x;
y = target.y;
}
}
}
これは基本的にプレイヤーをターゲットの方向に一定の速度で動かします。問題は、サーバーから次の情報が到着する前または後にプレイヤーがターゲットに到着することです。
編集:私はこの主題に関するGabriel Bambettasの記事を読んだばかりで、彼はこれについて言及しています:
t = 1000で位置データを受信したとします。すでにt = 900でデータを受信しているため、プレーヤーがt = 900およびt = 1000でどこにいたかがわかります。したがって、t = 1000およびt = 1100から、他のプレーヤーは、t = 900からt = 1000までの時間を記録しました。この方法では、100 msの「遅れ」を除いて、ユーザーの実際の移動データを常に表示しています。
これも、正確に100ミリ秒遅れていると想定しています。pingが大きく異なる場合、これは機能しません。
これを行う方法のアイデアを得るために、いくつかの疑似コードを提供できますか?
私はマルチプレイヤーゲームのクライアント/サーバーアーキテクチャとアルゴリズムに完全に慣れていますが、この質問を読んで最初に頭に浮かんだのは、各プレイヤーに関連する変数に2次(またはそれ以上)のカルマンフィルターを実装することでした。
特に、単純な推測航法よりもはるかに優れたカルマン予測ステップ。また、カルマンの予測および更新ステップは、重み付けされた、または最適な補間器としていくらか機能するという事実。さらに、プレーヤーのダイナミクスは、他のメソッドで使用される抽象化されたパラメーター化をいじるのではなく、直接エンコードできます。
一方、クイック検索で私はこれに行きました:
3Dオンラインゲームのネットワークトラフィックを最小化するためのカルマンフィルターを使用した推測航法アルゴリズムの改善
要約:
オンライン3Dゲームは、ネットワークを介した効率的で高速なユーザーインタラクションサポートを必要とし、ネットワークサポートは通常、ネットワークゲームエンジンを使用して実装されます。ネットワークゲームエンジンは、ネットワーク遅延を最小限に抑え、ネットワークトラフィックの輻輳を緩和する必要があります。ゲームユーザー間のネットワークトラフィックを最小限に抑えるために、クライアントベースの予測(推測航法アルゴリズム)が使用されます。各ゲームエンティティはアルゴリズムを使用して自身の動き(他のエンティティの動きも)を推定し、推定エラーがしきい値を超えると、エンティティはUPDATE(位置、速度など)パケットを他のエンティティに送信します。推定精度が向上するにつれて、各エンティティはUPDATEパケットの送信を最小限に抑えることができます。推測航法アルゴリズムの予測精度を向上させるために、カルマンフィルターに基づく推測航法アプローチを提案します。実際のデモンストレーションを示すために、人気のあるネットワークゲーム(BZFlag)を使用し、カルマンフィルターを使用してゲームに最適化された推測航法アルゴリズムを改善します。予測精度を向上させ、ネットワークトラフィックを12%削減します。
それはすべてが何であるかを学ぶために言葉っぽく、まったく新しい問題のように見えるかもしれません...そしてその問題のために離散状態空間。
簡単に言うと、カルマンフィルターは不確実性を考慮に入れたフィルターであり、これがここにあるものです。通常、既知のサンプルレートでの測定の不確かさを処理しますが、測定期間/フェーズの不確実性を処理するように再調整できます。
適切な測定の代わりに、カルマン予測で単に更新するという考えです。この戦術は、ターゲット追跡アプリケーションに似ています。
私は自分でstackexchangeでそれらを推奨しました-それらがどのように関連しているかを理解するのに約1週間かかりましたが、それ以来、ビジョン処理作業でそれらを正常に実装しました。
(...私は今あなたの問題を実験したいと思っています!)
フィルターをより直接制御したかったので、他の誰かが独自に作成したカルマンフィルターのmatlabでの実装をopenCV(C ++)にコピーしました。
void Marker::kalmanPredict(){
//Prediction for state vector
Xx = A * Xx;
Xy = A * Xy;
//and covariance
Px = A * Px * A.t() + Q;
Py = A * Py * A.t() + Q;
}
void Marker::kalmanUpdate(Point2d& measuredPosition){
//Kalman gain K:
Mat tempINVx = Mat(2, 2, CV_64F);
Mat tempINVy = Mat(2, 2, CV_64F);
tempINVx = C*Px*C.t() + R;
tempINVy = C*Py*C.t() + R;
Kx = Px*C.t() * tempINVx.inv(DECOMP_CHOLESKY);
Ky = Py*C.t() * tempINVy.inv(DECOMP_CHOLESKY);
//Estimate of velocity
//units are pixels.s^-1
Point2d measuredVelocity = Point2d(measuredPosition.x - Xx.at<double>(0), measuredPosition.y - Xy.at<double>(0));
Mat zx = (Mat_<double>(2,1) << measuredPosition.x, measuredVelocity.x);
Mat zy = (Mat_<double>(2,1) << measuredPosition.y, measuredVelocity.y);
//kalman correction based on position measurement and velocity estimate:
Xx = Xx + Kx*(zx - C*Xx);
Xy = Xy + Ky*(zy - C*Xy);
//and covariance again
Px = Px - Kx*C*Px;
Py = Py - Ky*C*Py;
}
私はあなたがこれを直接使用できるとは思いませんが、誰かがそれに遭遇して 'A'、 'P'、 'Q'および 'C'が状態空間にあるものを理解している場合(ヒント、状態-空間理解はここでの前提条件です)彼らはおそらくドットを接続する方法を見るでしょう。
(ちなみに、MATLABとopenCVには、独自のカルマンフィルター実装が含まれています...)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加