Week 4 - Organizing your code

Pseudocode, Handlers, Points and Rects

Pseudocode

When coming up with ideas for a project, or considering how to do what you want to do, it is extremely helpful to think (and write!) in what is called pseudocode.

This means to write in plain English what you want your program to accomplish--one step at a time. Once you have done this, it is a lot easier to translate those thoughts into Lingo.

This may also be a good time to think about what elements you might need in your project.

For example, let's take Mattia's Speak and Spell: First, we need to think about the interface. We will need a keyboard interface with a display, buttons for each letter, a button to ask Director for a new word, and a button to tell Director that we have finished spelling.

If we were going to break it down into rough PseudoCode, it would go something like this:
1. User asks for a word to spell.
2. Director speaks a word.
3. User attempts to spell that word.
4. Director checks to see if it is correct and lets user know if spelling is correct.
6. User asks for another word.
[This is obviously not the only way to break it into pseudocode. Everyone will have their own unique method of breaking down their thoughts.]

Once you have done that first breakout, natural questions will arise as you break it down further. Be as explicit as possible. Better to spell more things out than less.

1. User asks for a word to spell - How does user do this?
Watch for the "new word" button to be pressed.

2. Director speaks a word. - Where does this word come from?? And how does Director choose it?
Put a list of words into Director. [Initialize a list with words.]
When user presses "new word" button, choose randomly from that list. [This implies we will use random() function.]
Speak the chosen word.

3. User attempts to spell word - How does this happen??
If a particular letter button is pressed, add it to the display.
If user presses enter, remember the text (word) that is in the display. [Remember implies that you should use a variable.]

4. Director checks to see if it is correct and lets user know - Again, how??
Director remembers which word it spoke and then compares that word to what the user has typed in.
Either the words equal each other or they don't.
Let the user know if she is correct.

So now you have specific things you need to figure out. One step at a time.

Next step: Write pseduocode in Lingo format
on beginSprite
    --initialize variables
    --intialize the list of words

end

on exitFrame
    go to the frame
end

on mouseDown
    --if mouse is on "new word" choose a random word and speak it. put that word into a variable called spokenWord
    --if mouse is on one of the letter buttons, put that letter into the display field
    --if mouse is on "enter" or "done" button,
    --put the text that is in the field into a variable called usersWord
    --compare that text to the spoken text
    --if it is correct, put a correct message into the field. if not, put an incorrect message

end


For any project, you are thinking of, write pseudocode! It will help you figure out how complex a project it really is - and will clue you in to the things you will need to learn. If you have very good pseudocode, writing your scripts will become much, much easier.

Handlers

Handlers are a way of organzing your code and making it modular. Once you start to deal with more complicated projects, all the code will get to be too much. It is much easier to understand your code if you break it up into discrete chunks. And you can keep a more organized sense of what you are trying to do.

Always want to be aiming for REUSE and ENCAPSULATION OF COMPLEXITY. So that you only have to write code once - and then you don't have to think about it again. And even if it has been difficult (or very difficult), from then on, you just have to send some values to it and it will do what is is supposed to.

When to use handlers
1. When you notice that you try to do the same thing in different parts of your project - or in more than one project.
example: Making sprites appear or disappear.
2. When you have a discrete task you are trying to accomplish.

Handler syntax
Name a handler anything you like. Include () after it. [Technically, you only have to include () if you are expecting an output to be returned (see below) but I use it in all cases just to be consistent.]
Place the handler in the movie script. Make sure it is a movie script by setting it in the property inspector in the script window.

Input Parameters
Send along the important information that the handler needs to know, i.e. variables or values.

example:
I want to set a handler that will make a range of sprites invisible. I need to let the handler know which specific sprites to make invisible. So I will send it the first and last sprite numbers.

from frame script:
makeInvisible(1,6)

from movie script:
on makeInvisible(_firstSprite, _lastSprite)
    repeat with i = _firstSprite to _lastSprite
        sprite(i).visible = false
    end repeat
end


Things to know about input parameters:
1. You can pass values or variables to a handler.
2. There must be the same number of parameters in the handler call as in the handler.
3. Whatever you pass will be placed into the parameters in the order they are received.
3. Parameters can be called anything. I am starting them with _'s as a convention.
4. Parameters should ideally be local to their handler.

Output Parameters
Sometimes you will want a handler to send back a value. Do this by using the return command.

ex. I want to figure out what my windspeed should be for each of my flowers if the wind is coming from the left.

from frame script:
speed = setWindSpeed(i, windDir, currentWindspeed)
In this case, my handler is setWindSpeed and I am sending it these inputs:
sprite number(i), the variable for the direction of the wind winDir
I am passing to it the default windspeed and am looking for it to return the value of the currentWindspeed for each specific sprite.

from movie script:
on setWindSpeed(i, _comingfrom, _windspeed)
    if _comingfrom = "left" then
        if i = 2 or i = 5 then
            _windspeed = _windspeed - 20
        else if i = 3 or i = 6 then
            _windspeed = _windspeed - 25
        end if
    else if _comingfrom = "right" then
        if i = 2 or i = 5 then
            _windspeed = _windspeed - 20
        else if i = 1 or i = 4 then
            _windspeed = _windspeed - 25
        end if
    end if
    return _windspeed
end


Things to know about output parameters:
1. You can only return one thing at a time. If you want to return multiple things, you need to add each to a list.
2. The function will stop executing after the return command.


Points and Rects

So far we have been using sprite(i).loch and sprite(i).locv to describe
the location of a sprite.
You can also use sprite(i).loc (without the h or v) which will give you a point(loch, locv).

put sprite(i).loc
--point(40, 200)


You can also get/set the coordinates of the sprite's bounding rectangle -
two values for the upper left hand point and two values for the lower right hand point

put sprite(i).rect
-- rect(2, 61, 79, 140)


You can put these kind of values inside a variable or a list.