View this PageEdit this PageUploads to this PageVersions of this PageHomeRecent ChangesSearchHelp Guide

Squeak How-To

Here are some Squeak Intro Links to smalltalk, not the etoy scripting. Some deal with both. Help decide which if any are good for etoy learning deal with both. Help decide which if any are good for etoy learning, and put links to the BEST tutorials on the following page:
Tutorials

The "how-to"s on our website are in various levels of detail. Some are just a couple of words to jog my memory so I'll know how I did something. They may be of no use to people who are not deeply invested until they are expanded. Other "how-to"s are at a level which should be enough for an accomplished programmer to understand and implement. Others are parts of tutorials, or pointers to walk-throughs for somebody learning squeak and perhaps programming for the first time.

NEW Comprehensibility Ranking.
Next to each topic covered is a number in red which indicates how much sense and use a beginning squeak (adult) will make of it. Basic scale:
[3] should be quite useful and intelligible for the reader
[2] rather sketchy, but should give main ideas
[1] not very helpful, needs major expansion
Since some expositions are aimed at people who have programmed already and may have advanced knowledge, the letter X is appended to indicate that it is aimed at an "expert" (anybody in this class). Thus, "[3X]" should be quite useful for the experienced programmer, be complete enough in description to get across the ideas, but these may or may not make sense to the beginning programmer. Finally, there may be TWO numbers, e.g., [1][3X] would indicate that the exposition is complete for an expert, but needs a lot more detail for a beginner.

Please help assign rankings. AND, more importantly, please help move things UP in the comprehensibility scale. Note also, don't be afraid to use "3". It doesn't mean the perfect exposition. Ultimately, all of this needs to be done nicely, with illustrations, perhaps within squeak, or nicely printable document.

Our Goals


  • Add to this list as needed
  • Expand and revise exposition to make sense,
    eventually to beginning programers
  • Create images to go with the explanations
  • Make the lessons look like this: http://www.dmu.com/squeak, a very nice presentation indeed. The only problem is that a lot of it uses the underlying smalltalk, instead of etoys. Will somebody please give two-line summaries of contents of individual lessons, and indicate which are etoys-only (or etoys-mostly) and good for us, providing links directly to the pages? We can include the links under the appropriate headings here, and avoid working on things that have already been done.
    DMU Tutorials
  • Create mini-squeak-tutorials that take people through all of these
    tips. It would be nice to think of mini-projects that chains several together.


Kathleen's suggested priorities, based on her experiences starting (a lot) of people on squeak. These are moved from the pedagogy page and slightly edited.
As these get done, lets turn the items into links to where they appear.
  1. motion bounce
  2. pen control: {pen down true/false line,dot,arrow, arrowhead, pensize, pen color}
  3. how to draw basic things: circles, triangles, squares, penta, hexa, octagons.One of my first grade students was experimenting in this area and the trail she happened to make reminded her of the flight of a bee but we ran out of class time before she could go back into paint and draw one. Maybe next week.
  4. Playfield use
  5. Supplies flap: the "all scripts" button, joystick, sound recorder,
  6. Object catalog: basic, useful,
  7. Object catalog: graphics, demo, 3D, connectors

How-To Directory

Links to stuff below, but probably incomplete.

Technical Problems

Technical Issues
Importing Images

CS Concepts in Squeak

Variables (separate page) [3]
Control (separate page) [3(X?)]
Sequentail vs concurrent scheduling confusion [3] is related
Tail Recursion
Arrays [2X]

Squeak Supplies

An Introduction to Squeak
Using the Paint tool
Using a joystick [3]
Using the Button object [1]
Using the Button button [1]
Using a Holder (for animation) [3]
Using a ListBox

Other Techniques

Simple Collision Detection [3]
Setting up Scorekeeping [2]
Returning objects to a home position[3]
Making things happen randomly once in a while[2][3X]
Programing a delay
Shooting things and Shooting things alternative explanation (these need to be merged into one. The second link immediately follows the first).
Multi-object Interaction
Finding the Mouse's location [1][3X]

A "fire" button
Balls bouncing correctly
Using keyboard controls

Distributing a project

Bugs and other Weird Things

Objects not moving straight
I lost an object [3]



Squeak Technical Issues...


Publishing and Saving


  • If publishing hangs, you can sometimes fix it by alt-clicking (or
    cmd-clicking if on a mac) on the "Publishing" notification window, and
    simply deleting it.
  • Alt-period works sometimes also.


Flaps

If after publishing, the Navigation flap loses all of its
icons, you can destroy all flaps, and then reinstall them.
If you had created any flaps though, you'll lose them.
To do this, get a desktop menu (available from red halo menu for
"World", which is the basic background object of your project) and
click on "flaps".

Tiles

You can modify a compound tile by dragging/dropping individual tiles to replace parts of the compount tile. For example, if you had objects redCar and greenCar, each with a variable "speed", and a tile "redCar's speed", then you can drag a tile "greenCar" (available from the halo of the greenCar, or from the menu next to its name at the top of the viewer: "tile representing me") and drop it inp lace of "redCar's" to obtain "greenCar's speed". This kind of substitutionwill usually work as long as the type of tile you're dropping is the same as the type of thing it is replacing. A special trick is the "double-possessive", which is explained in Scott Wallace's tutorial "multi-instance simulations".

Scripts, panes, variables

Sometimes when you change the name of a script, its name does not appear in the list of available scripts in the menus "object start scriptname", object pause scriptname", etc. Suggestions:
  • First, make sure that you have hit "return" after changing the script name.
  • Second, you can close the scripting pane, then re-open it.
  • Finally, you can close the viewer for the object, and then open a new viewer. Often this updates the list of scripts that will show up.
Similar tricks as above for when you change the name of a variable. You can drag out the "All Scripts" tool from the supplies bin. Clicking on the small blue circle will open up a more detailed view, and deselecting "tickers only" will show you all scripts. This is often a good way to debug - you can find scripts that you didn't know were running, ect.

Importing Images


To import an image, go to the Navigator tab and hold down the Find button. A menu will appear. Click "Find any File". From here, you can browse for a picture to load. It will act as any other object would in Squeak.

For more help, see: http://www.dmu.com/squeak/sq23.html

CS Concepts in Squeak


Creating an Array

  1. Create a holder which is the array.
  2. The object to go into the array can be anything, as there is a property called "number at cursor" that will hold the value. But you want to be able to see the value. The easiest way to get the object to be identified with the number at cursor is to have the object be a piece of text.
  3. So: drag some raw text out as your prototype newarrayelement.
  4. Then to add an item to the array, use holder include newarrayelement copy
  5. Then use holder number at cursor -- desired value.
  6. The desired value can be a number passed in as a parameter to the "include new element" script.

Squeak Supplies


An Introduction to Squeak


These links are a good place to start.

Using the Paint tool


The Paint tool is located on the Navigator tab. It can be used to draw your own objects. See the tutorial at http://www.dmu.com/squeak/sq18.html

Using the joystick

Drag a joystick out of the widgets or supplies bin. Once you set it down it will resist moving (unless you use the black "tongs" icon in the halo). Bring up a viewer for it, and select the category "joystick" in one of the panes. You'll notice "joystick's leftRight", and "joystick's upDown" variables. Watch how these values change as you move the joystick's red "knob" in various directions by dragging it with the mouse. You can use these to get the value that the joystick is moved, and tie that to the motion of your object. For example, if you want the up/down action of the joystick to control forward/back motion of your car, in a script for your car you'd include the statement:
 
car forward by joystick's upDown.


Similarly, you might want car to turn by joystick's leftRight.

Of course, you need to build these statements with tiles. Drag out the phrase "car forward by 5" from the car's viewer (foward is found in the "basic" or "motion" pane). Either drop it into an already existing script, or drop the tile on the background and a script will sprout around it. Then drag the "joystick's upDown" tile, and place it over the "5". Do the same for "car turn by 5" and "joystick's leftRight".

Now set the script ticking, and move the joystick in different directions to see the effect.

You can make the joystick more or less sensitive by multiplying or dividing the amount the car moves. For example, click on the triangle to the right of "joystick's upDown" in your script, and the expression "+1" will appear at the end. Change the plus to times (an asterisk), and change the 1 to 5, so that the tile reads "car forward by joystick's upDown x 5". This has the effect of moving the car 5 times as far as the joystick is pushed - so it will be faster.

Notice that there is a difference between absolute direction, and relative direction. If I give you directions to my house, "turn right" is different from "go east". Similarly, you must decide how the joystick will influence the motion of your object.

For example, if you have "car turn by joystick's leftRight", and the car is doing down the screen, then moving the joystick to the right will cause the car to turn right - which means head to the left on your screen. This will be fine when the user is comfortable projecting themselves into the game, imagining being the car.

Instead of the above command, you might have used


car's x increase by joystick's leftRight

This will have the effect of always moving the car to the right on the screen, regardless of which direction it is facing. This kind of motion is more appropriate for a pac-man style game. Notice also that for such games, you may need to set up a script that tests the direction the object is facing, so that it is consistent with the motion from the joystick. If the object is moving to the left, you don't want it pointing to the right. A way to correct this is to have the heading be 90 when the joystick is pushed to the right, and be -90 when it is pushed to the left:
 
pacman's x increase by joystick's leftRight
TEST joystick's leftRight > 0
YES pacman's heading -- 90
NO pacman's heading --> -90


Using a Button

Write a script that you want to be executed by pressing a button. If you only want to run the script once, skip to the next paragraph. If you want the script to run indefinitely,
  1. create a new script
  2. open the "scripting" category pane in the object's viewer
  3. drag "Object start script emptyScript" into your new script
  4. on the tile you just dragged in, change "emptyScript" to the script you want to run continually
Fire this script once to run the other one indefinitely. You may then want to create a button that stops the script. For this, create a new button and follow the instructions for the continuous script, but choose "stop script" at step 3 instead of "start script".

In the viewer for the object that holds the script, open a "scripts" category pane. To the left of the script you wish to fire once, there is a white menu icon. Click it to get a menu, and select "button to fire this script". This attaches a button to your mouse, and you can click anywhere in the world to place it.

Using a Button button

To use the button button from the supplies flap, you can drag the button off of the supplies flap onto the workspace. Then, bring up the halo. You will see an extra light green button next to the resize button in the lower right hand corner. If you click this, it will bring up the script for the button. You'll then probably want to click the black square to hide the code and return the button's script back to the normal tile scripting view.

Using a Holder


To animate something, see the wonderful tutorial at
A slightly more advanced example can be found at

This, by the way, is what these lessons should strive to look like.

Using a ListBox


To create a scrollbox with a list inside it, see the tutorial at
http://www.dmu.com/squeak/sq7.html

Other Techniques


Simple Collision Detection

Suppose we have a cannon ball that shoots across the screen. Our job is to manueveur a ship from the bottom of the screen to the top. If the cannon ball hits the ship, we must start the game over and make a sound. We have two objects: Cannon Ball and Ship. One way to determine if we have a collision is to use the "overlaps function found in an objects "Tests" catalog.
Cannon Ball Shoot
	Test Cannon ball overlaps Ship
	   YES  Ship start script StartGameOver
		Cannon Ball make sound Splash
	   No   Cannon ball forward by 5
If the cannon ball overlaps (is on top) of the ship, the script "StartGameOver" runs. THere is also a splash sound that is made. If the cannon ball does not overlap the ship, the cannon ball moves forward by 5. Another way to determine if an object collides into another object is to use the "color sees" in an objects "Test" catalog. The "color sees" can be handy if one wishes to do different things if the cannon ball hits different parts of the boat. Suppose that the left side of the boat is resistant to cannon balls but the right side is not. All one must do is paint the left side of the boat a different color then the right side. (in the script below, XCOLOR would be the color of the cannon ball and YCOLOR would be the color of the boat)
Cannon Ball Shoot
	Test Cannon Ball XCOLOR sees YCOLOR     
	   YES  Ship start script StartGameOver
		Cannon Ball make sound Splash
	   No   Cannon ball forward by 5
For a more indepth example, suppose the left side of the ship is colored RED and the right side is colored BLUE. The left side is resistant to cannons, that is, if the left side of the boat is hit by a cannon ball, a motor sound is made but the game does not start over. If the right side of the boat is hit by a cannon ball, we must start the game over and make a splash sound. (assume the cannon ball is colored black)
Cannon Ball Shoot
	Test Cannon ball [black] sees [blue]
	   YES  Ship start script StartGameOver
		Cannon Ball make sound Splash
	   NO   Cannon Ball forward by 5
	Test Cannon ball [black] sees [red]
	   YES  Cannon Ball make sound Motor
		Cannon Ball forward by 5
	   No   Cannon Ball forward by 5
Both "overlap" and "color sees" can be used to determine if a collision occurs. Overlap should be used if the same action will happen regardless of how the collision occurs. Color sees should be used if different actions occur if the collision occurs on different areas of an object.
Also see the tutorials at

Implement scoring

(Read *Variables* first). Create a variable called "score", or whatever. From the menu next to the variable name, you can select the number of decimal places (probably you want 0). From this menu you can drag out a "detailed watcher", which will give a rectangle showing the name of the variable and the value. You can use this as a scorebox - any changes to the score variable will be reflected here.

If you don't like the way that looks, you can instead select a "simple watcher", which gives you just the value of the score. You can increase the font size, style, etc., and embed it into any object or graphic that you want.

Read about *Tests* and assigning values of variables to figure out how to change the score when you want to.


Get things to reset to a home position.

Let's suppose your object is a car.
  • Create variables for the car called "homeX" and "homeY".
  • Set the car where you want it to be at the start.
  • Set the variable homeX to be what the current car's x position is.
  • Set the variable homeY to be what the current car's y position is.
  • Create a script "goHome" which does this:
     
    car's x <-- car's homeX 
    car's y <-- car's homeY 
    
Notice that you really didn't need the variables homeX and homeY. You could have simply put into the script the actual desired values for the car's x and y location. There are two reasons for doing it with the variables:

  1. If you want to change the home location, you don't need to find the script and open it. You just change the variables homeX and homeY in the viewer. This is a cleaner way to plan for possible changes. All "constants" that affect your objects behavior can be set within the variables pane for the object, rather than searching through scripts.
  2. More importantly: if you have multiple versions of your object, then you must use variables, so that each of the cars will have its own particular homeX and homeY. Remember, all siblings share the same scripts, and the only way to get them to behave differently is to use variables that you've defined for them within the script. To get them all to go home, you'd then simply fire "car send to all goHome" available on the scripting pane for any of the cars. You could do this manually, or you might want that command as part of another script that reset various things to begin again.


Make something happen "once in a while"

This is achieved in a manner similar to the traffic light delay that built. As an example, suppose we'd like apples to fall from a tree once in a while. We might have many apples, and we'd like them all to fall at different times, randomly. Assume that they are siblings, so that they can all execute the same scripts. We'll use the following for each apple:

  • Variable delay, which will indicate how much time to wait before the apple is dropped.
  • Variable timer, which will be used to count up to the delay
  • Script decideDelay, which will set the delay time randomly, and set the counter to 0. This will execute once, and start script wasteTime.
  • Script wasteTime, which will be a "ticker" that counts up to delay.
  • Script fall, which will start ticking and moving the apple down the screen once wasteTime is finished.
Create the variables timer and delay. Now the scripts look like this: (you can get "random number tile" from the menu that appears when you hold the cursor over the objects name "apple" in the title of the window for a script).
 
apple decideDelay apple's delay <-- random 50 
apple's timer <-- 0 
apple start script wasteTime

apple wasteTime
  TEST apple's timer < apple's delay
      YES  apple's timer increase by 1
       NO  apple start script fall
           apple stop script wasteTime

The fall script moves the apple down the screen (either by apple's y decrease by 1, or apple forward by 1, aassuming the heading was 180)). It may also test for when it hits the ground (using a color test, or testing it's y-value.) At that point, it should stop script fall. If you want to recycle the apple for another round, then you'll need to send the apple back to its home position, and then run decideDelay again.

Notice that when all siblings execute the script, they each will choose a random number and set it to their own variable "delay", so they will each count up to a different amount before starting to fall. You can control the rate by choosing a smaller or larger range for the random number.




Shoot something


Suppose we've drawn a bubble-gun that we'd like to shoot bubbles.
  1. Create a script that will position the bubble at the gun and heading in the right direction just before it shoots.
    bubble findGun
      bubble hide
      bubble's x <- gun's x
      bubble's y <- gun's y
      bubble's heading <- gun's heading
      bubble forward 20
      bubble show
    
    Above, "forward 20" is used to position the bubble at the tip of the gun, instead of over it. You will need to adjust this, and/or the x,y coordinates of the bubble, depending on your drawing.
  2. Create a script that when ticking will make the bubble fly forward until it hits reaches the edge of the screen.
    bubble fly
     TEST bubble obtrudes
          YES bubble hide
              bubble stop script fly
          NO  bubble forward by 3
    
    The test "bubble obtrudes" is found in the "tests" pane of the viewer for the bubble. You might instead want the bubble to stop after a fixed distance. In this case you'd need to create a counter as a variable and count as the bubble moved forward 1 at each tick of the clock. Once the counter reached the right value, you'd stop script fly.
  3. We need some way to fire the gun. We'll script a button to do it. Drag a button (or just a shape) from the supplies or widgets flap.
  4. Change the text in the button to read what you'd like. (If you dragged a shape, you can put some text into it by dragging text from the supplies flap, and "embedding it" into the shape (see the red menu icon from the halo of the text).
  5. Create a script for the button called "shoot", for example.
  6. Decide when you want the shooting to occur: when you click on the button, or when your mouse just passes over the button. (These, and other options, are available by clicking on "normal" in the script window title.
  7. What should happen once, and what will have to happen over and over? The findGun script should fire just once. If it were ticking, then the bubble would never be able to escape the position at the gun. The fly script should happen over and over, as it advances the bubble a little bit at each step. Thus, we put the following in the "shoot" script:
    button shoot
       bubble findGun
       bubble start script fly
    
  8. That's it. Now when the button is pressed, the bubble should first appear at the tip of the gun, and then start flying. It should stop and disappear when it reaches the edge of the screen. If it does not disappear, it may be because it never "obtrudes" - which means hangs over the edge of its container. This may not occur because the world (or playfield, if you are on one) has the option "fence enabled" checked. You can change this setting by clicking ont the red halo for the world, then selecting "playfield options", where you'll find fence enabling along with other behaviors that you can modify.
  9. Oh - wait! What if you wanted some other object, like a person you drew, to get all soapy and fall down if a bubble hits them? You could do this in a couple of ways. Somewhere you need a test that checks if the person is hit by a bubble. Once place you could check is in the bubble's fly script. This makes the most sense, since you do not want to be checking unless the bubble is actually flying.
    bubble fly
     TEST bubble obtrudes
          YES bubble hide
              bubble stop script fly
          NO  bubble forward by 3
     TEST bubble overlaps person
         YES  person start script getAllSoapyAndFallDown
              bubble hide
              bubble stop script fly
          NO  bubble forward by 3
    
    Notice that in this script, we really could've used an "OR" statement:
    TEST bubble obtrudes OR bubble overlaps person
       YES ...
        NO ..
    
    But since there are no such tiles available in Etoys, we simply do a separate test.





To shoot something A simple project that you might like to try, that
may come in handy in some game that you might write, involves getting
one object to launch or shoot out of another. Challenge: Draw a
picture of somebody eating watermelon, and write a "spitseed" script
that has them spit watermelon seeds. What is involved? Draw a
person in profile as one object, and draw a watermelon seed. What
has to happen when the spitseed script fires? The watermelon seed
should move to the right place on the screen relative to your drawing
(i.e., at the person's mouth). (Spitseed Simply sets the x and y
coordinates of the seed). It should then appear ("show", available
under scripting pane). The spitseed script should then start a
separate script whose only function is to make the seed move foward a
little at each tick. (Make sure the heading is correct.)




Bonus fun: create a controller that changes the heading of your
person, and now you can direct the seeds. Add moving targets, and
have points score when they are hit.



  • bullet hides
  • sets x and y to shooting object's x and y, plus offset
  • show and trigger flying ticker
  • flying ticker tests for obtrudes to know when to vanish
  • can erase (which means need to create a bullet on each shot) or
    hide (which means only one bullet at a time)


  • Handle interaction between one object and many other objects
    Consider:
    • In pac-man, the pacman runs around, eating various power dots.
    • In "breakout", a ball hits bricks, causing them to disappear.
    • In "space-invaders", a bullet may hit one of any number of alien ships.
    In all of these, we have the situation where we want to test whether or not a given object has touched one of a collection of other objects, and would like something to happen to either the main object, the one that was touched, or both.

    There are three different types of tests you might use. "isover", "overlaps", and "colorsees". (There is actually a fourth, "touchesA", but we will not address this test at this time). These are available on the tests pane in the viewer for an object.

    As an example, let us suppose we have a game where a dart is thrown at balloons. We will consider several variations, from simplest to more complicated,to illustrate when we'd use the different tests, and the difference between them. Here are the variations:

    1. There is one dart, and one balloon. All that happens when the dart hits the balloon is that the score changes, and the dart returns to its home position.
    2. There is one dart, and many balloons, all the same color. When any is hit, the score changes, and the dart returns to home location.
    3. There is one dart, and many balloons, all the same color. When any is hit, the score changes, the balloon pops, and the dart returns to home location.
    4. There is one dart, and many differently colored balloons. When any is hit, the score changes, the balloon pops, and the dart returns to home location.

    1. Suppose the balloon is red, and that dart's script "balloonHit" increases the score, and sends the dart back to its home location. Then when the dart was thrown, we could start any of the following scripts ticking.

    OPTION 1:

    dart's checkHit
    TEST  dart isover [red] (you'd put the actual color here)
        YES  dart balloonHit
             dart stop script checkHit
        NO
    
    OPTION 2: Same as option 1, but the test is
         TEST dart's [yellow] sees [red]
    

    OPTION 3: Same as option 1, but the test is

    TEST dart overlaps balloon
    

    We might like option 2, because we could test whether the tip of the dart (we've assumed it is yellow) is over the balloon, instead of whether, say, the tail of the dart (not yellow) grazed the balloon.

    2. Here we have one dart, and many red balloons. It is not hard to see that either of the first two cases will work regardless of how many ballons we have, assuming they are all the same color red. However, Option 3 will not work, because we'd have to test each balloon individually... as written, the balloonHit script would not fire unless the specific balloon mentioned in the test was overlapped by the dart.

    3. Now we have a challenge. We'd like the balloon to pop. Suppose we have written a script pop, which animates a popping balloon, and then hides the balloon. A simple version would just be to hide the balloon:

    balloon's pop
      balloon hide
    

    Now, if we created a single balloon, wrote this script, and then created sibling balloons, then they all would have this script. So, which test should we use? Let's add a call to the "balloon pop" script when the dart is over red, as in the first option above:

    dart's checkHit
    TEST  dart isover [red] (you'd put the actual color here)
        YES  dart balloonHit
             balloon pop
             dart stop script checkHit
        NO
    

    What will happen? Which balloon will pop? The balloon that will pop is the specific one that you mentioned in "balloon pop" above. If you wanted balloon3 to pop, you'd have had to have had the tile "balloon3 pop". Having balloon pop will be fine, if the dart was actually over that particular balloon. But the way it is written, regardless of which balloon has been hit, a specific balloon will execute its "pop" script.

    One solution to the problem, is to use the "overlaps" test, and write 37 different tests, one for each of our 37 balloons:

    TEST dart overlaps balloon1...
         YES balloon1 pop
    
    ..
    
    TEST dart overlaps balloon37...
        YES balloon37 pop
    

    YUCCH. There must be a better way. There is. Whenever you find yourself having to type the same thing over and over, it is a good sign that you have not abstracted or generalized enough, and captured the same behavior in a single script that varies depending on only a variable, or who is executing it.

    In this case, suppose we script a balloon to do the checkHit script instead of scripting the dart:

    balloon's checkHit
    TEST  dart's [yellow] sees [red]
        YES  dart balloonHit
             balloon pop
             balloon stop script checkHit
        NO
    

    Now, assuming that all of the balloons were siblings, they all should have this script, and when they execute it, "balloon" refers to the particular balloon running the script. To make all this work, when the dart was launched, we'd want to execute the statement "balloon start all checkHit" so that all balloons would start to check for overlap with the dart. OOOPS - when any of the balloons was hit, we'd want all of the balloons scripts to stop checking... so actually, we'd replace "balloon stop script checkHit" with "balloon stop all checkHit".

    While the above works, it is kind of ugly - it doesn't make sense to have to run so many scripts simultaneously. This will slow the whole program down. There should be a way to have the dart check which balloon it hit, and then to tell that balloon to pop. In object-oriented programming, this is usually no problem. There should be a way to specify that when a dart hits any particular balloon, that particular balloon should execute its "pop" script. However, there appears not to be a way to do this at present using the Etoys tiles. A clever work-around is to have the dart run the checkHit script, and when it is over red, send a message to all balloons to run their checkhit script exactly once. So, we'd have the following:

    dart's checkHit
    TEST  dart's [yellow] sees  [red] 
        YES  dart balloonHit
             balloon sendtoall checkHit
             dart stop script checkIfHit
        NO
    
    balloon's checkIfHit
    TEST  dart overlaps balloon
       YES pop
        NO
    

    Notice that we don't start the "checkIfHit" scripts ticking. We just run them once, just when the dart detects it is over something red.

    4. Now we'd like to do the same thing, but with many different colored balloons. Assuming that the only thing that the dart can hit is a balloon (i.e., there are not other objects), we can simply test whether the dart is over the background color. If so, do nothing, but if not, then do as above.

    dart's checkHit
    TEST  dart's [yellow] sees  [white]   (the background color)
        YES  
        NO   dart balloonHit
             balloon sendtoall checkHit
             dart stop script checkIfHit
    

    Probably Irrelevant Comment, given current version: While "eToys friendly" seems to be desirable, the unavailability of "touchesA" can be a significant limitation if you are scripting with multiple copies of the same object. One work-around is to temporarily change to not being eToys friendly, go and get a "touchesA" tile, and store it for later duplication and use. (You will be able to replace the parts of the tile for who is touching, and who is being touched, by dragging tiles with the names of the relevant objects.) To change eToys friendly option, drag out an object catalog from the supplies or widgets flap, click on "tools", then drag out the "Preferences" window. Within that window, click on "scripting", and then you can select/deselect the eToys friendly option.

  • Handle interaction between one of many, and one of many other objects

    This is for another day.


    To make a delay

    • set counter in pre-script, call "while ticker"
    • "while ticker" waits for end condition, then triggers post-script.
    Button to fire things
    • (widgets/supplies button bar (tickers only... "paused")
    • script the button to do what you want

    Finding the Mouse's location

    You can get the mouse's current X and Y position to any object that has a Playfield tab in the viewer window. Some objects that contain this tab include the world, playfields, holders, and the pages of books.
    Uploaded Image: playfield.PNG
    The lower left hand corner of the playfield is where X and Y are both 0. If you move the mouse up on the screen, the Y value will increase, similarly by moving the mouse right, the X value will increase. If you move the mouse below or to the left of the playfield, you will get negative numbers.

    These variables can be used for many things. One basic example of what you can do with the location of the mouse is to control the location of an object, such as a paddle in a game like pong or breakout. The following tiles would be used to set the X position of the mouse.

    Uploaded Image: basicmouse.PNG

    Extension:

    Using the above tiles, how could you make an object move towards the mouse? Solutions (mouse)


    Making a ball bounce correctly off of a flat bar that is at an angle.
    • set the heading to 360 - heading - 2flat-bar's heading.



    Using keyboard controls

    To allow input through the keyboard, go to the world's viewer and under the input tab you will find lastKeystroke. Then, in a script, put lastKeystroke in a Test statement.
    TEST lastKeystroke=w
    YES object forward by 5

    However, if you do not press another key after the w, it will continue testing true and the object will continually go forward. To get around this, manually change lastKeystroke within the Yes area.
    TEST lastKeystroke=w
    YES object forward by 5
    world's lastKeystroke=stop



    Sequential vs Concurrent in squeak.



    script A:

    start script B (ticking)

    script B:
    stop script B
    (call) script A

    Question 1: If we execute A, will this infinite loop, or stop?
    • Thought: it seems like it should all stop.
    • The correct answer, explained below, is that it is an infinite loop.

    Now suppose A is the same, but we replace B with


    script B:
    (call) script A
    stop script B

    Question 2: will this infinite loop, or stop?
    • Thought: it is an infinite loop.
    • The correct answer is that it will stop.

    Explanation


    When you read the code, it looks like it makes no sense... why would
    you need to stop a script before doing something that you wanted to
    happen before the script was stopped? It is natural to do the
    opposite!




    Yet the above is what happens, and this is consistent with our
    model of how squeak schedules.



    FIRST CASE:

    tick 1:
    B is schedule to start next tick
    tick 2:
    B starts
    B is scheduled to stop next tick
    A called, so B is schedule to start next tick.

    tick 3:
    B stops
    B starts (in order of queued schedule above

    SECOND CASE:


    same as above, but on tick 2, B is scheduled to start via call to A

    before B is scheduled to stop. Thus, on tick 3, B starts, then stops.




    Tail Recursion

    When you want to program a multi-step algorithm in squeak it can be difficult getting deterministic behavior using features like ticking or (shudder) tellAllSiblings, sendToAll. One option is to call scripts using normal function calls, but that may be undesireable if you want to visually see the algorithm's progress. Another option is to use the "do" feature from the Scripting pane. This tile does exactly what the bubble help says it does. It tells squeak to run a particular script on a particular object once, during the next tick.

    This is useful simply for the fact that you know what is going to happen when you call it, but it doesn't really get interesting until you consider what happens when multiple objects/scripts call "do" during a particular tick. The requested scripts will be called on the requested objects, but not until the current tick is done. In terms of recursive functions this means that if you branch into several subcases each case in the current level of recursion completes before the next level starts.

    Of course, you should also note that since you're not using function calls when you use "do" there really isn't any implicit recursion going on. When you call "do" nothing happens until the next tick, so you can't use the results of the called script in the currently executing script. What you do get is tail recursion, which means that you do something and then tell another object/script to take over where you left off. This can be used to program explicit loops. To program recursion with it you need to explicitly return control by having the script calling "do" save itself in a variable of the object being called and then having the script on the called object call a script on the object that called it.

    I know, I need to explain this better, but I wanted to get the idea out there since using this programming style has helped me a lot to get things working like Game of Life and Merge Sort.


    Bugs


    Object not moving straight

    If your object is gradually drifting from where it is supposed to go, find its Heading variable under the Basic tab. The value displayed is an integer rounded from the actual heading. For instance, if the object's heading is 89.7 degrees, it will display 90.

    To fix this, type in the value you want directly into the field.


    I lost an object

    If one of your objects has become hidden and you do not have the viewer available for it, go to the World menu -> playfield options -> show all players, and you will be able to see it.

    Another way to find a lost object is:
    On the right side of the Squeak screen, thumbnails of all the objects (except the World) should exist. If you lose an object or cannot find it, click on the desired objects thumbnail.

    At the top of the object viewer, there is rectangular box that displays the objects menu. Click on the Menu button. There are now two options.

    1) Reveal me - click this option and your object will start flashing on the screen
    2) Grab me - this option will move the object to wherever your mouse is

    Links to this Page

    • A Squeaky Introduction to Programming last edited on 6 August 2005 at 8:43:17 am by 12-221-97-163.client.insightBB.com
    • Control last edited on 6 February 2005 at 3:24:05 pm by 12-221-97-163.client.insightBB.com
    • Pedagogy Place last edited on 30 March 2005 at 5:19:17 pm by csil-cbt6.cs.uiuc.edu
    • hw-2-02 last edited on 6 February 2005 at 2:34:56 pm by 12-210-160-251.client.insightBB.com
    • Beginning Tutorials last edited on 6 July 2005 at 4:29 pm by vpn82-7e-92-97.near.uiuc.edu
    • Squeak Troubleshooting last edited on 9 February 2005 at 9:12:57 pm by 12-221-97-163.client.insightBB.com
    • notes-3-09 last edited on 11 March 2005 at 9:10:52 pm by hh-1-213.flexabit.net
    • Concept Nuggets Listing last edited on 11 May 2005 at 1:23:16 pm by hh-1-213.flexabit.net