Using Our API to Quickly Create Content
The CD-ROM accompanying this book contains a file called "basic primitives." This file contains all the custom handlers discussed in this chapter. If you play this movie, notice that nothing seems to happen. However, with the movie playing, type the following code into the message window and press Return:
Createsphere("firstsphere", 30, rgb(255,255,255))
You should see a white sphere directly in the middle of the Stage. If you stop the movie and start it again, the sphere should disappear. Take the line of code that you typed into the message window and insert it into the initialize() handler. Now when you restart the movie, the sphere is created automatically. While the movie is playing, type the following into the message window:
Scene.model("firstsphere").shaderlist.diffuse = rgb(255,0,0)
The sphere should turn a bright red color. If you restart the movie again, notice that the sphere is now white. This is because the sphere is created every single time you start the movie, no matter what its final state was. This leads to what can appear to be a difficulty: You cannot save changes made to the 3D Castmember. However, I believe that this difficulty is actually a positive benefit, because 3D Castmembers can be very lightweight. The code to generate Models is much smaller than the Models would be to download themselves.
One problem that you may encounter at this point occurs when you attempt to create multiple Models. Chapter 4, "Transformations," discusses the concepts and processes of moving, rotating, and scaling objects. By default, new Models are created at the "origin" of the world. Consider this the origin of our 3D Cartesian coordinate system. The default Camera of 3D Castmembers is pointed at the origin, which is the only reason why we can see newly created Models. Figure 3.3 illustrates what is happening when we create more than one Model.
Figure 3.3 Wire-frame view of primitives created on top of one another.
Notice that in wire-frame mode, it is apparent that the primitives are actually inside of one another. For now, we will work with one Model at a time.
To continue with our demonstration, open the file "sphere color cycle" on the CD-ROM. In this example, a slightly larger sphere is created, and the 3D Castmember takes up the entire stage. Also, the stage background is now black, so the transition from frame 1 to frame 2 is not obvious. The "loop here & color cycle" script provides the color changes:
--gain access to the scene global variable 1: global scene -- create a custom property which we will use to count up 2: property pcount 4: 3: on beginsprite -- set the initial value of pcount to zero 4: pcount = 0 5: end 6: on exitFrame me --stay on this frame 7: go "run" --add one to the current value of pcount 8: pcount = pcount + 1 -- constrain the value of pcount to a number between 0 and 255 9: pcolor = pcount mod 255 -- find the rgb color located at the paletteindex of pclor* 10: pcolor = paletteIndex(pcolor) -- change the color of the sphere 11: scene.model("firstsphere").shaderlist.diffuse = pcolor 12: end
Lines 12 and 13 deserve explanation. Remember that we are always adding 1 to the value of pcount; therefore, its value at any given time may well be very large (or more specifically, larger than 255). Because we are going to use the color palette to determine which colors we change the sphere to, we need to limit the value of pcount to within the range of 0 to 255. The mod (modulus) operator is a mathematical operator that has been in Lingo for quite some time, but it's often overlooked. It takes any numerical value and constrains it to a predetermined range. Appendix D, "2D Mathematics and Utilities," explains more about this useful operator. To continue, the current color palette of this movie is the "vivid" palette. Line 13 determines what the rgb(R,G,B) value of a given palette index number is. It is this RGB data that is then used to change the color. The reason for all of this is to make the color change very smooth. Try changing your color palette to the "grayscale" or "metallic" palette to see how this affects your color cycling.
Now open the "basic interaction" file on the CD-ROM. This example of basic interaction with the 3D Model we have created uses the following exitframe() handler:
1: global scene 2: 3: on exitFrame me --stay on this frame 4: go "run" 5: --offset the mouseloc by the center of the stage 6: offsetML = the mouseloc - point(250,165) --get absolute values of X & Y 7: offsetML = point(abs(offsetML), abs(offsetML)) 8: --determine (roughly) how far from center of sphere we are 9: if (offsetML + offsetML)/2 < 255 then 10: pcolor = (offsetML + offsetML) 11: pcolor = paletteIndex(pcolor) 12: else 13: pcolor = rgb(0,0,0) 14: end if 15: 16: scene.model("firstsphere").shaderlist.diffuse = pcolor 17: 18: end
This example determines a rough estimate of how far the mouse is from the center of the stage. If the mouse is roughly within 255 pixels, we change the color based on the palette index. If the mouse is outside that range, we automatically choose black as the new color of the sphere. The overall effect makes it appear as if the sphere is aware of the presence of the mouse. This method works well here, but with multiple Models, we will need a more concise way of determining mouse interaction. Chapter 13, "A 2D Mouse in a 3D World," explores methods of negotiating a two-dimensional mouse in a three- dimensional space.