开发者

JavaScript pausing execution of function to wait for user input

开发者 https://www.devze.com 2023-02-22 08:10 出处:网络
I\'m trying to make a sort of game using the HTML5 canvas, JavaScript and XML. The idea is that you can make a quiz by putting questions and answers in an XML file.

I'm trying to make a sort of game using the HTML5 canvas, JavaScript and XML. The idea is that you can make a quiz by putting questions and answers in an XML file. I wrote a main loop that loops through all the questions, poses them and checks the correctness of the answer. For now I'm simply using alerts and dialog boxes to answer the questions The problem is that my main loop is one big interconnected whole that walks through the entire game from beginning to end, and instead of having alert boxes posing questions and dialog boxes to answer, immediately after one another, I want some user interaction. The answers to the questions appear on boxes at the bottom of the screen, and the user gets to control a crane to pick the right answer. Here's the snippet of code from the main loop I'm stuck on:

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[currentQuesti开发者_JAVA技巧on] = "error";
                // show 'next'-button and wait for press to continue

            }

As you can see I'm calling loadQuestion, which instantly loads the question, shows the possible answers, and for now immediately throws a dialog box where you can type the answer. This answer is returned and validated.

I have already programmed the controls of the crane, the user can already pick up a box with it. But because I'm calling loadQuestion and expecting it to return a value, this doesn't work. How do I make my main loop "pause" until an answer has been given by the player using the crane, and then proceed? I already tried making the answer a global variable, and just having an empty while answer == "" to keep the function busy doing nothing until answer gets a value, but this just freezes the script. I also messed around with intervals in an attempt to monitor the status of the answer variable, and clear the interval and return the value when this happens, but that simply returns false since the function completes without immediately returning a value.


How do I make my main loop "pause" until an answer has been given by the player using the crane, and then proceed?

By breaking it up. The only "yield" in JavaScript on browsers is to let your function end and then arrange to get called back later (via setTimeout, setInterval, an ajax callback, etc.). In your case, I'd tend to think the trigger to call you back should be the user's action answering the previous question, e.g., a click handler on the answer boxes or some such (rather than setTimeout and such, which are automated).

For instance, this code:

function loopArray(ar) {
    var index;
    for (index = 0; index < ar.length; ++index) {
       doSomething(ar[index]);
    }
}

...can be recast like this:

function loopArrayAsync(ar, callback) {
    var index;

    index = 0;
    loop();

    function loop() {
        if (index < ar.length) {
            doSomething(ar[index++]);
            setTimeout(loop, 0);
        }
        else {
            callback();
        }
    }
}

The second version yields control back to the browser on every loop iteration. It's also important to note that the second version returns before the loops have been completed, whereas the first version waits until all loops are done, which is why the second version has the callback function it calls when it's done looping.

Code calling the first one might look like this:

var a = ["one", "two", "three"];
loopArray(a);
// Code that expects the loop to be complete:
doTheNextThing();
doYetAnotherThing();

...whereas using the async version looks like this:

var a = ["one", "two", "three"];
loopArrayAsync(a, function() {
    // Code that expects the loop to be complete:
    doTheNextThing();
    doYetAnotherThing();
});

Doing this, you'll probably find you use closures (loop, above, is a closure), and so this article may be useful: Closures are not complicated


There is no sync. paused input/output tools in browser JS except of alert, confirm and prompt. Since you don't want to use those - try the following pattern:

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();
});

I.e. when user answers it - the callback function gets executed and you know that you're good to go.


From what I understand you have a questionnaire application, where you ask a series of questions and then ask the user to drop his answer using some drag and drop control ( a crane).

I am going to go an a tangent and say the design seems to be wrong. Javascript is event based and having one main thread looping around for user interaction is going to reduce the usability. I will not use any way of stalling the thread ( aka in java). Javascript is not written for such an usecase. Your application will be perceived as non responsive by some browsers and by almost all performance analyzers (like Yslow).

So I would provide each question with a div identified by a class which internally is a sequence (question1..2). Initially only one question will be enabled or visible. Once user answers the question, I will enable the enabled question. ( on the appropriate event, in this case probably the drop event of drag and drop). Since it is sequential, I will just have to check if the user has answered question1, then I will enable question2 appropriately. The whole flow should be event driven. The event here being the user answering the question.

0

精彩评论

暂无评论...
验证码 换一张
取 消