Previous: Using the keyboard

Using the mouse

The Acknex engine can be used to create any type of game you can think of and the built in mouse code isn't lagging behind. There are three mouse modes to choose from; each one of these modes can be set using a simple line of code that looks like this:

mouse_mode = 0; // we can use 0, 1 or 2 here

Set "mouse_mode = 0;" and the mouse pointer will become invisible, as if the mouse didn't exist at all (good setting for racing games, shooter games, etc). Use "mouse_mode = 1;" when you want to create a pointer that is visible and also able to control the camera position or angles (ex: first / third person action games, role-playing games). Finally, set "mouse_mode = 2;" to get a pointer that is visible, but can't control the camera. This is the mode for clicking objects, etc (ex: any strategy game, including board games). Don't bother to learn all this stuff now; we will see all the mouse modes in action pretty soon.

Oh, and you've guessed it again: mouse_mode is a predefined variable; you can read more about it in the second part of the manual.

Start WED and open the level named work14, build it and run it:

It looks like nobody is at home... move the mouse around and you will be able to change the camera pan and tilt angles:

Now press the "M" key once and witness the miracle:

A grey crosshair came out of nowhere! I can move the camera around and the crosshair changes it position too!

Press "M" one more time and you will see a cursor on the screen:

Now that's intriguing! The cursor can be moved around but the camera doesn't change its angles anymore!

You can press "M" for as many times as you like to test the three mouse modes; and while you're doing that we will take a look at the code inside the script14 file:

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

BMAP cursor_pcx = "cursor.pcx";
BMAP crosshair_pcx = "crosshair.pcx";

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

function change_mouse_mode()
{
	mouse_mode += 1;
	mouse_mode %= 3;
	if (mouse_mode == 1)
	{
		mouse_map = crosshair_pcx;
	}
	if (mouse_mode == 2)
	{
		mouse_map = cursor_pcx;
	}
}

function main()
{
	level_load ("work14.wmb");
	on_m = change_mouse_mode;
	
	while (1)
	{
		mouse_pos.x = pointer.x;
		mouse_pos.y = pointer.y;
		camera.pan -= mouse_force.x;
		camera.tilt += mouse_force.y;
		wait (1);
	}
}

The code doesn't look too complicated; we've dealt with some of these things before, right?

We have defined two bitmaps for the cursor and the crosshair; you can see the actual picture files inside the \workshop14 folder. Let's see the code used for function main:

function main()
{
    level_load (work14_wmb);
    on_m = change_mouse_mode;

    while (1)
    {
          mouse_pos.x = pointer.x;
          mouse_pos.y = pointer.y;
          camera.pan -= mouse_force.x;
          camera.tilt += mouse_force.y;
          wait (1);
    }
}

We load the level and then we repeat a few lines of code inside a while (1) loop that uses a "wait (1);" instruction too. Let's take a closer look at the first two lines of code inside the while loop:

mouse_pos.x = pointer.x;
mouse_pos.y = pointer.y;

The predefined variables named mouse_pos.x and mouse_pos.y control the position of the mouse pointer on the screen; if I set mouse_pos.x = 200 and mouse_pos.y = 300 (just an example), the pointer appears on the screen just like in the picture below:

Guess what? The predefined variables named pointer.x and pointer.y convert the mouse movement to screen coordinates in pixels - that's exactly the data that was needed for mouse_pos.x and mouse_pos.y! I wonder if they did that on purpose... Anyway, you don't have to remember the whole story; put the two lines of code inside a while loop and you will be able to use the mouse in any project. Oh, and don't forget to add the "wait (1);" instruction inside any of your loops!

Let's take a look at the next two lines of code:

camera.pan -= mouse_force.x;
camera.tilt += mouse_force.y;

Ok, so we're changing the camera pan and tilt using mouse_force.x and mouse_force.y; these are two predefined variables that store the speed with which the mouse is moved horizontally (mouse_force.x) and vertically (mouse_force.y). Whenever you stop the movement, mouse_force.x and mouse_force.y are set to zero, but they can range from -1 to 1.

Let's see the code for the function that changes the predefined variable named mouse_mode:

function change_mouse_mode()
{
     mouse_mode += 1;
     mouse_mode %= 3;
     if (mouse_mode == 1)
     {
          mouse_map = crosshair_pcx;
     }
     if (mouse_mode == 2)
     {
          mouse_map = cursor_pcx;
     }
}

It is pretty clear that this function runs when we press the "M" key. When we start the game, mouse_mode is zero (that's its default value) so the pointer doesn't show up. As soon as we press the "M" key, function change_mouse_mode runs once and then it stops. Let's discuss the first two lines of code:

mouse_mode += 1;
mouse_mode %= 3;

You should remember that "mouse_mode += 1;" is just the shorter version of "mouse_mode = mouse_mode + 1;". Both expressions do the same thing: increase mouse_mode by 1. The initial mouse_mode value was zero, so now mouse_mode == 1. The pointer shows up as a crosshair that can be moved around and the mouse controls the camera at the same time. This is the mouse mode that should be used for an action or a role-playing game (RPG).

The second line of code "mouse_mode %= 3;" is the shorter version for "mouse_mode = mouse_mode % 3;" right? The modulo operator (%) is the remainder of a division between two numbers; for instance 14 % 3 = 2 because 14 = 3 * 4 + 2 and the remainder of the operation is 2.

Why do we need to use this modulo operator? Mainly because we can set the range of the values that result from an operation if we use the modulo operator. If we use "some_number %= 3;" we can be sure that "some_number" can only be 0, 1 or 2. If we use "some_other_number  %= 7;" we can be sure that "some_other_number" can only have one of these values: 0, 1, 2, 3, 4, 5 or 6.

We need to set mouse_mode to a valid value: 0, 1 or 2. What would happen if the player would press "M" five times? We can't allow mouse_mode to be set to 5! The second line of code makes sure that mouse_mode = 2 when we press "M" five times because 5 = 3 * 1 + 2, with 2 being the remainder. You can press "M" for as many times as you want because mouse_mode will change its value this way: 0, 1, 2, 0, 1, 2, 0, 1, 2, ...

Let's take a look at the rest of the code inside function change_mouse_mode:

if (mouse_mode == 1)
{
     mouse_map = crosshair_pcx;
}
if (mouse_mode == 2)
{
     mouse_map = cursor_pcx;
}

These lines of code change the mouse pointer bitmap (predefined as mouse_map) to one of our bitmaps: crosshair_pcx or cursor_pcx. That's all the code there is to be discussed in this script file! You can see that we aren't using any code to hide the mouse pointer when mouse_mode is set to zero; the engine does that by itself. I didn't have to change the mouse pointer bitmaps either, but I wanted to show you how and when you should use a certain type of mouse pointer.

The variables named mouse_force.x and mouse_force.y respond to mouse movement (have non-zero values that can be used in our scripts) only if mouse_mode is set to 0 or 1. Don't expect to be able to move the camera around using the mouse if you have set mouse_mode to 2; that's the mouse mode that should be used for strategy games, board games, etc.

You can mix all the three mouse modes in a single game, just like I did in this workshop. If you want to have a cut scene, you will want to hide the mouse pointer while the characters are talking to each other (mouse_mode = 0); as soon as the cut scene has finished you will want to switch to mouse_mode = 1 or mouse_mode = 2, depending on what type of game you are creating.

Are you ready to try something new? Copy and paste these lines of code into the while loop of function main:

if (mouse_left == on)
{
    camera.ambient += 1;
}
if (mouse_right == on)
{
    camera.ambient -= 1;
}

The resulting script file should look like in the image below (the new lines of code are green):

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

BMAP cursor_pcx = "cursor.pcx";
BMAP crosshair_pcx = "crosshair.pcx";

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

function change_mouse_mode()
{
	mouse_mode += 1;
	mouse_mode %= 3;
	if (mouse_mode == 1)
	{
		mouse_map = crosshair_pcx;
	}
	if (mouse_mode == 2)
	{
		mouse_map = cursor_pcx;
	}
}

function main()
{
	level_load ("work14.wmb");
	on_m = change_mouse_mode;
	
	while (1)
	{
		mouse_pos.x = pointer.x;
		mouse_pos.y = pointer.y;
		camera.pan -= mouse_force.x;
		camera.tilt += mouse_force.y;
		camera.tilt += mouse_force.y;
if (mouse_left == ON)
{
camera.ambient += 1;
}
if (mouse_right == ON)
{
camera.ambient -= 1;
}
wait (1); } }

Run the level again and you will notice something interesting: you can increase and decrease the ambient light in the level by holding down the left or right mouse buttons. The trick is really simple: different camera.ambient values translate to different ambient lights in our levels. What we don't know (yet) is that the mouse buttons use some predefined variables named mouse_left, mouse_middle (not used here) and mouse_right, that are set to "ON" when the corresponding mouse buttons are pressed and are set to "OFF" when the mouse buttons aren't pressed.

Does this line of code ring a bell?

if (key_w == ON)
{
    ........
}

Yes! We have used it to change one of the angles for the camera in our previous workshop! The same method can be used for the three mouse buttons; replace key_something with mouse_something(left, middle or right) and you will be able to control the things using the mouse!

Ok, let's take a break.
 

Next: Using the joystick