Published: November 6, 2007
Updated: October 27, 2007
By Richard G. Baldwin
Alice Programming Notes # 930
This document serves as an appendix to a series of programming tutorial lessons that are designed to teach you how to program using the Alice programming environment under the assumption that you have no prior programming knowledge or experience. In case you have happened upon this document as a result of a web search, an index to all of the material contained in the series is available in Resources.
A work in progress
From time to time I receive email requests, or see requests posted in the Alice forum for information on how to solve a particular programming problem using Alice. My plan is to respond to some of those requests by providing sample programs in this appendix. Therefore, this document is a work in progress that will be updated as such requests are received and honored.
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. Note that because material will be added to this document from time to time, the figures and the listings may not be in numeric order in the body of the document.
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.
One of the earliest computer games that I recall seeing during my lifetime is a simple game involving the trajectory of a projectile. The computer-game magazines of the sixties contained numerous such programs written in BASIC and other early programming languages. I have recently seen several requests for information on how to program the trajectory of a projectile.
Many applications
The use of a ballistic trajectory has many applications in programming games. For example, the path of a basketball after leaving the player's hands is probably a very close approximation to an idealized ballistic trajectory. The same holds true for the path of the human cannonball at the circus, (which I just witnessed this past weekend). An interesting animation would be to create a human cannonball using a Coach object from the gallery and finding something in the gallery that looks like a net to catch the coach.
|
The equations of motion
The first challenge in writing such a program is understanding the equations of motion for a projectile. An excellent treatment is of the equations of motion is referenced in the accompanying sidebar.
The animation program
The Alice animation program shown in Listing 1 causes a safe (of the money storage variety) to be shot as a projectile across the screen in a two-dimensional universe. The user specifies the launch angle relative to the horizontal axis. Screen shots from this program are somewhat less than exciting, so I didn't provide any. You can download a zip file containing the Alice world for this program, extract the world file from the zip file, load the world into your Alice programming environment, and play it to see the animated trajectory.
Improvements to the program
Paraphrasing the opening scene from an old TV show, your challenge, if you choose to accept it, is to extend this projectile-trajectory program into three dimensions. If you are really ambitious, you could also add the effects of wind at some fixed velocity blowing from some particular direction in 3D space.
If you load and run the 2D projectile trajectory program you may find it to be a little jerky, depending on the speed of your computer. This is because computing and rendering the parabolic trajectory at a large number of closely spaced points places a significant computational load on the computer.
A smoother animation
This program produces an approximate trajectory that should run smoothly on most computers that are capable of running Alice programs. While this trajectory is circular rather than being parabolic like a true ballistic trajectory, it is close enough that it should be suitable for most Alice animations. When viewed in three dimensions, it is very difficult to tell the difference between this approximate trajectory and a true ballistic trajectory unless the viewer's line of sight is exactly perpendicular to the plane of the trajectory.
The source code
The source code for this program is shown in Listing 6. The actual trajectory is produced by the two statements shown in Figure 7. These two statements were copied from the method named jump belonging to the fish class in Listing 6.
Figure 7. Trajectory code.
fish.move(FORWARD,length meters); style = BEGIN_AND_END_ABRUPTLY duration = 2.5 seconds fish.turn(FORWARD,0.25 revolutions); style = BEGIN_AND_END_ABRUPTLY duration = 2.5 seconds |
Note that the two statements in Figure 7 (along with some other code) are inside a doTogether block so that they will execute concurrently:
Catching a bug
Figure 8 shows an image of a fish that has launched itself from the water in a long arc-shaped trajectory in an attempt to catch and eat a bug.
Figure 8. Jumping fish going after a bug.
|
|
Initially, the blue (forward) axis of the fish is rotated upward by 45 degrees. The first statement in Figure 7 causes the fish to launch itself from the water at an angle of 45 degrees.
What produces the circular arc?
As the fish moves forward, the second statement in Figure 7 causes the fish to continuously rotate its blue axis downward toward the water. Because it is continuously moving in the direction of the blue axis, this motion describes a circular arc with the fish entering the water at an angle of 45 degrees. This approximate trajectory is circular instead of parabolic as in the case of a true ballistic trajectory. However, this approach takes advantage of several primitive capabilities of Alice resulting in a smoother animation than is the case with the earlier trajectory program.
A rather long program
Although the code that actually creates the trajectory is very short, the entire program shown in Listing 6 is rather long. This results from the creation and animation of five similar bugs that fly around above the water as shown in Figure 8. The bugs fly in a random manner, but one of the bugs has a predisposition to get closer and closer to the water. When that bug lands on the water, the fish launches itself from some distance away and eats the bug.
You can download and play this world (see Resources).
The previous discussion of an approximate trajectory program was designed to be a lot of fun, but was short on mathematics and technical details. Furthermore, some of the parameters used in the animation were designed to simply look good and were not based on mathematical accuracy. Now it is time to step back and take a look at the mathematics involved and to show you how to compute the required parameters as a function of target distance and launch angle.
Implementing a parabolic arc in Alice
Recall that you learned earlier that the ballistic trajectory of a projectile under the influence of gravity (ignoring air resistance) is a parabolic arc. However, Alice does not provide a primitive method for moving a projectile in a parabolic arc. Therefore, it is necessary to write the code to move the projectile in short increments so that the overall shape of the trajectory is a parabolic arc. This places a significant computational load on the computer and may cause the performance to be poor on some computers.
|
A reasonable approximation
Alice provides two primitive methods that, when used together, make it possible to move a projectile in a circular arc with very smooth animation on most computers. The circular arc is a reasonable approximation of a parabolic arc, particularly when viewed as a three-dimensional animation. In 3D, it is difficult to visually distinguish between the circular arc and a parabolic arc unless the viewer's line of sight is perpendicular to the plane of the arc.
Computing the arc length
In order to use the circular arc as an approximation of a parabolic trajectory, it is necessary to compute the length of the arc as a function of the launch angle and the distance to the target. This program will show you how to do that.
Some screen shots
Before getting into the technical details, lets look as some screen shots taken from the program while it is running. Figure 9 shows shows the projectile in the aiming phase during which the launch angle is being established.
Figure 9. Projectile aiming phase.
|
|
For this program, the flashlight object on the left in Figure 9 represents the projectile. The flashlight object on the right represents the target, and the vertical magician's wand on the left is there simply to mark the launching point of the projectile for later reference.
The projectile in flight
Figure 10 shows the projectile in flight. In Figure 10, the projectile is tangent to an invisible circular arc that intersects the point where the wand intersects the white line on the left (the launching point) and also intersects the point where the target intersects the white line on the right.
Figure 10. Projectile in flight.
|
|
The center point of the circle (of which the circular arc is a part) is somewhere below the white line midway between the launching point and the target. The radius of the circle is greater than the distance between the launching point and the target.
The segment of the white line that connects the launching point to the target is a chord of the circle. The actual distance that the projectile must travel along the circular arc to reach the target is the arc length or length of the arc.
Projectile impact on target
Figure 11 shows a screen shot of the projectile after it has impacted the target.
Figure 11. Projectile impact on target.
|
|
Ideally the projectile, the target, and the white line would intersect at exactly the same point. The fact that they don't probably indicates some computational inaccuracies in the evaluation and execution of the two statements shown in Figure 7.
The required parameters
In order to cause the projectile to impact the target for a given launch angle and target distance, the value of length shown in the first statement in Figure 7 must equal the arc length. The turning angle in the second statement in Figure 7 must be twice the launch angle.
Formula for computing arc length
If we represent the distance between the launching point and the target to be a chord of the circle, and represent the launch angle as angle, we can compute the arc length using the formula given in Figure 12.
Figure 12. Formula for computing arc length.
arcLength = (pi * chord * angle)/(180 * sin(angle)) |
If you are familiar with trigonometry, you should be able to derive this formula on your own. If not, just accept it as fact.
Behavior of the program
This program requests the target distance and the launch angle from the user. Then it computes the arc length and causes the projectile to move in a circular arc to impact the target as shown in the screen shots of Figures 9, 10, and 11.
Remember, even though the projectile will impact the target for launch angles greater than 45 degrees, the trajectory produced by such launch angles is a very poor approximation of the parabolic trajectory of a ballistic missile.
You can demonstrate this by running the program with a target distance of eight meters and a launch angle of 120 degrees as shown by the screen shot in Figure 13. In this case, the projectile is launched in the wrong direction but still impacts the target.
Figure 13. Trajectory of a cruise missile.
|
|
You can download and run this program (see Resources).
I recently received an email message from a man who was thinking about teaching his twelve-year old son how to program using Alice. As an example of the kinds of programs that he might teach his son to write, he asked if Alice would be suitable for writing a simple game that can be used to teach a younger child how to learn their multiplication tables. I responded in the affirmative and decided to write such a program myself and present it to my young grandchildren who will be learning their "times tables" in preschool this year. A complete listing of the program is provided in Listing 2. A downloadable version of the world is provided in Resources.
|
Posing the multiplication problem
The program begins by presenting a multiplication problem to the student, expecting the student to enter the product of the two numbers in the text field as shown in Figure 1.
Figure 1. Presentation of multiplication problem to student.
|
|
A correct answer
If the student enters the correct answer, the program plays an audible moo sound, the cow moves her head up and down in an affirmative gesture, and the word Correct appears on the screen as shown in Figure 2.
Figure 2. Multiplication program output for correct answer.
|
|
An incorrect answer
If the student enters an incorrect answer:
Figure 3. Multiplication program output for incorrect answer.
|
|
A new multiplication problem
After a short time period, the program presents a new multiplication problem to the student as shown in Figure 1. The student should enter a value of 1000 to terminate the program.
Not a game of Doom ...
For teenagers accustomed to modern video games, the behavior of this game is clearly very simplistic. However, the behavior of this game was not intended for teenagers, it was intended for preschoolers.
Illustrates fundamental programming concepts
An examination of the code in Listing 2 will show that this simple program illustrates many fundamental programming concepts including types, variables, loops, relational operators, and if-else selection statements. Therefore, while the behavior of the game may be simplistic, the structure of the program should be useful in teaching students (even teenagers) how to write Alice programs.
Listing 3 provides the source code for an addition game based on the concepts explained for the multiplication game above.
Listing 4 provides the source code for a subtraction game based on the concepts explained for the multiplication game above.
Listing 5 shows the source code for a drag race game. Note that the first two events in Listing 5 should read as follows:
Unfortunately, the word mouse is not preserved in this source code listing format.
Drag race game at startup
Figure 4 shows an image of the game at startup. Two cars are at the starting line with instructions to the user to click on a car to start the race.
Figure 4. Drag race game at startup.
|
|
By clicking a particular car, the player not only starts the race, but also predicts which car will win the race.
Drag race game during running of Christmas tree lights
From what I read, drag races are started by running a drag strip "Christmas tree" through several colors of lights with the green light being the signal to start moving down the track.
When the user clicks on one of the cars, a simulated drag strip "Christmas Tree" cycles through red, yellow, and green as shown by the yellow circle in Figure 5.
Figure 5. Drag race game during running of Christmas tree lights.
|
|
When the Christmas tree turns green, the two cars start moving down the track.
A while loop and a random number generator are used to control the motion of each car. During each iteration of the while loop, each car moves forward by a random distance ranging from 0.5 to 1.5 meters.
Crossing the finish line
When one (or both) car crosses the finish line during an iteration of the while loop, the loop terminates and the motion of both cars stops. The winner is determined to be the car that went the greatest distance beyond the finish line before stopping as shown in Figure 6.
Figure 6. Drag race game at end of game.
|
|
The text at the bottom of Figure 6 shows which car won, and also shows whether or not the player correctly predicted the winner by clicking on the car that won the race.
Method parameters of type Object
When you define a new method, you can declare the method parameters to be any of the following types:
A parameter of type Object
If you need to pass the light object, the ground object, or any object that was created from the gallery to a method, you need to define the parameter in your method as type Object.
You can only pass objects that appear in the object tree or <None> to the method. You cannot pass the world object to the method.
What can the code in the method do with the parameter?
The issue under discussion in this section centers on what the code in the method can do with the incoming parameter of type Object when the method is called and begins execution.
One of the things that the code in the method can do is to directly call any one of sixteen primitive methods on the parameter.
Another thing that the code in the method can do is to use the parameter to set the values for the following five properties:
Another thing that the code in the method can do is to set the value of the parameter so that it actually represents a different object from the object that was passed as a parameter when the method was called.
There is at least one other thing that the code in the method can do with the parameter that I will explain shortly.
What the code in the method cannot do with the parameter
One of the things that the code in the method cannot do is to use the parameter to directly call any of the custom methods belonging to the object that was passed as a parameter. This is a serious restriction. As you will see later, however, there is a way to at least partially work around this restriction.
A similar situation in Java?
In an attempt to put this situation in perspective, I am going to discuss and explain a similar situation in Java, which is the underlying language for Alice.
Java also contains a class named Object. This class is the root of the entire class inheritance hierarchy. The Object class defines eleven methods and no variables. It is perfectly legal to pass an object's reference to a method as a parameter of type Object. However, I often tell my students that when that is done there are only twelve things that the code in the method can do with the incoming parameter:
What is not possible?
It is not possible to use the method parameter of type Object in Java to call any of the methods defined in the class from which the object was instantiated (other than the eleven methods inherited from Object) without first using a cast operator to change the type of the parameter.
The mechanics of the cast operation
If the actual type of the incoming object reference is known when the program is written, it is a simple matter to cast it to the actual type of the object.
If the actual type of the incoming object reference is not known when the program is written, but it is known that the actual type is one of a finite number of possible types, it is possible to use the instanceof operator to determine the actual type of the object reference and to apply an appropriate cast operator to change the type of the reference to the actual type of the object at runtime.
Getting back to Alice...
Earlier in this document, I explained some of the things that the code in an Alice method can do with an incoming parameter of type Object, and I promised to explain one other option later. The time has come to explain that other option.
While there is no cast operator and no instanceof operator in Alice, it is possible to use the Alice equality operator (==) to determine if an incoming method parameter of type Object refers to a specific object. This is illustrated in Listing 8 where a test is made to determine if the parameter named obj refers to an object named cow.
Listing 8. Testing an Object parameter for equality to a specific object.
| if ( ( obj == cow ) ) { | |
| cow.dance ( ); | |
| } else { | |
Calling custom methods
If the parameter does refer to a specific object, code can then be written to call custom methods on that object. In Listing 8, the custom method named dance is called on the cow object after determining that the method parameter refers to the cow object.
Similar to the use of instanceof in Java
Note that this is similar to, but different from using the instanceof operator in Java to determine the actual type of an incoming parameter before applying a cast operator followed by a call to a custom method. The Java instanceof operator is used to determine if the incoming parameter is of a particular type (not to determine if the parameter refers to a specific object). The Alice code in Listing 8 determines if the incoming parameter refers to a specific object.
Java approach is somewhat more general
Because objects can be created and destroyed at runtime in Java on the basis of many different runtime conditions, the Java programmer doesn't know about specific objects when the program is written. Therefore, the Java programmer must deal with objects at the more general class level when resolving parameters of type Object.
All Alice objects are known to the programmer
However, all objects in an Alice world must be created when the program is written and before the program is run. Therefore, the Alice programmer knows about the existence of every object in the Alice world.
Although it may be somewhat cumbersome, the Alice programmer can use code similar to that shown in Listing 8 to determine which of the objects in the world was actually passed as a parameter to the method, and can then call custom methods on that specific object in the body of the if-else statement.
A program named ObjectParameters01
Figure 14 shows a screen shot of a program named ObjectParameters01.
Figure 14. Screen shot from the program named ObjectParameters01.
|
|
Program behavior
The main method calls a world method named makeObjectsDance four times in succession. The first three calls to the method pass the cow and each of the two penguins as parameters of type Object. The fourth call passes the ground as a parameter of type Object.
The makeObjectsDance method
The makeObjectsDance method begins by calling the primitive turn method directly on the incoming parameter each time it is called. This code is shown in Listing 10, which contains the entire program listing. Nothing special is required to use the incoming parameter of type Object to call any of the sixteen primitive methods mentioned earlier.
Identifying the objects and calling the custom methods
Then the makeObjectsDance method uses the incoming parameter to identify the object that is referenced by the incoming parameter. It calls the custom dance method on the cow and each of the two penguin objects after determining that those are the objects referred to by the incoming parameter of type Object. This is shown by the code fragment in Listing 9.
Listing 9. Calling custom methods on a parameter of type.
| if ( ( obj == cow ) ) { | |||
| cow.dance ( ); | |||
| } else { | |||
| if ( ( obj == penguin1 ) ) { | |||
| penguin1.dance ( ); | |||
| } else { | |||
| if ( ( obj == penguin2 ) ) { | |||
| penguin2.dance ( ); | |||
| } else { | |||
| // Cause the parameter to point to the camera | |||
| // instead of the ground. Note that the ground | |||
| // was caused to turn at the beginning of this method. | |||
| ground .say( No match. Make the parameter point to camera instead of ground. ); duration = 3 seconds | |||
| obj .set( value , camera ); | |||
| obj .turn( LEFT , 1 revolution ); asSeenBy = cow | |||
| } | |||
| } | |||
| } | |||
The dance method belonging to each object causes the object to step forward, do a little dance, and then return to its position in the line. The program also causes some text bubbles to appear on the screen to explain what is happening as the program executes.
Changing the value of the parameter
The last call to the makeObjectsDance method in the main method passes the ground object as a parameter of type Object. This results in the final else clause in Listing 9 being executed. The code in the else clause calls the set method on the incoming parameter to change its value. Following the call to the the set method, the parameter refers to the camera instead of the ground, which was actually passed as a parameter.
Then the primitive turn method is called on the modified parameter. This causes the camera (not the ground) to fly around the cow, making one complete revolution around the cow and ending up where it started.
List items of type Object
When you store objects in a list as type Object and later extract items from the list, you encounter a situation very similar to that discussed above regarding a parameter of type Object. You cannot directly call custom methods on the list items when you extract them from the list. However, you can use the same technique shown above to identify the object referenced by a list item and then call custom methods on that object. This is illustrated by the program named ObjectListItem01, which is presented in Listing 11.
This program is very similar to the program named ObjectParameters01 that I explained above. Therefore, the program named ObjectListItem01 shouldn't require further explanation.
You can download a zip file containing both of these programs (see Resources).
To progress beyond Alice in 3D programming, students will need to get beyond thinking in terms of moving forward, backward, left, right, up, and down. They will need to start thinking in terms of the 3D coordinates x, y, and z. However, the methodology for programming using coordinates in Alice is somewhat obscure. Furthermore, there is an apparent bug in Alice that makes programming using 3D coordinates even more complicated than it would otherwise need to be.
In this section, I will show you how to move an object to a new location in 3D space using either absolute or relative coordinates. Movement in absolute coordinates refers to movement relative to the origin of the world. Movement in relative coordinates refers to movement relative to the object's current position along each of the three axes in 3D space. Unlike the use of the primitive move method, neither absolute nor relative movements depend on the current orientation of the object. Also, the orientation of the object is not changed when the object is moved.
The program named Vector01
Listing 12 contains a complete listing of a program named Vector01. I won't provide a screen shot for this program because all it would show is a penguin and a magician's wand in 3D space. You need to run the program and view the animation to appreciate it. See Resources for a link to download a zip file containing this program.
The purpose of this program is to illustrate the use of the following methods to move an object on the basis of 3D coordinates:
Behavior of the program
This program places the ground, a penguin, and a magician's wand at the origin of the world. The wand is used solely to provide a visual marker for the origin of the world when the penguin moves away from the origin.
The main method
The main method is shown in Listing 13.
Listing 13. The main method for Vector01.
|
|||||||||||||||||||||||
Making an absolute move
The program begins by setting the stage to cause the camera and the other objects to assume their initial positions. Then it calls the method named vectorMoveAbs to cause the penguin to move to a position specified by the following coordinates:
x = 3, y = 2, z = 1
The duration and style of the move are controlled by parameters passed to the method.
Pause the action
Then the program pauses for one second to allow the user to visually absorb what has just happened. (Pauses are inserted at several points during the running of the program for that purpose.)
Move back to the origin
Following the pause, the main method calls the vectorMoveAbs method again to cause the penguin to move back to the origin specified by the following coordinates:
x = 0, y = 0, z = 0
Another absolute move
Following another pause, the vectorMoveAbs method is called to cause the penguin to move to:
x = -1, y = 2, z = 3
Move relative
Then the vectorMoveRel method is called to cause the penguin to move by the following incremental amounts relative to its current position:
dx = 0.75, dy = -1, dz = -1
Another pause
This is followed by another pause. Then the vectorMoveRel method is called again to cause the penguin to move by the following incremental amounts relative to its current position:
dx = 0.25, dy = -1, dz = -2
That relative move causes the penguin to end up back at the origin..
The method named vectorMoveAbs is shown in Listing 14. The purpose of this method is to move an object to a position in 3D space specified by x, y, and z coordinates without changing the orientation of the object.
Listing 14. The method named vectorMoveAbs
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||
Dealing with the style
The most complicated thing about this method is the code required to handle the style (treatment at the beginning and the end of the move). Had I been satisfied to accept the default style value for the moveTo method, the entire vectorAbsMove method would have consisted of only about three statements.
Map style to numeric values
It is not possible to declare a parameter of type style so that the user can pass the desired style directly to the vectorAbsMove method. Therefore, it was necessary to map the four different style types into the following numeric values:
Method parameters
The vectorAbsMove method requires the following six incoming parameters:
Construct a vector and make the move
The incoming x, y,and z values are used to construct a vector, which is used in a subsequent call to the moveTo method to establish the position, (relative to the origin of the world), that the object will be moved to by the moveTo method.
The method named vectorMoveRel is shown in Listing 15. The purpose of this method is to move an object by an incremental amount in 3D space relative to its current position. Values are specified for x, y, and z, which will cause the object to be moved by those incremental distances along the corresponding axes. The orientation of the object is not changed.
Listing 15. The method named vectorMoveRel
| ||||||||||
Method parameters
This method requires the following six parameters:
The method in action
The method begins by calling the getPosition method on the object to get its current absolute coordinates. Then it uses those coordinates along with the incoming parameter values to compute a new set of absolute coordinates for the object. Finally, it calls the vectorMoveAbs method described above to move the object. Therefore, the vectorMoveRel method must have access to the vectorMoveAbs method to function properly.
As mentioned earlier, you will find a link in Resources to download a zip file containing this program.
I have seen several postings on the Alice Community Forum asking how to save a method or function and use it in future programs. One solution is to create and save a library class containing methods, functions, and properties. It is a simple matter to save the class in the local gallery. Then you can add an object of that class to future programs that need access to the methods, functions, and constants stored there.
The procedure for creating a library class
The procedure for creating a library class is as follows. Choose the smallest class that you can find in the gallery. The smallest class that I have been able to find in the gallery is a MagicianWand, which has a size of 9 kb.
Create an object from that class and add it to an Alice world. Make the object invisible by setting its isShowing property to false. Rename the object to Library in the object tree.
Create a folder (thumbnail) in the local gallery
Create a new folder named A-Custom on your hard disk with the following path:
C:\...\Alice\Required\gallery\A-Custom
This will create a new folder (thumbnail) in your local gallery in which you can store your new Library class and other new classes that you may create as well.
Create new methods, functions, and properties and save the class
Create new methods, functions, and properties for the Library object. Once you have created and tested your methods, functions, and properties, right click on Library in the object tree. Select save object... from the popup menu. Follow the instructions to save your new class in the folder named A-Custom as described above.
The next time you start Alice, your new library class should appear in your local gallery in a thumbnail named A-Custom.
Updating the library
As time goes on, you can add new methods, functions, and properties to the class by:
Over time, you should be able to create a very useful collection of custom methods, functions, and properties.
Using methods, functions, and properties from the library
To use these custom methods, functions, and properties in a future program, simply create a new object of the Library class and add it to the new world.
I can envision at least three different kinds of methods and functions that would be appropriate for saving in the Library class.
Methods and functions that apply to all objects...
Methods and functions that require an object as a parameter and can be applied to any object created from the gallery would be appropriate for including in the Library class. The sample program named Library01 (see Listing 16) contains two such methods named vectorMoveAbs and vectorMoveRel. (I developed and explained these two methods earlier in this lesson.)
Functions that apply to no object in particular...
Functions that don't apply to any object in particular but are similar to the primitive functions belonging to the world would also be appropriate for inclusion in the Library class. See the function named degreesToRev in Listing 16 for example. This function accepts an incoming parameter in degrees and returns a value in revolutions corresponding to that number of degrees. (Recall that one revolution equals 360 degrees.)
Methods and functions that apply to a specific object
The methods and functions described above can be called directly on the Library object and are very convenient to use. It may also be useful to include methods and functions in the Library class that apply to a specific object . They would be less convenient to use, but would still be more convenient than re-writing them every time they are needed. In this case, it would be necessary to use the Alice clipboard and copy the method or function from the Library object to some other object.
In this case, the Library class would serve simply as a convenient repository for saving a method that will need to be copied to another object later. The ability to create an object of the Library class in the new world would facilitate the ability to copy the method or function to another object. Once the method or function has been successfully copied to another object in the new world, the object of the Library class could be deleted from the world to reduce its overall memory requirements.
The Library class is also useful for storing frequently used constants, such as the mathematical constant PI. Curiously, there is no world function named PI or anything similar, although the value of PI can be easily obtained by calling the Math.toRadians method on the world passing 180 degrees as a parameter. (I wonder how many Alice students are aware of the relationship between degrees and radians.)
The program named Library01
The program named Library01 demonstrates the use of a Library class containing:
The program doesn't demonstrate the use of methods or functions that must be copied to some other object as described above.
Listing 17 shows the main method for the program named Library01.
Listing 17. The main method for the program named Library01.
|
||||||||||||||||||
Description of the program
You can download a zip file containing this program (see Resources).
The world initially consists of a chicken object that has been aligned with the pointOfView of the world. In addition to the chicken, an invisible object of the class named Library was added to the world.
Behavior of the program
The program begins by printing the value of the Library property named Library.pi.
Then the program calls the library method named Library.vectorMoveAbs to move the chicken to a new position on the basis of the absolute coordinate values (-1, 2, 3). The duration for the move is one second, and the style is specified as 4 using the mapping shown earlier.
Then the program calls the method named Library.vectorMoveRel to move the chicken to a new position on the basis of relative coordinate values (0.75, -1, -1).
Turn the chicken
Following that relative move, the program calls the library function named Library.degreesToRev to convert 90 degrees to revolutions and to pass that value as a parameter to the primitive turn method belonging to the chicken object.
Return to the origin of the world
Finally, the program once again calls the method named Library.vectorMoveRel to move the chicken to a new position on the basis of relative coordinate values (0.25, -1, -2). When this move is completed, the chicken is back at its original position at the origin of the world, but the chicken has a different orientation. It is no longer facing in the direction of the world's blue axis, but is now facing in the opposite direction from the world's red axis.
I encourage you to either download the zip file containing the programs, or copy the code from the listings into your Alice development environment and play the programs. Experiment with the code, making changes, and observing the results of your changes.
General resources
Resources from earlier lessons in the series titled "Learn to Program using Alice"
Downloads
Listing 1. Two-dimensional projectile trajectory program.
Trajectory01's CodeCreated by: Dick BaldwinworldEvents
Methods
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Listing 2. Multiplication game program.
MultTables01's CodeCreated by: Dick BaldwinworldEvents
Methods
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||