Timer

If you want to create a racing game you will certainly need a good timer for it. The function start_counter() will run as soon as you start the level; let's take a look at the code:

string temp_str;
string counter_str;

function start_counter()
{
str_cpy (counter_str, "0.000"); // show this string at start
while (1)
{
if (start == 1)
{
current_ticks = total_ticks - temp_ticks;
seconds = (current_ticks / 16) % 1000;
miliseconds = (current_ticks * 1000 / 16) % 1000;
str_for_num (temp_str, seconds);
str_cpy (counter_str, temp_str);
str_cat (counter_str, ".");
str_for_num (temp_str, miliseconds);
str_trunc (counter_str, 1);
}
else
{
temp_ticks = total_ticks;
}
wait (1);
}
}

function toggle_counter()
{
start = (start == 0);
}

on_s = toggle_counter;

First of all, we copy "0.000" in the string that will be used to display the time; it is always nice to show the counter this way before the race starts. Start = 1 should be set to 1 by our racing game at game start, but I have created a small function (toggle_counter) that sets start to 1 or 0 when the "S" key is pressed.

We will use current_ticks to store the number of frames (ticks) that pass from the moment we started the counter. I'll use some numbers in my example to make the things easier for you.

Let's say that the games has started 10 seconds ago and your frame rate is 60 fps. This means that at this point, total_ticks = 10 seconds * 60 fps = 600, because total_ticks counts the number of frames that have passed since your game has started. Temp_ticks is zero at game start, so current_ticks = 600. We compute the number of seconds and miliseconds, we convert them to strings and we store them in counter_str this way: seconds.miliseconds. If we press "S" again, start = 0 and the "else" branch will run. We know that at this point total_ticks = 600 so temp_ticks (a temporary variable) will be set to 600 too.

Total_ticks keeps counting and counting even if we pause the game, load, save, etc - we can't stop it! When we press "S" again to start the timer, start = 1 and current_ticks = total_ticks - temp_ticks = 0, because the "else" branch copies total_ticks in temp_ticks when the timer is stopped. This way our counter will start from zero every time we reset it.

The time is displayed on the screen using a simple text definition:

text counter_pan
{
layer = 20;
pos_x = 0;
pos_y = 0;
font = speed_font;
string = counter_str;
flags = visible;
}

Vertical mirrors

If you own A5 pro, you are familiar with the horizontal mirror that is placed on the floor in the office level. The code for the vertical mirror is similar, but there are a few tips:
1) The mirror shouldn't be rotated at all in your level. If you want to place a mirror on the wall that faces south, the mirror should be horizontal.

2) The mirror code changes depending on mirror's orientation. Here's the mirror code used in my example:

function init_mirror()
{
camera.portal = mirror;
mirror.noshadow = on; // suppress shadows in the mirror
mirror.noparticle = on; // suppress particles in the mirror
mirror.portalclip = on; // clip at portal plane
while (1)
{
proc_late(); // place it at the end of the function list
mirror.genius = camera.genius;
mirror.aspect = camera.aspect;
mirror.arc = -camera.arc;
mirror.fog = camera.fog;
mirror.x = camera.x;
mirror.y = camera.portal_y - (abs(camera.portal_y - camera.y));
mirror.z = camera.z;
mirror.pan = -camera.pan;
mirror.tilt = camera.tilt;
mirror.roll = camera.roll;
wait(1);
}
}

If you want to place the mirror on your western wall, the code should be modified this way:

function init_mirror()
{
camera.portal = mirror;
mirror.noshadow = on; // suppress shadows in the mirror
mirror.noparticle = on; // suppress particles in the mirror
mirror.portalclip = on; // clip at portal plane
while (1)
{
proc_late(); // place it at the end of the function list
mirror.genius = camera.genius;
mirror.aspect = camera.aspect;
mirror.arc = -camera.arc;
mirror.fog = camera.fog;
mirror.x = camera.portal_x - (abs(camera.portal_x - camera.x));
mirror.y = camera.y;
mirror.z = camera.z;
mirror.pan = -camera.pan;
mirror.tilt = camera.tilt;
mirror.roll = camera.roll;
wait(1);
}
}

3) When you create your mirror entity, set "flat" for the faces that aren't interesting and "mirror" for the face that will be used as the mirror.

4) The back of your mirror should have enough "space" because what you see in the mirror is "created" on the other side of the wall, through the hole, using an imaginary "camera" view.

5) It might be a good idea to place an invisible block in front of your mirror if the player can reach it; if the player penetrates the mirror a little you won't be able to see it. I did that in my example level.

6) Don't forget to set to "none" any surface in the level that surrounds the mirror.

I have included a folder with a vertical mirror demo in aum16.zip; copy the \mirrors folder inside your Gamestudio folder, open mirrors.wmp (not mirror.wmp!), build it and run it.

Happy mirroring!