Previous: Actions

Pointers

Any pointer stores a reference to an object. Let's imagine the following situation: you want to create a pong clone using the Acknex engine:

You want the left paddle to be controlled by the player and the right paddle to be controlled by the computer. The problem is... how can you tell in your code who is the player and who is the computer? The answer is simple: you create a pointer, which is just another name for an object. A typical pointer definition looks like this:

ENTITY the_player;

or

function check_status;

or

STRING my_name;

or

PANEL game_over;

or

BMAP health_picture;

Ok, so it looks like we can define pointers for entities, functions, strings, panels and bitmaps. We simply add a "*" to the object keyword and we have created a pointer.

I know you're feeling a little dizzy right now so let's fire up an example: start WED and open the level file named work11 inside the \workshop11 folder:

The level is a slightly modified version of the level with the house and the wizard model:

This level has 2 wizard models; let's build and run it right away:

Oh, I see! The twin wizard brothers are dressed in red and blue! They don't do anything special but they aren't passing through all their animation frames, like they did in the first workshop; this happens because each wizard has an action attached to it. Attach any action to any entity and it will stop its chaotic animation.

Time to write some console code; press Tab on your keyboard and type the following line:

wizard.x = 300;

The red wizard has come much closer to the camera!

But why did the red wizard move? Why didn't the blue wizard move? Why didn't both wizards move at the same time? And why didn't we see the house moving at all?

I'm afraid I can't cope with that many questions at once, but I'll give you a phrase that answers them all: I have used a pointer for the red wizard. You see, we are living in a cruel world. These nasty computers don't care about us, humans. You and I know how that wizard model looks like but the computer isn't interested in learning that. If you tell a computer to move the red wizard model it will laugh at you; it doesn't know and it doesn't care who and where is the red wizard model. You have to use a pointer for every entity that needs special treatment from your computer.

Let's fire up SED; we will look inside the script file named script11:

Thank God! The script doesn't look complicated at all!

We set the screen resolution and color depth, we define a string named work11_wmb (the level we're going to load) and then we define a pointer named "wizard". Let's take a closer look at this line of code:

ENTITY* wizard;

We have defined a pointer that will be used by an entity and we have named it wizard. We can use any other name here; it doesn't matter if we use a pointer named robot_12 for a monkey.

Function main simply loads the level named work11.wmb. Let's get back to our pointers; we will look at the action named wizard_with_pointer:

action wizard_with_pointer()
{
     wizard = me;
     my.ambient = 100;
}

We have defined a pointer named wizard, right? The first line of code assigns the pointer to the entity that has the action attached to it. In other words, "wizard = me;" means I'm the wizard! I, the entity that has this action attached to it, will be known as "wizard" from now on! And guess what? The action named wizard_with_pointer is attached to the red wizard model so the red wizard model becomes "wizard".

The second line of the action sets the ambient for the red wizard to 100, which makes it look brighter. Curious to see the difference? Take a look at the picture below:

The second action doesn't contain a pointer so all it does is to increase the ambient for the model attached to it.

action wizard_simple()
{
     my.ambient = 100;
}

Well, you've guessed it again... this action is attached to the blue model. Oh, and I forgot to tell you that "my" is a pointer too! It's a predefined pointer so we don't have to write its definition first. Don't worry; we will talk about it close to the end of the workshop.

Ok, so how do we create a pointer? There are two steps:

1) We define the pointer using a single line of code:

ENTITY* horse;

2) We tell the pointer who will be its owner by placing a line that contains its name in the action that interests us:

action players_horse()
{
    horse = me;
    ...
}

From now on you will be able to control the entity that has action players_horse attach to it using the dot method: object.property

Let's play a little more with our test level, shall we? Run the level again and type this line of code at the console:

wizard.z = 100;

The wizard has changed its height indeed! You can play with its x, y, z, pan, tilt, roll, invisible, transparent... If you want to hide the wizard type:

wizard.invisible = ON;

and it will disappear! Type

wizard.invisible = OFF;

and you will be able to see it again.

The good news is that you can change the properties of the red wizard from within any other action or function in your script. Copy and paste the code before the main function of your script10 file:

function move_up()
{
    wizard.z = wizard.z + 5;
}

And put the following line into the main function:

on_u = move_up;

The modified script file should look like this:

//////////////////////////////////////////////////
var video_mode = 7; // 800x600 pixels

//////////////////////////////////////////////////
ENTITY* wizard;

//////////////////////////////////////////////////

function move_up() 
{
wizard.z = wizard.z + 5;
} function main() { level_load ("work11.wmb"); on_u = move_up; } action wizard_with_pointer() { wizard = me; my.ambient = 100; } action wizard_simple() { my.ambient = 100; }

You can see a function named move_up that increases the height (z) of the wizard with 5 units; if its initial height was 15 quants, the function will set it to 20 and so on. Now this line of code looks weird:

on_u = move_up;

Well, on_u means "when the player presses the U key on the keyboard" and move_up is the name of the function, written without parenthesis, that will be executed every time we press the "U" key (it doesn't matter if Caps Lock is on or off). As a conclusion, every time we press the "U" key, function move_up will add 5 more quants to the height of the red wizard.

Save the script, run the level and then press the "U" key several times to move the wizard upwards. It is clear that the function named move_up knows who "wizard" is.

A final note: the most important pointer used by the engine is "my". Let's get back to the action attached to the blue wizard model:

action wizard_simple()
{
     my.ambient = 100;
}

The line of code inside the action sets the ambient to 100 for any entity that is attached to it; "my.ambient = 100;" means "I, the entity that has this action attached to it, will set my ambient to 100". Attach this action to a sprite and the ambient for that sprite will be set to 100; attach it to a wmb entity and it will set its ambient to 100. Pretend that "my" is the universal pointer; every entity can use it but it isn't known outside the action or function that contains it. If you try to type

my.invisible = ON;

at the console it won't work, because "my" isn't known outside its action or function; however, the code below will make invisible the entity that has the action attached to it:

action hide_me
{
    my.invisible = ON;
}
 

Next: If - Else branching