1. Use s = new Turtle
to make a
second turtle. Each turtle is called an instance, and
Turtle
is a class that can be used to make
many instances of the same type. Send function calls to an
instance by using a dot after its name:
s.fd 50
moves the second turtlea
forward by 50.
s = new Turtle # Create a new Turtle and hold it under the name s. s.wear red # Tell s to color itself red. s.rt 90 # Tell s to turn right. s.fd 50 # Tell s to move forward.
2. Invent a new subclass of Turtle that always comes in red. Try this:
class Drifter extends Turtle # Define a new type of Turtle called Drifter. constructor: -> # constructor is a special function for making a new Drifter. super() # super() means: first make a normal Turtle. @wear red # @ means "tell this new object to" wear red. @speed Infinity # Then set this object's speed to Infinity. d = new Drifter # Make one of our new type of object. d.fd 25 # Notice that it is red, and it moves instantly.
The code above defines a class Drifter
that extends
the built-in base class Turtle
. It will act just like
a normal turtle, except that it will start with infinite speed, wearing red.
3. Modify Drifter
to add two new properties and
a method, like this:
class Drifter extends Turtle constructor: (@spin, @vel) -> # The constructor takes and saves two properties spin and vel. super() @wear red @speed Infinity drift: -> # Define the drift() method @movexy @vel # Change x and y by the vector v @rt @spin # Turn right by the angle spin d = new Drifter(60, [20, 50]) # Make a Drifter with spin = 60 and vel = [20, 50] see 'spin', d.spin # Print out the spin property of d. see 'vel', d.vel # Print out the vel property of d. d.drift() # Tell the drifter to run its drift() method.
(@spin, @vel)
in the
constructor
, the properties spin
and
vel
are added to each drifter as part of the
new Drifter
call. For example,
d = new Drifter(60, [20, 30])
creates a
Drifter
with d.spin
set to 60 and with
d.vel
set to the vector [20, 30].
drift
is a method of the
Drifter
class. When it runs @rt @spin
,
it means "turn this object right by this object's spin
degrees".
d.spin
to access the
spin
property of d
or
d.drift()
to call its drift
method.
@
to use properties and methods of "this" object: @spin
to access a property or @movexy @vel
to call the
movexy
method.
4. Add a class variable to keep a list of all the drifters and a class method to animate them:
class Drifter extends Turtle constructor: (@spin, @vel) -> super() @wear red @speed Infinity Drifter.list.push(@) # Add this object to the list when it is created. drift: -> @movexy @vel @rt @spin @list: [] # This list is a property of the Drifter class itself. @run: -> # This is a method of the Drifter class itself. tick 60, -> # Set up an animation to run 60 times per second: for d in Drifter.list # Loop over each drifter in the list. d.drift() # Call d.drift() on each drifter. new Drifter(1, [1, 1]) # Make a drifter with a slower velocity. new Drifter(2, [-1, 2]) # Make a second drifter. Drifter.run() # Call the class method to get the animation going.
@
(the
object being constructed) into the list Drifter.list
.
Drifter.list
is a
class variable
defined by @list: []
. Because it is
declared with an @
, it is a
property of the Drifter
class itself,
not each instance. That means there is just one
list
.
run
is a
class method attached
to the Drifter
class instead of each instance.
5. Now experiment! Here is a bounce()
method
that keeps the Drifters inside a box:
class Drifter extends Turtle constructor: (@spin, @vel) -> super() @wear red @speed Infinity Drifter.list.push(@) bounce: -> # Define the bounce() method for each instance. pos = @getxy() # Set pos to the current [x, y] of the drifter. for i in [0..1] # Check each (x and y) component if outside 0..100: if pos[i] < (edge = 0) or pos[i] > (edge = 100) # set edge where crossed. pos[i] = 2 * edge - pos[i] # Reflect over the crossed edge. @moveto pos # Move inside the crossed edge. @vel[i] = -@vel[i] # Reflect the velocity. @spin = -@spin # Reverse the spin. drift: -> @movexy @vel @bounce() # Bounce after each move. @rt @spin @list: [] @run: -> tick 60, -> for d in Drifter.list d.drift() for [1..5] # Make five Drifters with random velocity and spin. new Drifter(random(), [random(), random()]) Drifter.run() pen blue; (fd 100; rt 90) for [1..4]; ht() # With the main turtle, draw a square.
Can you add gravity? Can you add interaction with the mouse?