HTML5キャンバス、JavaScript、XMLを使って一種のゲームを作ろうとしています。質問と回答をXMLファイルに入れることでクイズを作成できるという考え方です。私はすべての質問をループし、それらを提起し、答えの正しさをチェックするメインループを作成しました。今のところ、私は単にアラートとダイアログボックスを使用して質問に答えています問題は、私のメインループが、ゲーム全体を最初から最後までウォークスルーする1つの大きな相互接続された全体であり、アラートボックスが質問やダイアログボックスを表示するのではなく、答え、次々と、ユーザーとの対話が必要です。質問への回答は画面下部のボックスに表示され、ユーザーはクレーンを操作して正しい回答を選択できます。これが私が立ち往生しているメインループからのコードスニペットです:
answer = loadQuestion(i);
if (answer == "correct") {
// answered correctly, update scoreArray and load next question
scoreArray[currentQuestion] = "correct";
// show 'next'-button and wait for press to continue
} else {
// answered incorrectly again, update scoreArray and load next question
scoreArray[currentQuestion] = "error";
// show 'next'-button and wait for press to continue
}
ご覧のとおり、loadQuestionを呼び出しています。これは、質問を即座にロードし、可能な回答を表示し、今のところ、回答を入力できるダイアログボックスをすぐにスローします。この回答が返され、検証されます。
私はすでにクレーンの制御をプログラムしました、ユーザーはすでにそれで箱を拾うことができます。しかし、loadQuestionを呼び出して値を返すことを期待しているため、これは機能しません。クレーンを使用しているプレーヤーから回答が得られるまでメインループを「一時停止」してから続行するにはどうすればよいですか?私はすでに答えをグローバル変数にして、空のwhile answer == ""を持って、答えが値を取得するまで関数をビジー状態に保つことを試みましたが、これはスクリプトをフリーズさせるだけです。また、回答変数のステータスを監視し、間隔をクリアして値を返すために間隔をいじりましたが、関数がすぐに値を返さずに完了するため、単にfalseが返されます。
クレーンを使用しているプレーヤーから回答が得られるまでメインループを「一時停止」してから続行するにはどうすればよいですか?
それを分割することによって。ブラウザでのJavaScriptの唯一の「歩留まり」は、関数を終了させてから、後で(setTimeout
、setInterval
、ajaxコールバックなどを介して)呼び出されるように調整することです。あなたの場合、コールバックのトリガーは、前の質問に答えるユーザーのアクションであると思う傾向があります。たとえば、回答ボックスのclick
ハンドラーなど(setTimeout
など、自動化されています)。
たとえば、次のコードは次のとおりです。
function loopArray(ar) {
var index;
for (index = 0; index < ar.length; ++index) {
doSomething(ar[index]);
}
}
...次のようにリキャストできます:
function loopArrayAsync(ar, callback) {
var index;
index = 0;
loop();
function loop() {
if (index < ar.length) {
doSomething(ar[index++]);
setTimeout(loop, 0);
}
else {
callback();
}
}
}
2番目のバージョンでは、ループが繰り返されるたびにブラウザに制御が戻ります。 2番目のバージョンはbeforeループが完了したのに対し、最初のバージョンはループが完了したことを返すことに注意することも重要です。 versionは、すべてのループが完了するまで待機します。そのため、2番目のバージョンには、ループが完了したときに呼び出すcallback
関数があります。
最初のコードを呼び出すコードは次のようになります。
var a = ["one", "two", "three"];
loopArray(a);
// Code that expects the loop to be complete:
doTheNextThing();
doYetAnotherThing();
...非同期バージョンの使用は次のようになります。
var a = ["one", "two", "three"];
loopArrayAsync(a, function() {
// Code that expects the loop to be complete:
doTheNextThing();
doYetAnotherThing();
});
これを行うと、おそらく closures (上記のloop
はクロージャです)を使用していることに気付くでしょう。役に立つ: クロージャは複雑ではない
同期はありません。 alert
、confirm
、およびPrompt
を除く、ブラウザーJSの入出力ツールを一時停止しました。それらを使用したくないので、次のパターンを試してください。
loadQuestion(i, function(answer) {
if (answer == "correct") {
// answered correctly, update scoreArray and load next question
scoreArray[currentQuestion] = "correct";
// show 'next'-button and wait for press to continue
} else {
// answered incorrectly again, update scoreArray and load next question
scoreArray[currentQuestion] = "error";
// show 'next'-button and wait for press to continue
}
resumeGameExecution();
});
つまりユーザーがそれに答えると、コールバック関数が実行され、準備ができていることがわかります。
私の理解では、一連の質問をしてから、ドラッグアンドドロップコントロール(クレーン)を使用してユーザーに回答をドロップするように求めるアンケートアプリケーションがあります。
私は正接して、デザインが間違っているようだと言います。 Javascriptはイベントベースであり、ユーザーとの対話のために1つのメインスレッドをループさせると、使いやすさが低下します。スレッドをストールさせる方法は使用しません(Javaでは別名)。 Javascriptはそのようなユースケース向けには書かれていません。アプリケーションは、一部のブラウザーおよびほとんどすべてのパフォーマンスアナライザー(Yslowなど)によって応答しないものとして認識されます。
したがって、内部的にシーケンスであるクラス(question1..2)によって識別されるdivを各質問に提供します。最初は、1つの質問のみが有効化または表示されます。ユーザーが質問に回答したら、有効な質問を有効にします。 (適切なイベント、この場合はおそらくドラッグアンドドロップのドロップイベント)。シーケンシャルなので、ユーザーが質問1に回答したかどうかを確認するだけで、質問2を適切に有効にします。フロー全体はイベント駆動型である必要があります。ここでのイベントは、質問に答えるユーザーです。