Author : Filipe Medeiros
Page : << Previous 12 Next >>
low volumes but with your stereo system's volume knob turned right up will also introduce distortion, not to mention noise ;). Try to use the full range of volume values, and also use samples which internally use the full range of values, if possible.
A typical call to play_sample, then, would be:
play_sample (gun_sound, 255, 128, 1000, 0);
which plays `gun_sound' (previously loaded as above) at full volume, centre pan, and its original frequency, without looping it.
play_sample (some_sound, 192, 96, 1200, 1);
would play `some_sound' at 3/4 volume, panned slightly left, a little above its normal pitch, and set it to loop back to the start each time it reached the end.
To stop a sample playing, use the `stop_sample' function:
stop_sample (gun_sound);
This is especially useful on looped samples.
8.2.3 Adjusting a playing sample's parameters
You can also adjust these parameters while a sound is playing. To do this, you call `adjust_sample'. It takes the same parameters as `play_sample', and searches through the list of playing samples for the one you pass. So if `some_sound' is still playing from above, we could make it stop looping like this:
adjust_sample (some_sound, 192, 96, 1200, 0);
We could also have changed some of the other parameters, of course. If you want to adjust samples while they're playing, avoid playing more than one copy of the sample at a time -- `adjust_sample' will only change the first sample it finds, so the others will carry on the way they were.
For a more sophisticated way to play and control samples, which does not suffer from the above problem, see Subsec 8.2.5: Voice functions.
8.2.4 Unloading samples
When you have finished with a sample you can unload it from memory using the `destroy_sample' function like this:
destroy_sample (some_sound);
If the sample is playing at the time, it will automatically be stopped.
8.2.5 Voice functions
This section has not yet been written. It will contain information on using the voice functions directly to gain more control over sounds.
8.3 MIDI music
8.3.1 Loading MIDI music
At present Allegro supports only MIDI music, which it can load from type 0 or type 1 (i.e. most) .MID files.
To load MIDI files you pass the filename to the `load_midi' function, which returns a `MIDI *', or NULL if it's not successful.
8.3.2 Playing MIDI music
To start a MIDI object playing you simply call `play_midi':
play_midi (title_theme, 0);
The second parameter is a loop flag; 0 means no looping, anything else causes the file to loop back to the start when it ends. If you want your file to loop at other positions (for example, if it has an introduction you might want it to skip that when it loops) you can call:
play_looped_midi (background_music, loop_start, loop_end);
When position `loop_end' is reached the player will jump back to `loop_start'. If `loop_end' is -1 the end loop point is the very end of the music. The units for `loop_start' and `loop_end' are beats, as measured by the `midi_pos' variable mentioned below.
In either case you can stop the music by calling `stop_midi':
stop_midi();
Since Allegro can only play one piece of music at a time this function needs no parameters. Starting a piece of music while other music is already playing will stop the first piece immediately. Calling the `stop_midi' function has the same effect as calling `play_midi' with a NULL first parameter.
8.3.3 Controlling MIDI music
While a MIDI file is playing, Allegro increases the global variable `midi_pos' once per beat. If there is no MIDI file playing (or a non-looped file has finished) it will be set to -1.
Note that it won't necessarily increase on every beat -- if the music doesn't play a note on the beat, it won't be updated until the next note is played. If you want to synchronise events with this you need to make sure there's a note on the beat; you could put in a zero volume note, for instance, just to trigger the event.
You can pause and resume playback using the `midi_pause' and `midi_resume' functions. You can jump to a certain position in the file by passing the target `midi_pos' value to the `midi_seek' function. Be aware that seeking backwards involves rewinding the file to the beginning, and then seeking forwards; consequently doing a lot of small reverse seeks isn't a good idea.
Lastly, if the file is looping you can change its loop points on the fly. The two variables are `midi_loop_start' and `midi_loop_end', and are measured in `midi_pos' units. A value of -1 for `midi_loop_start' or `midi_loop_end' indicates the start or end of the file, respectively.
I mentioned earlier that you might have some music with an introduction that you don't want to loop every time, and the `play_looped_midi' function can solve that problem; adjusting the loop points can allow you to do a similar thing if the piece has an ending that you don't want to play while it's looping -- i.e. you want to play the introduction once, then loop the main body of the music a few times, and finally play the ending.
To do this you'd start the music using the `play_looped_midi' function, passing the position of the start of the main part of the music as the loop start parameter and the position of the end of the main part as the loop end parameter. Then you'd let the music play; it will loop each time it reaches the loop end. Later on you'd then set the loop end parameter to the end of the music.
There are a few caveats though:
* `midi_loop_start' must always be earlier in the file than `midi_loop_end'; if your new start value is greater than the old end value then you must alter the end value first, and if your new end value is less than the old start value then you should alter the start value first.
* Excepting the above, it's generally better to change `midi_loop_end' before `midi_loop_start' if the end point is moving later in the file, and to change them the other way around if the end point is moving earlier in the file. This reduces the possibility of extra skipping during the change.
The chances of either of the above being a serious problem are pretty small, but it's better to be safe than sorry. The second one is purely cosmetic.
8.3.4 Unloading MIDI music
To unload a MIDI file use the `destroy_midi' function:
destroy_midi (background_music);
If it's playing at the time, the music will be stopped first.
9.1 Uses of timers
This is a list of some uses of timers. Of course it's not complete -- it's just meant to give you some idea of their most common uses. Some or all of these will appear as examples later on.
* Timing a game
This is probably the most obvious use. You can use a timer to count how long a player has been on a level, perhaps to give them a bonus later for completing it quickly, or to kill them for taking too long.
* Counting a game's frame rate
If you increase a global variable each time you draw a frame to the screen, you can set up a timer to copy this value elsewhere once per second. The place to which it is copied will then show the number of frames drawn in the previous second -- in short, it's the FPS (frames per second) number, or frame rate, of the game. This is very useful when you're finding out how well your game runs on other people's systems; if the number is high, they are getting smooth graphics; if not, the graphics are more jerky.
* Regulating game speed
Earlier you may remember that we briefly tried using a constant delay when moving a circle across the screen, then switched to using `vsync' to control the speed.
The former system is fatally flawed in that the speed of the circle still depends on the speed of the computer -- if we delay 10 ms between draws, and the draws take 5 ms, we'll have one draw every 15 ms; but if the draws take 10 ms, we'll only have one every 20 ms. So much for speed regulation.
Using `vsync' is better; the vertical blanking intervals occur at regular intervals, so provided our drawing and movement always takes less time than a full retrace (or more accurately, always takes the same number of retraces to complete) we'll get a constant speed. If we take a bit too long on the occasional frame, the game will seem to stop for a fraction of a second, because `vsync' will have missed one VBI and
Page : << Previous 12 Next >>