Duke University Department of Computer Science
This is a tutorial for a very specific technique: How do I make it so that, when the user presses a key or clicks on something, the action associated with the event is only executed some of the time, but not all of the time? Also, can I make a particular key press trigger different actions from Alice at different points in the game? Users of Alice might want to create worlds where events are executed conditionally. It is not difficult to control action in this way, and we will look at several examples in this tutorial.
Start by downloading this Alice world.
This world features the barest beginnings of a game where you have to complete a series of tasks in order. The first task is to help the chicken find her (somehow invisible) chick, and the second task is uncreated and unimportant for this exercise. When the first task is completed, the user (player) should press the Enter key to move on to the second task. In this world without control, you should verify that pressing enter at ANY point during the first task, and not just when you've found the chick, will cause the scene to shift to the second task. Moreover, once you've arrived at the second task, subsequent pressing of the enter key causes the chicken to repeat her statement.
Press enter at both of the below points in the game.
There then, is precisely what I mean about an Alice world without control. The enter keypress by the user has been hardwired to a method, and it will now invoke that method at any point during the game that the Enter key is pressed, regardless of situation or timing. We will fix the first issue over the course of this tutorial, and the second will be left as an exercise.
The key to control in computer programming is to use Booleans (both variables and expressions) and take certain actions only if they are what they should be at a particular time. We, as the programmers, DECIDE what they ought to be at a particular time, and then check against that condition. For this tutorial, we will begin by creating a boolean to keep track of whether or not the second task is available yet. Click on "world" in the object tree, and click the properties tab. Then click "create new variable."
A dialog box will appear, and you should type a name and select the boolean type. I've called my variable 'taskOneCompleted' to remind myself that task 2 is not supposed to start until task one is done.
Now, we want to change the starting value for this boolean to false, since presumably the game starts with the first task incompleted. To do this, simply click on true in the properties window and select "false" from the menu.
Now, we need to make it so that, when the first task is completed (you've found the chick), this boolean indicates that this is the case. Notice in the Events panel that, when the mouse is clicked on Chick, the method world.foundChick is run. This is the method we're interested in, since this is the method that handles everything after the first task is completed. Double-Click on the method in the events panel to open it, or open it from the methods tab of the world's details:
Add the statement to change the status of the taskOneCompleted boolean by dragging it into the method editor and selecting 'true.'
Now that we have our boolean set up as we want it, we want to USE to put the brakes on the Enter key response.
One way to do this would be to open up the method world.nextTask, and put all the code under it in an if statement. This works, but it is limited (in the sense that if you want to add additional functionality to the Enter key later, that one method will keep growing in size) and there is a better way. Instead, we're going to create a new method. Go under the world's methods, and click 'create new method.' I am going to call my new method "reactToEnter."
Now, drag an If/Else block into the reactToEnter method, selecting true for a default option.
Then, drag our boolean variable into and replace the "true" in the If statement:
We would like the method "nextTask" to be executed if taskOne is completed, so drag that method into the if block:
Finally, we want Alice to run reactToEnter rather than nextTask directly, so replace nextTask with reactToEnter in the events panel:
Now, when we run the program, we should move to the next task by pressing enter if we have completed the first task. Of course, you can still fix the fact that the behavior after clicking the little chicken is repeated on the second click, and that you can continue to press enter even after moving to the second level, and get some undesired behavior from the world. Try creating boolean variables to control these events. In case you're wondering how it is done, here is the file with those things fixed as well. In this file, I've also made it so that you can't start chicken-finding until the mother chicken finishes speaking.
Professor Rodger's Homepage
Main Tutorial Website
Alice Materials at Duke