Topic : Allegro Vivace
Author : Filipe Medeiros
Page : << Previous 9  Next >>
Go to page :


key combinations which, when pressed, mask out other keys -- even when you have good keyboard routines like Allegro's. It's a hardware limitation. Example `src/6.2/iv/keyclash' is a simple program which repeatedly prints a list of all keys currently flagged by Allegro as pressed; run this and try holding down keys, until you find that a keypress is not detected. On my keyboard, holding down Z, X and C together means pressing F goes unnoticed.
    Even more unfortunately, not all keyboards "clash" in the same places. So how are you supposed to choose keys for your game if they might not work on all systems?
    The answer is, of course, to allow the users to define their own keys. Then if there is a keyclash they can choose some other keys.
    To do this, you will want to replace the `KEY_*' constants in your input routines with variables, which you can initialise to some default values, and allow the user to change them if they want to. Naturally you shouldn't expect the user to know what all the scancodes are; you should write a routine to check this for them.
    Using the `key' array this is fairly trivial; you simply cycle from 1 to the highest scancode there and note which key is pressed. Put this into your `userkey_left' variable, wait for the user to let go of it, and then ask for a right key, and so on. It's safe to assume the first pressed key you find is the only one; what stupid luser would press two keys together when asked for a single key? :)
    The question is, though, how far up the `key' array should you go? Unfortunately Allegro doesn't define the size of the array. As of writing this, the array has 128 elements, but this could change in future versions of Allegro. For now, though, it's the best you can do.

6.2 Joystick input

6.2.1 Digital readings


    Reading the joystick digitally is simple. Make sure the user has the joystick centred (i.e. tell them to centre it and wait for them to acknowledge that they've done this), then call `initialise_joystick()'. Now whenever you want to read from the joystick, call `poll_joystick()'. This reads from the joystick and, among other things, updates the global variables `joy_left', `joy_right', `joy_up' and `joy_down', each indicating whether or not the joystick is pushed in its direction.
    The input code example given in the keyboard section earlier now becomes:

poll_joystick();
if (joy_left) x--; /* if the joystick is pushed to the left, go left */
if (joy_right) x++; /* same for right */ if (joy_up) y--; /* same for up; note that y _decreases_ to go up */
if (joy_down) y++; /* and for down y _increases_ */


    Make sure, though, that the joystick is centred when you initialise it, though. The `initialise_joystick' function returns zero only if there is a joystick present, so you could check this, then ask the user to centre the joystick, and finally call the `initialise_joystick' function again to update the centre position.
    Try modifying the previous example to read the joystick instead of the keyboard. If you get stuck, look at the example program `src/6.3/i'.

6.2.2 The fire buttons

These are easy to read; the average joystick has two, and their status is stored in `joy_b1' and `joy_b2', which go TRUE (non-zero) when the buttons are pressed. As with all of the `joy_*' variables, they are only updated when you call the `poll_joystick' function. If you never call that function, they'll always stay the same; you don't need to call it too often, though. Once per game cycle should be plenty, except when you're checking the following...
    Apparently, most joysticks do not have their fire buttons debounced, so you should be aware that pressing a fire button can cause several changes from `off' to `on' and back; this has never caused me any problems but maybe my joystick just doesn't suffer from this. In most games where this is a problem, setting a maximum fire rate will get around this anyway (i.e. not allowing the user to fire a second time until, say, 20 game cycles have passed). One thing bouncing can really mess up is double-clicks on the joystick button; single presses may look like two (or more) presses. Note though that this is only an issue if the time between joystick polls is very short.
    Try modifying the digital joystick example to make the circle change colour when the fire button is pressed. Try to make it only change once on each press (by waiting for the button to release each time -- remember to poll the joystick inside your waiting loop, otherwise the variables won't get updated). If the colours don't change in the right order, the button may be bouncing; try to debounce it. Now (harder) make it still let you move the circle around while you're holding down fire.
    Examples of all the above are in `src/6.3/ii'; look particularly at the technique used in the last case.

6.2.3 Analogue readings and calibration

The PC joystick is supposed to be an analogue device; in other words, you can find out not only which way the stick is pointing but also how far it is pointing in that direction. However, as Shawn points out in `allegro.txt':
     ...the exact results of this can vary depending on the type of joystick, the speed of your computer, the temperature of the room, and the phases of the moon. If you want to get meaningful input you have to calibrate the joystick before using it, which is a royal pain in the arse.
    Calibration isn't really that hard, but it is a little irritating to the user. Most PC gamers are pretty used to calibrating their joysticks by now, though.
    The point about calibration is that the joystick routines need to find out what range of values the joystick gives, in both the X and Y axes. Allegro does this using three functions: `initialise_joystick', as mentioned before, marks the centre values; `calibrate_joystick_tl' notes the values given when the stick is in the extreme top-left position, and `calibrate_joystick_br' does the same for bottom-right.
    Again, normally you'll want to call `initialise_joystick' once on startup, to see whether or not a joystick is present. If one is, and you later want to calibrate it, follow this sequence:

1. Ask the user to centre joystick, then wait for them to acknowledge (for example, by pressing a key)
2. Call the `initialise_joystick' function to note the centre position
3. Ask the user to push it to the top left and acknowledge
4. Call the `calibrate_joystick_tl' function
5. Ask the user to pull it to the bottom right and acknowledge
6. Call the `calibrate_joystick_br' function

    Now Allegro has everything it needs to know to be able to give you analogue positions. For aesthetic reasons it's a good idea to now have the joystick returned to its centre position; otherwise you might dive into something important with them still holding it in the bottom right hand corner. Either ask them to centre it and acknowledge once again, or keep reading it until they do (see below).
    For an example of this in code, have a look at `src/6.3/calib'.
    Having calibrated the joystick we can at last read its position in more detail. The variables `joy_x' and `joy_y' give its X and Y positions, from -128 to 128, with (-128,-128) being the top left corner, (0,0) being the centre, and (128,128) the bottom right corner.
    Have a go at modifying the circle-moving program to move the circle at a speed relative to how far the stick is moved. `src/6.3/iii' demostrates this in case you can't do it. Note the `#define' near the start; it controls the maximum speed for the circle, which corresponds to full deflection of the joystick. Using a `#define' or a constant variable rather than just a number makes it simpler to change the speed in the future.

6.3 Mouse input

You can view the mouse in one of two ways -- either it is a point-and-click device, or it is somewhat like an analogue joystick, giving direct control over a character.

6.3.1 Point-and-click

The point-and-click approach involves putting a pointer of some sort on the screen, and making the mouse move it around. When a button is pressed you do something, depending on what the mouse is pointing at. Examples of this are WIMP GUIs (like Windows), Dune 1 and 2, Warcraft 1 and 2, numerous front-ends (menus), etc. It is a very popular technique.

6.3.1.1 Initialising the mouse

To initialise the mouse, call `install_mouse()'. As noted in allegro.txt, this returns -1 on failure, or the number of buttons on the mouse if it succeeds.

6.3.1.2 Reading the mouse

Now you

Page : << Previous 9  Next >>