Items that the player can pick up
This tutorial shows you how to place items on the screen, and
allow the player to pick them up.
Step 1: Draw the item
You need to draw two views. One is the item as shown on the
screen, and the other is a close-up view used for when the player
has it in their inventory and examines it. The latter should also
have a description.

Step 2: Adding the item to the OBJECT file.
Because this is an item that the player will be able to carry
around in their inventory, it must be added to the OBJECT file.
The name of the file is a little confusing - it actually has
nothing to do with what we normally refer to as objects (screen
objects), but it contains the list of names of inventory objects
(which I always refer to as inventory items). The name of item 1
should be set to "portable radio". This is the name
that will be displayed in the inventory screen when the player
has the radio.
The room number for this item should also be set to 2. This is
the room number the item is to be found in, and will be used
later to determine if the radio is in the room or not (if set to
255, then the item is put in the player's inventory).
Step 2: Placing the item in the room
To put the item in the room, we will use an object. For this
example I will use object 1, but I want to refer to it as
"radio", so I will define "radio" as o1 at
the top of the logic:
#define radio o1
The object is set up by putting the following code in the
initialization section of the room's logic:
animate.obj(radio);
load.view(2);
set.view(radio,2);
set.loop(radio,0);
set.cel(radio,0);
position(radio,43,104);
set.priority(radio,11);
ignore.objs(radio);
stop.cycling(radio);
draw(radio);
The first 8 lines basically say the following: I want to use
the radio object. Load view 2 into memory and assign it to the
radio. I initially want to display cel 0 of loop 0, and position
it at 43,104 with a priority of 11. And I don't want it to
obstruct or be obstructed by other objects (such as ego).
The priority is set to 11 because that is the same priority as
the bench (as you'll see in the picture included with the
tutorial game). This means that when ego is behind the bench, it
will also be behind the radio and when it is in front of the
bench it will also be in front of the radio.
The stop.cycling command is used to stop it from cycling
through the cels in the loop. There is only 1 cel in the loop for
this object, so the command isn't really necessary, but it is a
good idea to do so in case you add some more cels later or
something. The set.loop and set.cel commands aren't absolutely
necessary either, but it'is also a good idea to use them so you
know for sure which loop and which cel is being used.
The draw command makes the object visible on screen.
Step 3: Modifying logic 90 to handle the new item
Logic 90 in the template game (and hence games that are based
on the template game) handles non-room specific game functions -
things like the player asking to examine items that they have in
their inventory (e.g. typing "look keycard" and being
shown a close-up view of the keycard along with a description).
There are also responses to inputs like "get
<something>" and "look <something>"
that haven't yet been parsed by other logics (in each interpreter
cycle, logic 90 is always called AFTER the room's logic), so for
example if the player is in a forest and types "get remote
control" they'll get a response like "You can't get
that here!" because there is no remote control in the
forest, and hence that input hasn't been parsed (responded to) by
the room's logic.
So for every inventory item in the game, there should be some
code to handle player inputs regarding those items. I always put
responses to the inputs "look <item>" and
"get <item>".
If the player types "look <item>" and they
have the item in their inventory, the show.obj command is used to
show them a close-up of the inventory item along with a
description. If they don't have the item in their inventory, the
flag input_parsed is reset so that the if
(said("look","anyword")) command will pick it
up afterwards and say "What? Where?".
if (said("look","radio")) {
if (has("portable radio")) {
show.obj(220); // 220 is the number of the view with the
// close-up and description of the radio.
}
else {
reset(input_parsed);
}
}
Here is the code that responds to the player's
"look" input if it hasn't been parsed yet:
if ((said("look", "anyword") ||
said("look", "anyword", "anyword"))) {
print("What? Where?");
}
Remember, the said test command always returns false if the
input_parsed flag is set (so the player doesn't get multiple
responses), and always sets the input_parsed flag when it returns
true. So when the player types "look radio", and they
don't have the radio, input_parsed is reset so the second bit of
code will give the response instead of the first.
In the room that the object is to be found, there should be a
test to see if the player has types "look
<item>". If the item is in that room (which can be
tested for using the obj.in.room test command), then it should
give a brief description of the item. Otherwise, it should reset
the input_parsed so that logic 90 will take care of it. Logic 90
will test for the player typing "look <item>",
and if they have the item it will show the close-up. But if they
don't have the item, it will reset input_parsed so that the bit
down the bottom will give the response "What? Where?".
I know this technique wasn't used in the template game, but I
came up with it after that was written.
The other response I put in is to the input "get
<item>". This is done in basically the same way as the
response to "look <item>":
if (said("get","radio")) {
if (has("portable radio")) {
print("You already have it.");
}
else {
reset(input_parsed);
}
}
The modified logic 90 should look like this:
// ****************************************************************************
//
// Logic 90: Game-specific functions
//
// You should use this logic to perform any game specific functions, such as
// counting down timers, etc and processing player input related to the game
// (such as examining/using inventory items) and any other things that are
// required in several rooms that you don't want to duplicate in each room.
//
// This logic is called from logic 0, on every cycle.
// If you like, you could only make it called only when disable_game_functions
// is not set.
//
// Sierra did not use a separate logic for all this - they just did it all
// from logic 0. I find it is neater this way, as you can keep your game
// specific processing separate from other system-related things (although
// these may require some modification for your game). Also, this makes logic 0
// easier to manage.
//
// ****************************************************************************
#include "defines.txt"
// put all non-input-reponse game functions here
if (input_recieved &&
unknown_word_no == 0 &&
!input_parsed) {
// put various input responses here
if (said("die")) { // this one should not be in your game - it is
load.view(1); // only to demostrate the death handler (logic 94)
set.view(ego,1);
program.control();
stop.motion(ego);
death_type = 1;
}
if (said("look","radio")) {
if (has("portable radio")) {
show.obj(220); // 220 is the number of the view with the
// close-up and description of the radio.
}
else {
reset(input_parsed);
}
}
if (said("get","radio")) {
if (has("portable radio")) {
print("You already have it.");
}
else {
reset(input_parsed);
}
}
if ((said("look", "anyword") ||
said("look", "anyword", "anyword"))) {
print("What? Where?");
}
if ((said("get", "anyword") ||
said("get", "anyword", "anyword"))) {
print("You can't get that here!");
}
if ((said("use", "anyword") ||
said("use", "anyword", "anyword"))) {
print("What do you want me to do with it?");
}
}
return();
|
Step 4: Allowing the player to get the item
For the player to pick up the radio, they must walk near it
and type "get radio". When they do this, we first check
if the item is in the current room. Remember how we set the room
number of the item back in step 2? This is where it comes in
handy. If the player has the item in their inventory, it's room
number will be 255, or if they have used it somewhere else then
then it's room number will probably be 0 or the number of that
room. So we test to see if it is in room 2. If it isn't, we reset
input_parsed and let logic 90 give the response - if it's in the
player's inventory they will be shown a close-up of it, otherwise
they will be told it's not there (see step 3).
Next we test the ego's position on screen. If they're in the
right position, we erase the radio object from screen and place
the "portable radio" item in their inventory (the get
command basically sets the item's room number to 255). Otherwise,
they're told they are not close enough.
Note: The obj.in.room command only accepts a variable as the
second parameter, so we must temporarily set the value of some
variable (I'll use v255) to the room we want and then give that
as the parameter.
This is done with the following code:
if (said("get","radio")) {
v255 = 2;
if (obj.in.room("portable radio",v255)) {
if (posn(ego,37,111,51,124)) {
print("Ok.");
erase(radio);
get("portable radio");
}
else {
print("You're not close enough.");
}
}
else {
reset(input_parsed); // let logic 90 take care of it
}
}
Of course, the words "get" and "radio"
must be present in the WORDS.TOK file.
Step 5: Responding to the player typing "look
radio"
As mentioned in step 3, the room's logic should test for the
player typing "look <item>" and if the item is in
the current room, providing a brief description, or if it isn't,
resetting input_parsed so logic 90 will give the response.
if (said("look","radio")) {
v255 = 2;
if (obj.in.room("portable radio",v255)) {
print("There is a portable radio sitting on the bench.");
}
else {
reset(input_parsed); // let logic 90 take care of it
}
}
Step 6: Only showing the item if it is in the room
In the initialization section, you'll notice that the item is
always drawn on screen even if it is not supposed to be there.
There is an easy way around this - and that is to test if the
item is in the room before drawing it. Just replace this line
from the initialization section:
draw(radio);
with this:
v255 = 2;
if (obj.in.room("portable radio",v255)) { draw(radio); }
The finished room with the radio in it should look something
like this:
// ****************************************************************************
//
// Logic 2: Item tutorial room
//
// ****************************************************************************
#include "defines.txt"
#define radio o1
if (new_room) {
load.pic(room_no);
draw.pic(room_no);
discard.pic(room_no);
set.horizon(50);
animate.obj(radio);
load.view(2);
set.view(radio,2);
set.loop(radio,0);
set.cel(radio,0);
position(radio,43,104);
set.priority(radio,11);
ignore.objs(radio);
stop.cycling(radio);
v255 = 2;
if (obj.in.room("portable radio",v255)) { draw(radio); }
// The next 6 lines need only be in the first room of the game
if ((prev_room_no == 1 || // just come from intro screen
prev_room_no == 0)) { // or just started game
position(ego,120,140);
status.line.on();
accept.input();
}
if (prev_room_no == 3) {
position(ego,150,114);
}
draw(ego);
show.pic();
}
if (said("look")) {
print("This is the room for the item tutorial.");
}
if (said("get","radio")) {
v255 = 2;
if (obj.in.room("portable radio",v255)) {
if (posn(ego,37,111,51,124)) {
print("Ok.");
erase(radio);
get("portable radio");
}
else {
print("You're not close enough.");
}
}
else {
reset(input_parsed); // let logic 90 take care of it
}
}
if (said("look","radio")) {
v255 = 2;
if (obj.in.room("portable radio",v255)) {
print("There is a portable radio sitting on the bench.");
}
else {
reset(input_parsed); // let logic 90 take care of it
}
}
if (ego_edge_code == right_edge) { // ego touching right edge of screen
new.room(3);
}
return();
|