Learn to Program using Alice

Events and Interactive Programming

Learn the general theory and practice behind interactive programming using events and event handlers.  Learn about all thirteen of the event types supported by Alice.  Learn how to enable events and how to register event handler methods on events.  Examine code samples that illustrate six of the thirteen available event types in Alice.

Published:  April 18, 2007
By Richard G. Baldwin

Alice Programming Notes # 190


Preface

This tutorial lesson is part of a series designed to teach you how to program using the Alice programming environment under the assumption that you have no prior programming knowledge or experience.

Have some fun

Because Alice is an interactive graphics 3D programming environment, it is not only useful for learning how to program, Alice makes learning to program fun.  Therefore, you should be sure to explore the many possibilities for being creative provided by Alice while you are learning to program using these tutorials.  And above all have fun in the process of learning.

General

In the lesson titled "Lists" (see Resources) I taught you about the differences between an array and a list, including some of the pros and cons of each.

I compared the methods and functions belonging to a list with the methods and functions belonging to an array.

I presented and explained a simple program that illustrates most of the methods and functions belonging to a list.

I presented and explained a program that illustrates the use of the following tiles from the bottom of the Alice development screen:

In this lesson, I will teach you the general theory and practice behind interactive programming using events and event handlers.  I will teach you about all of the event types supported by Alice.  I will teach you how to enable events and how to register event handler methods on events.  Finally, I will explain code samples that illustrate six of the thirteen available event types in Alice.

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Supplementary material

Once you have mastered Alice, I recommend that you also study the other lessons in my extensive collection of online programming tutorials.  You will find a consolidated index at www.DickBaldwin.com.

General background information

Alice provides a rudimentary capability for using events to write interactive programs.  While not nearly as flexible or as powerful as the capability provided by other languages such as Java and C#, this capability is entirely adequate for teaching the rudiments of interactive programming to beginning programming students.

An extremely important topic

Interactive programming using events is one of the most important topics in modern computer programming.  Every program that you use on a daily basis that involves a Graphical User Interface (GUI) probably bases its interactive capability on the detection and handling of events.  In fact, if you are less than about 23 years of age, you may never have seen a commercial program that isn't based on event handling.

What do we mean by interactive programming and handling events?

When you use a GUI, (such as the Alice development screen) to do your work, you constantly find yourself performing a variety of interactive operations, such as the following:

Similarly, when you play a computer game, you perform similar operations in the context of the game to cause the game to progress according to your wishes.

The firing of events

Each time you perform one of the actions mentioned above, (and many other actions as well), the operating system fires an event.  In some cases, it fires a single event of a given type.  In some cases it fires many events of different types, and in some cases it fires a sequence of one or more types of events, (such as when you hold a particular key down).  The author of the program has the option of responding to all of the events that are fired, or responding to some of the events and ignoring others (very few programs respond to all of the events that are fired).

Handling an event

Writing code to respond to a particular event in order to cause the program to react in a particular way is known a handling the event.  The code that is written to handle the event is commonly known as an event handler.  That code usually consists of a method in Alice.   (Some event types in Alice don't require methods as event handlers and we will see sample code for such an event type in this lesson.)  The process of connecting the event handler method to the event is often referred to as registering the handler on the event or possibly enabling the event.

Events supported by Alice

Alice programs can respond to and handle the thirteen types of events shown in Figure 1.

Figure 1. Event types in Alice.
Event types in Alice
  1. *When the world starts
  2. While the world is running
  3. *When a key is typed
  4. While  a key is pressed
  5. *When the mouse is clicked on something
  6. While the mouse is pressed on something
  7. *While something is true
  8. When something becomes true
  9. When a variable changes
  10. Let the mouse move <objects>
  11. Let the arrow keys move <subject>
  12. Let the mouse move the camera
  13. Let the mouse orient the camera

Note:  Event types in boldface are illustrated by sample code in this lesson.

A somewhat fragile system
I would be remiss if I failed to tell you that the event handling and concurrent programming system in Alice is somewhat fragile.  It is not too difficult to write Alice programs that involve event handling along with concurrent programming that should work properly but fail at runtime.  Therefore, just because your program fails at runtime doesn't necessarily mean that you have an error in your program.  You may simply have stressed the Alice event handling and concurrent programming system beyond its breaking point.  Although I don't have any statistics to back me up, it seems that the problem is worse when using the while event types than when using the other event types.  Therefore, you may want to be particularly careful when using while event types.

While this is a relatively small number of event types as compared to other programming languages, Alice supports enough different event types to make it useful for teaching the basics of interactive programming and event handling.  Learning how to handle events in Alice will get you well on your way to being able to learn how to handle events in other languages.

Creating event handlers

You begin creating event handlers in Alice by making certain that the event editor pane shown in Figure 2 is showing.  It should be visible in the upper right of the screen in program edit mode.  (Sometimes it simply disappears for some unexplained reason and is replaced by a large black area.  The only way that I have found to restore it in those cases is to terminate and restart Alice.)

Figure 2. Alice's event editor pane.

Registering event handlers

You begin the process of handling an individual event in Alice by clicking the button labeled create new event in Figure 2.  (Note that clicking the button is another example of interacting with a program on the basis of events.)

When you click that button, the menu of available event types shown in Figure 3 will appear.

Figure 3. Selecting an event type in Alice.

When you select one of the menu items in Figure 3, skeleton code for enabling the event or registering a method on the event of the selected type will appear in the event edit pane as shown by the bottom block of code in Figure 4.

Where are the other event types?

Note that the menu shown in Figure 3 shows only nine types of events, but I told you that Alice can handle the thirteen types of events listed in Figure 1.  For reasons that I am unable to explain, four of the event types shown in Figure 1 aren't available directly from the menu shown in Figure 3.  To select the events in those four cases, you must:

That will cause the skeleton for the new type of event to replace the original skeleton.  Items 1, 3, 5, and 7 in Figure 1 (each marked with an asterisk) identify the menu items in Figure 3 that must be selected to actually end up with items 2, 4, 6, and 8 in Figure 1.

Registration of a default event handler

When you create a new world in Alice and select the program edit screen, the registered event in Figure 4 named When the world starts will appear in the event edit pane by default.  (Note that you can drag this event and drop it into the trash can if you don't need it.)  As you will recall, a skeleton world-level method named my_first_method also appears in the code edit pane at that point.  That method is registered on this event by default.  (This is the method that I typically rename main to make it more consistent with Java, C++, and C#.)

Figure 4. A completed event and a skeleton event in Alice.

When you click the Play button

When you click the Play button in Alice and the program first starts running, an event of the type When the world starts occurs.  This is a one-time event.  It is never fired again during the execution of the program.

Inconsistent naming
Unfortunately, the folks who developed Alice weren't very consistent in their handling of method names, because the method named myfirstmethod in Figure 4 corresponds to the skeleton method named my_first_method.  Naming inconsistencies such as this frequently show up when working with Alice.

The default registered event handler

The registered event of the type named When the world starts shown in Figure 4 instructs the system to execute the world-level method named myfirstmethod when the event is fired.  In other words, the method named my_first_method was registered by default to be called when the event named When the world starts occurs.  This is the mechanism by which Alice connects events to the code that is written to handle them.  (This mechanism is very similar to how events are registered and handled in Java.  Note that some Alice event types do not require methods to be registered on them in order to enable the event.  I will discuss this in more detail later.)

Conceivably you could also register other methods to be called and executed concurrently when that event occurs, but be careful about doing this.  As I mentioned earlier, it is not difficult to stress the event handling and concurrent programming capability of Alice 2.0 beyond the breaking point, causing your program to fail for unexplainable reasons at runtime.

Skeleton event registration code

The bottom item in Figure 4 also shows the skeleton code for registering an event handler on the event type listed as item 4 in Figure 1 (While  a key is pressed).  To complete the registration of an event handler on this event, you need to replace the red text shown in Figure 4 with something else using typical drag-and-drop and menu-driven Alice programming procedures.

An actual matching registered event handler

For example, the fifth registered event handler from the top in Figure 2 shows the completed version of event registration for an event of this type in the program that I will explain later.  In this program, whenever the D-key (upper or lower case) is pressed and held down while the program is running, the method named dance belonging to the object named dancer will be called repeatedly.  (Unfortunately, I'm unaware of any Alice documentation that tells us how often the method will be called, but I have a pretty good idea based on many years of event-driven programming experience across a variety of languages.)

Three events under one event type name

The skeleton shown in Figure 4 actually makes it possible to register three different methods (although I only registered one method for that event type in Figure 2).  One method is called when the key is first pressed (Begin).  As mentioned above, a second method is called repeatedly while the key is held down (During).  A third method is called when the key is released (End).  If you don't specify the name of a method as a replacement for <None> no method is called when that particular event occurs.  In other words, if you don't specify methods for events that require them, the event is essentially ignored by the program.

Several of the event types shown in Figure 1, including items 2, 4, 6, and 7, actually consist of Begin, During, and End events under the umbrella of a single event name.  Therefore, the number of actual event types supported by Alice is greater than the thirteen event names shown in Figure 1.

The six registered events shown in Figure 2 are the actual registered events that I will explain in the program named Alice0190a.  They correspond to the boldface event types shown in Figure 1.

Mouse icons and a documentation problem

Note that the event types shown in Figure 2 that involve the mouse contain a picture of the mouse instead of the word mouse.  This probably seemed like a clever idea by someone at the time the Alice program was written, but in retrospect it was a bad idea.

  1. First, and probably not too important, many laptop computers don't use a mouse that looks like the pictures of the mouse shown in Figure 2.  Instead, they have a little panel at the bottom that you slide your finger on, or perhaps a little joystick in the middle of the keys.  And then there are those folks who use a trackball instead of a mouse.
  2. Second, and very important, the HTML program documentation that is generated by selecting the Export Code For Printing... item on the Alice File menu doesn't contain a picture of a mouse.  Instead, there is simply a word missing where the word mouse should appear.

So where are we?

Hopefully you now understand some of the background information on interactive programming and event handling in general.  You also know something about the procedures used to register event handlers on specific types of events or to enable specific types of events in Alice.  Therefore, the time has come to quit talking in general terms and get down to cases with an actual interactive program.

Preview

I will present and explain one program named Alice0190a in this lesson.  This program isn't intended to do anything useful other than to teach you how to write interactive event-driven programs.  Hopefully you will be able to go forward with what you have learned in this lesson and write simple games and other kinds of simple interactive programs using Alice.

The program output shortly after startup

Figure 5 is a screen shot of the program output shortly after startup.

Figure 5. Output from the program named Alice0190a shortly after startup.

The coach does jumping jack exercises

The word Events that is barely showing across the screen in large letters in Figure 5 quickly fades away.  Shortly thereafter, the Coach object in the left of the screen shot starts doing jumping jack exercises and continues doing them during the entire time that the program is running.

Dancing around the flag

If you press the D-key and hold it down, the Japanese dancer dances in a circle around the flagpole as shown in the screen shot of Figure 6.  (Note that the coach is in the middle of one of his jumping jack exercises in Figure 6.)

Figure 6. FanDancer object dancing around the flag.

Dragging the beach chair

If you point to the beach chair with the mouse and then press and hold either the left or right mouse button down, you can drag the beach chair around on the beach.  Figure 7 shows the result of dragging the beach chair from right to left and toward the foreground.

Figure 7. The BeachChair object has been dragged to the left foreground.

This is a very significant capability that would require quite a lot of programming to accomplish if you were to program it in Java3D, because the beach chair maintains the 3D perspective while it is being dragged.

An unplanned capability

Although I didn't knowingly do anything to make it happen, I discovered quite by accident that this program provides a bonus capability associated with the mouse wheel on my mouse.  If I point to any object in Figure 7 and then press and hold the mouse wheel down, dragging the mouse rotates the object around its vertical axis.  However, because I have found that the behavior of the mouse wheel varies widely on different computers running under Windows XP, (which probably has something to do with how you configure the mouse, the brand of the mouse, etc.) I don't know if this is consistent behavior for Alice on different computers.

Dragging the flag

Just like the beach chair, you can drag the flag around the screen with the mouse.  The interesting thing about this is that if you move the flag and then hold down the D-key, the dancer will initially begin dancing in a larger circle but will eventually spiral in and resume dancing around the flagpole in a circle with a radius of one meter.  Also if you move the flagpole while she is dancing, she will try to track the flagpole.  You will see the reason for this when I explain the event handling code for the dancer.  This is illustrated by the screen shots shown in Figure 8 and Figure 9.

In Figure 8, the flag was moved from its original position, causing the dancer to dance in a circle with a large radius with the flag at the center of the circle.

Figure 8. Dancer at some distance from the flag.

Spiraling back toward the flagpole

In Figure 9, the dancer has spiraled back in and is once again dancing around the flag in a circle with a radius that is very lose to one meter centered on the flagpole.

Figure 9. Dancer back close to the flag.

Clicking the hare

Figure 10 shows the result of clicking the hare.  Although you can't tell it by looking at Figure 10, in addition to displaying the comic strip bubble above the hare's head, clicking the hare with the mouse also causes the blades on the fan to start spinning.  They continue spinning until you click the hare again as shown in Figure 11.

Figure 10. Result of a mouse click on the Hare object.

Turn fan off

Figure 11 shows the result of a second mouse click on the hare.

Figure 11. Result of a second mouse click on the Hare object.

In other words, successively clicking the mouse on the hare causes the messages shown in Figure 10 and Figure 11 to be displayed and also causes the blades on the fan to first start spinning and then to stop spinning.

Time for some code

Now that you understand the general behavior of this program, it is time for us to examine the code that produces that behavior.  Note that I will concentrate on the event registration and event handling aspects of the code rather than the detailed code inside the event handler methods. You should already understand most of the code inside the event handler methods.

The source code

The source code for this program is shown in Listing 9.  In addition to the word mouse being missing from the code as explained earlier, there is something else that is missing as well.  In particular, in order for this program to work properly, it is necessary for you to manually create an empty list named moveableObjects as a property of the world.  However, this is not reflected in the source code in the same way that lists are shown when they belong to methods.  In fact, if I had manually populated that list when I created it, there would be nothing whatsoever in the source code to tell you that it exists and the nature of its contents.

Because I manually created it as an empty list and populated it with program code, an experienced programmer might be able to figure out what is going on.  However, that would probably be well beyond the capabilities of a beginning programming student.

Create your world

Create a new world and select the sand template option.  Add one each of the following objects from the local gallery to the world and give them the names shown below:

Add an empty list to the properties pane for the world and name it moveableObjects.

Don't worry about the position or orientation of any of the objects in the above list.  The code in the method named doSetup will take care of the position and orientation of each object at program startup.

Discussion and sample code

As mentioned earlier, the source code for this program is presented in Listing 9 near the end of the lesson.  An executable version of the program can be downloaded by following the links in Resources.

The Events section of the code

With two exceptions, the code in the Events section of Listing 9 reflects the information shown in the event edit panel of Figure 2.  The two exceptions are:

The two world events

Note that the first two registered events in Figure 2 are named:

As you can see, I wrote code to handle the first of the two above events, as well as the Begin and During phases of the second of the two events.  This may be a bad practice unless you are very careful.  In effect, the Begin phase of While the world is running is a replacement for When the world starts

In theory, you should probably never need to register a different method on both.  You should be able to accomplish the same thing by registering a single method on the either the first event or on the Begin phase of the second event.  In fact, this may be the explanation for why four of the event types shown in Figure 1 are missing from the menu shown in Figure 3.  This may be a message from the Alice development team that we should handle one, but not both of the events in each pair of event types in the first eight event types in Figure 1.

Why did I handle both?

I handled both events simply to illustrate this point.  When we examine the code, you will see that I was very careful to make certain that the code in the two methods that will be called and executed currently will not conflict.  In particular, the code in the main method and the code in the doSetup method, (which will execute concurrently), does not deal with the same objects.

The main method

In addition to referring to the code in Listing 9, in some cases, I will also present and discuss the program code in fragments.  The code for the main method is shown in Listing 1.

Listing 1. The main method.
  public void main ( ) {
    
       // Copyright 2007 R.G.Baldwin
  // Show 3D text for a short period fading out.
  doTogether {
       startUpText .set( color , (1, 0, 0) ); duration = 2 seconds
  startUpText .set( opacity , 0 (0%) ); duration = 3 seconds
  }
  }

As you can see, the code in the main method deals only with the 3D text object that appears and then fades away when the program starts running.  I was careful not to deal with the 3D text object in the doSetup method that is shown in Listing 2.

Beginning of the doSetup method

The method named doSetup begins in Listing 2.

Listing 2. Beginning of the doSetup method.
  public void doSetup ( ) {
    
       // Copyright 2007 R.G.Baldwin
  // Make objects invisible.
  doTogether {
       ground .set( isShowing , false ); duration = 0 seconds
  coach .set( isShowing , false ); duration = 0 seconds
  beachChair .set( isShowing , false ); duration = 0 seconds
  hare .set( isShowing , false ); duration = 0 seconds
  dancer .set( isShowing , false ); duration = 0 seconds
  flagpole .set( isShowing , false ); duration = 0 seconds
  startUpText .set( isShowing , false ); duration = 0 seconds
  fan .set( isShowing , false ); duration = 0 seconds
  }
  // Align the world.
  doTogether {
       ground .setPointOfView( world ); duration = 0 seconds
  camera .setPointOfView( world ); duration = 0 seconds
  coach .setPointOfView( world ); duration = 0 seconds
  beachChair .setPointOfView( world ); duration = 0 seconds
  hare .setPointOfView( world ); duration = 0 seconds
  dancer .setPointOfView( world ); duration = 0 seconds
  startUpText .setPointOfView( world ); duration = 0 seconds
  flagpole .setPointOfView( world ); duration = 0 seconds
  fan .setPointOfView( world ); duration = 0 seconds
  }
  // Position the camera
  doTogether {
       camera .turn( LEFT , 0.5 revolutions ); duration = 0 seconds
  camera .move( BACKWARD , 10 meters ); duration = 0 seconds
  camera .move( UP , 1 meter ); duration = 0 seconds
  }//following code deleted for brevity
  }//end of method named doSetup

You should already be familiar not only with the code in Listing 2, but also with the reasons for providing the code shown in Listing 2.  If not, see the lessons on setting the stage in Resources.

Position and pose the players

The code in Listing 3 puts each object into its startup position, orientation, and pose.

Listing 3. Position and pose the players.
  // Position and pose the players.
  doTogether {
       coach .move( RIGHT , 4 meters ); duration = 0 seconds
  coach .move( BACKWARD , 4 meters ); duration = 0 seconds
  beachChair .move( LEFT , 4 meters ); duration = 0 seconds
  beachChair .move( BACKWARD , 4 meters ); duration = 0 seconds
  hare .move( LEFT , 1 meter ); duration = 0 seconds
  hare .move( FORWARD , 3 meters ); duration = 0 seconds
  fan.spin .set( value , false );
  fan .move( LEFT , 1.5 meters ); duration = 0 seconds
  fan .move( FORWARD , 3.5 meters ); duration = 0 seconds
  fan .turn( LEFT , .45 revolutions );
  dancer .move( BACKWARD , 1 meter ); duration = 0 seconds
  startUpText .move( FORWARD , 1 meter ); duration = 0 seconds
  }

Probably the only thing worth mentioning in Listing 3 is the statement that sets the spin property of the fan to false.  The blades on the fan spin whenever this property is true, so the property value needs to be false when the program starts running so that the fan won't be spinning.

Moveable objects

The ability to drag the beach chair and the flag with the mouse results from enabling the event named Let the mouse move (item 10 in Figure 1) as the third event down from the top in Figure 2.  Unlike many other event types, it is not necessary to register a method in order to enable this event.  Rather, what is required is to identify a list that contains one or more objects that can be moved by dragging them with the mouse.

The third event down from the top in Figure 2 specifies a list named world.moveableObjects for this purpose.  You created that list as an empty list earlier during the manual setup.

Populate the list

Listing 4 adds the beachChair object and the flagPole object to that list, making them capable of being dragged with the mouse.

Listing 4. Populating the list with objects that can be dragged with the mouse.
  // Add moveable objects to the list.
  doTogether {
       world.movableObjects .add( beachChair );
  world.movableObjects .add( flagpole );
  }

Make objects visible

Up to this point, all of the activities of the objects have been invisible to the user and only a blue screen has been showing.  All of the objects have been properly positioned and oriented, and all of the objects other than the coach have been posed.  The code in Listing 5 makes all of the objects visible.

Listing 5. Make objects visible and show coach lowering his arms.
  // Make objects visible.
  doTogether {
       ground .set( isShowing , true );
  coach .set( isShowing , true );
  beachChair .set( isShowing , true );
  hare .set( isShowing , true );
  dancer .set( isShowing , true );
  flagpole .set( isShowing , true );
  startUpText .set( isShowing , true );
  fan .set( isShowing , true );
  }
  // Show coach lowering his arms.
  coach.lowerArms ( );

Cause the coach to lower his arms

When the Coach object is created from the gallery and added to the world, he has his arms outstretched on each side of his body.  I decided to make that a part of the visible animation and let the viewer see him lower his arms to his sides before beginning his exercises.  The call to the method named coach.lowerArms in Listing 5 accomplishes that.  You can view that method in Listing 9.  The code in the method is almost trivial by this point in the course of study, so it shouldn't need an explanation.

Coach does his exercises

That gets us through the explanation of the code through the Begin phase of the event named While the world is running in Figure 2.  The next thing of interest is the method that is registered on the During phase of that same event type.  During the entire time that the program is running, the method named coach.doJumpingJack is repeatedly called.  Thus, the behavior of that method is evidenced during the entire running of the program.

The behavior of the coach.doJumpingJack method is to cause the coach in Figure 5 to do jumping jack exercises.  You can view the method named coach.doJumpingJack in Listing 9.  Each time the method is called, the coach object performs one cycle of a jumping jack exercise.  Thus repeated calls to the method causes the coach to do one cycle after another producing the impression of continuous jumping jack exercises.

Although the code in the coach.doJumpingJack method is rather long and tedious, it doesn't contain anything that you haven't already learned in earlier lessons.  Therefore, it should not require an explanation.

That completes the registration operation on the first two event types in Figure 2.  In addition, I have already explained how the third event type in Figure 2 becomes enabled, so I don't need to say any more about that.

When the mouse is clicked on the hare

The fourth event registration operation shown in Figure 2 causes the method named hare.clickHandler to be called each time the mouse is clicked on the hare shown in Figure 10 and Figure 11.  The code for this method is shown in Listing 6.

Listing 6. The hare.clickHandler method.
  public void clickHandler ( ) {
    
       // Copyright 2007, R.G.Baldwin
  if ( ( fan.spin == false ) ) {
       // Fan is not spinning, make it spin.
  doTogether {
       hare .say( Turn fan on. ); duration = 2 seconds
  fan.spin .set( value , true ); duration = 0 seconds
  }
  } else {
    // Make fan stop spinning.
  doTogether {
       hare .say( Turn fan off. ); duration = 2 seconds
  fan.spin .set( value , false ); duration = 0 seconds
  }
  }
  }

Mostly straightforward

With a couple of exceptions, the code in Listing 6 is straightforward.  Those exceptions have to do with the two statements that set the value of the spin property belonging to the fan object.  As you will see later when I explain the last event registration block in Figure 2, the state of this property determines whether the fan blades spin or don't spin.  If the property value is true, the blades spin.  Otherwise, they don't spin.

Successively clicking the hare toggles the state of this property between true and false, thus controlling whether or not the fan blades spin.

The code in Listing 6 also displays the two messages shown in Figure 10 and Figure 11.  You are already familiar with the effect of calling the method named say on an object.

While D is pressed

The fifth event registration block down from the top in Figure 2 causes the method named dancer.dance to be called repeatedly while the D-key (upper or lower case) is pressed and held down.  This results from the fact that I registered that method on the During phase of that event type.  Note, however, that I didn't register any methods on either the Begin or End phases of that event type simply because there was no special behavior that was needed at the points in time when the user first presses and later releases the key.

Source code for the method named dancer.dance

The source code for this method is shown in Listing 7.

Listing 7. Source code for the method named dancer.dance.
  public void dance ( ) {
    Number distance = 1 ;
       // Copyright 2007, R.G.Baldwin
  distance .set( value , ( dancer .distanceTo( flagpole ) ) ); duration = 0 seconds
  doTogether {
       dancer .moveToward( target = flagpole , ( ( distance - 1 ) ) ); duration = 4 seconds
  dancer .turnToFace( flagpole ); duration = 0 seconds
  dancer .turn( RIGHT , 1 revolution ); asSeenBy = flagpole duration = 4 seconds style = BEGIN_AND_END_ABRUPTLY
  }
  }

Circle up the wagons

You learned how to make one object circle and face another object in an earlier lesson, so the final two statements in Listing 7 should not require an explanation.  However, the statements before that probably do deserve an explanation.

The distance to the flagpole

When you use code such as the final statement in Listing 7 to cause one object to circle another object, by default the radius of the circle will be the distance between the two objects when the statement is executed.  In this case, I wanted the dancer to circle the flagpole at a distance of one meter from the flagpole.

Recall, however, that it is possible to drag the flagpole with the mouse and increase or decrease the distance between the flagpole and the dancer.  This can be done while the dancer is dancing, or while the dancer is at rest.

Repeatedly circle the flagpole

The last statement in Listing 7 causes the dancer to complete one revolution around the flagpole each time the method is called.  Because the type of event on which this method is registered causes the method to be called repeatedly while the D-key is held down, the effect is to cause the dancer to circle the flagpole continuously while the D-key is held down.

Calculate the distance to and spiral toward or away from the flagpole

Each time the method is called, the first statement in Listing 7 calculates the distance from the dancer to the flagpole.  The first statement inside the doTogether block in Listing 7 causes the dancer to move toward or away from the flagpole (a negative distance causes a move away from) by a distance that will place the dancer at a distance of one meter from the flagpole.  As a result, if you move the flagpole some distance away from the dancer and hold the D-key down, she will spiral in toward the flagpole and after a few revolutions will be circling the flagpole at a distance of about one meter from the flagpole.

If you move the flagpole and hold the D-key down at the same time, she will attempt to track the flagpole and may or may not be successful, depending on how fast you are moving the flagpole.  An interesting experiment is to hold the D-key down and try to place the flagpole at the same location as the dancer.

While fan.spin is true

The last event shown in Figure 2 causes the fan blades to spin whenever the property named spin belonging to the fan is true.  As I explained earlier, successively clicking the hare causes this property value to toggle between true and false.

This behavior of the fan is controlled by the last event registration block in Figure 2.  As with all but one of the events that I handled in this program, this event type requires the registration of from one to three event handler methods.  In this case, the behavior that I wanted to see could be achieved simply by registering one of the primitive methods belonging to the fan, and it was not necessary for me to write a special event handler method.  Listing 8 shows the registration of the roll method on the During phase of the While fan.spin is true event type.

Listing 8. Registration of the roll method on the While fan.spin is true event type.
While fan.spin is true
Begin: Nothing
During:
fan.blades .roll( LEFT , 1 revolution ); duration = 1 second style = BEGIN_AND_END_ABRUPTLY
End: Nothing

As a result of the code in Listing 8, the roll method belonging to the fan will be called repeatedly during any periods that the value of the fan.spin property is true.  Each call to the method causes the fan blades to spin through one revolution.  Repeatedly calling the method causes it to appear that the fan blades are spinning continuously.

Run the program

An executable version of the program that I explained in this lesson is available for downloading (see Resources).  I encourage you to either download the program, or copy the code from Listing 9 into your Alice development environment and run the program.  Experiment with the code, making changes, and observing the results of your changes.  Above all, have fun in the process.

Summary

In this lesson, I taught you about the general theory and practice behind interactive programming using events and event handlers.  I provided a brief explanation of all the event types supported by Alice.  I explained how to enable events and how to register event handler methods on events using the event edit panel.  I presented and explained code samples to illustrate six of the thirteen available event types in Alice.

What's next?

In future lessons I will teach you about the following topics and perhaps some other topics as well:

So stay tuned.  There will be lots of fun ahead.

Resources

General resources

Resources from earlier lessons in the series titled "Learn to Program using Alice"

Downloads

Complete program listing

A complete listing of the program discussed in this lesson is shown in Listing 9 below.

Listing 9. Source code for the program named Alice0190a.

Alice0190a's Code

Created by: Dick Baldwin

world

Events

When the world starts
Do:
world.main ( );


While the world is running
Begin:
world.doSetup ( );
During:
coach.doJumpingJack ( );
End: <None>


Let move world.movableObjects


When is clicked on hare
Do:
hare.clickHandler ( );


While D is pressed
Begin: <None>
During:
dancer.dance ( );
End: <None>


While fan.spin is true
Begin: Nothing
During:
fan.blades .roll( LEFT , 1 revolution ); duration = 1 second style = BEGIN_AND_END_ABRUPTLY
End: Nothing


Methods

  public void main ( ) {
    
       // Copyright 2007 R.G.Baldwin
  // Show 3D text for a short period fading out.
  doTogether {
       startUpText .set( color , (1, 0, 0) ); duration = 2 seconds
  startUpText .set( opacity , 0 (0%) ); duration = 3 seconds
  }
  }


  public void doSetup ( ) {
    
       // Copyright 2007 R.G.Baldwin
  // Make objects invisible.
  doTogether {
       ground .set( isShowing , false ); duration = 0 seconds
  coach .set( isShowing , false ); duration = 0 seconds
  beachChair .set( isShowing , false ); duration = 0 seconds
  hare .set( isShowing , false ); duration = 0 seconds
  dancer .set( isShowing , false ); duration = 0 seconds
  flagpole .set( isShowing , false ); duration = 0 seconds
  startUpText .set( isShowing , false ); duration = 0 seconds
  fan .set( isShowing , false ); duration = 0 seconds
  }
  // Align the world.
  doTogether {
       ground .setPointOfView( world ); duration = 0 seconds
  camera .setPointOfView( world ); duration = 0 seconds
  coach .setPointOfView( world ); duration = 0 seconds
  beachChair .setPointOfView( world ); duration = 0 seconds
  hare .setPointOfView( world ); duration = 0 seconds
  dancer .setPointOfView( world ); duration = 0 seconds
  startUpText .setPointOfView( world ); duration = 0 seconds
  flagpole .setPointOfView( world ); duration = 0 seconds
  fan .setPointOfView( world ); duration = 0 seconds
  }
  // Position the camera
  doTogether {
       camera .turn( LEFT , 0.5 revolutions ); duration = 0 seconds
  camera .move( BACKWARD , 10 meters ); duration = 0 seconds
  camera .move( UP , 1 meter ); duration = 0 seconds
  }
  // Position and pose the players.
  doTogether {
       coach .move( RIGHT , 4 meters ); duration = 0 seconds
  coach .move( BACKWARD , 4 meters ); duration = 0 seconds
  beachChair .move( LEFT , 4 meters ); duration = 0 seconds
  beachChair .move( BACKWARD , 4 meters ); duration = 0 seconds
  hare .move( LEFT , 1 meter ); duration = 0 seconds
  hare .move( FORWARD , 3 meters ); duration = 0 seconds
  fan.spin .set( value , false );
  fan .move( LEFT , 1.5 meters ); duration = 0 seconds
  fan .move( FORWARD , 3.5 meters ); duration = 0 seconds
  fan .turn( LEFT , .45 revolutions );
  dancer .move( BACKWARD , 1 meter ); duration = 0 seconds
  startUpText .move( FORWARD , 1 meter ); duration = 0 seconds
  }
  // Add moveable objects to the list.
  doTogether {
       world.movableObjects .add( beachChair );
  world.movableObjects .add( flagpole );
  }
  // Make objects visible.
  doTogether {
       ground .set( isShowing , true );
  coach .set( isShowing , true );
  beachChair .set( isShowing , true );
  hare .set( isShowing , true );
  dancer .set( isShowing , true );
  flagpole .set( isShowing , true );
  startUpText .set( isShowing , true );
  fan .set( isShowing , true );
  }
  // Show coach lowering his arms.
  coach.lowerArms ( );
  }


coach

Methods

  public void doJumpingJack ( ) {
    
       // Copyright 2007 R.G.Baldwin
  // Causes coach to complete one cycle of a jumping jack.
  // Intended to be called While the world is running.
  // Up
  doTogether {
       coach.upperBody.rightArm .roll( LEFT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.upperBody.leftArm .roll( RIGHT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.rightLeg .roll( LEFT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.leftLeg .roll( RIGHT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach .move( UP , 0.5 meters ); duration = 0.5 seconds style = BEGIN_AND_END_GENTLY
  }
  // Down
  doTogether {
       coach.upperBody.rightArm .roll( LEFT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.upperBody.leftArm .roll( RIGHT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.rightLeg .roll( LEFT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.leftLeg .roll( RIGHT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach .move( DOWN , .55 meters ); duration = 0.5 seconds style = BEGIN_AND_END_GENTLY
  }
  // Up
  doTogether {
       coach.upperBody.rightArm .roll( RIGHT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.upperBody.leftArm .roll( LEFT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.rightLeg .roll( RIGHT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.leftLeg .roll( LEFT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach .move( UP , 0.55 meters ); duration = 0.5 seconds style = BEGIN_AND_END_GENTLY
  }
  // Down
  doTogether { . . . . . }
       coach.upperBody.rightArm .roll( RIGHT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.upperBody.leftArm .roll( LEFT , .25 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.rightLeg .roll( RIGHT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach.leftLeg .roll( LEFT , .0625 revolutions ); style = BEGIN_AND_END_ABRUPTLY duration = 0.5 seconds
  coach .move( DOWN , 0.5 meters ); duration = 0.5 seconds style = BEGIN_AND_END_GENTLY
  }
  }


  public void lowerArms ( ) {
    
       // Copyright 2007 R.G.Baldwin
  // Put coach in initial pose with arms down.
  doTogether {
       coach.upperBody.leftArm .roll( LEFT , 0.25 revolutions );
  coach.upperBody.rightArm .roll( RIGHT , 0.25 revolutions );
  }
  }


hare

Methods

  public void clickHandler ( ) {
    
       // Copyright 2007, R.G.Baldwin
  if ( ( fan.spin == false ) ) {
       // Fan is not spinning, make it spin.
  doTogether {
       hare .say( Turn fan on. ); duration = 2 seconds
  fan.spin .set( value , true ); duration = 0 seconds
  }
  } else {
    // Make fan stop spinning.
  doTogether {
       hare .say( Turn fan off. ); duration = 2 seconds
  fan.spin .set( value , false ); duration = 0 seconds
  }
  }
  }


dancer

Methods

  public void dance ( ) {
    Number distance = 1 ;
       // Copyright 2007, R.G.Baldwin
  distance .set( value , ( dancer .distanceTo( flagpole ) ) ); duration = 0 seconds
  doTogether {
       dancer .moveToward( target = flagpole , ( ( distance - 1 ) ) ); duration = 4 seconds
  dancer .turnToFace( flagpole ); duration = 0 seconds
  dancer .turn( RIGHT , 1 revolution ); asSeenBy = flagpole duration = 4 seconds style = BEGIN_AND_END_ABRUPTLY
  }
  }

 


Copyright

Copyright 2007, Richard G. Baldwin.  Faculty and staff of public and private non-profit educational institutions are granted a license to reproduce and to use this material for purposes consistent with the teaching process.  This license does not extend to commercial ventures.  Otherwise, reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP).  His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments.  (TI is still a world leader in DSP.)  In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com

-end-