PencilCoder

Teacher's Guide: Chase Other Sprites!

In the previous lesson, students learned to pass pairs of numeric values representing x and y coordinates to the moveto, jumpto, and turnto functions. This lesson expands on that base, teaching students to pass sprites as the argument to those functions.

Overview

More about the lesson

The fact that moveto, jumpto, and turnto can be used with sprite arguments is intuitive. In the case of moveto and jumpto, an additional benefit of passing a sprite as an argument is that we can pass a numeric value as a second argument to establish a maximum distance the calling sprite can move toward the target sprite.

(This distance-limiting features will also work if you pass an object representing HTML coordinates as the first argument, e.g., jumpto {pageX:0, pageY:0}, 50. HTML coordinates are described in the Custom(ized) Objects! lesson).

jQuery.turtle.nowarn

Use of moveto, jumpto, and turnto with sprite arguments involves an unfortunate complication: such function calls can cause the program to produce warning messages and to behave erratically or even seem to crash:

As the lesson notes, this unintended behavior arises as a result of a failsafe that is built into Pencil Code to alert users to potential coding errors involving the animation queue. However, for coding activities in this lesson, this failsafe is likely only to produce false alarms. It is therefore more a source of frustration than help.

Thankfully, it is easy to turn off the failsafe mechanism with the assignment jQuery.turtle.nowarn = true. Turning off the failsafe is an appropriate and sufficient step for "solving" the (nonexistent) animation queue issues related to use of statements like turtleA.moveto turtleB. However, students need to understand that turning off the warning is not a panacea for all animation-queue problems. For example, as demonstrated in the previous lesson, statements involving getxy needs to be preceded by calls to await done defer() in order for that function's output to match the position of the turtle at the correct point in the animation.

Notes to activities

The FollowTheLeader and WatchfulEyes activities both involve motion. After students have made an initial design, they will likely desire to make sprite movements more smoothly. An effective approach is to use smaller movements and turn angles combined with a much higher setting for speed, as done in the example solution for FollowTheLeader.

TeamStringArt provides an alternative approach to coding the StringArt activity in the Coordinates! lesson. Aside from perhaps being easier to code, using sprites to determine start- and end points of each line segment facilitates drawing strings between non-perpendicular lines, opening up the possibility to create many interesting shapes, as illustrated through the examples in the lesson. Accomplishing this without using sprites would be mathematically challenging.

Additional activities

  • Code a new OddStarMaker modeled off of the program with the same name in the previous lesson. But this time, do not use getxy or await done defer().
  • A vertex (plural: vertices) is a location where two line segments connect to form an angle. Observe that a star with n points contains 2n vertices. In a regular star, these vertices lie on concentric circles, with half on the outer circle (forming the star's points) and the other half on the inner circle. This observation suggests an algorithm for drawing a star with any number of points. Code a VertexStarMaker that uses three turtles to draw a star. Move two of the turtles around concentric circles to identify vertices; direct the third turtle to connect successive vertices.

    Blank space Blank space
  • Using two sprites, draw a set of parallel lines that form a SlicedCircle.
  • Code a script based on the following recipe to create a SierpinskiTriangle:

    1. Select three points on the screen to be the vertices of a triangle. Mark each vertex using a sprite in the shape of a small dot.
    2. Randomly select any point inside the triangle and consider that your current position.
    3. Randomly select any one of the three vertex sprites.
    4. Move half the distance from your current position to the selected vertex sprite.
    5. Draw a very small dot at the current position.
    6. Repeat from step 3 many, many times.

    The fact that this algorithm creates a Sierpinski Triangle is pretty cool. But the real motivation for creating this activity is to get you to use jumpto with two arguments, a sprite and a distance, with the distance being the value needed for step 4. Computing the distance is arguably the trickiest part of the activity. Your solution will likely entail getxy (and therefore also await done defer()), array destructuring, the distance formula (i.e., the Pythagorean Theorem), and Math.sqrt.

Beyond the lesson

Other usage for jumpto, moveto, and turnto

jumpto, moveto, and turnto accept some additional argument types besides those addressed so far, as summarized in the following table. These will be addressed in subsequent lessons.

jumpto x, y jump to (x, y) in a center-based, Cartesian coordinate system.
jumpto otherSprite jump to another sprite.
jumpto otherSprite, 100 second arg to limit the distance moved towards another sprite
jumpto [x,y] same as jumpto x,y
jumpto {pageX: x, pageY: y} jump using HTML page coordinates (with the origin in the upper-left-hand corner of the screen)
jumpto lastmouse jump to the location of the last mouse event
jumpto lastmouse, 100 second arg to limit the distance moved towards another sprite
jumpto window jump to the center of the visible window

Understanding the animation-queue failsafe

The animation-queue failsafe gets triggered when two conditions are met: (1) a program includes a call (likely indirectly) to the jQuery function pagexy, and (2) the program's queues contains at least 100 scheduled animations. Whenever these conditions are met, a warning is printed in the test panel (as shown above) and the program flushes the animation queue. Flushing the queue causes all animations in the queue to be carried out immediately, without showing the animation. This is what typically results in the program appearing glitchy and/or yielding bizarre output. Technically speaking, and despite appearances, however, the program has not "crashed."

pagexy is similar to getxy, except it returns a sprite's current location as an object expressed in HTML coordinates, e.g., {pageX:100, pageY:-50}. Students have little need to call this function directly, and in fact rarely do. However, many functions that students make use of contain embedded calls to pagexy, and this satisfies the first condition of the failsafe just the same. Functions that internally call pagexy include getxy, moveto, jumpto, and turnto, as well as a number of functions that students will encounter in subsequent lessons, such as touches, inside, and direction.

Although the first condition of the failsafe is met regardless of the context in which pagexy is called, the animation-queue problems it aims to resolve only arise when the user calls a function that returns information based on pagexy's output. Examples of this include a direct call to pagexy, getxy, touches, inside, and direction. Although functions such as moveto and jumpto make use of pagexy to obtain location data needed for their computations, they don't return information based on that location data. Consequently, these functions don't give rise to animation queue problems. The reason for this difference is that these functions are written using advanced techniques that take care of animation-queue concerns for us. That is why, for the purposes of this lesson at least, the failsafe can (and should) safely be turned off when using these functions as described in this lesson.

A potentially confusing aspect of the pagexy failsafe is that it may seem inconsistent, i.e., cropping up in some programs that make either direct or indirect use of pagexy, but not in others. This pattern is easily explained by condition (2), above: the failsafe is only triggered when the queue containing the call to pagexy includes 100 or more scheduled animations.

Animating with speed Infinity

The Notes to activities section above describes how animation results can be improved by decreasing the distance that sprites move, while increasing speed. Taken to the extreme, speed can be set to Infinity. This setting can speed up animations to near-instantaneous change, but in the presence of calls to await done defer(), animations often end up being visible. An illustration is provided here.

What can go wrong

getxy vs. pagexy

Having seen warnings messages referencing pagexy, students might inadvertently call it instead of getxy. This will typically lead to errors when they try to subsequently access the specific values in the object using array destructuring, e.g., [x,y] = sizexy(). This error will not result in an exception (i.e., the program will not crash, at least not right away), but the variables will not be assigned numeric values as expected. Rather, they will have the value undefined, likely causing problems further in execution when these variables are referenced.

Using home as an argument

home is a sprite-specific function. However, it is not uncommon to see home passed to moveto or jumpto. Such calls, such as jumpto home (or equivalently, jumpto home()), will seem to work, but they should nonetheless be avoided. When used with other sprites, passing home as an argument in this manner has some odd side-effects. For example, r.jumpto home will cause that sprite to return to the origin, but it's orientation will not be set to north. Additionally, the default turtle will also return to the origin.

Pedagogy

Productive struggle

The exercises in this curriculum are designed to provide students with relevant and authentic coding challenges. They are not meant to be easy. Rather, they are intended to engage students in what the late Seymour Papert—creater of the Logo language, on which Pencil Code's turtle is modeled—called "hard fun".

For students to learn to code, and especially for them to develop computational thinking skills, they need to have repeated opportunities to work through challenges. Student learning is diminished if coding tasks are made too easy or overly scaffolded. Moreover, students derive greater satisfaction when they have worked through a challenge on their own. Of course, it is important not to let students get discouraged. The key is to strive for the right balance. However, too often, we teachers are guilty of short-circuiting the learning process by providing too much guidance too soon. Resist that urge. Strive to give students time to wrestle through challenges and develop solutions themselves.

Because of the difficult nature of the material, students won't always succeed in their coding efforts. However, this does not mean that the time devoted to that activity was a waste of time. Educational research has demonstrated that students benefit more from being shown how to solve a problem after they have struggled and failed, than they do if they are simply shown the solution and given a chance to practice with it. Take advantage of this insight: after your students have progressed through their work, individually or in pairs or even small groups, share out and/or highlight alternative approaches to coding the activities. Students benefit from seeing alternative solutions, ideally those generated by their peers.

Spiral learning

Encourage students to continue to apply what they have learned in previous lessons as they work on activities that highlight new material. The more practice they get, especially when done intermittently over a more extended period of time, the stronger their overall coding skillset will become.

Sometimes the current lesson's activities naturally tie in previously-learned skills, and they may even explicitly call for students to to make use of a specific technique or function. However, encourage students to be self-starters, and to look for additional opportunities themselves. An great example of this is applying the concepts and functions learned in the Array Destructuring! lesson to make animations dependent on the size of the visible window. Most activities won't call for this, but with encouragement students can get into the habit of using these skills in future lessons. Each time they do, they get valuable reinforcement of myriad skills, from array destructuring and use of variables to incorporating the screen dimensions info into various apsects of the new script's logic.

Technicalities

plan

The lesson notes that animation queue issues don't surface when using function calls such as turtleA.jumpto turtleB because the definitions for jumpto, moveto, and turnto include code which takes care of the issues for us when these functions are called with sprites as arguments (emphasis added). However, this statement is misleading. It implies that jumpto, moveto, and turnto can somtimes lead to animation-queue problems, when in fact they never do, thanks to the code they include that "takes care of the animation queue issues for us." However, a statement such as moveto otherTurtle.getxy() will lead to animation-queue problems, but the problematic code here has nothing to do with moveto, but rather with the call to getxy, which provides the (likely "incorrect") input to moveto.

Functions such as jumpto, moveto, and turnto resolve potential animation-queue problems using the plan function. plan is used to insert, into the animation queue, blocks of code that contain function calls that normally would be evaluated immediately, before a program's animation begins. For example, with proper use of plan, execution of a statement that contains getxy can be delayed until after certain scheduled animation are completed, thereby ensuring that getxy gets evaluated "at the right time" and returns values corresponding to the appropriate stage of the animation.

plan is useful because it allows for much more fine-tuned manipulations of the animation queue than accomplished with calls to await done defer(). However, plan is more complicated to use than await done defer(). Effective use of plan requires knowledge of several advanced topics, notably callbacks. Students are encouraged to explore use of plan in several of the additional activities in the notes to the Callbacks! lesson.