5

Meteorで簡単なリアルタイムマルチプレイヤー数学ゲームを作成しました。ここで試すことができます:http://mathplay.meteor.com

ローカルで(異なるブラウザを使用して)プレイする場合、すべてが正常に機能します。しかし、インターネットを介して友達とプレイすると、クライアントの同期がとれることがよくあります。あるプレーヤーに対してアクティブとしてリストされている質問は、実際には別のプレーヤーによってすでに解決されています。

私の推測では、サーバー専用であるはずの一部のコードは、代わりにクライアントの1つで実行されます。この動作をデバッグする方法に関する提案はありますか?

ユーザーが回答を送信すると、クライアントで何が起こるかを次に示します。

Template.number_input.events[okcancel_events('#answertextbox')] = make_okcancel_handler({
    ok: function (text, event) {
        question = Questions.findOne({ order_number: Session.get("current_question_order_number") });
        if (question.answer == document.getElementById('answertextbox').value) {
            console.log('True');
            Questions.update(question._id, {$set: {text: question.text.substr(0, question.text.length - 1) + question.answer, player: Session.get("player_name")}});
            callGetNewQuestion();
        }
        else {
            console.log('False');
        }
        document.getElementById('answertextbox').value = "";
        document.getElementById('answertextbox').focus();
    }
});

callGetNewQuestion()は、クライアントとサーバーの両方でこれをトリガーします。

getNewQuestion: function () {
    var nr1 = Math.round(Math.random() * 100);
    var nr2 = Math.round(Math.random() * 100);
    question_string = nr1 + " + " + nr2 + " = ?";
    question_answer = (nr1 + nr2);
    current_order_number = Questions.find({}).count() + 1;
    current_question_id = Questions.insert({ order_number: current_order_number, text: question_string, answer: question_answer });
    return Questions.findOne({_id: current_question_id});//current_question_id;
},

完全なソースコードは参照用にここにあります:https ://github.com/tomsoderlund/MathPlay

4

1 に答える 1

3

あなたの問題はこれにあります:

callGetNewQuestion()クライアントとサーバーの両方でこれをトリガーします

これ_idにより、タイミングの違いと、サーバーが生成した質問に置き換えられる別の質問のために、異なる質問が生成されます。ただし、これが常に当てはまるとは限りません。これにより、クライアントが独自のものを生成しているという理由だけで、物事の同期が非常に簡単になります。


クライアントがサーバーと同じデータを生成することを確認するためのより良いアプローチを理解する必要があります。これは、乱数ジェネレーターが同じ方法でシードされていることを確認することで実行できます。したがって、毎回同じ乱数が生成されます。値が異なるため、これによりちらつきが解決されます。


次に、実際のバグについては、これを実行したくない場合があります。

return Questions.findOne({_id: current_question_id});

ただし、代わりにこれを実行してください(クライアントでのみ、サーバーでは何も実行しないでください)。

Session.set('current_order', current_order_number); // ORDER! Not the _id / question_id.

このようにして、テンプレートヘルパーに次のものを入れることができます。

return Questions.findOne({ order_number: Session.get('current_order') });

本質的に、これはコレクションに対してリアクティブな方法で機能し、戻り値に依存しません。

于 2012-06-07T15:20:47.363 に答える