Chapter 15: Programming The First Room

We will now continue the script programming by building upon the first room.

By default, SCI Studio uses the naming system rmXXX for rooms, so the first room is naturally rm001. You could name them anything you like, but this naming system works the best. Sierra used it as well.

Getting Started

In the Game Explorer, there's a list of the game's resources.

| Click on the script folder and the list of scripts in your game will appear on the right, along with a preview of the first script.

| Scroll down the list until you read the "rm001" script. Double click on it, and the script editor will open up.

Programming The Script

Start by scrolling down to the rm001 instance. It is the first instance in the script. This too, can be named anything you wish, but it only makes sense to name it the same name as the script.

| The properties specify the characteristics of your room. picture indicates the number of the picture to use for it's background. The scriptNumber keyword is specified, so it will use the picture with the same number as the script. This being script.001, it will use pic.001. The north, east, south and west properties specify the room numbers that surround the room. If ego walks off the right side of the screen, for example, it will go to the room specified by the east property. If east was 10, for example, it would switch to rm010 (script.010). If their value is zero, then it won't switch to any room.

Positioning Ego

In each room, you'll want the ego to be at a certain position on the screen. To handle this, there is a switch statement at the top of the room instance's init() method. This can be used to check the room that the ego has come from. For example, if the ego came from the west room, you'll want to position in on the left side of the screen. You can put in cases for any or all of the four surrounding rooms. At the end of it is the default case, so if the room the ego has come from doesn't match any of the cases, the default is executed. When starting the game, the default case will be executed since the ego hasn't been in any other rooms. This being the case, it is where you will set up the coordinates for the ego when the game is started.

| Scroll down to the send to gEgo. This code tells the interpreter to position ego at 150 pixels from the left and 130 pixels from the top. It then tells the interpreter to set the ego's loop to loop #1, which is ego facing left. You can change these values. Just remember that the X coordinate must be from 0 to 319, the Y must be from 0 to 189, and the loop must be from 0 to 3.

| Click the "Compile and Run" button and you will see the actor is now part of your game!

Your game will now look something like this:

How Rooms Work

Each room consists of two main instances: a public Rm instance and a local Script instance.

When the game changes to a new room, it calls the Rm instance's init() method. In this case, it's rm001's init() method. This method is executed only once, and used to set things up. The init() method sets up the room's script as the RoomScript instance. As soon as the Rm's init() method is done, your room becomes controlled by the RoomScript instance. The rm001 is just used for initialization.

Using The RoomScript Instance

The RoomScript instance is used to handle and perform all the room's events. There are three methods which you can have in it: the doit() method, the handleEvent() method, and the changeState() method. Some rooms may not need any of these, while some others may use all of them.

The RoomScript Methods
doit
> | If your RoomScript has a doit method, it's code will be executed repeatedly, once per interpreter cycle. How many times per second it is called depends on the speed the game is set to. Example:
> (method (doit) (super:doit()) Display( "Hello World" dsCOORD 0 0 dsCOLOUR Random(0 15) dsBACKGROUND clBLACK ) )
| Inserting the code
The brackets and indents clarify where blocks begin and where blocks end. The RoomScript instance starts with a "(" and ends with a ")". Everything in those brackets is part of the RoomScript. In the current RoomScript instance, there are two elements, the properties block and the handleEvent method. They start with their first "(" and end with their last ")"
Inserting the doit() method, or any other element into the block is simple. You can put it anywhere in the block you like. I just goes between where the block's body begins and where it ends, and before or after any existing elements in the block. Look at the diagram on the left for a visual example. Now, insert the doit() example into your RoomScript instance and run your game. You will see the text "Hello World" flashing in random colours in the top left corner. You can put anything in the doit method that you want to be executed constantly.
If no doit method is in your RoomScript instance, the super class' doit method is executed. When defining your own doit method, you'll still want the super's doit method to be executed, so you must insert the line (super:doit()) at the beginning of it. This ensures that your doit method will perform everything it's supposed to. In this case the super is Script, so (Script:doit()) is the method actually executed.
handleEvent
> | The handleEvent method is the most important method for rooms. It handles the input from the user, including the text that they enter in the "Enter Input" dialog. This is where you check what they input and perform the the tasks complementary to it. Example:
> (method (handleEvent pEvent) (super:handleEvent(pEvent)) (if(Said('look')) Print("You are in an empty room") )(else (if(Said('take/key')) Print("O.K.") (send gEgo:get(INV_KEY)) ) ) )
Like the doit method, you must insert the line (super:handleEvent(pEvent)) at the beginning of it. This ensures that your handleEvent method will perform everything it's supposed to. This checks if the user enters "look". If they do, it prints "You are in an empty room". Otherwise, if they enter "take key", it prints "O.K." and adds the key to the ego's inventory. Said statements will be fully explained in the next chapter, and the inventory in the chapter following that.
changeState
> | The changeState method is similar to the doit method, but it is only executed if your set it up to be. This can be used in any room, but it primarily used on the title screen. For example, you can use this to draw a view, then move it for 3 seconds, then play a sound for 5 seconds, then draw a different view, then animate it for 8 seconds, then wait for 10 seconds, then go to another screen, etc. You can use this for absolutely anything you want. Each RoomScript instance has state and cycles properties. The state property indicates which state case should be executed. The cycles property specifies how many interpreter cycles to wait before executing the next state. If cycles is not set in your changeState, it stops (see case 4 in the example). The actual time in seconds of the cycles varies depending on the game speed. With the game speed set to 1, 60 cycles equals about one second. However, if the speed was set to 2 for example, 30 cycles would be about one second. The default speed gives about 10 cycles per second. You should never set the game speed to 0 when doing timed animation, as it will remove the cycle delay, which will give unpredictable speeds from computer to computer. Example:
> (method (changeState newState) = state newState (switch(state) (case 0 Display( "State 0: waiting 20 cycles..." dsCOORD 0 0 dsCOLOUR clWHITE dsBACKGROUND clBLACK ) = cycles 20 ) (case 1 Display( "State 1: waiting 50 cycles..." dsCOORD 0 0 dsCOLOUR clWHITE dsBACKGROUND clBLACK ) = cycles 50 ) (case 2 Display( "State 2: waiting 10 cycles..." dsCOORD 0 0 dsCOLOUR clWHITE dsBACKGROUND clBLACK ) = cycles 10 ) (case 3 Display( "State 3: waiting 40 cycles..." dsCOORD 0 0 dsCOLOUR clWHITE dsBACKGROUND clBLACK ) = cycles 40 ) (case 4 Display( "State 4: this is the last cycle." dsCOORD 0 0 dsCOLOUR clWHITE dsBACKGROUND clBLACK ) ) ) )
> Paste the example into your RoomScript instance and see it for yourself. Then, change some values to get familiar with it. The start property, by default, 0, specifies the first state to execute. The start state is executed as soon as the RoomScript is initialized. As stated, if the cycles property is not set in the changeState method, it stops. However, you can call any state you want with the (RoomScript:cue(aState)) method and the changeState will begin executing again.
> | Note that your can use the "seconds" property instead of the cycles property. However, for animation, you should generally use the "cycles" property since they player could have the game set to any speed.

That concludes the RoomScript instance. In the next chapter, you will learn all about handling the user's "Said" input.

<< Prev | Next >>