Animating Props

From SCI Wiki
Jump to navigationJump to search

SCI Tutorials

Chapter: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12


Animating Props
Author: Phil Fortier


This will show you how to use Cycle objects to create animations.


A simple animation

Remember that blue box? Go back to the box view, and add a third cel. Color shift it so it’s yellow (or do whatever you want).

Go to your script file, and add at a setCycle method call to the box’s initialization:

Code:
(theBox
    approachVerbs: V_DO
    setCycle: Forward
    init:
)

This uses the Forward cycler to cycle forward through the loops cels. So when you run the game, the blue box will now cycle between blue, red and yellow. Easy!

To adjust the speed, you can set a different cycleSpeed on the object:

Code:
(instance theBox of Prop
    (properties
        view 123
        x 150
        y 100
        signal ignAct
        loop 0
        cel 0
        noun N_BOX
        priority 0
        approachX 130
        approachY 110
        cycleSpeed 15   ; Large numbers are slower.
    )
)


Triggering Off Animation Events

Let’s do something a little more complicated. Let’s make the box shrink when the player touches it. Go back to view 123, and create a new loop. When you create a new loop, by default it should contain the first cel of the previous loop (it has to contain something). That’s great, it’s our blue box.

Add three more cels to the loop. They should all have blue boxes in them by default.

Click on the second cel and resize the borders while holding down the SHIFT key (this makes resizing the borders grow or shrink the view inside). Make the box a little smaller. Click on the third cel and make it even smaller, and so on. You should end up with something like this:

ShrinkingBox.png
 

Now we’ll write code that triggers off the ego performing the V_DO verb on the N_BOX. In that, we’ll make the box cels cycle from beginning to end. To do that, we’ll need to do a few things:

  • Remove the (theBox:setCycle(Forward)) we added in the previous section (in the room’s init()).
  • Make theBox use loop 1 by default (since that’s where our shrinking box is).
  • Add a doVerb method to theBox, and tell the box to cycle from beginning to end.

 

Code:
(instance theBox of Prop
    (properties
        view 123
        x 150
        y 100
        signal ignAct
        loop 1
        cel 0
        noun N_BOX
        priority 0
        approachX 130
        approachY 110
        cycleSpeed 15
    )

    (method (doVerb theVerb)
        (switch theVerb
            (V_DO
                (self setCycle: EndLoop)
            )
            (else
                (super doVerb: theVerb &rest)
            )
        )
    )
)

Compile and run the game to test it.

That’s nice, but what if we want to display a message after the box has shrunk? This is where Script objects come in (not to be confused with script files). With a Script we can choreograph a sequence of events. We’ll make a Script that has a state for shrinking the box, followed by a state for displaying a message. We’ll attach this Script to theBox.

First, create a new Script object (you can use Insert Object->Script for convenience):

Code:
(instance shrinkBoxScript of Script
    (properties)

    (method (changeState newState)
        (= state newState)
        (switch state
            (0)
        )
    )
)

Then, replace our previous handling of theBox doVerb with a call to set the Script on the box:

Code:
(method (doVerb theVerb)
    (switch theVerb
        (V_DO
            (self setScript: shrinkBoxScript)
        )
        (else
            (super doVerb: theVerb &rest)
        )
    )
)

Now add some meat to the shrinkBoxScript.

Code:
(instance shrinkBoxScript of Script
    (properties)

    (method (changeState newState)
        (= state newState)
        (switch state
            (0
                (gGame handsOff:)
                ; We could also say (theBox setCycle: EndLoop self)
                (client setCycle: EndLoop self)
            )
            (1
                (= seconds 2)
            )
            (2
                (Prints {The box shrunk!})
                (gGame handsOn:)
            )
        )
    )
)

Ok, what is all that? First of all, case 0 will be executed as soon as the Script is set on the box. So that will start the cycle to shrink the box. Note that we added a self parameter to the setCycle call. This is a common thing for setCycle (and setMotion). It means that self will be cued() when the cycle is finished. And what happenes when a Script is cued()? It’s changeState() is called with an incremented newState. So basically this is saying: “when we reach the End of the cycle, go to the next state”.

The next state sets the Script’s seconds to 2. So after 2 seconds, changeState will be called again with an incremented newState. In this final case, we print some text to notify the player what happened (of course, we should probably use a message here).

We also put calls to handsOff and handsOn so that the player can’t go and do something else while this short Script is executing (for instance, to prevent them from touching the box again and re-triggering the Script).

Now, the player can keep touching theBox and it will appear large again and shrink down. Because that’s what the End cycle does: Starts from cel 0 and goes to the end. So maybe we should handle that case.

Go to the top of the script and add a local variable:

Code:
(local
    hasBoxShrunk = FALSE
)

Then modify theBox:doVerb() like so:

Code:
(method (doVerb theVerb)
    (switch theVerb
        (V_DO
            (if (not hasBoxShrunk)
                (= hasBoxShrunk TRUE)
                (self setScript: shrinkBoxScript)
            else
                (Prints {What a small box!})
            )
        )
        (else
            (super doVerb: theVerb &rest)
        )
    )
)

Now the box can only shrink once, and we can respond to V_DO with something else when the box is already shrunk.


switchto

This might be a good time to introduce the switchto statement. It’s just like a switch statement, except the cases are implicitly number from 0 upwards. This can be useful if you’re adding and removing lots of cases as you create your room scripts.

This is what shrinkBoxScript’s changeState method looks like if we use a switchto:

Code:
(method (changeState newState)
    (= state newState)
    (switchto state
        (
            (gGame handsOff:)
            ; We could also say (theBox setCycle: EndLoop self)
            (client setCycle: EndLoop self)
        )
        (
            (= seconds 2)
        )
        (
            (Prints {The box shrunk!})
            (gGame handsOn:)
        )
    )
)

It doesn’t look much different, but there’s no chance we miss a state number when we’re adding and removing states.

 

< Previous: The Priority Screen Next: Managing the Player’s Inventory >