______ ___ ___ /\ _ \ /\_ \ /\_ \ \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ /\____/ \_/__/ Version 4.2.2 A game programming library. By Shawn Hargreaves, Jul 22, 2007. See the AUTHORS file for a complete list of contributors.
#include <std_disclaimer.h>
"I do not accept responsibility for any effects, adverse or otherwise, that this code may have on you, your computer, your sanity, your dog, and anything else that you can think of. Use it at your own risk."
API
Platform specifics
Miscellaneous
Tools
See readme.txt for a general introduction, copyright details, and information about how to install Allegro and link your program with it.
The available system ID codes will vary from one platform to another, but you will almost always want to pass SYSTEM_AUTODETECT. Alternatively, SYSTEM_NONE installs a stripped down version of Allegro that won't even try to touch your hardware or do anything platform specific: this can be useful for situations where you only want to manipulate memory bitmaps, such as the text mode datafile tools or the Windows GDI interfacing functions.
The `errno_ptr' and `atexit_ptr' parameters should point to the errno variable and atexit function from your libc: these are required because when Allegro is linked as a DLL, it doesn't have direct access to your local libc data. `atexit_ptr' may be NULL, in which case it is your responsibility to call allegro_exit() manually. Example:
install_allegro(SYSTEM_AUTODETECT, &errno, atexit);
Return value: This function returns zero on success and non-zero on failure (e.g. no system driver could be used). Note: in previous versions of Allegro this function would abort on error.
See also: allegro_init, allegro_exit, set_uformat, set_config_file.
See also: install_allegro, allegro_exit.
Examples using this: Available Allegro examples.
Note that after you call this function, other functions like destroy_bitmap() will most likely crash. This is a problem for C++ global destructors, which usually get called after atexit(), so don't put Allegro calls in them. You can write the destructor code in another method which you can manually call before your program exits, avoiding this problem.
See also: install_allegro, allegro_init, destroy_bitmap.
Examples using this: ex3d, exscn3d, exswitch, exxfade, exzbuf.
int main(void) { allegro_init(); /* more stuff goes here */ ... return 0; } END_OF_MAIN()
See also: Windows specifics, Unix specifics, MacOS X specifics, Differences between platforms.
Examples using this: Available Allegro examples.
void abort_on_error(const char *message) { if (screen != NULL) set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); allegro_message("%s.\nLast Allegro error `%s'\n", message, allegro_error); exit(-1); } ... if (some_allegro_function() == ERROR_CODE) abort_on_error("Error calling some function!");
See also: set_gfx_mode, install_sound.
Examples using this: Available Allegro examples.
const int year = ALLEGRO_DATE / 10000; const int month = (ALLEGRO_DATE / 100) % 100; const int day = ALLEGRO_DATE % 100; allegro_message("Year %d, month %d, day %d\n", year, month, day);
#define OSTYPE_LINUX AL_ID('T','U','X',' ')
See also: DAT_ID.
/* Check if the current version is compatible with Allegro 4.2.0 */ #if (MAKE_VERSION(4, 2, 0) <= MAKE_VERSION(ALLEGRO_VERSION, \ ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)) /* Allegro 4.2.0 compatibility */ #else /* Work-around */ #endif
See also: ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION.
OSTYPE_UNKNOWN - unknown, or regular MSDOS OSTYPE_WIN3 - Windows 3.1 or earlier OSTYPE_WIN95 - Windows 95 OSTYPE_WIN98 - Windows 98 OSTYPE_WINME - Windows ME OSTYPE_WINNT - Windows NT OSTYPE_WIN2000 - Windows 2000 OSTYPE_WINXP - Windows XP OSTYPE_WIN2003 - Windows 2003 OSTYPE_WINVISTA - Windows Vista OSTYPE_OS2 - OS/2 OSTYPE_WARP - OS/2 Warp 3 OSTYPE_DOSEMU - Linux DOSEMU OSTYPE_OPENDOS - Caldera OpenDOS OSTYPE_LINUX - Linux OSTYPE_SUNOS - SunOS/Solaris OSTYPE_FREEBSD - FreeBSD OSTYPE_NETBSD - NetBSD OSTYPE_IRIX - IRIX OSTYPE_DARWIN - Darwin OSTYPE_QNX - QNX OSTYPE_UNIX - Unknown Unix variant OSTYPE_BEOS - BeOS OSTYPE_MACOS - MacOS OSTYPE_MACOSX - MacOS X
See also: allegro_init, os_version, os_multitasking.
See also: os_type, os_multitasking.
See also: os_type, os_version.
On platforms featuring a windowing system, it will bring up a blocking GUI message box. If there is no windowing system, it will try to print the string to a text console, attempting to work around codepage differences by reducing any accented characters to 7-bit ASCII approximations. Example:
if (allegro_init() != 0) exit(1); if (init_my_data() != 0) { allegro_message("Sorry, missing game data!\n"); exit(2); }
See also: allegro_init, install_allegro, set_uformat.
Examples using this: Available Allegro examples.
set_window_title("Allegro rules!");
See also: set_close_button_callback, set_uformat.
Examples using this: exunicod.
This function should not generally attempt to exit the program or save any data itself. The function could be called at any time, and there is usually a risk of conflict with the main thread of the program. Instead, you should set a flag during this function, and test it on a regular basis in the main loop of the program.
Pass NULL as the `proc' argument to this function to disable the close button functionality, which is the default state.
Note that Allegro cannot intercept the close button of a DOS box in Windows.
Also note that the supplied callback is also called under MacOS X when the user hits Command-Q or selects "Quit" from the application menu. Example:
volatile int close_button_pressed = FALSE; void close_button_handler(void) { close_button_pressed = TRUE; } END_OF_FUNCTION(close_button_handler) ... allegro_init(); LOCK_FUNCTION(close_button_handler); set_close_button_callback(close_button_handler); ... while (!close_button_pressed) do_stuff();
Return value: Returns zero on success and non-zero on failure (e.g. the feature is not supported by the platform).
See also: set_window_title.
Under some OSes, switching to a full screen graphics mode may automatically change the desktop color depth. You have, therefore, to call this function before setting any graphics mode in order to retrieve the real desktop color depth. Example:
allegro_init(); ... if ((depth = desktop_color_depth()) != 0) { set_color_depth(depth); }
Return value: Returns the color depth or zero on platforms where this information is not available or does not apply.
See also: get_desktop_resolution, set_color_depth, set_gfx_mode.
Under some OSes, switching to a full screen graphics mode may automatically change the desktop resolution. You have, therefore, to call this function before setting any graphics mode in order to retrieve the real desktop resolution. Example:
int width, height; allegro_init(); ... if (get_desktop_resolution(&width, &height) == 0) { /* Got the resolution correctly */ }
Return value: Returns zero on success, or a negative number if this information is not available or does not apply, in which case the values stored in the variables you provided for `width' and `height' are undefined.
See also: desktop_color_depth, set_gfx_mode.
See also: cpu_vendor, cpu_family, cpu_model, cpu_capabilities, allegro_init.
See also: check_cpu, cpu_family, cpu_model, cpu_capabilities, allegro_init.
You can read this variable after you have called check_cpu() (which is automatically called by allegro_init()).CPU_FAMILY_UNKNOWN - The type of processor is unknown CPU_FAMILY_I386 - The processor is an Intel-compatible 386 CPU_FAMILY_I486 - The processor is an Intel-compatible 486 CPU_FAMILY_I586 - The processor is a Pentium or equivalent CPU_FAMILY_I686 - The processor is a Pentium Pro, II, III or equivalent CPU_FAMILY_ITANIUM - The processor is an Itanium processor CPU_FAMILY_POWERPC - The processor is a PowerPC processor CPU_FAMILY_EXTENDED - The processor type needs to be read from the cpu_model
See also: check_cpu, cpu_vendor, cpu_model, cpu_capabilities, allegro_init.
You can read this variable after you have called check_cpu() (which is automatically called by allegro_init()). Make sure you check the cpu_family and cpu_vendor so you know which models make sense to check.CPU_FAMILY_I586: CPU_MODEL_PENTIUM, CPU_MODEL_K5, CPU_MODEL_K6 CPU_FAMILY_I686: CPU_MODEL_PENTIUMPRO, CPU_MODEL_PENTIUMII, CPU_MODEL_PENTIUMIIIKATMAI, CPU_MODEL_PENTIUMIIICOPPERMINE, CPU_MODEL_ATHLON, CPU_MODEL_DURON CPU_FAMILY_EXTENDED: CPU_MODEL_PENTIUMIV, CPU_MODEL_XEON, CPU_MODEL_ATHLON64, CPU_MODEL_OPTERON CPU_FAMILY_POWERPC: CPU_MODEL_POWERPC_x, for x=601-604, 620, 750, 7400, 7450
See also: check_cpu, cpu_vendor, cpu_family, cpu_capabilities, allegro_init.
You can check for multiple features by OR-ing the flags together. For example, to check if the CPU has an FPU and MMX instructions available, you'd do:CPU_ID - Indicates that the "cpuid" instruction is available. If this is set, then all Allegro CPU variables are 100% reliable, otherwise there may be some mistakes. CPU_FPU - An FPU is available. CPU_IA64 - Running on Intel 64 bit CPU CPU_AMD64 - Running on AMD 64 bit CPU CPU_MMX - Intel MMX instruction set is available. CPU_MMXPLUS - Intel MMX+ instruction set is available. CPU_SSE - Intel SSE instruction set is available. CPU_SSE2 - Intel SSE2 instruction set is available. CPU_SSE3 - Intel SSE3 instruction set is available. CPU_3DNOW - AMD 3DNow! instruction set is available. CPU_ENH3DNOW - AMD Enhanced 3DNow! instruction set is available. CPU_CMOV - Pentium Pro "cmov" instruction is available.
You can read this variable after you have called check_cpu() (which is automatically called by allegro_init()).if ((cpu_capabilities & (CPU_FPU | CPU_MMX)) == (CPU_FPU | CPU_MMX)) { printf("CPU has both an FPU and MMX instructions!\n"); }
See also: check_cpu, cpu_vendor, cpu_family, cpu_model, cpu_capabilities, allegro_init.
There are several structures and types defined by Allegro which are used in many functions (like the BITMAP structure). This section of the manual describes their useful content from a user point of view when they don't fit very well any of the existing manual sections, and redirects you to the appropriate section when it's already described there. Note that unless stated otherwise, the contents shown here are just for read only purposes, there might be other internal flags, but you shouldn't depend on them being available in past/future versions of Allegro.
See also: Fixed point math routines.
Examples using this: ex12bit, ex3buf, ex3d, excustom, exfixed, exspline, exsprite, exstars, exupdate.
There is some other stuff in the structure as well, but it is liable to change and you shouldn't use anything except the above. The `w' and `h' fields can be used to obtain the size of an existing bitmap:int w, h; - size of the bitmap in pixels int clip; - non-zero if clipping is turned on int cl, cr, ct, cb; - clip rectangle left, right, top, and bottom unsigned char *line[]; - pointers to the start of each line
The clipping rectangle is inclusive on the left and top (0 allows drawing to position 0) but exclusive on the right and bottom (10 allows drawing to position 9, but not to 10). Note this is not the same format as that of the clipping API, which takes inclusive coordinates for all four corners. All the values of this structure should be regarded as read-only, with the exception of the line field, whose access is described in depth in the "Direct access to video memory" section of the manual. If you want to modify the clipping region, please refrain from changing this structure. Use set_clip_rect() instead.bmp = load_bitmap("file.bmp", pal); allegro_message("Bitmap size: (%dx%d)\n", bmp->w, bmp->h);
See also: create_bitmap, set_clip_rect, bitmap_color_depth, RLE_SPRITE, COMPILED_SPRITE, Direct access to video memory.
Examples using this: Available Allegro examples.
RLE sprites store the image in a simple run-length encoded format, where repeated zero pixels are replaced by a single length count, and strings of non-zero pixels are preceded by a counter giving the length of the solid run. Read chapter "RLE sprites" for a description of the restrictions and how to obtain/use this structure.int w, h; - width and height in pixels int color_depth; - color depth of the image
See also: get_rle_sprite, BITMAP, COMPILED_SPRITE, RLE sprites.
Compiled sprites are stored as actual machine code instructions that draw a specific image onto a bitmap, using mov instructions with immediate data values. Read chapter "Compiled sprites" for a description of the restrictions and how to obtain/use this structure.short planar; - set if it's a planar (mode-X) sprite short color_depth; - color depth of the image short w, h; - size of the sprite
See also: get_compiled_sprite, BITMAP, RLE_SPRITE, Compiled sprites.
Read chapter "Joystick routines" for a description on how to obtain/use this structure.int flags; - status flags for this joystick int num_sticks; - how many stick inputs? int num_buttons; - how many buttons? JOYSTICK_STICK_INFO stick[n]; - stick state information JOYSTICK_BUTTON_INFO button[n]; - button state information
See also: joy, Joystick routines.
Read chapter "Joystick routines" for a description on how to obtain/use this structure.int b; - boolean on/off flag char *name; - description of this button
See also: joy, Joystick routines.
Read chapter "Joystick routines" for a description on how to obtain/use this structure.int flags; - status flags for this input int num_axis; - how many axes do we have? (note the misspelling) JOYSTICK_AXIS_INFO axis[n]; - axis state information char *name; - description of this input
See also: joy, Joystick routines.
Read chapter "Joystick routines" for a description on how to obtain/use this structure.int pos; - analogue axis position int d1, d2; - digital axis position char *name; - description of this axis
See also: joy, Joystick routines.
Structure returned by get_gfx_mode_list, which contains an array of GFX_MODE structures.int num_modes; GFX_MODE *mode;
See also: GFX_MODE, get_gfx_mode_list.
Structure contained in GFX_MODE_LIST.int width, height, bpp;
See also: GFX_MODE_LIST, get_gfx_mode_list.
See also: RGB, PALETTE, COLOR_MAP.
See also: RGB, Palette routines.
Examples using this: Available Allegro examples.
Palette entry. It contains an additional field for the purpose of padding but you should not usually care about it. Read chapter "Palette routines" for a description on how to obtain/use this structure.unsigned char r, g, b;
See also: Palette routines, PALETTE.
Examples using this: ex12bit, ex3d, excolmap, exconfig, expal, exrgbhsv, exscroll, exshade, extrans, extruec.
A vertex structure used by polygon3d and other polygon rendering functions. Read the description of polygon3d() for a description on how to obtain/use this structure.fixed x, y, z; - position fixed u, v; - texture map coordinates int c; - color
See also: V3D_f, polygon3d, Fixed point trig.
Examples using this: ex3d.
Like V3D but using float values instead of fixed ones. Read the description of polygon3d_f() for a description on how to obtain/use this structure.float x, y, z; - position float u, v; - texture map coordinates int c; - color
See also: V3D, polygon3d_f, Fixed point trig.
Examples using this: excamera, exscn3d, exzbuf.
Read chapter "Transparency and patterned drawing", section "256-color transparency" for a description on how to obtain/use this structure.unsigned char data[PAL_SIZE][PAL_SIZE];
See also: 256-color transparency, color_map.
Examples using this: ex3d, excolmap, exlights, exshade, extrans.
Read chapter "Converting between color formats" for a description on how to obtain/use this structure.unsigned char data[32][32][32];
See also: Converting between color formats, create_rgb_table.
Examples using this: ex3d, excolmap, exrgbhsv, exshade, extrans.
Read the description of al_findfirst for a description on how to obtain/use this structure.int attrib; - actual attributes of the file found time_t time; - modification time of file char name[512]; - name of file
See also: al_findfirst, al_ffblk_get_size.
Read chapter "Datafile routines", section "Using datafiles" for a description on how to obtain/use this structure.void *dat; - pointer to the actual data int type; - type of the data long size; - size of the data in bytes void *prop; - list of object properties
See also: load_datafile, Using datafiles.
Examples using this: excustom, exdata, exexedat, exgui, exsprite, exunicod.
Fixed point matrix structure. Read chapter "3D math routines" for a description on how to obtain/use this structure.fixed v[3][3]; - 3x3 scaling and rotation component fixed t[3]; - x/y/z translation component
See also: MATRIX_f, 3D math routines.
Examples using this: ex12bit, ex3d, exstars.
Floating point matrix structure. Read chapter "3D math routines" for a description on how to obtain/use this structure.float v[3][3]; - 3x3 scaling and rotation component float t[3]; - x/y/z translation component
See also: MATRIX, 3D math routines.
Examples using this: excamera, exquat, exscn3d, exzbuf.
Read chapter "Quaternion math routines" for a description on how to obtain/use this structure.float w, x, y, z;
See also: Quaternion math routines.
Examples using this: exquat.
This is the structure which contains a GUI object. Read chapter "GUI routines" for a description on how to obtain/use this structure.int (*proc)(int, DIALOG *, int); - dialog procedure (message handler) int x, y, w, h; - position and size of the object int fg, bg; - foreground and background colors int key; - ASCII keyboard shortcut int flags; - flags about the status of the object int d1, d2; - whatever you want to use them for void *dp, *dp2, *dp3; - pointers to more object-specific data
See also: do_dialog, GUI routines.
Examples using this: excustom, exgui, exrgbhsv.
Structure used to hold an entry of a menu. Read chapter "GUI routines", section "GUI menus" for a description on how to obtain/use this structure.char *text; - the text to display for the menu item int (*proc)(void); - called when the menu item is clicked struct MENU *child; - nested child menu int flags; - disabled or checked state void *dp; - pointer to any data you need
See also: do_menu, GUI menus.
Examples using this: exgui.
See also: init_dialog, update_dialog, shutdown_dialog, GUI routines.
See also: init_menu, update_menu, shutdown_menu, GUI menus.
See also: font.
Examples using this: excustom, exfont, exunicod.
See also: Zbuffered rendering, BITMAP.
Examples using this: exzbuf.
A sample structure, which holds sound data, used by the digital sample routines. You can consider all of these fields as read only except priority, loop_start and loop_end, which you can change them for example after loading a sample from disk.int bits; - 8 or 16 int stereo; - sample type flag int freq; - sample frequency int priority; - 0-255 unsigned long len; - length (in samples) unsigned long loop_start; - loop start position unsigned long loop_end; - loop finish position void *data; - raw sample data
The priority is a value from 0 to 255 (by default set to 128) and controls how hardware voices on the sound card are allocated if you attempt to play more than the driver can handle. This may be used to ensure that the less important sounds are cut off while the important ones are preserved.
The variables loop_start and loop_end specify the loop position in sample units, and are set by default to the start and end of the sample.
If you are creating your own samples on the fly, you might also want to modify the raw data of the sample pointed by the data field. The sample data are always in unsigned format. This means that if you are loading a PCM encoded sound file with signed 16-bit samples, you would have to XOR every two bytes (i.e. every sample value) with 0x8000 to change the signedness.
See also: load_sample, Digital sample routines, Voice control.
Examples using this: exsample.
See also: load_midi, Music routines (MIDI).
Examples using this: exmidi.
A structure holding an audiostream, which is a convenience wrapper around a SAMPLE structure to double buffer sounds too big to fit into memory, or do clever things like generating the sound wave real time.int voice; - the hardware voice used for the sample
While you shouldn't modify directly the value of the voice, you can use all of the voice functions in chapter "Digital sample routines" to modify the properties of the sound, like the frequency.
See also: play_audio_stream, Audio stream routines, Voice control.
Examples using this: exstream.
See also: File and compression routines, pack_fopen, pack_fopen_chunk, pack_fopen_vtable.
Examples using this: expackf.
This is the vtable which must be provided for custom packfiles, which then can read from and write to wherever you like (eg. files in memory). You should provide all the entries of the vtable, even if they are empty stubs doing nothing, to avoid Allegro (or you) calling a NULL method at some point.int pf_fclose(void *userdata); int pf_getc(void *userdata); int pf_ungetc(int c, void *userdata); long pf_fread(void *p, long n, void *userdata); int pf_putc(int c, void *userdata); long pf_fwrite(const void *p, long n, void *userdata); int pf_fseek(void *userdata, int offset); int pf_feof(void *userdata); int pf_ferror(void *userdata);
See also: File and compression routines, pack_fopen_vtable.
Examples using this: expackf.
See also: File and compression routines, create_lzss_pack_data.
See also: File and compression routines, create_lzss_unpack_data.
Allegro can manipulate and display text using any character values from 0 right up to 2^32-1 (although the current implementation of the grabber can only create fonts using characters up to 2^16-1). You can choose between a number of different text encoding formats, which controls how strings are stored and how Allegro interprets strings that you pass to it. This setting affects all aspects of the system: whenever you see a function that returns a char * type, or that takes a char * as an argument, that text will be in whatever format you have told Allegro to use.
By default, Allegro uses UTF-8 encoded text (U_UTF8). This is a variable-width format, where characters can occupy anywhere from one to four bytes. The nice thing about it is that characters ranging from 0-127 are encoded directly as themselves, so UTF-8 is upwardly compatible with 7-bit ASCII ("Hello, World!" means the same thing regardless of whether you interpret it as ASCII or UTF-8 data). Any character values above 128, such as accented vowels, the UK currency symbol, and Arabic or Chinese characters, will be encoded as a sequence of two or more bytes, each in the range 128-255. This means you will never get what looks like a 7-bit ASCII character as part of the encoding of a different character value, which makes it very easy to manipulate UTF-8 strings.
There are a few editing programs that understand UTF-8 format text files. Alternatively, you can write your strings in plain ASCII or 16-bit Unicode formats, and then use the Allegro textconv program to convert them into UTF-8.
If you prefer to use some other text format, you can set Allegro to work with normal 8-bit ASCII (U_ASCII), or 16-bit Unicode (U_UNICODE) instead, or you can provide some handler functions to make it support whatever other text encoding you like (for example it would be easy to add support for 32 bit UCS-4 characters, or the Chinese GB-code format).
There is some limited support for alternative 8-bit codepages, via the U_ASCII_CP mode. This is very slow, so you shouldn't use it for serious work, but it can be handy as an easy way to convert text between different codepages. By default the U_ASCII_CP mode is set up to reduce text to a clean 7-bit ASCII format, trying to replace any accented vowels with their simpler equivalents (this is used by the allegro_message() function when it needs to print an error report onto a text mode DOS screen). If you want to work with other codepages, you can do this by passing a character mapping table to the set_ucodepage() function.
Note that you can use the Unicode routines before you call install_allegro() or allegro_init(). If you want to work in a text mode other than UTF-8, it is best to set it with set_uformat() just before you call these.
Although you can change the text format on the fly, this is not a good idea. Many strings, for example the names of your hardware drivers and any language translations, are loaded when you call allegro_init(), so if you change the encoding format after this, they will be in the wrong format, and things will not work properly. Generally you should only call set_uformat() once, before allegro_init(), and then leave it on the same setting for the duration of your program.U_ASCII - fixed size, 8-bit ASCII characters U_ASCII_CP - alternative 8-bit codepage (see set_ucodepage()) U_UNICODE - fixed size, 16-bit Unicode characters U_UTF8 - variable size, UTF-8 format Unicode characters
See also: get_uformat, register_uformat, set_ucodepage, set_uformat, uconvert, ustrsize, ugetc, ugetx, usetc, uwidth, ucwidth, uisok, uoffset, ugetat, usetat, uinsert, uremove, allegro_init.
Examples using this: exunicod.
switch(get_uformat()) { case U_ASCII: do_something(); break; case U_UTF8: do_something_else(); break; ... }
Return value: Returns the currently selected text encoding format. See the documentation of set_uformat() for a list of encoding formats.
See also: set_uformat.
See also: set_uformat, uconvert, ugetc, ugetx, usetc, uwidth, ucwidth, uisok.
The `table' parameter points to an array of 256 shorts, which contain the Unicode value for each character in your codepage. The `extras' parameter, if not NULL, points to a list of mapping pairs, which will be used when reducing Unicode data to your codepage. Each pair consists of a Unicode value, followed by the way it should be represented in your codepage. The list is terminated by a zero Unicode value. This allows you to create a many->one mapping, where many different Unicode characters can be represented by a single codepage value (eg. for reducing accented vowels to 7-bit ASCII).
Allegro will use the `table' parameter when it needs to convert an ASCII string to an Unicode string. But when Allegro converts an Unicode string to ASCII, it will use both parameters. First, it will loop through the `table' parameter looking for an index position pointing at the Unicode value it is trying to convert (ie. the `table' parameter is also used for reverse matching). If that fails, the `extras' list is used. If that fails too, Allegro will put the character `^', giving up the conversion.
Note that Allegro comes with a default `table' and `extras' parameters set internally. The default `table' will convert 8-bit characters to `^'. The default `extras' list reduces Latin-1 and Extended-A characters to 7 bits in a sensible way (eg. an accented vowel will be reduced to the same vowel without the accent).
See also: set_uformat.
if (need_uconvert(text, U_UTF8, U_CURRENT)) { /* conversion is required */ }
Return value: Returns non-zero if any conversion is required or zero otherwise.
See also: set_uformat, get_uformat, do_uconvert, uconvert.
length = uconvert_size(old_string, U_CURRENT, U_UNICODE); new_string = malloc(length); ustrcpy(new_string, old_string);
Return value: Returns the number of bytes required to store the string after conversion.
See also: need_uconvert, do_uconvert.
Note that, even for empty strings, your destination string must have at least enough bytes to store the terminating null character of the string, and your parameter size must reflect this. Otherwise, the debug version of Allegro will abort at an assertion, and the release version of Allegro will overrun the destination buffer.char temp_string[256]; do_uconvert(input_string, U_CURRENT, temp_string, U_ASCII, 256);
See also: uconvert.
As a convenience, if `buf' is NULL it will convert the string into an internal static buffer and the `size' parameter will be ignored. You should be wary of using this feature, though, because that buffer will be overwritten the next time this routine is called, so don't expect the data to persist across any other library calls. The static buffer may hold less than 1024 characters, so you won't be able to convert large chunks of text. Example:
char *p = uconvert(input_string, U_CURRENT, buffer, U_ASCII, 256);
Return value: Returns a pointer to `buf' (or the static buffer if you used NULL) if a conversion was performed. Otherwise returns a copy of `s'. In any cases, you should use the return value rather than assuming that the string will always be moved to `buf'.
See also: set_uformat, need_uconvert, uconvert, uconvert_ascii, uconvert_toascii, do_uconvert.
See also: uconvert.
Examples using this: exunicod.
See also: uconvert.
int first_unicode_letter = ugetc(text_string);
Return value: Returns the character pointed to by `s' in the current encoding format.
See also: ugetx, usetc, uwidth, ucwidth, uisok.
char *p = string; int first_letter, second_letter, third_letter; first_letter = ugetx(&p); second_letter = ugetx(&p); third_letter = ugetx(&p);
Return value: Returns the character pointed to by `s' in the current encoding format, and advances the pointer to the next character after the one just returned.
See also: ugetc, usetc, uwidth, ucwidth, uisok.
Return value: Returns the number of bytes written, which is equal to the width of the character in the current encoding format.
See also: ugetc, ugetx, uwidth, ucwidth, uisok.
Return value: Returns the number of bytes occupied by the first character of the specified string, in the current encoding format.
See also: uwidth_max, ugetc, ugetx, usetc, ucwidth, uisok.
Return value: Returns the number of bytes that would be occupied by the specified character value, when encoded in the current format.
See also: uwidth_max, ugetc, ugetx, usetc, uwidth, uisok.
Return value: Returns non-zero if the value can be correctly encoded, zero otherwise.
See also: ugetc, ugetx, usetc, uwidth, ucwidth.
int from_third_letter = uoffset(text_string, 2);
Return value: Returns the offset in bytes to the specified character.
See also: ugetat, usetat, uinsert, uremove.
int third_letter = ugetat(text_string, 2);
Return value: Returns the character value at the specified index in the string.
See also: uoffset, usetat, uinsert, uremove.
usetat(text_string, 2, letter_a);
Return value: Returns the number of bytes by which the trailing part of the string was moved. This is of interest only with text encoding formats where characters have a variable length, like UTF-8.
See also: uoffset, ugetat, uinsert, uremove.
uinsert(text_string, 0, prefix_letter);
Return value: Returns the number of bytes by which the trailing part of the string was moved.
See also: uoffset, ugetat, usetat, uremove.
int length_in_bytes = ustrsizez(text_string); ... length_in_bytes -= uremove(text_string, -1);
Return value: Returns the number of bytes by which the trailing part of the string was moved.
See also: uoffset, ugetat, usetat, uinsert.
See also: ustrsizez, empty_string.
Examples using this: exunicod.
See also: ustrsize, empty_string.
Examples using this: exunicod.
char *temp_buffer = malloc(256 * uwidth_max(U_UTF8));
See also: uwidth, ucwidth.
See also: utoupper, ugetc, ugetx, usetc, uwidth, ucwidth, uisok.
See also: utolower, ugetc, ugetx, usetc, uwidth, ucwidth, uisok.
for (counter = 0; counter < ustrlen(text_string); counter++) { if (uisspace(ugetat(text_string, counter))) usetat(text_string, counter, '_'); }
See also: uisdigit, ugetc, usetc, uwidth, ucwidth, uisok.
for (counter = 0; counter < ustrlen(text_string); counter++) { if (uisdigit(ugetat(text_string, counter))) usetat(text_string, counter, '*'); }
See also: uisspace, ugetc, usetc, uwidth, ucwidth, uisok.
void manipulate_string(const char *input_string) { char *temp_buffer = ustrdup(input_string); /* Now we can modify temp_buffer */ ...
Return value: Returns the newly allocated string. This memory must be freed by the caller. Returns NULL if it cannot allocate space for the duplicated string.
See also: _ustrdup, uconvert, ustrsize, ustrsizez.
Examples using this: exconfig.
See also: ustrdup, uconvert, ustrsize, ustrsizez.
Return value: Returns the value of dest.
See also: uconvert, ustrzcpy, ustrncpy.
Examples using this: exunicod.
Note that, even for empty strings, your destination string must have at least enough bytes to store the terminating null character of the string, and your parameter size must reflect this. Otherwise, the debug version of Allegro will abort at an assertion, and the release version of Allegro will overrun the destination buffer.
Return value: Returns the value of `dest'.
See also: uconvert, ustrcpy, ustrzncpy.
Examples using this: ex3buf, exgui.
Return value: Returns the value of `dest'.
See also: uconvert, ustrzcat, ustrncat.
Examples using this: exunicod.
Note that, even for empty strings, your destination string must have at least enough bytes to store the terminating null character of the string, and your parameter size must reflect this. Otherwise, the debug version of Allegro will abort at an assertion, and the release version of Allegro will overrun the destination buffer.
Return value: Returns the value of `dest'.
See also: uconvert, ustrcat, ustrzncat.
Examples using this: exgui.
See also: uconvert, ustrsize, ustrsizez.
Return value: Returns zero if the strings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number.
See also: uconvert, ustrsize, ustrsizez, ustrncmp, ustricmp, ustrnicmp.
Note that if `src' is longer than `n' characters, `dest' will not be null-terminated.
Return value: The return value is the value of `dest'.
See also: uconvert, ustrcpy, ustrzncpy.
Note that, even for empty strings, your destination string must have at least enough bytes to store the terminating null character of the string, and your parameter `size' must reflect this. Otherwise, the debug version of Allegro will abort at an assertion, and the release version of Allegro will overrun the destination buffer.
Return value: The return value is the value of `dest'.
See also: uconvert, ustrzcpy, ustrncpy.
Examples using this: exkeys.
Return value: The return value is the value of `dest'.
See also: uconvert, ustrcat, ustrzncat.
Return value: The return value is the value of `dest'.
See also: uconvert, ustrzcat, ustrncat.
if (ustrncmp(prefix, long_string, ustrlen(prefix)) == 0) { /* long_string starts with prefix */ }
Return value: Returns zero if the substrings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number.
See also: uconvert, ustrsize, ustrsizez, ustrcmp, ustricmp, ustrnicmp.
if (ustricmp(string, user_input) == 0) { /* string and user_input are equal (ignoring case) */ }
Return value: Returns zero if the strings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number.
See also: uconvert, ustrsize, ustrsizez, ustrnicmp, ustrcmp, ustrncmp.
Examples using this: exconfig.
if (ustrnicmp(prefix, long_string, ustrlen(prefix)) == 0) { /* long_string starts with prefix (ignoring case) */ }
Return value: Returns zero if the strings are equal, a positive number if `s1' comes after `s2' in the ASCII collating sequence, else a negative number.
See also: uconvert, ustrsize, ustrsizez, ustricmp, ustrcmp, ustrncmp.
char buffer[] = "UPPER CASE STRING"; allegro_message(ustrlwr(buffer));
Return value: The return value is the value of `s'.
See also: uconvert, utolower, ustrupr.
char buffer[] = "lower case string"; allegro_message(ustrupr(buffer));
Return value: The return value is the value of `s'.
See also: uconvert, utolower, ustrlwr.
char *p = ustrchr("one,two,three,four", ',');
Return value: Returns a pointer to the first occurrence of `c' in `s', or NULL if no match was found. Note that if `c' is NULL, this will return a pointer to the end of the string.
See also: uconvert, ustrrchr, ustrstr, ustrpbrk, ustrtok.
char *p = ustrrchr("one,two,three,four", ',');
Return value: Returns a pointer for the last occurrence of `c' in `s', or NULL if no match was found.
See also: uconvert, ustrchr, ustrstr, ustrpbrk, ustrtok.
char *p = ustrstr("hello world", "world");
Return value: Returns a pointer within `s1', or NULL if `s2' wasn't found.
See also: uconvert, ustrchr, ustrrchr, ustrpbrk, ustrtok.
char *p = ustrpbrk("one,two-three.four", "-. ");
Return value: Returns a pointer to the first match, or NULL if none are found.
See also: uconvert, ustrchr, ustrrchr, ustrstr, ustrtok.
char *word; char string[]="some-words with dashes"; char *temp = ustrdup(string); word = ustrtok(temp, " -"); while (word) { allegro_message("Found `%s'\n", word); word = ustrtok(NULL, " -"); } free(temp);
Return value: Returns a pointer to the token, or NULL if no more are found.
See also: uconvert, ustrchr, ustrrchr, ustrstr, ustrpbrk, ustrtok_r, allegro_message, ustrncpy.
Examples using this: exgui.
char *word, *last; char string[]="some-words with dashes"; char *temp = ustrdup(string); word = ustrtok_r(string, " -", &last); while (word) { allegro_message("Found `%s'\n", word); word = ustrtok_r(NULL, " -", &last); } free(temp);
Return value: Returns a pointer to the token, or NULL if no more are found. You can free the memory pointed to by `last' once NULL is returned.
See also: ustrtok.
Return value: Returns the equivalent value, or zero if the string does not represent a number.
See also: uconvert, ustrtol, ustrtod.
char *endp, *string = "456.203 askdfg"; int number = ustrtol(string, &endp, 10);
Return value: Returns the string converted as a value of type `long int'. If nothing was converted, returns zero with `*endp' pointing to the beginning of `s'.
See also: uconvert, ustrtod, uatof.
char *endp, *string = "456.203 askdfg"; double number = ustrtod(string, &endp);
Return value: Returns the string converted as a value of type `double'. If nothing was converted, returns zero with *endp pointing to the beginning of s.
See also: uconvert, ustrtol, uatof.
PACKFILE *input_file = pack_fopen("badname", "r"); if (input_file == NULL) allegro_message("%s\nSorry!\n", ustrerror(errno));
Return value: Returns a pointer to a static string that should not be modified or freed. If you make subsequent calls to ustrerror(), the string will be overwritten.
See also: uconvert, allegro_error.
Return value: Returns the number of characters written, not including the terminating null character.
See also: uconvert, uszprintf, uvsprintf.
Examples using this: exkeys.
char buffer[10]; int player_score; ... uszprintf(buffer, sizeof(buffer), "Your score is: %d", player_score);
Return value: Returns the number of characters that would have been written without eventual truncation (like with usprintf), not including the terminating null character.
See also: uconvert, usprintf, uvszprintf.
Examples using this: exgui.
Return value: Returns the number of characters written, not including the terminating null character.
See also: uconvert, usprintf, uvszprintf.
#include <stdarg.h> void log_message(const char *format, ...) { char buffer[100]; va_list parameters; va_start(parameters, format); uvszprintf(buffer, sizeof(buffer), format, parameters); va_end(parameters); append_buffer_to_logfile(log_name, buffer); send_buffer_to_other_networked_players(multicast_ip, buffer); and_also_print_it_on_the_screen(cool_font, buffer); } void some_other_function(void) { log_message("Hello %s, are you %d years old?\n", "Dave", 25); }
Return value: Returns the number of characters that would have been written without eventual truncation (like with uvsprintf), not including the terminating null character.
See also: uconvert, uszprintf, uvsprintf.
Various parts of Allegro, such as the sound routines and the load_joystick_data() function, require some configuration information. This data is stored in text files as a collection of `variable=value' lines, along with comments that begin with a `#' character and continue to the end of the line. The configuration file may optionally be divided into sections, which begin with a `[sectionname]' line. Each section has a unique namespace, to prevent variable name conflicts, but any variables that aren't in a section are considered to belong to all the sections simultaneously.
Note that variable and section names cannot contain spaces.
By default the configuration data is read from a file called `allegro.cfg', which can be located either in the same directory as the program executable, or the directory pointed to by the ALLEGRO environment variable. Under Unix, it also checks for `~/allegro.cfg', `~/.allegrorc', `/etc/allegro.cfg', and `/etc/allegrorc', in that order; under BeOS only the last two are also checked. MacOS X also checks in the Contents/Resources directory of the application bundle, if any, before doing the checks above.
If you don't like this approach, you can specify any filename you like, or use a block of binary configuration data provided by your program (which could for example be loaded from a datafile). You can also extend the paths searched for allegro resources with set_allegro_resource_path().
You can store whatever custom information you like in the config file, along with the standard variables that are used by Allegro (see below). Allegro comes with a setup directory where you can find configuration programs. The standalone setup program is likely to be of interest to final users. It allows any user to create an `allegro.cfg' file without the need to touch a text editor and enter values by hand. It also provides a few basic tests like sound playing for sound card testing. You are welcome to include the setup program with your game, either as is or with modified graphics to fit better your game.
All pointers returned by previous calls to get_config_string() and other related functions are invalidated when you call this function! You can call this function before install_allegro() to change the configuration file, but after set_uformat() if you want to use a text encoding format other than the default.
See also: set_config_data, override_config_file, push_config_state, set_uformat, Standard config variables, set_config_string, get_config_string.
Examples using this: exconfig.
See also: set_config_file, override_config_data, push_config_state, Standard config variables, set_config_string, get_config_string.
The override config file will not only take precedence when reading, but will also be used for storing values. When you are done with using the override config file, you can call override_config_file with a NULL parameter, so config data will be directly read from the current config file again.
Note: The override file is completely independent from the current configuration. You can e.g. call set_config_file, and the override file will still be active. Also the flush_config_file function will only affect the current config file (which can be changed with set_config_file), never the overriding one specified with this function. The modified override config is written back to disk whenever you call override_config_file.
Example:
override_config_file("my.cfg"); /* This will read from my.cfg, and if it doesn't find a * setting, will read from the current config file instead. */ language = get_config_string("system", "language", NULL); /* This will always write to my.cfg, no matter if the * settings is already present or not. */ set_config_string("system", "language", "RU"); /* This forces the changed setting to be written back to * disk. Else it is written back at the next call to * override_config_file, or when Allegro shuts down. */ override_config_file(NULL);
Note that this function and override_config_data() are mutually exclusive, i.e. calling one will cancel the effects of the other.
See also: override_config_data, set_config_file.
/* Force German as system language, Spanish keyboard map. */ const char *override_data = "[system]\n" "language=DE\n" "keyboard=ES"; override_config_data(override_data, ustrsize(override_data));
Note that this function and override_config_file() are mutually exclusive, i.e. calling one will cancel the effects of the other.
See also: override_config_file, set_config_data.
See also: pop_config_state, set_config_file, save_joystick_data.
Examples using this: exconfig.
See also: push_config_state.
Examples using this: exconfig.
See also: set_config_file, override_config_file, push_config_state.
... /* The user selects French from a language choice menu. */ reload_config_texts("FR");
See also: get_config_text, get_config_string, Standard config variables.
int decode_encrypted_int(const char *name, int def) { ... } const char *decode_encrypted_string(const char *name, const char *def) { ... } void encode_plaintext_string(const char *name, const char *value) { ... } int main(int argc, char *argv[]) { ... /* Make it harder for users to tinker with the high scores. */ hook_config_section("high_scores", decode_encrypted_int, decode_encrypted_string, encode_plaintext_string); ... } END_OF_MAIN()
See also: config_is_hooked.
if (config_is_hooked("high_scores")) { hook_config_section("high_scores, NULL, NULL, NULL); }
See also: hook_config_section.
const char *lang = get_config_string("system", "language", "EN");
Return value: Returns a pointer to the constant string found in the configuration file. If the named variable cannot be found, or its entry in the config file is empty, the value of `def' is returned.
See also: set_config_file, set_config_string, get_config_argv, get_config_float, get_config_hex, get_config_int, get_config_id, get_config_text.
Examples using this: exconfig.
See also: set_config_file, set_config_int, get_config_string, get_config_argv, get_config_float, get_config_hex, get_config_id.
Examples using this: exconfig.
See also: set_config_file, set_config_hex, get_config_string, get_config_argv, get_config_float, get_config_int, get_config_id.
See also: set_config_file, set_config_float, get_config_string, get_config_argv, get_config_hex, get_config_int, get_config_id.
See also: set_config_file, set_config_id, get_config_string, get_config_argv, get_config_float, get_config_hex, get_config_int.
Return value: Returns an argv style argument list and sets `argc' to the number of retrieved tokens. If the variable is not present, returns NULL and sets argc to zero.
See also: set_config_file, get_config_string, get_config_float, get_config_hex, get_config_int, get_config_id.
Examples using this: exconfig.
This is basically the same thing as calling get_config_string() with `[language]' as the section, `msg' as the variable name, and `msg' as the default value, but it contains some special code to handle Unicode format conversions. The `msg' parameter is always given in ASCII format, but the returned string will be converted into the current text encoding, with memory being allocated as required, so you can assume that this pointer will persist without having to manually allocate storage space for each string.
Note that if you are planning on distributing your game on the Unix platform there is a special issue with how to deal with the `language.dat' file. Read section "Files shared by Allegro" of the chapter "Unix specifics" to learn more about this.
Return value: Returns a suitable translation if one can be found or a copy of the parameter if nothing else is available.
See also: get_config_string, reload_config_texts, Standard config variables.
As a special case, variable or section names that begin with a '#' character are treated specially and will not be read from or written to the disk. Addon packages can use this to store version info or other status information into the config module, from where it can be read with the get_config_string() function.
See also: set_config_file, get_config_string, set_config_float, set_config_hex, set_config_int, set_config_id.
See also: set_config_file, get_config_int, set_config_string, set_config_float, set_config_hex, set_config_id.
See also: set_config_file, get_config_hex, set_config_string, set_config_float, set_config_int, set_config_id.
See also: set_config_file, get_config_float, set_config_string, set_config_hex, set_config_int, set_config_id.
See also: set_config_file, get_config_id, set_config_string, set_config_float, set_config_hex, set_config_int.
int i, n; char const **sections = NULL; char const **entries = NULL; /* List all entries not in any section. */ n = list_config_entries(NULL, &entries); for (i = 0; i < n; i++) printf(" %s=\"%s\"\n", entries[i], get_config_string( NULL, entries[i], "-")); /* List all sections (and entries in them). */ n = list_config_sections(§ions); /* loop through all section names */ for (i = 0; i < n; i++) { int j, m; printf("%s\n", sections[i]); m = list_config_entries(sections[i], &entries); /* loop through all entries in the section */ for (j = 0; j < m; j++) { printf(" %s=\"%s\"\n", entries[j], get_config_string( sections[i], entries[j], "-")); } } /* It is enough to free the arrays once at the end. */ free_config_entries(§ions); free_config_entries(&entries);
Return value: Returns the number of valid strings in the names array.
See also: set_config_file, get_config_string, list_config_sections, free_config_entries.
Return value: Returns the number of valid strings in the names array.
See also: list_config_entries, set_config_file, get_config_string, free_config_entries.
Once you are done with the string arrays filled in by list_config_entries and list_config_sections, you can free them again with this function. The passed array pointer will be set to NULL, and you directly can pass the same pointer again to list_config_entries or list_config_sections later - but you also could pass them again without freeing first, since the memory is re-allocated when the pointer is not NULL.
See list_config_entries for an example of how to use it.
See also: list_config_entries, list_config_sections.
Allegro uses these standard variables from the configuration file:
Linux console mouse drivers are:MICK - mickey mode driver (normally the best) I33 - int 0x33 callback driver POLL - timer polling (for use under NT)
MS - Microsoft serial mouse IMS - Microsoft serial mouse with Intellimouse extension LPS2 - PS2 mouse LIPS - PS2 mouse with Intellimouse extension GPMD - GPM repeater data (Mouse Systems protocol) EV - Event interfaces (EVDEV)
0 - fast mixing of 8-bit data into 16-bit buffers 1 - true 16-bit mixing (requires a 16-bit stereo sound card) 2 - interpolated 16-bit mixing
specifies that whenever GM program 36 (which happens to be a fretless bass) is selected, Allegro should send a bank change message #0 with a parameter of 0, a bank change message #32 with a parameter of 34, a program change with a parameter of 9, and then should shift everything up by an octave.p36 = 0 34 9 12
See also: set_config_file, set_config_string, get_config_string.
Allegro provides functions for reading the mouse state and displaying a mouse cursor on-screen. You can read the absolute position of the mouse and the state of the mouse buttons from global variables. Additionally, you can read the mouse position difference as mouse mickeys, which is the number of pixels the cursor moved since the last time this information was read.
Allegro offers three ways to display the mouse cursor:
Return value: Returns -1 on failure, zero if the mouse handler is already installed (in which case this function does nothing) and the number of buttons on the mouse if the mouse handler has successfully been installed (ie. this is the first time a handler is installed or you have removed the previous one).
Note that the number of mouse buttons returned by this function is more an indication than a physical reality. With most devices there is no way of telling how many buttons there are, and any user can override the number of mouse buttons returned by this function with a custom configuration file and the variable num_buttons. Even if this value is overridden by the user, the global mouse variables will still report whatever the hardware is sending.
See also: remove_mouse, poll_mouse, mouse_x, show_mouse, get_mouse_mickeys, position_mouse, set_mouse_range, set_mouse_speed, Standard config variables.
Examples using this: Available Allegro examples.
See also: install_mouse, allegro_exit.
Return value: Returns zero on success, or a negative number on failure (ie. no mouse driver installed).
See also: mouse_needs_poll, install_mouse, mouse_x.
Examples using this: exlights, exmouse, exshade, exspline, extrans.
See also: poll_mouse, install_mouse, mouse_x.
See also: install_mouse, show_mouse, set_mouse_sprite, get_mouse_mickeys, gfx_capabilities, disable_hardware_cursor, show_os_cursor.
Examples using this: exsyscur.
See also: install_mouse, show_mouse, set_mouse_sprite, get_mouse_mickeys, gfx_capabilities, enable_hardware_cursor.
Note that the effects of this function are not apparent until show_mouse() is called.
To know whether the operating system's native cursor is being used, or if Allegro has made a substitution, you can check the GFX_SYSTEM_CURSOR flag in gfx_capabilities after calling show_mouse().
The cursor argument selects the type of cursor to be displayed:
MOUSE_CURSOR_NONE
Selects an invisible mouse cursor. In that sense, it is similar to calling
show_mouse(NULL);
MOUSE_CURSOR_ALLEGRO
Selects the custom Allegro cursor, i.e. the one that you set with
set_mouse_sprite().
MOUSE_CURSOR_ARROW
The operating system default arrow cursor.
MOUSE_CURSOR_BUSY
The operating system default `busy' cursor (hourglass).
MOUSE_CURSOR_QUESTION
The operating system default `question' cursor (arrow with question mark).
MOUSE_CURSOR_EDIT
The operating system default `edit' cursor (vertical bar).
Example:
/* initialize mouse sub-system */ install_mouse(); enable_hardware_cursor(); /* Set busy pointer */ select_mouse_cursor(MOUSE_CURSOR_BUSY); show_mouse(screen); /* Initialize stuff */ ... /* Set normal arrow pointer */ select_mouse_cursor(MOUSE_CURSOR_ARROW);
See also: install_mouse, show_mouse, set_mouse_sprite, gfx_capabilities, enable_hardware_cursor, set_mouse_cursor_bitmap, show_os_cursor.
Examples using this: exsyscur.
The cursor argument can be one of:
MOUSE_CURSOR_ALLEGRO
MOUSE_CURSOR_ARROW
MOUSE_CURSOR_BUSY
MOUSE_CURSOR_QUESTION
MOUSE_CURSOR_EDIT
but not MOUSE_CURSOR_NONE.
The bmp argument can either point to a valid bitmap or it can be NULL. Passing a bitmap makes Allegro use that image in place of its own default substitution (should the operating system's native cursor be unavailable). The bitmap must remain available for the duration in which it could be used. Passing NULL lets Allegro revert to its default substitutions.
The effect of this function will not be apparent until show_mouse() is called.
See also: install_mouse, show_mouse, set_mouse_sprite, gfx_capabilities, enable_hardware_cursor, show_os_cursor.
The `mouse_pos' variable has the current X coordinate in the upper 16 bits and the Y in the lower 16 bits. This may be useful in tight polling loops where a mouse interrupt could occur between your reading of the two separate variables, since you can copy this value into a local variable with a single instruction and then split it up at your leisure. Example:if (mouse_b & 1) printf("Left button is pressed\n"); if (!(mouse_b & 2)) printf("Right button is not pressed\n");
int pos, x, y; pos = mouse_pos; x = pos >> 16; y = pos & 0x0000ffff;
See also: install_mouse, poll_mouse, mouse_needs_poll.
Examples using this: exalpha, exlights, exmouse, exshade, exspline, extrans.
See also: set_mouse_sprite, set_mouse_sprite_focus.
Warning: if you draw anything onto the screen while the pointer is visible, a mouse movement interrupt could occur in the middle of your drawing operation. If this happens the mouse buffering and graphics drawing code will get confused and will leave 'mouse droppings' all over the screen. To prevent this, you must make sure you turn off the mouse pointer whenever you draw onto the screen. This is not needed if you are using a hardware cursor.
Note: you must not be showing a mouse pointer on a bitmap at the time that the bitmap is destroyed with destroy_bitmap(), e.g. call show_mouse(NULL); before destroying the bitmap. This does not apply to `screen' since you never destroy `screen' with destroy_bitmap().
See also: install_mouse, install_timer, set_mouse_sprite, scare_mouse, freeze_mouse_flag, show_os_cursor.
Examples using this: exmouse, expal, exshade, exspline, exsyscur.
See also: unscare_mouse, scare_mouse_area, show_mouse.
See also: unscare_mouse, scare_mouse, show_mouse.
See also: scare_mouse, scare_mouse_area.
The most common use for this function is to just call it once at the beginning of the program to tell it to display the system cursor inside the Allegro window. The return value can be used to see if this succeeded or not. On some systems (e.g. DirectX fullscreen) this is not supported and the function will always fail, and in other cases only some of the cursors will work, or in the case of MOUSE_CURSOR_ALLEGRO, only certain bitmap sizes may be supported.
You never should use show_os_cursor together with the function show_mouse and other functions affecting it (select_mouse_cursor, enable_hardware_cursor, disable_hardware_cursor, scare_mouse, unscare_mouse). They implement the standard high level mouse API, and don't work together with this low level function.
Return value: Returns 0 if a system cursor is being displayed after the function returns, or -1 otherwise.
See also: show_mouse, set_mouse_cursor_bitmap, select_mouse_cursor.
See also: show_mouse.
See also: install_mouse, position_mouse_z, set_mouse_range, set_mouse_speed, position_mouse_w.
See also: install_mouse, position_mouse, position_mouse_w.
See also: install_mouse, position_mouse.
See also: install_mouse, set_mouse_speed, position_mouse.
See also: install_mouse, set_mouse_range, position_mouse.
As a bonus, set_mouse_sprite(NULL) uses the current palette in choosing colors for the arrow. So if your arrow mouse sprite looks ugly after changing the palette, call set_mouse_sprite(NULL).
See also: install_mouse, show_mouse, set_mouse_sprite_focus.
Examples using this: exmouse.
See also: set_mouse_sprite.
Examples using this: exmouse.
Note that the infinite movement may not work in windowed mode, since under some platforms the mouse would leave the window, and may not work at all if the hardware cursor is in use.
See also: install_mouse.
Examples using this: exmouse.
See also: install_mouse.
Allegro can set up several virtual timer functions, all going at different speeds.
Under DOS it will constantly reprogram the clock to make sure they are all called at the correct times. Because they alter the low level timer chip settings, these routines should not be used together with other DOS timer functions like the DJGPP uclock() routine. Moreover, the FPU state is not preserved across Allegro interrupts so you ought not to use floating point or MMX code inside timer interrupt handlers.
Under other platforms, they are usually implemented using threads, which run parallel to the main thread. Therefore timer callbacks on such platforms will not block the main thread when called, so you may need to use appropriate synchronisation devices (eg. mutexes, semaphores, etc.) when accessing data that is shared by a callback and the main thread. (Currently Allegro does not provide such devices.)
Return value: Returns zero on success, or a negative number on failure (but you may decide not to check the return value as this function is very unlikely to fail).
See also: remove_timer, install_int.
Examples using this: Available Allegro examples.
See also: install_timer, allegro_exit.
Return value: Returns zero on success, or a negative number if there is no room to add a new user timer.
See also: install_timer, remove_int, install_int_ex, install_param_int.
Examples using this: exscn3d, exswitch, extimer, exzbuf.
There can only be sixteen timers in use at a time, and some other parts of Allegro (the GUI code, the mouse pointer display routines, rest(), the FLI player, and the MIDI player) need to install handlers of their own, so you should avoid using too many at the same time. If you call this routine without having first installed the timer module, install_timer() will be called automatically.SECS_TO_TIMER(secs) - give the number of seconds between each tick MSEC_TO_TIMER(msec) - give the number of milliseconds between ticks BPS_TO_TIMER(bps) - give the number of ticks each second BPM_TO_TIMER(bpm) - give the number of ticks per minute
Your function will be called by the Allegro interrupt handler and not directly by the processor, so it can be a normal C function and does not need a special wrapper. You should be aware, however, that it will be called in an interrupt context, which imposes a lot of restrictions on what you can do in it. It should not use large amounts of stack, it must not make any calls to the operating system, use C library functions, or contain any floating point code, and it must execute very quickly. Don't try to do lots of complicated code in a timer handler: as a general rule you should just set some flags and respond to these later in your main control loop.
In a DOS protected mode environment like DJGPP, memory is virtualised and can be swapped to disk. Due to the non-reentrancy of DOS, if a disk swap occurs inside an interrupt handler the system will die a painful death, so you need to make sure you lock all the memory (both code and data) that is touched inside timer routines. Allegro will lock everything it uses, but you are responsible for locking your handler functions. The macros LOCK_VARIABLE (variable), END_OF_FUNCTION (function_name), END_OF_STATIC_FUNCTION (function_name), and LOCK_FUNCTION (function_name) can be used to simplify this task. For example, if you want an interrupt handler that increments a counter variable, you should write:
and in your initialisation code you should lock the memory:volatile int counter; void my_timer_handler() { counter++; } END_OF_FUNCTION(my_timer_handler)
Obviously this can get awkward if you use complicated data structures and call other functions from within your handler, so you should try to keep your interrupt routines as simple as possible.LOCK_VARIABLE(counter); LOCK_FUNCTION(my_timer_handler);
Return value: Returns zero on success, or a negative number if there is no room to add a new user timer.
See also: install_timer, remove_int, install_int, install_param_int_ex.
Examples using this: excamera, exsprite, extimer, exunicod, exupdate.
See also: install_int, install_int_ex.
Examples using this: exscn3d, exsprite, exswitch, extimer, exupdate, exzbuf.
See also: install_int, install_int_ex.
Examples using this: exkeys, exscn3d, exsprite, exswitch, extimer, exupdate, exzbuf.
See also: install_int, install_int_ex.
Examples using this: exkeys, exscn3d, exsprite, exswitch, extimer, exupdate, exzbuf.
See also: install_int, install_int_ex, remove_param_int.
See also: install_timer, remove_param_int, install_param_int_ex, install_int.
See also: install_timer, remove_param_int, install_param_int, install_int_ex.
See also: install_param_int, install_param_int_ex, remove_int.
Examples using this: ex3d, exblend, exdbuf, exflip, exlights.
Passing 0 as parameter will not wait, but just yield. This can be useful in order to "play nice" with other processes. Other values will cause CPU time to be dropped on most platforms. This will look better to users, and also does things like saving battery power and making fans less noisy.
Note that calling this inside your active game loop is a bad idea, as you never know when the OS will give you the CPU back, so you could end up missing the vertical retrace and skipping frames. On the other hand, on multitasking operating systems it is good form to give up the CPU for a while if you will not be using it.
See also: install_timer, rest_callback, vsync, d_yield_proc.
Examples using this: exkeys, exmidi, exquat, exsample, exsprite, extimer, extrans, exunicod.
See also: install_timer, rest.
The Allegro keyboard handler provides both buffered input and a set of flags storing the current state of each key. Note that it is not possible to correctly detect every combination of keys, due to the design of the PC keyboard. Up to two or three keys at a time will work fine, but if you press more than that the extras are likely to be ignored (exactly which combinations are possible seems to vary from one keyboard to another).
On DOS, Allegro requires the user to specify the language of the keyboard mapping because it is impossible to obtain this information from the OS, otherwise the default US keyboard mapping will be used. Allegro comes with a prepackaged `keyboard.dat' file which you can put along with your binary. If this file is present, Allegro will be able to extract the keyboard mapping information stored there. However, the end user still needs to select which keyboard mapping to use. This can be accomplished through the keyboard variable of the system section in a standard `allegro.cfg' configuration file. Read chapter "Configuration routines" for more information about this.
Note that on some platforms the keyboard won't work unless you have set a graphics mode, even if this function returns a success value before calling set_gfx_mode. This can happen in environments with graphic windowed modes, since Allegro usually reads the keyboard through the graphical window (which appears after the set_gfx_mode call). Example:
allegro_init(); install_timer(); install_keyboard(); /* We are not 100% sure we can read the keyboard yet! */ if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) abort_on_error("Couldn't set graphic mode!"); /* Now we are guaranteed to be able to read the keyboard. */ readkey();
Return value: Returns zero on success, or a negative number on failure (but you may decide not to check the return value as this function is very unlikely to fail).
See also: remove_keyboard, poll_keyboard, key, keypressed, readkey, ureadkey, keyboard_callback, keyboard_ucallback, keyboard_lowlevel_callback, three_finger_flag, key_led_flag, set_leds, set_keyboard_rate, set_gfx_mode, Standard config variables.
Examples using this: Available Allegro examples.
remove_keyboard(); /* Switch to Spanish keyboard mapping. */ set_config_string("system", "keyboard", "es"); install_keyboard();
See also: install_keyboard, allegro_exit, set_config_string.
See also: install_keyboard, keypressed, readkey.
To help you test your keyboard polling code even if you are programming on a platform that doesn't require it, after the first time that you call this function Allegro will switch into polling mode, so from that point onwards you will have to call this routine in order to get any keyboard input at all, regardless of whether the current driver actually needs to be polled or not.
The keypressed(), readkey(), and ureadkey() functions call poll_keyboard() automatically, so you only need to use this function when accessing the key[] array and key_shifts variable.
Return value: Returns zero on success, or a negative number on failure (ie. no keyboard driver installed).
See also: keyboard_needs_poll, install_keyboard, key, key_shifts.
Examples using this: excamera, exsample, exstars.
See also: poll_keyboard, install_keyboard, key.
if (key[KEY_SPACE]) printf("Space is pressed\n");
Note that the array is supposed to represent which keys are physically held down and which keys are not, so it is semantically read-only.
These are the keyboard scancodes:
KEY_A ... KEY_Z, KEY_0 ... KEY_9, KEY_0_PAD ... KEY_9_PAD, KEY_F1 ... KEY_F12, KEY_ESC, KEY_TILDE, KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, KEY_OPENBRACE, KEY_CLOSEBRACE, KEY_ENTER, KEY_COLON, KEY_QUOTE, KEY_BACKSLASH, KEY_BACKSLASH2, KEY_COMMA, KEY_STOP, KEY_SLASH, KEY_SPACE, KEY_INSERT, KEY_DEL, KEY_HOME, KEY_END, KEY_PGUP, KEY_PGDN, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_SLASH_PAD, KEY_ASTERISK, KEY_MINUS_PAD, KEY_PLUS_PAD, KEY_DEL_PAD, KEY_ENTER_PAD, KEY_PRTSCR, KEY_PAUSE, KEY_ABNT_C1, KEY_YEN, KEY_KANA, KEY_CONVERT, KEY_NOCONVERT, KEY_AT, KEY_CIRCUMFLEX, KEY_COLON2, KEY_KANJI, KEY_LSHIFT, KEY_RSHIFT, KEY_LCONTROL, KEY_RCONTROL, KEY_ALT, KEY_ALTGR, KEY_LWIN, KEY_RWIN, KEY_MENU, KEY_SCRLOCK, KEY_NUMLOCK, KEY_CAPSLOCK KEY_EQUALS_PAD, KEY_BACKQUOTE, KEY_SEMICOLON, KEY_COMMAND
Finally, you may notice an `odd' behaviour of the KEY_PAUSE key. This key only generates an interrupt when it is pressed, not when it is released. For this reason, Allegro pretends the pause key is a `state' key, which is the only way to make it usable.
See also: install_keyboard, poll_keyboard, key_shifts.
Examples using this: Available Allegro examples.
KB_SHIFT_FLAG KB_CTRL_FLAG KB_ALT_FLAG KB_LWIN_FLAG KB_RWIN_FLAG KB_MENU_FLAG KB_COMMAND_FLAG KB_SCROLOCK_FLAG KB_NUMLOCK_FLAG KB_CAPSLOCK_FLAG KB_INALTSEQ_FLAG KB_ACCENT1_FLAG KB_ACCENT2_FLAG KB_ACCENT3_FLAG KB_ACCENT4_FLAG
Example:
if (key[KEY_W]) { if (key_shifts & KB_SHIFT_FLAG) { /* User is pressing shift + W. */ } else { /* Hmmm... lower case W then. */ } }
See also: install_keyboard, poll_keyboard, key.
Examples using this: excamera, exkeys.
while (!keypressed()) { /* Show cool animated logo. */ } /* So he skipped our title screen. */
See also: install_keyboard, readkey, ureadkey, clear_keybuf, simulate_keypress, simulate_ukeypress.
Examples using this: Available Allegro examples.
The low byte of the return value contains the ASCII code of the key, and the high byte the scancode. The scancode remains the same whatever the state of the shift, ctrl and alt keys, while the ASCII code is affected by shift and ctrl in the normal way (shift changes case, ctrl+letter gives the position of that letter in the alphabet, eg. ctrl+A = 1, ctrl+B = 2, etc). Pressing alt+key returns only the scancode, with a zero ASCII code in the low byte. For example:
This function cannot return character values greater than 255. If you need to read Unicode input, use ureadkey() instead.int val; ... val = readkey(); if ((val & 0xff) == 'd') /* by ASCII code */ allegro_message("You pressed 'd'\n"); if ((val >> 8) == KEY_SPACE) /* by scancode */ allegro_message("You pressed Space\n"); if ((val & 0xff) == 3) /* ctrl+letter */ allegro_message("You pressed Control+C\n"); if (val == (KEY_X << 8)) /* alt+letter */ allegro_message("You pressed Alt+X\n");
See also: install_keyboard, ureadkey, keypressed, clear_keybuf, simulate_keypress.
Examples using this: Available Allegro examples.
You should be able to find Unicode character maps at http://www.unicode.org/. Remember that on DOS you must specify a custom keyboard map (like those found in `keyboard.dat') usually with the help of a configuration file specifying the language mapping (keyboard variable in system section of `allegro.cfg'), or you will get the default US keyboard mapping.int val, scancode; ... val = ureadkey(&scancode); if (val == 0x00F1) allegro_message("You pressed n with tilde\n"); if (val == 0x00DF) allegro_message("You pressed sharp s\n");
See also: install_keyboard, readkey, keypressed, clear_keybuf, simulate_ukeypress.
Examples using this: exkeys.
Example:
int ascii; ... ascii = scancode_to_ascii(scancode); allegro_message("You pressed '%c'\n", ascii);
See also: scancode_to_name.
char const *keyname = scancode_to_name(scancode); allegro_message("You pressed the %s key.", keyname);
See also: scancode_to_ascii.
Examples using this: exkeys.
simulate_keypress(KEY_SPACE << 8); if (readkey() == (KEY_SPACE << 8)) allegro_message("You simulated Alt+Space\n");
See also: install_keyboard, simulate_ukeypress, keypressed, readkey.
/* We ignore the scancode simulation. */ simulate_ukeypress(0x00DF, 0); if (ureadkey(&scancode) == 0x00DF) allegro_message("You simulated sharp s\n");
See also: install_keyboard, simulate_keypress, keypressed, ureadkey.
int enigma_scrambler(int key) { /* Add one to both the scancode and ascii values. */ return (((key >> 8) + 1) << 8) | ((key & 0xff) + 1); } END_OF_FUNCTION(enigma_scrambler) ... install_timer(); LOCK_FUNCTION(enigma_scrambler); install_keyboard(); keyboard_callback = enigma_scrambler;
Note that this callback will be ignored if you also set the unicode keyboard callback.
See also: install_keyboard, readkey, ureadkey, keyboard_ucallback, keyboard_lowlevel_callback.
int silence_g_key(int key, int *scancode) { if (key == 'g') { *scancode = 0; return 0; } return key; } END_OF_FUNCTION(silence_g_key) ... install_timer(); LOCK_FUNCTION(silence_g_key); install_keyboard(); keyboard_ucallback = silence_g_key;
Note that this keyboard callback has priority over the non unicode callback. If you set both, only the unicode one will work.
See also: install_keyboard, readkey, ureadkey, keyboard_callback, keyboard_lowlevel_callback.
volatile int key_down, key_up; void keypress_watcher(int scancode) { if (scancode & 0x80) { key_up = 1; } else { key_down = 1; } } END_OF_FUNCTION(keypress_watcher) ... install_timer(); LOCK_FUNCTION(silence_g_key); LOCK_VARIABLE(key_down); LOCK_VARIABLE(key_up); install_keyboard(); keyboard_lowlevel_callback = keypress_watcher; /* Disable keyboard repeat to get typewriter effect. */ set_keyboard_rate(0, 0); ... while (game_loop) { if (key_down) { key_down = 0; /* Play sample of typewriter key press. */ } if (key_up) { key_up = 0; /* Play sample of typewriter key release. */ } }
See also: install_keyboard, keyboard_callback, keyboard_ucallback.
Examples using this: exkeys.
Note that the led behaviour cannot be guaranteed on some platforms, some leds might not react, or none at all. Therefore you shouldn't rely only on them to communicate information to the user, just in case it doesn't get through./* Cycle led indicators. */ set_leds(KB_SCROLOCK_FLAG); rest(1000); set_leds(KB_CAPSLOCK_FLAG); rest(1000); set_leds(KB_NUMLOCK_FLAG); rest(1000); set_leds(-1);
See also: install_keyboard, key_led_flag.
See also: install_keyboard, readkey, ureadkey.
See also: install_keyboard, keypressed, readkey, ureadkey.
Examples using this: Available Allegro examples.
See also: install_keyboard.
See also: install_keyboard, set_leds.
Unlike keyboard or mouse input, which are usually read through hardware interrupts by Allegro, joystick input functions have to be polled because there are no hardware interrupts for them on most platforms. This doesn't mean that you have to poll the joysticks on each line of code you want to read their values, but you should make sure to poll them at least once per frame in your game loop. Otherwise you face the possibility of reading stale incorrect data.
textout_centre_ex(screen, font, "Center the joystick and press a key", SCREEN_W/2, SCREEN_H/2, red_color, -1); readkey(); if (install_joystick(JOY_TYPE_AUTODETECT) != 0) abort_on_error("Error initialising joystick!");
Return value: Returns zero on success. As soon as you have installed the joystick module, you will be able to read the button state and digital (on/off toggle) direction information, which may be enough for some games. If you want to get full analogue input, though, you need to use the calibrate_joystick() functions to measure the exact range of the inputs: see below.
See also: remove_joystick, num_joysticks, load_joystick_data, calibrate_joystick, calibrate_joystick_name, poll_joystick, Standard config variables, JOY_TYPE_*/DOS, JOY_TYPE_*/Windows, JOY_TYPE_*/Linux.
Examples using this: exjoy.
See also: install_joystick, allegro_exit.
do { /* Get joystick input */ poll_joystick(); /* Process input for the first joystick */ if (joy[0].button[0].b) first_button_pressed(); if (joy[0].button[1].b) second_button_pressed(); ... } while(!done);
Return value: Returns zero on success or a negative number on failure (usually because no joystick driver was installed).
See also: install_joystick, joy, num_joysticks.
Examples using this: exjoy.
See also: install_joystick, joy.
Examples using this: exjoy.
The button status is stored in the structure:typedef struct JOYSTICK_INFO { int flags; - status flags for this joystick int num_sticks; - how many stick inputs? int num_buttons; - how many buttons? JOYSTICK_STICK_INFO stick[n]; - stick state information JOYSTICK_BUTTON_INFO button[n]; - button state information } JOYSTICK_INFO;
You may wish to display the button names as part of an input configuration screen to let the user choose what game function will be performed by each button, but in simpler situations you can safely assume that the first two elements in the button array will always be the main trigger controls.typedef struct JOYSTICK_BUTTON_INFO { int b; - boolean on/off flag char *name; - description of this button } JOYSTICK_BUTTON_INFO;
Each joystick will provide one or more stick inputs, of varying types. These can be digital controls which snap to specific positions (eg. a gamepad controller, the coolie hat on a Flightstick Pro or Wingman Extreme, or a normal joystick which hasn't yet been calibrated), or they can be full analogue inputs with a smooth range of motion. Sticks may also have different numbers of axes, for example a normal directional control has two, but the Flightstick Pro throttle is only a single axis, and it is possible that the system could be extended in the future to support full 3d controllers. A stick input is described by the structure:
A single joystick may provide several different stick inputs, but you can safely assume that the first element in the stick array will always be the main directional controller.typedef struct JOYSTICK_STICK_INFO { int flags; - status flags for this input int num_axis; - how many axes do we have? (note the misspelling) JOYSTICK_AXIS_INFO axis[n]; - axis state information char *name; - description of this input } JOYSTICK_STICK_INFO;
Information about each of the stick axis is stored in the substructure:
This provides both analogue input in the pos field (ranging from -128 to 128 or from 0 to 255, depending on the type of the control), and digital values in the d1 and d2 fields. For example, when describing the X-axis position, the pos field will hold the horizontal position of the joystick, d1 will be set if it is moved left, and d2 will be set if it is moved right. Allegro will fill in all these values regardless of whether it is using a digital or analogue joystick, emulating the pos field for digital inputs by snapping it to the min, middle, and maximum positions, and emulating the d1 and d2 values for an analogue stick by comparing the current position with the centre point.typedef struct JOYSTICK_AXIS_INFO { int pos; - analogue axis position int d1, d2; - digital axis position char *name; - description of this axis } JOYSTICK_AXIS_INFO;
The joystick flags field may contain any combination of the bit flags:
JOYFLAG_DIGITAL
This control is currently providing digital input.
JOYFLAG_ANALOGUE
This control is currently providing analogue input.
JOYFLAG_CALIB_DIGITAL
This control will be capable of providing digital input once it has
been calibrated, but is not doing this at the moment.
JOYFLAG_CALIB_ANALOGUE
This control will be capable of providing analogue input once it has
been calibrated, but is not doing this at the moment.
JOYFLAG_CALIBRATE
Indicates that this control needs to be calibrated. Many devices
require multiple calibration steps, so you should call the
calibrate_joystick() function from a loop until this flag is cleared.
JOYFLAG_SIGNED
Indicates that the analogue axis position is in signed format, ranging
from -128 to 128. This is the case for all 2d directional controls.
JOYFLAG_UNSIGNED
Indicates that the analogue axis position is in unsigned format,
ranging from 0 to 255. This is the case for all 1d throttle controls.
Note for people who spell funny: in case you don't like having to type "analogue", there are some #define aliases in allegro/joystick.h that will allow you to write "analog" instead.
See also: install_joystick, poll_joystick, num_joysticks, calibrate_joystick, calibrate_joystick_name.
Examples using this: exjoy.
Return value: Returns a text description for the next type of calibration that will be done on the specified joystick, or NULL if no more calibration is required.
See also: install_joystick, calibrate_joystick, joy, num_joysticks.
Examples using this: exjoy.
int i; for (i=0; i<;num_joysticks; i++) { while (joy[i].flags & JOYFLAG_CALIBRATE) { char *msg = calibrate_joystick_name(i); textprintf_ex(..., "%s, and press a key\n", msg); readkey(); if (calibrate_joystick(i) != 0) { textprintf_ex(..., "oops!\n"); readkey(); exit(1); } } }
Return value: Returns zero on success, non-zero if the calibration could not be performed successfully.
See also: install_joystick, calibrate_joystick_name, joy, num_joysticks.
Examples using this: exjoy.
Return value: Returns zero on success, non-zero if the data could not be saved.
See also: load_joystick_data, set_config_file.
Return value: Returns zero on success: if it fails the joystick state is undefined and you must reinitialise it from scratch.
See also: install_joystick, save_joystick_data, set_config_file.
See also: install_joystick.
Graphics modes are the common denominator for most Allegro programs. While it is possible to write platform specific programs using Allegro which don't set a graphic mode through the routines provided in this chapter, these are not very common.
The first thing to note is that due to the wide range of supported platforms, a graphic mode is the only way to safely communicate with the user. When Allegro was a DOS only library (versions 3.x and previous), it was frequent for programmers to use functions from the C standard library to communicate with the user, like calling printf() before setting a graphic mode or maybe scanf() to read the user's input. However, what would happen for such a game running under Windows where there is no default console output or it may be hidden from the user? Even if the game compiled successfully, it would be unplayable, especially if there was vital information for the user in those text only messages.
Allegro provides the allegro_message() function to deal with this problem, but this is not a very user friendly method of communicating with the user and its main purpose is displaying small error like messages when no graphic mode is available. Therefore, the first thing your Allegro program should do is set a graphic mode, and from there on, use Allegro's text output routines to display messages to the user, just like `allegro/examples/exhello.c' does.
Setting a graphic mode involves deciding how to allocate the memory of the video card for your program. On some platforms this means creating a virtual screen bigger than the physical resolution to do hardware scrolling or page flipping. Virtual screens can cause a lot of confusion, but they are really quite simple. Warning: patronising explanation coming up, so you may wish to skip the rest of this paragraph. Think of video memory as a rectangular piece of paper which is being viewed through a small hole (your monitor) in a bit of cardboard. Since the paper is bigger than the hole you can only see part of it at any one time, but by sliding the cardboard around you can alter which portion of the image is visible. You could just leave the hole in one position and ignore the parts of video memory that aren't visible, but you can get all sorts of useful effects by sliding the screen window around, or by drawing images in a hidden part of video memory and then flipping across to display them.
For example, you could select a 640x480 mode in which the monitor acts as a window onto a 1024x1024 virtual screen, and then move the visible screen around in this larger area (hardware scrolling). Initially, with the visible screen positioned at the top left corner of video memory, this setup would look like:
With a virtual screen bigger than the visible screen you can perform smooth CPU inexpensive scrolling: you draw your graphics once, and then only tell the video card to show a different portion of the screen. However, virtual screens are not supported on all platforms, and on some they might be emulated through software, losing any performance. On top of that, many video cards only allow horizontal scrolling in steps of 32 bytes. This is not a problem if your game runs in 24 or 32 bit, but it tends to mean jerky scrolling for other color depths.(0,0)------------(640,0)----(1024,0) | | | | visible screen | | | | | (0,480)----------(640,480) | | | | the rest of video memory | | | (0,1024)--------------------(1024,1024)
The other reason you could use virtual screens for is page flipping. This means showing one portion of the virtual screen while your program draws to the hidden one. When you finish, you show the part you have been drawing to and repeat the process with the area now hidden. The result is a perfectly smooth screen update without flickering or other graphical artifacts.
Scrolling manually to one part of the video memory is one non portable way to accomplish this. The portable way is to use functions like create_system_bitmap(), create_video_bitmap(), show_video_bitmap(), etc. These functions divide the memory of the video card in areas and switch between them, a feature supported on all platforms and video cards (given that they have enough memory for the screen resolutions you asked for).
The last thing you need to know about setting a graphic mode are drivers. Each platform has a number of graphic drivers which support a different range of hardware or behave in different ways. To avoid cluttering your own code with #ifdefs and dealing with drivers added after you release your program, Allegro provides several so called magic drivers. These magic drivers don't really exists, they wrap around a specific kind of functionality.
The magic drivers you can use are:
Note that the screen color depth won't change until the next successful call to set_gfx_mode().set_color_depth(32); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) { abort_on_error("Couldn't set a 32 bit color resolution"); }
See also: get_color_depth, set_gfx_mode, set_color_conversion, makecol, getr, desktop_color_depth.
Examples using this: Available Allegro examples.
Note that the function returns whatever value you may have set previously with set_color_depth(), which can be different from the current color depth of the screen global variable. If you really need to know the color depth of the screen, use bitmap_color_depth().
See also: set_color_depth, bitmap_color_depth.
Examples using this: exrgbhsv.
request_refresh_rate(60); if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) abort_on_error("Couldn't set graphic mode!"); if (get_refresh_rate() != 60) abort_on_error("Couldn't set refresh rate to 60Hz!");
See also: set_gfx_mode, get_refresh_rate.
See also: request_refresh_rate.
The mode entry points to the actual list of video modes.typedef struct GFX_MODE_LIST { int num_modes; GFX_MODE *mode; } GFX_MODE_LIST;
This list of video modes is terminated with an { 0, 0, 0 } entry.typedef struct GFX_MODE { int width, height, bpp; } GFX_MODE;
Note that the card parameter must refer to a _real_ driver. This function fails if you pass GFX_SAFE, GFX_AUTODETECT, or any other "magic" driver.
Return value: Returns a pointer to a list structure of the type GFX_MODE_LIST or NULL if the request could not be satisfied.
See also: destroy_gfx_mode_list, set_gfx_mode, set_color_depth.
See also: get_gfx_mode_list, set_gfx_mode, set_color_depth.
The v_w and v_h parameters specify the minimum virtual screen size, in case you need a large virtual screen for hardware scrolling or page flipping. You should set them to zero if you don't care about the virtual screen size.
When you call set_gfx_mode(), the v_w and v_h parameters represent the minimum size of virtual screen that is acceptable for your program. The range of possible sizes is usually very restricted, and Allegro may end up creating a virtual screen much larger than the one you request. Allowed sizes are driver dependent and some drivers do not allow virtual screens that are larger than the visible screen at all: don't assume that whatever you pass will always work.
In mode-X the virtual width can be any multiple of eight greater than or equal to the physical screen width, and the virtual height will be set accordingly (the VGA has 256k of vram, so the virtual height will be 256*1024/virtual_width).
Currently, using a big virtual screen for page flipping is considered bad practice. There are platforms which don't support virtual screens bigger than the physical screen but can create different video pages to flip back and forth. This means that, if you want page flipping and aren't going to use hardware scrolling, you should call set_gfx_mode() with (0,0) as the virtual screen size and later create the different video pages with create_video_bitmap(). Otherwise your program will be limited to the platforms supporting hardware scrolling.
After you select a graphics mode, the physical and virtual screen sizes can be checked with the macros SCREEN_W, SCREEN_H, VIRTUAL_W, and VIRTUAL_H.
Return value: Returns zero on success. On failure returns a negative number and stores a description of the problem in allegro_error.
See also: set_color_depth, request_refresh_rate, screen, gfx_capabilities, allegro_error, Standard config variables, GFX_*/DOS, GFX_*/Windows, GFX_*/X, GFX_*/Linux, GFX_*/BeOS, GFX_*/MacOSX, create_video_bitmap, get_desktop_resolution, SCREEN_W, SCREEN_H, VIRTUAL_W, VIRTUAL_H.
Examples using this: Available Allegro examples.
Return value: Returns zero on success, invalidating at the same time all callbacks previously registered with set_display_switch_callback(). Returns -1 if the requested mode is not currently possible.
See also: set_display_switch_callback, get_display_switch_mode.
Examples using this: exmidi, exswitch.
Return value: Returns zero on success, decreasing the number of empty callback slots by one. Returns -1 if the request is impossible for the current platform or you have reached the maximum number of allowed callbacks.
See also: remove_display_switch_callback, set_display_switch_mode.
Examples using this: exswitch.
See also: set_display_switch_callback.
See also: set_display_switch_mode.
Examples using this: exswitch.
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) abort_on_error("Couldn't set graphic mode!"); if (is_windowed_mode()) { /* Windowed mode stuff. */ } else { /* Fullscreen mode stuff. */ }
Return value: Returns true if the current graphics mode is a windowed mode, or zero if it is a fullscreen mode. You should not call this function if you are not in graphics mode.
See also: set_gfx_mode.
GFX_CAN_SCROLL:
Indicates that the scroll_screen() function may be used with this
driver.
GFX_CAN_TRIPLE_BUFFER:
Indicates that the request_scroll() and poll_scroll() functions may be
used with this driver. If this flag is not set, it is possible that
the enable_triple_buffer() function may be able to activate it.
GFX_HW_CURSOR:
Indicates that a hardware mouse cursor is in use. When this flag is
set, it is safe to draw onto the screen without hiding the mouse
pointer first. Note that not every cursor graphic can be implemented
in hardware: in particular VBE/AF only supports 2-color images up to
32x32 in size, where the second color is an exact inverse of the
first. This means that Allegro may need to switch between hardware and
software cursors at any point during the execution of your program, so
you should not assume that this flag will remain constant for long
periods of time. It only tells you whether a hardware cursor is in use
at the current time, and may change whenever you hide/redisplay the
pointer.
GFX_SYSTEM_CURSOR
Indicates that the mouse cursor is the default system cursor, not
Allegro's custom cursor.
GFX_HW_HLINE:
Indicates that the normal opaque version of the hline() function is
implemented using a hardware accelerator. This will improve the
performance not only of hline() itself, but also of many other
functions that use it as a workhorse, for example circlefill(),
triangle(), and floodfill().
GFX_HW_HLINE_XOR:
Indicates that the XOR version of the hline() function, and any other
functions that use it as a workhorse, are implemented using a hardware
accelerator.
GFX_HW_HLINE_SOLID_PATTERN:
Indicates that the solid and masked pattern modes of the hline()
function, and any other functions that use it as a workhorse, are
implemented using a hardware accelerator (see note below).
GFX_HW_HLINE_COPY_PATTERN:
Indicates that the copy pattern mode of the hline() function, and any
other functions that use it as a workhorse, are implemented using a
hardware accelerator (see note below).
GFX_HW_FILL:
Indicates that the opaque version of the rectfill() function, the
clear_bitmap() routine, and clear_to_color(), are implemented using a
hardware accelerator.
GFX_HW_FILL_XOR:
Indicates that the XOR version of the rectfill() function is
implemented using a hardware accelerator.
GFX_HW_FILL_SOLID_PATTERN:
Indicates that the solid and masked pattern modes of the rectfill()
function are implemented using a hardware accelerator (see note below).
GFX_HW_FILL_COPY_PATTERN:
Indicates that the copy pattern mode of the rectfill() function is
implemented using a hardware accelerator (see note below).
GFX_HW_LINE:
Indicates that the opaque mode line() and vline() functions are
implemented using a hardware accelerator.
GFX_HW_LINE_XOR:
Indicates that the XOR version of the line() and vline() functions are
implemented using a hardware accelerator.
GFX_HW_TRIANGLE:
Indicates that the opaque mode triangle() function is implemented
using a hardware accelerator.
GFX_HW_TRIANGLE_XOR:
Indicates that the XOR version of the triangle() function is
implemented using a hardware accelerator.
GFX_HW_GLYPH:
Indicates that monochrome character expansion (for text drawing) is
implemented using a hardware accelerator.
GFX_HW_VRAM_BLIT:
Indicates that blitting from one part of the screen to another is
implemented using a hardware accelerator. If this flag is set,
blitting within the video memory will almost certainly be the fastest
possible way to display an image, so it may be worth storing some of
your more frequently used graphics in an offscreen portion of the
video memory.
GFX_HW_VRAM_BLIT_MASKED:
Indicates that the masked_blit() routine is capable of a hardware
accelerated copy from one part of video memory to another, and that
draw_sprite() will use a hardware copy when given a sub-bitmap of the
screen or a video memory bitmap as the source image. If this flag is
set, copying within the video memory will almost certainly be the
fastest possible way to display an image, so it may be worth storing
some of your more frequently used sprites in an offscreen portion of
the video memory.
Warning: if this flag is not set, masked_blit() and draw_sprite() will not work correctly when used with a video memory source image! You must only try to use these functions to copy within the video memory if they are supported in hardware.
GFX_HW_MEM_BLIT:
Indicates that blitting from a memory bitmap onto the screen is being
accelerated in hardware.
GFX_HW_MEM_BLIT_MASKED:
Indicates that the masked_blit() and draw_sprite() functions are being
accelerated in hardware when the source image is a memory bitmap and
the destination is the physical screen.
GFX_HW_SYS_TO_VRAM_BLIT:
Indicates that blitting from a system bitmap onto the screen is being
accelerated in hardware. Note that some acceleration may be present
even if this flag is not set, because system bitmaps can benefit from
normal memory to screen blitting as well. This flag will only be set
if system bitmaps have further acceleration above and beyond what is
provided by GFX_HW_MEM_BLIT.
GFX_HW_SYS_TO_VRAM_BLIT_MASKED:
Indicates that the masked_blit() and draw_sprite() functions are being
accelerated in hardware when the source image is a system bitmap and
the destination is the physical screen. Note that some acceleration
may be present even if this flag is not set, because system bitmaps
can benefit from normal memory to screen blitting as well. This flag
will only be set if system bitmaps have further acceleration above and
beyond what is provided by GFX_HW_MEM_BLIT_MASKED.
GFX_HW_VRAM_STRETCH_BLIT:
Indicates that stretched blitting of video bitmaps onto the screen is
implemented using hardware acceleration.
GFX_HW_SYS_STRETCH_BLIT:
Indicates that stretched blitting of system bitmaps onto the screen is
implemented using hardware acceleration.
GFX_HW_VRAM_STRETCH_BLIT_MASKED:
Indicates that masked stretched blitting (including stretch_sprite) of
video bitmaps onto the screen is implemented using hardware acceleration.
NOTE: some display drivers may show artifacts when this function is used.
If the image does not look correct try updating your video drivers.
GFX_HW_SYS_STRETCH_BLIT_MASKED:
Indicates that masked stretched blitting (including stretch_sprite) of
system bitmaps onto the screen is implemented using hardware acceleration.
NOTE: some display drivers may show artefact's when this function is used.
If the image does not look correct try updating your video drivers.
Note: even if the capabilities information says that patterned drawing is supported by the hardware, it will not be possible for every size of pattern. VBE/AF only supports patterns up to 8x8 in size, so Allegro will fall back on the original non-accelerated drawing routines whenever you use a pattern larger than this.
Note2: these hardware acceleration features will only take effect when you are drawing directly onto the screen bitmap, a video memory bitmap, or a sub-bitmap thereof. Accelerated hardware is most useful in a page flipping or triple buffering setup, and is unlikely to make any difference to the classic "draw onto a memory bitmap, then blit to the screen" system.
See also: screen, create_video_bitmap, scroll_screen, request_scroll, show_mouse, enable_triple_buffer.
Examples using this: ex3buf, exaccel, exsyscur, exupdate.
Return value: Returns zero if triple buffering is enabled, -1 otherwise.
See also: gfx_capabilities, request_scroll, request_video_bitmap.
Examples using this: ex3buf, exupdate.
Mode-X scrolling is reliable and will work on any card, other drivers may not work or not work reliably. See the platform-specific section of the docs for more information.
Allegro will handle any necessary vertical retrace synchronisation when scrolling the screen, so you don't need to call vsync() before it. This means that scroll_screen() has the same time delay effects as vsync().
Return value: Returns zero on success. Returns non-zero if the graphics driver can't handle hardware scrolling or the virtual screen is not large enough.
See also: set_gfx_mode, show_video_bitmap, request_scroll, request_video_bitmap.
Examples using this: exscroll.
Triple buffering is only possible with certain drivers: you can look at the GFX_CAN_TRIPLE_BUFFER bit in the gfx_capabilities flag to see if it will work with the current driver.
Return value: This function returns zero on success, non-zero otherwise.
See also: poll_scroll, request_video_bitmap, gfx_capabilities, scroll_screen.
Return value: Returns non-zero if it is still waiting to take place, and zero if the requested scroll has already happened.
See also: request_scroll, request_video_bitmap.
Examples using this: ex3buf, exupdate.
Allegro will handle any necessary vertical retrace synchronisation when page flipping, so you don't need to call vsync() before it. This means that show_video_bitmap() has the same time delay effects as vsync() by default. This can be adjusted with the "disable_vsync" config key in the [graphics] section of allegro.cfg. Example:
int current_page; BITMAP *video_page[2]; ... /* Create pages for page flipping */ video_page[0] = create_video_bitmap(SCREEN_W, SCREEN_H); video_page[1] = create_video_bitmap(SCREEN_W, SCREEN_H); current_page = 0; ... /* draw the screen and flip pages */ draw_screen(video_page[current_page]); show_video_bitmap(video_page[current_page]); current_page = (current_page+1)%2; ...
Return value: Returns zero on success and non-zero on failure.
See also: scroll_screen, create_video_bitmap, Standard config variables.
Examples using this: exaccel, exflip, exupdate.
int current_page; BITMAP *video_page[3]; ... /* Create pages for page flipping */ video_page[0] = create_video_bitmap(SCREEN_W, SCREEN_H); video_page[1] = create_video_bitmap(SCREEN_W, SCREEN_H); video_page[2] = create_video_bitmap(SCREEN_W, SCREEN_H); current_page = 0; ... /* draw the screen and flip pages */ draw_screen(video_page[current_page]); do { } while (poll_scroll()); request_video_bitmap(video_page[current_page]); current_page = (current_page+1)%3; ...
Return value: Returns zero on success and non-zero on failure.
See also: poll_scroll, request_scroll, gfx_capabilities, create_video_bitmap, scroll_screen.
Examples using this: ex3buf, exupdate.
See also: set_palette, scroll_screen.
Examples using this: Available Allegro examples.
Once you have selected a graphics mode, you can draw things onto the display via the `screen' bitmap. All the Allegro graphics routines draw onto BITMAP structures, which are areas of memory containing rectangular images, stored as packed byte arrays (in 8-bit modes one byte per pixel, in 15- and 16-bit modes two bytes per pixel, in 24-bit modes 3 bytes per pixel and in 32-bit modes 4 bytes per pixel). You can create and manipulate bitmaps in system RAM, or you can write to the special `screen' bitmap which represents the video memory in your graphics card.
Read chapter "Direct access to video memory" for information on how to get direct access to the image memory in a bitmap.
Allegro supports several different types of bitmaps:
For example, to draw a pixel onto the screen you would write:
Or to implement a double-buffered system:putpixel(screen, x, y, color);
/* Make a bitmap in RAM. */ BITMAP *bmp = create_bitmap(320, 200); /* Clean the memory bitmap. */ clear_bitmap(bmp); /* Draw onto the memory bitmap. */ putpixel(bmp, x, y, color); /* Copy it to the screen. */ blit(bmp, screen, 0, 0, 0, 0, 320, 200);
Warning: be very careful when using this pointer at the same time as any bitmaps created by the create_video_bitmap() function (see the description of this function for more detailed information). And never try to destroy it with destroy_bitmap().
See also: set_gfx_mode, is_screen_bitmap, create_video_bitmap, scroll_screen.
Examples using this: Available Allegro examples.
char buf[100]; ... uszprintf(buf, sizeof(buf), "The screen size is %d x %d pixels", SCREEN_W, SCREEN_H);
See also: screen, set_gfx_mode, VIRTUAL_W, VIRTUAL_H.
Examples using this: Available Allegro examples.
char buf[100]; ... uszprintf(buf, sizeof(buf), "The virtual screen size is %d x %d pixels", SCREEN_W, SCREEN_H);
See also: screen, set_gfx_mode, SCREEN_W, SCREEN_H.
/* Create a 10 pixel tall bitmap, as wide as the screen. */ BITMAP *bmp = create_bitmap(SCREEN_W, 10); if (!bmp) abort_on_error("Couldn't create bitmap!"); /* Use the bitmap. */ ... /* Destroy it when we don't need it any more. */ destroy_bitmap(bmp);
Return value: Returns a pointer to the created bitmap, or NULL if the bitmap could not be created. Remember to free this bitmap later to avoid memory leaks.
See also: create_bitmap_ex, create_sub_bitmap, create_video_bitmap, create_system_bitmap, destroy_bitmap, set_color_depth, is_memory_bitmap, clear_bitmap, clear_to_color.
Examples using this: Available Allegro examples.
/* Create screen sized bitmap in 32 bits per pixel. */ BITMAP *bmp = create_bitmap_ex(32, SCREEN_W, SCREEN_H); if (!bmp) abort_on_error("Couldn't create bitmap!"); /* Use the bitmap. */ ... /* Destroy it when we don't need it any more. */ destroy_bitmap(bmp);
Return value: Returns a pointer to the created bitmap, or NULL if the bitmap could not be created. Remember to free this bitmap later to avoid memory leaks.
See also: create_bitmap, create_sub_bitmap, create_video_bitmap, create_system_bitmap, destroy_bitmap, is_memory_bitmap, clear_bitmap, clear_to_color.
Examples using this: ex12bit, exlights, exrgbhsv, extrans.
Return value: Returns a pointer to the created sub bitmap, or NULL if the sub bitmap could not be created. Remember to free the sub bitmap before freeing the parent bitmap to avoid memory leaks and potential crashes accessing memory which has been freed.
See also: create_bitmap, create_bitmap_ex, destroy_bitmap, is_sub_bitmap, clear_bitmap, clear_to_color.
Examples using this: expat, exscroll, exswitch.
Warning: video memory bitmaps are usually allocated from the same space as the screen bitmap, so they may overlap with it; it is therefore not a good idea to use the global screen at the same time as any surfaces returned by this function.
Return value: Returns a pointer to the bitmap on success, or NULL if you have run out of video ram. Remember to destroy this bitmap before any subsequent call to set_gfx_mode().
See also: create_bitmap, create_bitmap_ex, create_system_bitmap, create_sub_bitmap, destroy_bitmap, screen, show_video_bitmap, gfx_capabilities, is_video_bitmap, clear_bitmap, clear_to_color.
Examples using this: ex3buf, exaccel, exflip, exupdate.
Return value: Returns a pointer to the bitmap on success, NULL otherwise. Remember to destroy this bitmap before any subsequent call to set_gfx_mode().
See also: create_bitmap, create_bitmap_ex, create_video_bitmap, create_sub_bitmap, destroy_bitmap, is_system_bitmap, clear_bitmap, clear_to_color.
Examples using this: exupdate.
The bitmap must not have a mouse cursor shown on it at the time it is destroyed.
See also: create_bitmap, load_bitmap, show_mouse.
Examples using this: Available Allegro examples.
switch (bitmap_color_depth(screen)) { case 8: /* Access screen using optimized 8-bit code. */ break; default: /* Use generic slow functions. */ break; }
See also: set_color_depth, bitmap_mask_color.
Examples using this: ex3d, exlights, exscn3d, exswitch, extrans, exupdate, exzbuf.
/* Replace mask color with another color. */ for (y = 0; y < bmp->h; y++) for (x = 0; x < bmp->w; x++) if (getpixel(bmp, x, y) == bitmap_mask_color(bmp)) putpixel(bmp, x, y, another_color);
See also: MASK_COLOR_8, set_color_depth, bitmap_color_depth.
Examples using this: ex3d, exmouse, expat.
See also: create_sub_bitmap.
See also: is_linear_bitmap, is_memory_bitmap.
Historically there were only linear and planar bitmaps for Allegro, so is_linear_bitmap() is actually an alias for !is_planar_bitmap().
See also: is_planar_bitmap, is_memory_bitmap.
See also: is_linear_bitmap, is_planar_bitmap.
See also: screen, create_sub_bitmap.
See also: screen, create_video_bitmap, create_sub_bitmap.
See also: create_system_bitmap, create_sub_bitmap.
See also: create_sub_bitmap.
Note: You do never need to use acquire_bitmap on a memory bitmap, i.e. a normal bitmap created with create_bitmap. It will simply do nothing in that case.
It still can be useful, because e.g. under the current DirectDraw driver of Allegro, most drawing functions need to lock a video bitmap before drawing to it. But doing this is very slow, so you will get much better performance if you acquire the screen just once at the start of your main redraw function, then call multiple drawing operations which need the bitmap locked, and only release it when done.
Multiple acquire calls may be nested, but you must make sure to match up the acquire_bitmap and release_bitmap calls. Be warned that DirectX and X11 programs activate a mutex lock whenever a surface is locked, which prevents them from getting any input messages, so you must be sure to release all your bitmaps before using any timer, keyboard, or other non-graphics routines!
Note that if you are using hardware accelerated VRAM->VRAM functions, you should not call acquire_bitmap(). Such functions need an unlocked target bitmap under DirectX, so there is now just the opposite case from before - if the bitmap is already locked with acquire_bitmap, the drawing operation has to unlock it.
Note: For backwards compatibility, the unlocking behavior of such functions is permanent. That is, if you call acquire_bitmap first, then call e.g. an accelerated blit, the DirectX bitmap will be unlocked internally (it won't affect the nesting counter of acquire/release calls).
There is no clear cross-platform way in this Allegro version to know which drawing operations need a locked/unlocked state. For example a normal rectfill most probably is accelerated under DirectX, and therefore needs the screen unlocked, but an XOR rectfill, or one with blending activated, most probably is not, and therefore locks the screen. And while the DirectX driver will do automatic unlocking, there is no such thing under X11, where the function is used to synchronize X11 calls from different threads. Your best bet is to never use acquire_bitmap - changes are you are doing something in the wrong way if you think you need it.
Warning: This function can be very dangerous to use, since the whole program may get locked while the bitmap is locked. So the lock should only be held for a short time, and you should not call anything but drawing operations onto the locked video bitmap while a lock is in place. Especially don't call things like show_mouse (or scare_mouse which calls that) or readkey, since it will most likely deadlock your entire program.
See also: release_bitmap, acquire_screen, release_screen.
Examples using this: ex3buf, exaccel, expat, exquat, exscroll, exswitch, exupdate.
See also: acquire_bitmap, acquire_screen, release_screen.
Examples using this: ex3buf, exaccel, expat, exquat, exscroll, exswitch, exupdate.
See also: acquire_bitmap, release_bitmap, release_screen.
Examples using this: Available Allegro examples.
See also: acquire_bitmap, release_bitmap, acquire_screen.
Examples using this: Available Allegro examples.
Drawing operations will be performed (at least partially) on the bitmap as long as the first coordinates of its clipping rectangle are not greater than the second coordinates and its intersection with the actual image is non-empty. If either condition is not fulfilled, drawing will be turned off for the bitmap, e.g.
set_clip_rect(bmp, 0, 0, -1, -1); /* disable drawing on bmp */
Note that passing "out-of-bitmap" coordinates is allowed, but they are likely to be altered (and so the coordinates returned by get_clip_rect() will be different). However, such modifications are guaranteed to preserve the external effect of the clipping rectangle, that is not to modify the actual area of the image that it is OK to draw onto.
See also: get_clip_rect, add_clip_rect, set_clip_state, get_clip_state.
Examples using this: ex12bit, excamera.
See also: set_clip_rect, add_clip_rect, set_clip_state, get_clip_state.
See also: set_clip_rect, get_clip_rect, set_clip_state, get_clip_state.
See also: set_clip_rect, get_clip_rect, add_clip_rect, get_clip_state.
See also: set_clip_rect, get_clip_rect, add_clip_rect, set_clip_state.
See also: set_clip_rect, set_clip_state, getpixel.
Warning: when using truecolor images, you should always set the graphics mode before loading any bitmap data! Otherwise the pixel format (RGB or BGR) will not be known, so the file may be converted wrongly.
If the file contains a truecolor image, you must set the video mode or call set_color_conversion() before loading it. In this case, if the destination color depth is 8-bit, the palette will be generated by calling generate_optimized_palette() on the bitmap; otherwise, the returned palette will be generated by calling generate_332_palette().
The pal argument may be NULL. In this case, the palette data are simply not returned. Additionally, if the file is a truecolor image and the destination color depth is 8-bit, the color conversion process will use the current palette instead of generating an optimized one.
Example:
BITMAP *bmp; PALETTE palette; ... bmp = load_bitmap("image.pcx", palette); if (!bmp) abort_on_error("Couldn't load image.pcx!"); ... destroy_bitmap(bmp);
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_bmp, load_lbm, load_pcx, load_tga, destroy_bitmap, save_bitmap, register_bitmap_file_type, set_color_depth, set_color_conversion, generate_optimized_palette, generate_332_palette.
Examples using this: exaccel, exalpha, exbitmap, exblend, exconfig, exlights, exshade, extrans, exxfade.
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_bitmap, load_bmp_pf.
PACKFILE *packfile; BITMAP *bmp; packfile = pack_fopen("mybitmap.bmp", F_READ); if (!packfile) abort_on_error("Couldn't open mybitmap.bmp"); bmp = load_bmp_pf(packfile, pal); if (!bmp) abort_on_error("Error loading mybitmap.bmp");
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_bmp.
Examples using this: expackf.
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_bitmap.
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_bitmap.
Examples using this: expackf, exscale.
PACKFILE *packfile; BITMAP *bmp; packfile = pack_fopen("mybitmap.pcx", F_READ); if (!packfile) abort_on_error("Couldn't open mybitmap.pcx"); bmp = load_bmp_pf(packfile, pal); if (!bmp) abort_on_error("Error loading mybitmap.pcx");
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_pcx.
Examples using this: expackf.
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_bitmap.
PACKFILE *packfile; BITMAP *bmp; packfile = pack_fopen("mybitmap.tga", F_READ); if (!packfile) abort_on_error("Couldn't open mybitmap.tga"); bmp = load_bmp_pf(packfile, pal); if (!bmp) abort_on_error("Error loading mybitmap.tga");
Return value: Returns a pointer to the bitmap or NULL on error. Remember that you are responsible for destroying the bitmap when you are finished with it to avoid memory leaks.
See also: load_tga.
Examples using this: expackf.
Two things to watch out for: on some video cards it may be faster to copy the screen to a memory bitmap and save the latter, and if you use this to dump the screen into a file you may end up with an image much larger than you were expecting, because Allegro often creates virtual screens larger than the visible screen. You can get around this by using a sub-bitmap to specify which part of the screen to save, eg:
BITMAP *bmp; PALETTE pal; ... get_palette(pal); bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H); save_bitmap("dump.pcx", bmp, pal); destroy_bitmap(bmp);
Return value: Returns non-zero on error.
See also: save_bmp, save_pcx, save_tga, load_bitmap, register_bitmap_file_type.
Return value: Returns non-zero on error.
See also: save_bitmap.
See also: save_bmp.
Examples using this: expackf.
Return value: Returns non-zero on error.
See also: save_bitmap.
See also: save_pcx.
Return value: Returns non-zero on error.
See also: save_bitmap.
See also: save_tga.
Examples using this: expackf.
BITMAP *load_dump(const char *filename, RGB *pal) { ... } int save_dump(const char *filename, BITMAP *bmp, const RGB *pal) { ... } register_bitmap_file_type("dump", load_dump, save_dump);
See also: load_bitmap, save_bitmap.
For convenience, the following macros can be used to select common combinations of these flags:COLORCONV_NONE // disable all format // conversions COLORCONV_8_TO_15 // expand 8-bit to 15-bit COLORCONV_8_TO_16 // expand 8-bit to 16-bit COLORCONV_8_TO_24 // expand 8-bit to 24-bit COLORCONV_8_TO_32 // expand 8-bit to 32-bit COLORCONV_15_TO_8 // reduce 15-bit to 8-bit COLORCONV_15_TO_16 // expand 15-bit to 16-bit COLORCONV_15_TO_24 // expand 15-bit to 24-bit COLORCONV_15_TO_32 // expand 15-bit to 32-bit COLORCONV_16_TO_8 // reduce 16-bit to 8-bit COLORCONV_16_TO_15 // reduce 16-bit to 15-bit COLORCONV_16_TO_24 // expand 16-bit to 24-bit COLORCONV_16_TO_32 // expand 16-bit to 32-bit COLORCONV_24_TO_8 // reduce 24-bit to 8-bit COLORCONV_24_TO_15 // reduce 24-bit to 15-bit COLORCONV_24_TO_16 // reduce 24-bit to 16-bit COLORCONV_24_TO_32 // expand 24-bit to 32-bit COLORCONV_32_TO_8 // reduce 32-bit RGB to 8-bit COLORCONV_32_TO_15 // reduce 32-bit RGB to 15-bit COLORCONV_32_TO_16 // reduce 32-bit RGB to 16-bit COLORCONV_32_TO_24 // reduce 32-bit RGB to 24-bit COLORCONV_32A_TO_8 // reduce 32-bit RGBA to 8-bit COLORCONV_32A_TO_15 // reduce 32-bit RGBA to 15-bit COLORCONV_32A_TO_16 // reduce 32-bit RGBA to 16-bit COLORCONV_32A_TO_24 // reduce 32-bit RGBA to 24-bit COLORCONV_DITHER_PAL // dither when reducing to 8-bit COLORCONV_DITHER_HI // dither when reducing to // hicolor COLORCONV_KEEP_TRANS // keep original transparency
If you enable the COLORCONV_DITHER flag, dithering will be performed whenever truecolor graphics are converted into a hicolor or paletted format, including by the blit() function, and any automatic conversions that take place while reading graphics from disk. This can produce much better looking results, but is obviously slower than a direct conversion.COLORCONV_EXPAND_256 // expand 256-color to hi/truecolor COLORCONV_REDUCE_TO_256 // reduce hi/truecolor to 256-color COLORCONV_EXPAND_15_TO_16 // expand 15-bit hicolor to 16-bit COLORCONV_REDUCE_16_TO_15 // reduce 16-bit hicolor to 15-bit COLORCONV_EXPAND_HI_TO_TRUE // expand 15/16-bit to 24/32-bit COLORCONV_REDUCE_TRUE_TO_HI // reduce 24/32-bit to 15/16-bit COLORCONV_24_EQUALS_32 // convert between 24- and 32-bit COLORCONV_TOTAL // everything to current format COLORCONV_PARTIAL // convert 15 <-> 16-bit and // 24 <-> 32-bit COLORCONV_MOST // all but hi/truecolor <-> 256 COLORCONV_DITHER // dither during all color reductions COLORCONV_KEEP_ALPHA // convert everything to current format // unless it would lose alpha information
If you intend using converted bitmaps with functions like masked_blit() or draw_sprite(), you should specify the COLORCONV_KEEP_TRANS flag. It will ensure that the masked areas in the bitmap before and after the conversion stay exactly the same, by mapping transparent colors to each other and adjusting colors which would be converted to the transparent color otherwise. It affects every blit() operation between distinct pixel formats and every automatic conversion.
See also: set_color_depth, load_bitmap, load_datafile, fixup_datafile, makecol15_dither, get_color_conversion.
Examples using this: exalpha, exblend, exdata, exexedat, exlights, exxfade.
See also: set_color_conversion.
All the Allegro drawing functions use integer parameters to represent colors. In truecolor resolutions these numbers encode the color directly as a collection of red, green, and blue bits, but in a regular 256-color mode the values are treated as indexes into the current palette, which is a table listing the red, green and blue intensities for each of the 256 possible colors.
Palette entries are stored in an RGB structure, which contains red, green and blue intensities in the VGA hardware format, ranging from 0-63, and is defined as:
It contains an additional field for the purpose of padding but you should not usually care about it. For example:typedef struct RGB { unsigned char r, g, b; } RGB;
The type PALETTE is defined to be an array of PAL_SIZE RGB structures, where PAL_SIZE is a preprocessor constant equal to 256.RGB black = { 0, 0, 0 }; RGB white = { 63, 63, 63 }; RGB green = { 0, 63, 0 }; RGB grey = { 32, 32, 32 };
You may notice that a lot of the code in Allegro spells 'palette' as 'pallete'. This is because the headers from my old Mark Williams compiler on the Atari spelt it with two l's, so that is what I'm used to. Allegro will happily accept either spelling, due to some #defines in allegro/alcompat.h (which can be turned off by defining the ALLEGRO_NO_COMPATIBILITY symbol before including Allegro headers).
RGB rgb; ... vsync(); set_color(192, &rgb);
See also: set_palette, get_color, _set_color.
Examples using this: ex12bit, exrgbhsv, exscroll.
If you really must use _set_color from retrace_proc, note that it should only be used under DOS, in VGA mode 13h and mode-X. Some SVGA chipsets aren't VGA compatible (set_color() and set_palette() will use VESA calls on these cards, but _set_color() doesn't know about that).
See also: set_color, set_gfx_mode.
Examples using this: ex3buf.
BITMAP *bmp; PALETTE palette; ... bmp = load_bitmap(filename, palette); if (!bmp) abort_on_error("Couldn't load bitmap!"); set_palette(palette);
See also: set_gfx_mode, set_palette_range, set_color, get_palette, select_palette, palette_color.
Examples using this: Available Allegro examples.
PALETTE palette; ... /* Modify the first 16 entries. */ change_first_16_colors(palette); /* Now update them waiting for vsync. */ set_palette_range(palette, 0, 15, 1);
See also: set_palette, get_palette_range.
Examples using this: exzbuf.
RGB color; ... get_color(11, &color);
See also: get_palette, set_color.
PALETTE pal; ... get_palette(pal);
See also: get_palette_range, get_color, set_palette.
See also: get_palette, set_palette_range.
See also: fade_in, fade_out, fade_from.
Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution.
See also: fade_from.
Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution.
See also: fade_in.
Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution.
See also: fade_out.
Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution.
See also: fade_in, fade_out, fade_interpolate, fade_from_range.
Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution.
See also: fade_out, fade_from, fade_interpolate, fade_in_range.
Note that this function will block your game while the fade is in effect, and it won't work right visually if you are not in an 8 bit color depth resolution.
See also: fade_in, fade_from, fade_interpolate, fade_in_range.
Examples using this: ex12bit.
See also: set_palette, unselect_palette.
Examples using this: exlights.
See also: select_palette.
See also: generate_optimized_palette, set_color_depth.
Examples using this: excolmap, exrgbhsv, extruec, exupdate.
Return value: Returns the number of different colors recognised in the provided bitmap, zero if the bitmap is not a truecolor image or there wasn't enough memory to perform the operation, and negative if there was any internal error in the color reduction code.
See also: generate_332_palette, set_color_depth.
See also: black_palette, desktop_palette.
Examples using this: exjoy.
See also: default_palette, desktop_palette.
Examples using this: expal.
The contents of this palette are 16 colors repeated 16 times. Color entry zero is equal to color entry 16, which is equal to color entry 24, etc.
Index Color RGB values 0 White 63 63 63 1 Red 63 0 0 2 Green 0 63 0 3 Yellow 63 63 0 4 Blue 0 0 63 5 Pink 63 0 63 6 Cyan 0 63 63 7 Grey 16 16 16 8 Light grey 31 31 31 9 Light red 63 31 31 10 Light green 31 63 31 11 Light yellow 63 63 31 12 Light blue 31 31 63 13 Light pink 63 31 63 14 Light cyan 31 63 63 15 Black 0 0 0
See also: default_palette, black_palette.
Examples using this: Available Allegro examples.
In a truecolor video mode the red, green, and blue components for each pixel are packed directly into the color value, rather than using a palette lookup table. In a 15-bit mode there are 5 bits for each color, in 16-bit modes there are 5 bits each of red and blue and six bits of green, and both 24 and 32-bit modes use 8 bits for each color (the 32-bit pixels simply have an extra padding byte to align the data nicely). The layout of these components can vary depending on your hardware, but will generally either be RGB or BGR. Since the layout is not known until you select the video mode you will be using, you must call set_gfx_mode() before using any of the following routines!
/* 16 bit color version of green. */ int green_color = makecol16(0, 255, 0);
Return value: Returns the requested RGB triplet in the specified color depth.
See also: makeacol32, makecol, makecol_depth, makecol15_dither, rgb_map, bestfit_color, set_color_depth.
Examples using this: exrgbhsv.
See also: makeacol, set_alpha_blender, set_write_alpha_blender.
/* Regardless of color depth, this will look green. */ int green_color = makecol(0, 255, 0);
Return value: Returns the requested RGB triplet in the current color depth.
See also: makeacol, makecol8, makecol_depth, makecol15_dither, rgb_map, set_color_depth.
Examples using this: Available Allegro examples.
/* Compose the green color for 15 bit color depth. */ int green_15bit = makecol_depth(15, 0, 255, 0);
Return value: Returns the requested RGB triplet in the specified color depth.
See also: makeacol, makecol, makecol8, makecol15_dither, rgb_map, set_color_depth.
Return value: Returns the requested RGBA quadruplet.
See also: makecol, makecol_depth, set_alpha_blender, set_write_alpha_blender.
Example:
int pixel1, pixel2; /* The following two color values MAY be different. */ pixel1 = makecol16_dither(255, 192, 64, 0, 0); pixel2 = makecol16_dither(255, 192, 64, 1, 0);
Return value: Returns the RGB value dithered for the specified coordinate.
See also: makecol, makecol8, set_color_conversion.
int r, g, b, color_value; color_value = _getpixel15(screen, 100, 100); r = getr15(color_value); g = getg15(color_value); b = getb15(color_value);
See also: geta32, getr, getr_depth, makecol, set_color_depth.
See also: getr8.
int r, g, b, color_value; color_value = getpixel(screen, 100, 100); r = getr(color_value); g = getg(color_value); b = getb(color_value);
See also: getr8, getr_depth, makecol, set_color_depth.
Examples using this: exalpha.
int r, g, b, color_value, bpp; bpp = bitmap_color_depth(bitmap); color_value = getpixel(bitmap, 100, 100); r = getr_depth(bpp, color_value); g = getg_depth(bpp, color_value); b = getb_depth(bpp, color_value);
See also: getr, getr8, geta32, makecol, set_color_depth.
Examples using this: exlights.
set_color_depth(32); ... set_palette(desktop_palette); /* Put a pixel with the color 2 (green) of the palette */ putpixel(screen, 100, 100, palette_color[2]);
See also: set_palette, makecol, set_color_depth.
Examples using this: Available Allegro examples.
See also: bitmap_mask_color, makecol, draw_sprite, masked_blit.
Except for _putpixel(), all these routines are affected by the current drawing mode and the clipping rectangle of the destination bitmap. Unless specified otherwise, all coordinates for drawing operations are inclusive, and they, as well as lengths, are specified in pixel units.
See also: clear_to_color.
Examples using this: Available Allegro examples.
/* Clear the screen to red. */ clear_to_color(bmp, makecol(255, 0, 0));
See also: clear_bitmap, makecol.
Examples using this: Available Allegro examples.
putpixel(screen, 10, 30, some_color);
See also: getpixel, _putpixel, drawing_mode, makecol.
Examples using this: ex12bit, exalpha, exflame, exjoy, exstars, exswitch.
See also: putpixel, makecol.
Return value: Returns -1 if the point lies outside the bitmap (ignoring the clipping rectangle), otherwise the value of the pixel in the color format of the bitmap.
Warning: -1 is also a valid value for pixels contained in 32-bit bitmaps with alpha channel (when R,G,B,A are all equal to 255) so you can't use the test against -1 as a predicate for such bitmaps. In this cases, the only reliable predicate is is_inside_bitmap().
To extract the individual color components, use the getr() / getg() / getb() / geta() family of functions.
See also: putpixel, _getpixel, is_inside_bitmap, getr, getg, getb, geta, Truecolor pixel formats, Palette routines.
Examples using this: ex12bit, exalpha, exflame, exlights.
Return value: Returns the value of the pixel in the color format you specified.
See also: getpixel.
Note: vline() is implemented as an alias to another function. See ALLEGRO_NO_VHLINE_ALIAS in the `Differences between platforms' section for details.
See also: hline, line, drawing_mode, makecol, Differences between platforms.
Examples using this: exrgbhsv, exscroll, extruec.
Note: hline() is implemented as an alias to another function. See ALLEGRO_NO_VHLINE_ALIAS in the `Differences between platforms' section for details.
See also: vline, line, drawing_mode, makecol, Differences between platforms.
Examples using this: exsprite.
void draw_dust_particle(BITMAP *bmp, int x, int y, int d) { ... } do_line(screen, 0, 0, SCREEN_W-1, SCREEN_H-2, dust_strength, draw_dust_particle);
See also: do_circle, do_ellipse, do_arc, line.
See also: fastline, hline, vline, do_line, drawing_mode, makecol.
Examples using this: Available Allegro examples.
See also: line, hline, vline, do_line, drawing_mode, makecol.
Examples using this: Available Allegro examples.
See also: polygon, triangle3d, drawing_mode, makecol.
Examples using this: ex3buf, exstars, exupdate.
int points[12] = { 50, 50, 100, 100, 100, 150, 50, 200, 0, 150, 0, 100 }; ... clear_to_color(screen, makecol(255, 255, 255)); polygon(screen, 6, points, makecol(0, 0, 0));
See also: triangle, polygon3d, drawing_mode, makecol.
Examples using this: excamera.
See also: rectfill, drawing_mode, makecol.
Examples using this: ex3d, excamera.
See also: rect, clear_bitmap, drawing_mode, makecol.
Examples using this: exalpha, excolmap, exkeys, exmidi, expat, exscroll, exsprite, exstars, exswitch, extrans.
void draw_explosion_ring(BITMAP *bmp, int x, int y, int d) { ... } do_circle(screen, SCREEN_W/2, SCREEN_H/2, SCREEN_H/16, flame_color, draw_explosion_ring);
See also: do_ellipse, do_arc, do_line, circle, circlefill.
See also: ellipse, arc, circlefill, do_circle, drawing_mode, makecol.
Examples using this: ex12bit, exblend, excustom, exjoy, exmem, exmouse, exquat, exsprite.
See also: ellipsefill, circle, do_circle, drawing_mode, makecol.
Examples using this: excolmap, excustom, exdbuf, exflip, exlights, expal, exspline, extrans.
void draw_explosion_ring(BITMAP *bmp, int x, int y, int d) { ... } do_ellipse(screen, SCREEN_W/2, SCREEN_H/2, SCREEN_H/16, SCREEN_H/32, flame_color, draw_explosion_ring);
See also: do_circle, do_arc, do_line, ellipse, ellipsefill.
See also: circle, arc, ellipsefill, do_ellipse, drawing_mode, makecol.
See also: circlefill, ellipse, do_ellipse, drawing_mode, makecol.
Examples using this: ex12bit.
void draw_explosion_ring(BITMAP *bmp, int x, int y, int d) { ... } do_arc(screen, SCREEN_W/2, SCREEN_H/2, itofix(-21), itofix(43), 50, flame_color, draw_explosion_ring);
See also: do_circle, do_ellipse, do_line, arc.
/* Draw a black arc from 4 to 1 o'clock. */ arc(screen, SCREEN_W/2, SCREEN_H/2, itofix(-21), itofix(43), 50, makecol(0, 0, 0));
See also: circle, ellipse, drawing_mode, makecol.
See also: spline.
Examples using this: exspline.
See also: calc_spline, drawing_mode, makecol.
Examples using this: exspline.
See also: drawing_mode, makecol.
As far as Allegro is concerned, a bitmap and a sprite are the same thing, but to many people the two words imply slightly different things. The function draw_sprite() is called so rather than draw_bitmap() partly because it indicates that it uses a masked drawing mode (if it existed, you could expect draw_bitmap() to be a simple block copy), and partly for historical reasons. In Allegro 1.0 there were actually different structures for sprites and bitmaps, each with their own set of abilities. Allegro 2.0 merged these into a single more flexible structure, but retained some names like draw_sprite().
In wider (non-Allegro) terms, the two words can mean quite different things. Generally you can say that sprites are a subset of bitmaps, but even that isn't true in 100% of cases.
BITMAP: a widely accepted term that will be understood by anyone even remotely connected with computer graphics. It simply means an image built up from a grid of pixels, ie. just about any picture that you are likely to come across on a computer (vector graphics formats are the exception, but those must be rendered into a bitmap format before they can be displayed by most hardware). A more accurate term but slightly rarer term with the same meaning is "pixmap" (pixel-map).
SPRITE: a particular usage of bitmapped images, restricted to video games (other types of programmer probably won't be familiar with this term). Originally on machines like the C64, sprites were a hardware feature that allowed a number of small bitmap images to be loaded into special registers, and they could then be superimposed over the main graphics display and moved around just by modifying the position register. They were used for the moving objects (player and enemy characters), and enabled the C64 to do much more impressive things than would have been possible if all the drawing had to be done directly by the puny CPU.
Later on, a lot of old C64 programmers upgraded to machines like the Atari ST, which didn't have any special sprite hardware, but they carried on referring to their main moving objects as sprites (the routine to draw such a thing would obviously be called draw_sprite()). A sprite is really just a bitmap graphic which is drawn onto the screen, but when you call it a sprite rather than a bitmap, this suggests it is a gameplay element that can move freely around the world rather than being a static part of the environment, and that it will be drawn in a masked overlay mode rather than as a solid rectangle (there is also a strong implication that a sprite will be animated by cycling through a number of frames, but that isn't always the case).
In recent years some people have started using "sprite" to refer to any character graphics, even if they are not in fact drawn as 2d bitmaps, eg. "this game uses 3d polygonal player sprites". This is a confusing misuse of the word (Doom uses sprites, Quake does not), but it does happen.
The origin of the term "blit" is also rather interesting. This was originally BitBlt, an abbreviation of BITmap BLock Transfer, which was a function designed (possibly) by the people at Xerox who did so much of the pioneering work on graphics display systems, and subsequently copied by virtually everybody doing computer graphics (the Microsoft Windows GDI still provides a BitBlt function with identical functionality to the original). This routine was a workhorse for all sorts of drawing operations, basically copying bitmap graphics from one place to another, but including a number of different ROP modes (Raster OPerations) for doing things like XOR, inverting pixels, etc. A whole family of related words grew up around the BitBlt function, but "blt" is impossible to speak (try saying "bltter" or "bltting" :-) so people added the vowel to make it easier to pronounce.
Therefore, the act of calling the BitBlt function came to be known as "doing a blit". The obvious next step was to rename the function itself to blit(), which generally took place at the same time as people decided to simplify the original, removing the different ROP modes on the grounds that they aren't needed for games coding and don't work well with anything higher than monochrome images in any case. This leaves us with a function called blit(), which is an abbreviation for "block transfer". A strong case could be made for calling this blot() instead, but somehow that just doesn't sound the same!
Anyway, all the routines in this chapter are affected by the clipping rectangle of the destination bitmap.
You can blit between any parts of any two bitmaps, even if the two memory areas overlap (ie. source and dest are the same, or one is sub-bitmap of the other). You should be aware, however, that a lot of SVGA cards don't provide separate read and write banks, which means that blitting from one part of the screen to another requires the use of a temporary bitmap in memory, and is therefore extremely slow. As a general rule you should avoid blitting from the screen onto itself in SVGA modes.BITMAP *bmp; ... /* Blit src on the screen. */ blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); /* Now copy a chunk to a corner, slightly outside. /* blit(screen, screen, 100, 100, -10, -10, 25, 30);
In mode-X, on the other hand, blitting from one part of the screen to another can be significantly faster than blitting from memory onto the screen, as long as the source and destination are correctly aligned with each other. Copying between overlapping screen rectangles is slow, but if the areas don't overlap, and if they have the same plane alignment (ie. (source_x%4) == (dest_x%4)), the VGA latch registers can be used for a very fast data transfer. To take advantage of this, in mode-X it is often worth storing tile graphics in a hidden area of video memory (using a large virtual screen), and blitting them from there onto the visible part of the screen.
If the GFX_HW_VRAM_BLIT bit in the gfx_capabilities flag is set, the current driver supports hardware accelerated blits from one part of the screen onto another. This is extremely fast, so when this flag is set it may be worth storing some of your more frequently used graphics in an offscreen portion of the video memory.
Unlike most of the graphics routines, blit() allows the source and destination bitmaps to be of different color depths, so it can be used to convert images from one pixel format to another. In this case, the behavior is affected by the COLORCONV_KEEP_TRANS and COLORCONV_DITHER* flags of the current color conversion mode: see set_color_conversion() for more information.
See also: masked_blit, stretch_blit, draw_sprite, gfx_capabilities, set_color_conversion.
Examples using this: Available Allegro examples.
BITMAP *bmp; ... /* Stretch bmp to fill the screen. */ stretch_blit(bmp, screen, 0, 0, bmp->w, bmp->h, 0, 0, SCREEN_W, SCREEN_H);
See also: blit, masked_stretch_blit, stretch_sprite.
Examples using this: exalpha, exconfig, exscale, extrans.
BITMAP *hud_overlay; ... /* Paint hud overlay on the screen. */ masked_blit(hud_overlay, screen, 0, 0, 0, 0, hud_overlay->w, hud_overlay->h);
If the GFX_HW_VRAM_BLIT_MASKED bit in the gfx_capabilities flag is set, the current driver supports hardware accelerated masked blits from one part of the screen onto another. This is extremely fast, so when this flag is set it may be worth storing some of your more frequently used sprites in an offscreen portion of the video memory.
Warning: if the hardware acceleration flag is not set, masked_blit() will not work correctly when used with a source image in system or video memory so the latter must be a memory bitmap.
See also: blit, masked_stretch_blit, draw_sprite, bitmap_mask_color.
Examples using this: ex12bit, expat.
BITMAP *hud_overlay; ... /* Stretch hud overlay over the screen. */ masked_stretch_blit(hud_overlay, screen, 0, 0, hud_overlay->w, hud_overlay->h, 0, 0, SCREEN_W, SCREEN_H);
See also: blit, masked_blit, stretch_blit, stretch_sprite.
BITMAP *spaceship; ... draw_sprite(screen, spaceship, x, y);
If the GFX_HW_VRAM_BLIT_MASKED bit in the gfx_capabilities flag is set, the current driver supports hardware accelerated sprite drawing when the source image is a video memory bitmap or a sub-bitmap of the screen. This is extremely fast, so when this flag is set it may be worth storing some of your more frequently used sprites in an offscreen portion of the video memory.
Warning: if the hardware acceleration flag is not set, draw_sprite() will not work correctly when used with a sprite image in system or video memory so the latter must be a memory bitmap.
Although generally not supporting graphics of mixed color depths, as a special case this function can be used to draw 256-color source images onto truecolor destination bitmaps, so you can use palette effects on specific sprites within a truecolor program.
See also: draw_sprite_v_flip, draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite, stretch_sprite, rotate_sprite, draw_character_ex, draw_rle_sprite, draw_compiled_sprite, masked_blit, blit, bitmap_mask_color.
Examples using this: exsprite.
/* Create tunnel like effect. */ for (step = 1; step < 16; step++) { int width = SCREEN_W / step; int height = SCREEN_H / step; stretch_sprite(screen, image, SCREEN_W / 2 - width / 2, SCREEN_H / 2 - height / 2, width, height); }
See also: draw_sprite, stretch_blit, bitmap_mask_color.
if (key[KEY_RIGHT]) draw_sprite(screen, hero_right, pos_x, pos_y); else if (key[KEY_LEFT]) draw_sprite_h_flip(screen, hero_right, pos_x, pos_y); else draw_sprite(screen, hero_idle, pos_x, pos_y);
See also: draw_sprite, bitmap_mask_color.
Examples using this: exsprite.
/* Some one time initialisation code. */ COLOR_MAP global_trans_table; create_trans_table(&global_trans_table, my_palette, 128, 128, 128, NULL); ... if (get_color_depth() == 8) color_map = &global_trans_table; else set_trans_blender(128, 128, 128, 128); draw_trans_sprite(buffer, ghost_sprite, x, y);
The bitmap and sprite must normally be in the same color depth, but as a special case you can draw 32 bit RGBA format sprites onto any hicolor or truecolor bitmap, as long as you call set_alpha_blender() first, and you can draw 8-bit alpha images onto a 32-bit RGBA destination, as long as you call set_write_alpha_blender() first. As draw_sprite() this function skips transparent pixels, except if the source sprite is an 8-bit image; if this is the case, you should pay attention to properly set up your color map table for index 0.
See also: draw_sprite, draw_lit_sprite, draw_trans_rle_sprite, color_map, set_trans_blender, set_alpha_blender, set_write_alpha_blender, bitmap_mask_color.
Examples using this: exalpha, exblend, exlights, extrans, exxfade.
/* Some one time initialisation code. */ COLOR_MAP global_light_table; create_light_table(&global_trans_table, my_palette, 10, 10, 60, NULL); ... if (get_color_depth() == 8) color_map = &global_light_table; else set_trans_blender(40, 40, 255, 255); /* Lit the cape with a blueish light. */ draw_lit_sprite(buffer, colored_cape, x, y, 64);
See also: draw_sprite, draw_trans_sprite, draw_gouraud_sprite, draw_lit_rle_sprite, color_map, set_trans_blender, bitmap_mask_color.
Examples using this: exblend.
/* Some one time initialisation code. */ COLOR_MAP global_light_table; create_light_table(&global_trans_table, my_palette, 0, 0, 0, NULL); ... if (get_color_depth() == 8) color_map = &global_light_table; else set_trans_blender(0, 0, 0, 128); /* Enemies are in shadow unless lit by torch. */ draw_gouraud_sprite(buffer, menacing_spy, x, y, light_strength_on_corner_1, light_strength_on_corner_2, light_strength_on_corner_3, light_strength_on_corner_4);
See also: draw_sprite, draw_lit_sprite, color_map, set_trans_blender, bitmap_mask_color.
Examples using this: exshade.
BITMAP *logo; ... /* Draw the logo silhouette in red. */ draw_character_ex(screen, logo, SCREEN_W / 2, SCREEN_H / 2, makecol(255, 0, 0), -1);
See also: draw_sprite, bitmap_mask_color.
Positive increments of the angle will make the sprite rotate clockwise on the screen, as demonstrated by the Allegro example.
See also: draw_sprite, rotate_scaled_sprite, rotate_sprite_v_flip, rotate_scaled_sprite_v_flip, pivot_sprite, pivot_sprite_v_flip, pivot_scaled_sprite, pivot_scaled_sprite_v_flip, itofix, Fixed point trig.
Examples using this: exsprite.
See also: rotate_sprite, rotate_scaled_sprite_v_flip, pivot_sprite_v_flip, pivot_scaled_sprite_v_flip.
Examples using this: exsprite.
See also: rotate_sprite, rotate_scaled_sprite_v_flip, pivot_scaled_sprite, pivot_scaled_sprite_v_flip.
See also: rotate_sprite, rotate_scaled_sprite, rotate_sprite_v_flip.
See also: rotate_sprite, pivot_scaled_sprite, pivot_sprite_v_flip.
Examples using this: exsprite.
See also: rotate_sprite, rotate_sprite_v_flip, pivot_sprite.
Examples using this: exsprite.
See also: rotate_sprite, rotate_scaled_sprite, pivot_sprite, pivot_scaled_sprite_v_flip.
See also: rotate_sprite, rotate_scaled_sprite_v_flip, rotate_sprite_v_flip, pivot_sprite, pivot_scaled_sprite.
Because bitmaps can be used in so many different ways, the bitmap structure is quite complicated, and it contains a lot of data. In many situations, though, you will find yourself storing images that are only ever copied to the screen, rather than being drawn onto or used as filling patterns, etc. If this is the case you may be better off storing your images in RLE_SPRITE (read chapter "Structures and types defined by Allegro" for an internal description of the RLE_SPRITE structure) or COMPILED_SPRITE (see next chapter) structures rather than regular bitmaps.
RLE sprites store the image in a simple run-length encoded format, where repeated zero pixels are replaced by a single length count, and strings of non-zero pixels are preceded by a counter giving the length of the solid run. RLE sprites are usually much smaller than normal bitmaps, both because of the run length compression, and because they avoid most of the overhead of the bitmap structure. They are often also faster than normal bitmaps, because rather than having to compare every single pixel with zero to determine whether it should be drawn, it is possible to skip over a whole run of zeros with a single add, or to copy a long run of non-zero pixels with fast string instructions.
Every silver lining has a cloud, though, and in the case of RLE sprites it is a lack of flexibility. You can't draw onto them, and you can't flip them, rotate them, or stretch them. In fact the only thing you can do with them is to blast them onto a bitmap with the draw_rle_sprite() function, which is equivalent to using draw_sprite() with a regular bitmap. You can convert bitmaps into RLE sprites at runtime, or you can create RLE sprite structures in grabber datafiles by making a new object of type 'RLE sprite'.
RLE_SPRITE *rle; BITMAP *bmp; ... /* Create RLE sprite from an existent bitmap. */ rle = get_rle_sprite(bmp); if (!rle) abort_on_error("Couldn't create RLE sprite!"); /* We don't need the bitmap any more.*/ destroy_bitmap(bmp); /* Use the RLE sprite. */ ... /* Destroy it when we don't need it any more. */ destroy_rle_sprite(rle);
Return value: Returns a pointer to the created RLE sprite, or NULL if the RLE sprite could not be created. Remember to free this RLE sprite later to avoid memory leaks.
See also: draw_rle_sprite, destroy_rle_sprite.
See also: get_rle_sprite.
RLE_SPRITE *rle_sprite; ... draw_rle_sprite(screen, rle_sprite, 100, 100);
See also: get_rle_sprite, draw_sprite, draw_compiled_sprite, draw_trans_rle_sprite, draw_lit_rle_sprite, bitmap_mask_color.
/* Some one time initialisation code. */ COLOR_MAP global_trans_table; create_trans_table(&global_trans_table, my_palette, 128, 128, 128, NULL); ... if (get_color_depth() == 8) color_map = &global_trans_table; else set_trans_blender(128, 128, 128, 128); draw_trans_rle_sprite(buffer, rle_ghost_sprite, x, y);
See also: draw_rle_sprite, draw_lit_rle_sprite, draw_trans_sprite, color_map, set_trans_blender, set_alpha_blender, bitmap_mask_color.
/* Some one time initialisation code. */ COLOR_MAP global_light_table; create_light_table(&global_trans_table, my_palette, 10, 10, 60, NULL); ... if (get_color_depth() == 8) color_map = &global_light_table; else set_trans_blender(40, 40, 255, 255); /* Lit the cape with a blueish light. */ draw_lit_rle_sprite(buffer, rle_colored_cape, x, y, 64);
See also: draw_rle_sprite, draw_trans_rle_sprite, draw_lit_sprite, color_map, set_trans_blender, bitmap_mask_color.
Compiled sprites are stored as actual machine code instructions that draw a specific image onto a bitmap, using mov instructions with immediate data values. This is the fastest way to draw a masked image: on slow machines, up to and including a 486, drawing compiled sprites can be about to five times as fast as using draw_sprite() with a regular bitmap. On newer machines the difference is usually negligible.
Compiled sprites are big, so if memory is tight you should use RLE sprites instead, and what you can do with them is even more restricted than with RLE sprites, because they don't support clipping. If you try to draw one off the edge of a bitmap, you will corrupt memory and probably crash the system. You can convert bitmaps into compiled sprites at runtime, or you can create compiled sprite structures in grabber datafiles by making a new object of type 'Compiled sprite' or 'Compiled x-sprite'.
Returns a pointer to the created compiled sprite, or NULL if the compiled sprite could not be created. Remember to free this compiled sprite later to avoid memory leaks.COMPILED_SPRITE *cspr; BITMAP *bmp; ... /* Create compiled sprite from an existent bitmap. */ cspr = get_compiled_sprite(bmp, 0); if (!cspr) abort_on_error("Couldn't create compiled sprite!"); /* We don't need the bitmap any more.*/ destroy_bitmap(bmp); /* Use the compiled sprite. */ ... /* Destroy it when we don't need it any more. */ destroy_compiled_sprite(cspr);
See also: draw_compiled_sprite, destroy_compiled_sprite.
See also: get_compiled_sprite.
Hint: if not being able to clip compiled sprites is a problem, a neat trick is to set up a work surface (memory bitmap, mode-X virtual screen, or whatever) a bit bigger than you really need, and use the middle of it as your screen. That way you can draw slightly off the edge without any trouble...
See also: get_compiled_sprite, draw_sprite, draw_rle_sprite, bitmap_mask_color.
Allegro provides routines for loading fonts directly from GRX format .fnt files, 8x8 or 8x16 BIOS format .fnt files, from bitmap images, from datafiles or you can import a multiple-range Unicode font by writing a .txt script that specifies a number of different source files for each range of characters.
By default, Allegro can only use bitmapped (non-scalable) fonts. If you want to use TrueType fonts, you will need to use an add-on library which allows you to load them on the fly (like AllegTTF or Glyph Keeper, listed among others at http://www.allegro.cc/) and render them directly, or generate a bitmapped version of a TrueType font with tools like TTF2PCX (http://www.talula.demon.co.uk/ttf2pcx/index.html).
The pal parameter can optionally be used to return a palette for the FONT. The parameter param can be anything you like: you can use this to pass information to your loading routine, such as for instance the font height, the character range to load or the index number of a font in a datafile. If you choose to write your own font loading code, your function should be prepared to deal with a value of NULL for either of these parameters.FONT *load_my_font(const char *filename, RGB *pal, void *param) { ... }
See also: load_font.
If the font contains palette information, then the palette is returned in the second parameter, which should be an array of 256 RGB structures (a PALETTE). The pal argument may be NULL. In this case, the palette data, if present, is simply not returned.
The third parameter can be used to pass specific information to a custom loader routine. Normally, you can just leave this as NULL. Note that another way of loading fonts is embedding them into a datafile and using the datafile related functions.
Example:
FONT *myfont; PALETTE palette; ... myfont = load_font("my_font.pcx", palette, NULL); if (!myfont) abort_on_error("Couldn't load font!"); ... textout_centre_ex(screen, myfont, "This is my own pretty font!", SCREEN_W / 2, SCREEN_H / 2, white, black); ... destroy_font(myfont);
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: register_font_file_type, load_bitmap, load_dat_font, load_bios_font, load_grx_font, load_grx_or_bios_font, load_bitmap_font, load_txt_font, destroy_font.
Examples using this: exfont.
See also: load_datafile_object, load_font.
Examples using this: exfont.
FONT *f = load_font("alphafont.tga", NULL, NULL); make_trans_font(f); set_alpha_blender(); textprintf_centre_ex(screen, f, 320, 240, -1, -1, "Anti-aliased Font!");
See also: is_trans_font, set_alpha_blender, load_font, draw_trans_sprite.
Return value: Returns TRUE if the font uses transparency, FALSE if it does not.
See also: make_trans_font, is_color_font, is_mono_font.
Return value: Returns TRUE if the font is a color font, FALSE if it is not.
See also: is_trans_font, is_mono_font.
Return value: Returns TRUE if the font is a monochrome font, FALSE if it is not.
See also: is_trans_font, is_color_font.
Return value: Returns TRUE if any alpha pixels are found, else FALSE.
See also: is_trans_font.
Return value: Returns TRUE if the two fonts are of the same general type (both are color fonts or both are monochrome fonts, for instance).
See also: merge_fonts, is_trans_font, is_color_font, is_mono_font.
FONT *f; int range; int n; ... range = get_font_ranges(f); printf("The font has %d character ranges:\n", range); for (n = 0; n < range; n++) printf("Range %d from 0x%03x - 0x%03x\n", get_font_range_begin(f, n), get_font_range_end(f, n));
Return value: Returns the number of continuous character ranges in a font, or -1 if that information is not available.
See also: get_font_range_begin, get_font_range_end, transpose_font.
printf("The font has a character range of %d - %d\n", get_font_range_begin(font, -1), get_font_range_end(font, -1));
Return value: Returns the first character in the font range, or -1 if that information is not available.
See also: get_font_ranges, get_font_range_end, transpose_font.
printf("The font has a character range of %d - %d\n", get_font_range_begin(font, -1), get_font_range_end(font, -1));
Return value: Returns the last character in the font range, or -1 if that information is not available.
See also: get_font_ranges, get_font_range_begin, transpose_font.
FONT *myfont; FONT *capitals; FONT *fontcopy; ... /* Create a font of only capital letters */ capitals = extract_font_range(myfont, 'A', 'Z'); /* Create a copy of the font */ fontcopy = extract_font_range(myfont, -1, -1); ... destroy_font(capitals); destroy_font(fontcopy);
Return value: Returns a pointer to the new font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: get_font_range_begin, get_font_range_end, merge_fonts, transpose_font.
Examples using this: exfont.
FONT *myfont; FONT *capitals; ... /* Create a font of only capital letters */ capitals = extract_font_range(myfont, 'A', 'Z'); /* Now transpose the characters in the font so that they will be used */ /* for the lower case letters a-z */ transpose_font(capitals, 'a'-'A'); textout_ex(screen, capitals, "allcaps", 100, 100, makecol(255,255,255), 0);
Return value: Returns 0 on success, -1 on failure.
See also: get_font_range_begin, get_font_range_end, merge_fonts, extract_font_range.
FONT *myfont; FONT *myfancy_font; FONT *lower_range; FONT *upper_range; FONT *capitals; FONT *combined_font; FONT *tempfont; ... /* Create a font that contains the capitals from */ /* the fancy font but other characters from myfont */ lower_range = extract_font_range(myfont, -1, 'A'-1); upper_range = extract_font_range(myfont, 'Z'+1, -1); capitals = extract_font_range(myfancy_font, 'A', 'Z'); tempfont = merge_fonts(lower_range, capitals); combined_font = merge_fonts(tempfont, upper_range); /* Clean up temporary fonts */ destroy_font(lower_range); destroy_font(upper_range); destroy_font(capitals); destroy_font(tempfont);
Return value: Returns a pointer to the new font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: extract_font_range, is_trans_font, is_color_font, is_mono_font.
Examples using this: exfont.
For example, suppose you have a datafile named `fonts.dat' with the following contents:
Then the following code will load FONT_1_DATA as a FONT and return FONT_1_PALETTE as the palette:FONT FONT_1_DATA FONT FONT_2_DATA FONT FONT_3_DATA PAL FONT_1_PALETTE PAL FONT_2_PALETTE
If instead you want to load the second font, FONT_2, from the datafile, you would use:FONT *f; PALETTE pal; char *names[] = { "FONT_1_DATA", "FONT_1_PALETTE" } f = load_dat_font("fonts.dat", pal, names);
If you want to load the third font, but not bother with a palette, use:FONT *f; PALETTE pal; char *names[] = { "FONT_2_DATA", "FONT_2_PALETTE" } f = load_dat_font("fonts.dat", pal, names);
FONT *f; char *names[] = { "FONT_3_DATA", NULL } f = load_dat_font("fonts.dat", NULL, names);
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: register_font_file_type, load_font.
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: register_font_file_type, load_font.
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: register_font_file_type, load_font.
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: register_font_file_type, load_font.
The size of each character is determined by the layout of the image, which should be a rectangular grid containing all the ASCII characters from space (32) up to the tilde (126). The way the characters are separated depends on the color depth of the image file:
Note that in each horizontal row the bounding boxes around the characters should align and have the same height.
Probably the easiest way to get to grips with how this works is to load up the `demo.dat' file and export the TITLE_FONT into a PCX file. Have a look at the resulting picture in your paint program: that is the format a font should be in.
Take care with high and true color fonts: Allegro will convert these to the current color depth when you load the font. If you try to use a font on a bitmap with a different color depth Allegro will do color conversions on the fly, which will be rather slow. For optimal performance you should set the color depth to the color depth you want to use before loading any fonts.
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: register_font_file_type, load_font, load_bitmap, set_color_depth, grab_font_from_bitmap.
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: load_bitmap_font.
would import the first 96 characters from ascii.fnt as the range 0x20-0x7F, the next 96 characters from ascii.fnt as the range 0xA0-0xFF, and the entire contents of dingbats.fnt starting at Unicode position 0x1000.ascii.fnt 0x20 0x7F - 0xA0 0xFF dingbats.fnt 0x1000
Return value: Returns a pointer to the font or NULL on error. Remember that you are responsible for destroying the font when you are finished with it to avoid memory leaks.
See also: register_font_file_type, load_font.
Allegro provides text output routines that work with both monochrome and color fonts, which can contain any number of Unicode character ranges. The grabber program can create fonts from sets of characters drawn in a bitmap file (see grabber.txt for more information), and can also import GRX or BIOS format font files. The font structure contains a number of hooks that can be used to extend it with your own custom drawing code: see the definition in allegro/text.h for details.
See also: textout_ex, textprintf_ex.
Examples using this: Available Allegro examples.
/* Show unknown glyphs with an asterisk. */ allegro_404_char = '*';
See also: font.
int width = text_length(font, "I love spam"); ... bmp = create_bitmap(width, height);
See also: text_height.
Examples using this: ex12bit, exmidi, expat, exunicod.
int height = text_height(font); ... bmp = create_bitmap(width, height);
See also: text_length.
Examples using this: ex12bit, exmidi, expackf, expat, exsprite, exsyscur, exunicod.
/* Show the program's version in blue letters. */ textout_ex(screen, font, "v4.2.0-beta2", 10, 10, makecol(0, 0, 255), -1);
See also: font, textout_centre_ex, textout_right_ex, textout_justify_ex, textprintf_ex, text_height, text_length.
Examples using this: Available Allegro examples.
/* Important texts go in the middle. */ width = text_length("GAME OVER"); textout_centre_ex(screen, font, "GAME OVER", SCREEN_W / 2, SCREEN_H / 2, makecol(255, 0, 0), makecol(0, 0, 0));
See also: textout_ex, textprintf_centre_ex.
Examples using this: Available Allegro examples.
textout_right_ex(screen, font, "Look at this color!", SCREEN_W - 10, 10, my_yellow, -1);
See also: textout_ex, textprintf_right_ex.
char *lines[] = {"Draws justified text", "within the specified", "x2-x1 area. But not", "T H I S !", NULL}; /* Show the justification marker. */ vline(screen, 200, 0, SCREEN_H-1, makecol(0, 0, 0)); /* Draw all the lines until we reach a NULL entry. */ for (num = 0, y = 0; lines[num]; num++, y += text_height(font)) textout_justify_ex(screen, font, lines[num], 0, 200, y, 80, makecol(0, 0, 0), makecol(255, 255, 255));
See also: textout_ex, textprintf_justify_ex.
int player_score; ... textprintf_ex(screen, font, 10, 10, makecol(255, 100, 200), -1, "Score: %d", player_score);
See also: font, textout_ex, textprintf_centre_ex, textprintf_right_ex, textprintf_justify_ex, text_height, text_length, uszprintf.
Examples using this: Available Allegro examples.
textprintf_centre_ex(screen, font, SCREEN_W / 2, 120, makecol(0, 100, 243), -1, "Your best score so far was %d!", total_max_points);
See also: textprintf_ex, textout_centre_ex.
Examples using this: Available Allegro examples.
textprintf_right_ex(screen, font, SCREEN_W - 10, 10, makecol(200, 200, 20), -1, "%d bullets left", player_ammo);
See also: textprintf_ex, textout_right_ex.
Examples using this: exmouse.
char *lines[] = {"Line %02d: Draws justified text", "Line %02d: within the specified", "Line %02d: x2-x1 area. But not", "Line %02d: T H I S !", NULL}; /* Show the justification marker. */ vline(screen, 300, 0, SCREEN_H-1, makecol(0, 0, 0)); /* Draw all the lines until we reach a NULL entry. */ for (num = 0, y = 0; lines[num]; num++, y += text_height(font)) textprintf_justify_ex(screen, font, 0, 300, y, 180, makecol(0, 0, 0), makecol(255, 255, 255), lines[num], num);
See also: textprintf_ex, textout_justify_ex.
All the 3d functions that accept a `type' parameter are asking for a polygon rendering mode, which can be any of the following POLYTYPE_* values. If the CPU_MMX flag of the cpu_capabilities global variable is set, the GRGB and truecolor *LIT routines will be optimised using MMX instructions. If the CPU_3DNOW flag is set, the truecolor PTEX*LIT routines will take advantage of the 3DNow! CPU extensions.
Using MMX for *LIT routines has a side effect: normally (without MMX), these routines use the blender functions used also for other lighting functions, set with set_trans_blender() or set_blender_mode(). The MMX versions only use the RGB value passed to set_trans_blender() and do the linear interpolation themselves. Therefore a new set of blender functions passed to set_blender_mode() is ignored.
See also: Polygon rendering, polygon3d, drawing_mode.
Examples using this: ex3d, excamera.
See also: Polygon rendering, polygon3d, makecol.
Examples using this: ex3d, exscn3d, exzbuf.
See also: Polygon rendering, polygon3d, rgb_map.
Examples using this: ex3d.
See also: Polygon rendering, polygon3d.
Examples using this: ex3d.
See also: Polygon rendering, polygon3d, POLYTYPE_ATEX.
Examples using this: ex3d.
See also: Polygon rendering, polygon3d, POLYTYPE_ATEX, POLYTYPE_PTEX.
Examples using this: ex3d.
See also: Polygon rendering, polygon3d, POLYTYPE_ATEX, POLYTYPE_PTEX, color_map, Truecolor transparency.
Examples using this: ex3d.
See also: Polygon rendering, polygon3d, POLYTYPE_ATEX_LIT, POLYTYPE_PTEX_LIT.
Examples using this: ex3d.
See also: Polygon rendering, polygon3d.
Examples using this: ex3d.
See also: Polygon rendering, polygon3d.
Examples using this: ex3d.
How the vertex data is used depends on the rendering mode:typedef struct V3D { fixed x, y, z; - position fixed u, v; - texture map coordinates int c; - color } V3D; typedef struct V3D_f { float x, y, z; - position float u, v; - texture map coordinates int c; - color } V3D_f;
The `x' and `y' values specify the position of the vertex in 2d screen coordinates.
The `z' value is only required when doing perspective correct texture mapping, and specifies the depth of the point in 3d world coordinates.
The `u' and `v' coordinates are only required when doing texture mapping, and specify a point on the texture plane to be mapped on to this vertex. The texture plane is an infinite plane with the texture bitmap tiled across it. Each vertex in the polygon has a corresponding vertex on the texture plane, and the image of the resulting polygon in the texture plane will be mapped on to the polygon on the screen.
We refer to pixels in the texture plane as texels. Each texel is a block, not just a point, and whole numbers for u and v refer to the top-left corner of a texel. This has a few implications. If you want to draw a rectangular polygon and map a texture sized 32x32 on to it, you would use the texture coordinates (0,0), (0,32), (32,32) and (32,0), assuming the vertices are specified in anticlockwise order. The texture will then be mapped perfectly on to the polygon. However, note that when we set u=32, the last column of texels seen on the screen is the one at u=31, and the same goes for v. This is because the coordinates refer to the top-left corner of the texels. In effect, texture coordinates at the right and bottom on the texture plane are exclusive.
There is another interesting point here. If you have two polygons side by side sharing two vertices (like the two parts of folded piece of cardboard), and you want to map a texture across them seamlessly, the values of u and v on the vertices at the join will be the same for both polygons. For example, if they are both rectangular, one polygon may use (0,0), (0,32), (32,32) and (32,0), and the other may use (32,0), (32,32), (64,32), (64,0). This would create a seamless join.
Of course you can specify fractional numbers for u and v to indicate a point part-way across a texel. In addition, since the texture plane is infinite, you can specify larger values than the size of the texture. This can be used to tile the texture several times across the polygon.
The `c' value specifies the vertex color, and is interpreted differently by various rendering modes. Read the beginning of chapter "Polygon rendering" for a list of rendering types you can use with this function.
See also: triangle3d, quad3d, polygon, clip3d, cpu_capabilities.
Examples using this: excamera.
Read the beginning of chapter "Polygon rendering" for a list of rendering types you can use with this function.
See also: polygon3d, quad3d, triangle, Polygon rendering.
Read the beginning of chapter "Polygon rendering" for a list of rendering types you can use with this function.
See also: polygon3d, triangle3d, Polygon rendering.
Examples using this: ex3d.
As additional vertices may appear in the process of clipping, so the size of `vout', `vtmp' and `out' should be at least vc * (1.5 ^ n), where `n' is the number of clipping planes (5 or 6), and `^' denotes "to the power of".
The frustum (viewing volume) is defined by -z<x<z, -z<y<z, 0<min_z<z<max_z. If max_z<=min_z, the z<max_z clipping is not done. As you can see, clipping is done in the camera space, with perspective in mind, so this routine should be called after you apply the camera matrix, but before the perspective projection. The routine will correctly interpolate u, v, and c in the vertex structure. However, no provision is made for high/truecolor GCOL.
Return value: Returns the number of vertices after clipping is done.
See also: polygon3d, clip3d.
Examples using this: excamera, exscn3d.
Return value: Returns the number of vertices after clipping is done.
See also: polygon3d, clip3d_f.
A Z-buffer stores the depth of each pixel that is drawn on a viewport. When a 3D object is rendered, the depth of each of its pixels is compared against the value stored into the Z-buffer: if the pixel is closer it is drawn, otherwise it is skipped.
No polygon sorting is needed. However, backface culling should be done because it prevents many invisible polygons being compared against the Z-buffer. Z-buffered rendering is the only algorithm supported by Allegro that directly solves penetrating shapes (see example exzbuf.c, for instance). The price to pay is more complex (and slower) routines.
Z-buffered polygons are designed as an extension of the normal POLYTYPE_* rendering styles. Just OR the POLYTYPE with the value POLYTYPE_ZBUF, and the normal polygon3d(), polygon3d_f(), quad3d(), etc. functions will render z-buffered polygons.
Example:
polygon3d(bmp, POLYTYPE_ATEX | POLYTYPE_ZBUF, tex, vc, vtx);
Of course, the z coordinates have to be valid regardless of rendering style.
A Z-buffered rendering procedure looks like a double-buffered rendering procedure. You should follow four steps: create a Z-buffer at the beginning of the program and make the library use it by calling set_zbuffer(). Then, for each frame, clear the Z-buffer and draw polygons with POLYTYPE_* | POLYTYPE_ZBUF and finally destroy the Z-buffer when leaving the program.
Notes on Z-buffered renderers:
Return value: Returns the pointer to the ZBUFFER or NULL if there was an error. Remember to destroy the ZBUFFER once you are done with it, to avoid having memory leaks.
See also: create_sub_zbuffer, set_zbuffer, clear_zbuffer, destroy_zbuffer.
Examples using this: exzbuf.
When drawing z-buffered to a bitmap, the top left corner of the bitmap is always mapped to the top left corner of the current z-buffer. So this function is primarily useful if you want to draw to a sub-bitmap and use the corresponding sub-area of the z-buffer. In other cases, eg. if you just want to draw to a sub-bitmap of screen (and not to other parts of screen), then you would usually want to create a normal z-buffer (not sub-z-buffer) the size of the visible screen. You don't need to first create a z-buffer the size of the virtual screen and then a sub-z-buffer of that.
Return value: Returns the pointer to the sub ZBUFFER or NULL if there was an error. Remember to destroy the ZBUFFER once you are done with it, to avoid having memory leaks.
See also: create_zbuffer, create_sub_bitmap, destroy_zbuffer.
See also: create_zbuffer, clear_zbuffer, destroy_zbuffer.
Examples using this: exzbuf.
See also: create_zbuffer, set_zbuffer, destroy_zbuffer.
Examples using this: exzbuf.
See also: create_zbuffer, set_zbuffer, clear_zbuffer.
Examples using this: exzbuf.
Allegro provides two simple approaches to remove hidden surfaces:
The scene rendering has approximately the following steps:
For each horizontal line in the viewport an x-sorted edge list is used to keep track of what polygons are "in" and which is the nearest. Vertical coherency is used - the edge list for a scanline is sorted starting from the previous one - it won't change much. The scene rendering routines use the same low-level asm routines as normal polygon3d().
Notes on scene rendering:
Z-buffered rendering works also within the scene renderer. It may be helpful when you have a few intersecting polygons, but most of the polygons may be safely rendered by the normal scanline sorting algorithm. Same as before: just OR the POLYTYPE with POLYTYPE_ZBUF. Also, you have to clear the z-buffer at the start of the frame. Example:
clear_scene(buffer); if (some_polys_are_zbuf) clear_zbuffer(0.); while (polygons) { ... if (this_poly_is_zbuf) type |= POLYTYPE_ZBUF; scene_polygon3d(type, tex, vc, vtx); } render_scene();
The memory allocated is a little less than 150 * (nedge + npoly) bytes.
Return value: Returns zero on success, or a negative number if allocations fail.
See also: scene_polygon3d, render_scene, clear_scene, destroy_scene, scene_gap, create_zbuffer.
Examples using this: exscn3d.
See also: create_scene, scene_polygon3d, render_scene, destroy_scene, scene_gap.
Examples using this: exscn3d.
See also: create_scene, scene_polygon3d, clear_scene, render_scene, scene_gap.
Examples using this: exscn3d.
Arguments are the same as for polygon3d(), except the bitmap is missing. The one passed to clear_scene() will be used.
Unlike polygon3d(), the polygon may be concave or self-intersecting. Shapes that penetrate one another may look OK, but they are not really handled by this code.
Note that the texture is stored as a pointer only, and you should keep the actual bitmap around until render_scene(), where it is used.
Since the FLAT style is implemented with the low-level hline() function, the FLAT style is subject to DRAW_MODEs. All these modes are valid. Along with the polygon, this mode will be stored for the rendering moment, and also all the other related variables (color_map pointer, pattern pointer, anchor, blender values).
The settings of the CPU_MMX and CPU_3DNOW flags of the cpu_capabilities global variable on entry in this routine affect the choice of low-level asm routine that will be used by render_scene() for this polygon.
Return value: Returns zero on success, or a negative number if it won't be rendered for lack of a rendering routine.
See also: create_scene, clear_scene, render_scene, destroy_scene, polygon3d, cpu_capabilities.
Examples using this: exscn3d.
Note that between clear_scene() and render_scene() you shouldn't change the clip rectangle of the destination bitmap. For speed reasons, you should set the clip rectangle to the minimum.
Note also that all the textures passed to scene_polygon3d() are stored as pointers only and actually used in render_scene().
See also: create_scene, clear_scene, destroy_scene, scene_gap, scene_polygon3d.
Examples using this: exscn3d.
The default value means that if the 1/z values (in projected space) differ by only 1/100 (one percent), they are considered to be equal and the x-slopes of the planes are used to find out which plane is getting closer when we move to the right.
Larger values means narrower margins, and increasing the chance of missing true adjacent edges/planes. Smaller values means larger margins, and increasing the chance of mistaking close polygons for adjacent ones. The value of 100 is close to the optimum. However, the optimum shifts slightly with resolution, and may be application-dependent. It is here for you to fine-tune.
See also: create_scene, clear_scene, destroy_scene, render_scene, scene_polygon3d.
In DRAW_MODE_SOLID, pixels of the bitmap being drawn onto are simply replaced by those produced by the drawing function.DRAW_MODE_SOLID - the default, solid color drawing DRAW_MODE_XOR - exclusive-or drawing DRAW_MODE_COPY_PATTERN - multicolored pattern fill DRAW_MODE_SOLID_PATTERN - single color pattern fill DRAW_MODE_MASKED_PATTERN - masked pattern fill DRAW_MODE_TRANS - translucent color blending
In DRAW_MODE_XOR, pixels are written to the bitmap with an exclusive-or operation rather than a simple copy, so drawing the same shape twice will erase it. Because it involves reading as well as writing the bitmap memory, xor drawing is a lot slower than the normal replace mode.
With the patterned modes, you provide a pattern bitmap which is tiled across the surface of the shape. Allegro stores a pointer to this bitmap rather than copying it, so you must not destroy the bitmap while it is still selected as the pattern. The width and height of the pattern must be powers of two, but they can be different, eg. a 64x16 pattern is fine, but a 17x3 one is not. The pattern is tiled in a grid starting at point (x_anchor, y_anchor). Normally you should just pass zero for these values, which lets you draw several adjacent shapes and have the patterns meet up exactly along the shared edges. Zero alignment may look peculiar if you are moving a patterned shape around the screen, however, because the shape will move but the pattern alignment will not, so in some situations you may wish to alter the anchor position.
When you select DRAW_MODE_COPY_PATTERN, pixels are simply copied from the pattern bitmap onto the destination bitmap. This allows the use of multicolored patterns, and means that the color you pass to the drawing routine is ignored. This is the fastest of the patterned modes.
In DRAW_MODE_SOLID_PATTERN, each pixel in the pattern bitmap is compared with the mask color, which is zero in 256-color modes or bright pink for truecolor data (maximum red and blue, zero green). If the pattern pixel is solid, a pixel of the color you passed to the drawing routine is written to the destination bitmap, otherwise a zero is written. The pattern is thus treated as a monochrome bitmask, which lets you use the same pattern to draw different shapes in different colors, but prevents the use of multicolored patterns.
DRAW_MODE_MASKED_PATTERN is almost the same as DRAW_MODE_SOLID_PATTERN, but the masked pixels are skipped rather than being written as zeros, so the background shows through the gaps.
In DRAW_MODE_TRANS, the global color_map table or truecolor blender functions are used to overlay pixels on top of the existing image. This must only be used after you have set up the color mapping table (for 256 color modes) or blender functions (for truecolor modes). Because it involves reading as well as writing the bitmap memory, translucent drawing is very slow if you draw directly to video RAM, so wherever possible you should use a memory bitmap instead.
See also: xor_mode, solid_mode, color_map, set_trans_blender.
Examples using this: exalpha, excolmap, exjoy, expat, extrans.
See also: drawing_mode.
Examples using this: exspline, exupdate.
See also: drawing_mode.
Examples using this: exalpha, expat.
In paletted video modes, translucency and lighting are implemented with a 64k lookup table, which contains the result of combining any two colors c1 and c2. You must set up this table before you use any of the translucency or lighting routines. Depending on how you construct the table, a range of different effects are possible. For example, translucency can be implemented by using a color halfway between c1 and c2 as the result of the combination. Lighting is achieved by treating one of the colors as a light level (0-255) rather than a color, and setting up the table appropriately. A range of specialised effects are possible, for instance replacing any color with any other color and making individual source or destination colors completely solid or invisible. Color mapping tables can be precalculated with the colormap utility, or generated at runtime. Read chapter "Structures and types defined by Allegro" for an internal description of the COLOR_MAP structure.
color_map = malloc(sizeof(COLOR_MAP)); if (!color_map) abort_on_error("Not enough memory for color map!");
See also: create_color_table, create_light_table, create_trans_table, create_blender_table, set_trans_blender, draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite, drawing_mode.
Examples using this: ex3d, excolmap, exlights, exshade, extrans.
This function treats source color #0 as a special case, leaving the destination unchanged whenever a zero source pixel is encountered, so that masked sprites will draw correctly. This function will take advantage of the global rgb_map variable to speed up color conversions. If the callback function is not NULL, it will be called 256 times during the calculation, allowing you to display a progress indicator. Example:
COLOR_MAP trans_table; ... /* Build a color lookup table for translucent drawing. */ create_trans_table(&trans_table, pal, 128, 128, 128, NULL);
See also: color_map, create_light_table, create_color_table, create_blender_table, draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite, rgb_map.
Examples using this: ex3d, extrans.
This function will take advantage of the global rgb_ap variable to speed up color conversions. If the callback function is not NULL, it will be called 256 times during the calculation, allowing you to display a progress indicator. Example:
COLOR_MAP light_table; ... /* Build a color lookup table for lighting effects. */ create_light_table(&light_table, pal, 0, 0, 0, NULL);
See also: color_map, create_trans_table, create_color_table, create_blender_table, draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite, rgb_map.
Examples using this: ex3d, exshade, extrans.
Your blend routine will be passed a pointer to the palette and the two indices of the colors which are to be combined, and should fill in the RGB structure with the desired result in 0-63 format. Allegro will then search the palette for the closest match to the RGB color that you requested, so it doesn't matter if the palette has no exact match for this color.
If the callback function is not NULL, it will be called 256 times during the calculation, allowing you to display a progress indicator. Example:
COLOR_MAP greyscale_table; ... void return_grey_color(const PALETTE pal, int x, int y, RGB *rgb) { ... } ... /* Build a color lookup table for greyscale effect. */ create_color_table(&greyscale_table, pal, return_grey_color, NULL);
See also: color_map, create_light_table, create_trans_table, create_blender_table, draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite, rgb_map.
Examples using this: excolmap.
See also: color_map, create_light_table, create_trans_table, create_color_table, draw_trans_sprite, draw_lit_sprite, draw_gouraud_sprite, set_trans_blender, set_blender_mode.
In truecolor video modes, translucency and lighting are implemented by a blender function of the form:
unsigned long (*BLENDER_FUNC)(unsigned long x, y, n);
For each pixel to be drawn, this routine is passed two color parameters x and y, decomposes them into their red, green and blue components, combines them according to some mathematical transformation involving the interpolation factor n, and then merges the result back into a single return color value, which will be used to draw the pixel onto the destination bitmap.
The parameter x represents the blending modifier color and the parameter y represents the base color to be modified. The interpolation factor n is in the range [0-255] and controls the solidity of the blending.
When a translucent drawing function is used, x is the color of the source, y is the color of the bitmap being drawn onto and n is the alpha level that was passed to the function that sets the blending mode (the RGB triplet that was passed to this function is not taken into account).
When a lit sprite drawing function is used, x is the color represented by the RGB triplet that was passed to the function that sets the blending mode (the alpha level that was passed to this function is not taken into account), y is the color of the sprite and n is the alpha level that was passed to the drawing function itself.
Since these routines may be used from various different color depths, there are three such callbacks, one for use with 15-bit 5.5.5 pixels, one for 16 bit 5.6.5 pixels, and one for 24-bit 8.8.8 pixels (this can be shared between the 24 and 32-bit code since the bit packing is the same).
See also: set_blender_mode, set_alpha_blender, set_write_alpha_blender, color_map, draw_trans_sprite, draw_lit_sprite, drawing_mode, set_add_blender, set_burn_blender, set_color_blender, set_difference_blender, set_dissolve_blender, set_dodge_blender, set_hue_blender, set_invert_blender, set_luminance_blender, set_multiply_blender, set_saturation_blender, set_screen_blender.
Examples using this: ex3d, exblend, exshade, extrans, exxfade.
See also: set_trans_blender, draw_trans_sprite, draw_trans_rle_sprite, set_write_alpha_blender.
Examples using this: exalpha, extrans.
See also: set_alpha_blender, draw_trans_sprite, drawing_mode.
Examples using this: exalpha, extrans.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
Examples using this: exalpha.
See also: set_trans_blender, drawing_mode.
See also: set_trans_blender, drawing_mode.
See also: set_blender_mode_ex, set_trans_blender, color_map, draw_trans_sprite, draw_lit_sprite, drawing_mode.
See also: set_blender_mode, set_alpha_blender.
In general, Allegro is designed to be used in only one color depth at a time, so you will call set_color_depth() once and then store all your bitmaps in the same format. If you want to mix several different pixel formats, you can use create_bitmap_ex() in place of create_bitmap(), and call bitmap_color_depth() to query the format of a specific image. Most of the graphics routines require all their input parameters to be in the same format (eg. you cannot stretch a 15-bit source bitmap onto a 24-bit destination), but there are some exceptions:
Return value: Returns the index of the palette for the closest match to the requested color.
See also: makecol8.
See also: create_rgb_table, makecol8, create_trans_table, create_light_table, create_color_table.
Examples using this: ex3d, excolmap, exrgbhsv, exshade, extrans.
RGB_MAP rgb_table; create_rgb_table(&rgb_table, palette, NULL); rgb_map = &rgb_table;
See also: rgb_map.
Examples using this: ex3d, excolmap, exrgbhsv, exshade, extrans.
int r, g, b; float hue, saturation, value; ... /* Convert a reddish color to HSV format. */ rgb_to_hsv(255, 0, 128, &hue, &saturation, &value); /* Now put our tin foil hat, and verify that. */ hsv_to_rgb(hue, saturation, value, &r, &g, &b); ASSERT(r == 255); ASSERT(g == 0); ASSERT(b == 128);
Examples using this: exlights, exrgbhsv.
Read chapter "Structures and types defined by Allegro" for an internal description of the BITMAP structure. There are several ways to get direct access to the image memory of a bitmap, varying in complexity depending on what sort of bitmap you are using.
The simplest approach will only work with memory bitmaps (obtained from create_bitmap(), grabber datafiles, and image files) and sub-bitmaps of memory bitmaps. This uses a table of char pointers, called `line', which is a part of the bitmap structure and contains pointers to the start of each line of the image. For example, a simple memory bitmap putpixel function is:
For truecolor modes you need to cast the line pointer to the appropriate type, for example:void memory_putpixel(BITMAP *bmp, int x, int y, int color) { bmp->line[y][x] = color; }
If you want to write to the screen as well as to memory bitmaps, you need to use some helper macros, because the video memory may not be part of your normal address space. This simple routine will work for any linear screen, eg. a VESA linear framebuffers:void memory_putpixel_15_or_16_bpp(BITMAP *bmp, int x, int y, int color) { ((short *)bmp->line[y])[x] = color; } void memory_putpixel_32(BITMAP *bmp, int x, int y, int color) { ((long *)bmp->line[y])[x] = color; }
For truecolor modes you should replace the bmp_write8() with bmp_write16(), bmp_write24(), or bmp_write32(), and multiply the x offset by the number of bytes per pixel. There are of course similar functions to read a pixel value from a bitmap, namely bmp_read8(), bmp_read16(), bmp_read24() and bmp_read32().void linear_screen_putpixel(BITMAP *bmp, int x, int y, int color) { bmp_select(bmp); bmp_write8((unsigned long)bmp->line[y]+x, color); }
This still won't work in banked SVGA modes, however, or on platforms like Windows that do special processing inside the bank switching functions. For more flexible access to bitmap memory, you need to call the following routines. They are implemented as inline assembler routines, so they are not as inefficient as they might seem. If the bitmap doesn't require bank switching (ie. it is a memory bitmap, mode 13h screen, etc), these functions just return bmp->line[line].
Return value: Returns the address of the selected line for writing.
Examples using this: exflame, exlights.
Return value: Returns the address of the selected line for reading.
Examples using this: exflame.
Examples using this: exflame, exlights.
Although SVGA bitmaps are banked, Allegro provides linear access to the memory within each scanline, so you only need to pass a y coordinate to these functions. Various x positions can be obtained by simply adding the x coordinate to the returned address. The return value is an unsigned long rather than a char pointer because the bitmap memory may not be in your data segment, and you need to access it with far pointers. For example, a putpixel using the bank switching functions is:
You will notice that Allegro provides separate functions for setting the read and write banks. It is important that you distinguish between these, because on some graphics cards the banks can be set individually, and on others the video memory is read and written at different addresses. Life is never quite as simple as we might wish it to be, though (this is true even when we _aren't_ talking about graphics coding :-) and so of course some cards only provide a single bank. On these the read and write bank functions will behave identically, so you shouldn't assume that you can read from one part of video memory and write to another at the same time. You can call bmp_read_line(), and read whatever you like from that line, and then call bmp_write_line() with the same or a different line number, and write whatever you like to this second line, but you mustn't call bmp_read_line() and bmp_write_line() together and expect to be able to read one line and write the other simultaneously. It would be nice if this was possible, but if you do it, your code won't work on single banked SVGA cards.void banked_putpixel(BITMAP *bmp, int x, int y, int color) { unsigned long address = bmp_write_line(bmp, y); bmp_select(bmp); bmp_write8(address+x, color); bmp_unwrite_line(bmp); }
And then there's mode-X. If you've never done any mode-X graphics coding, you probably won't understand this, but for those of you who want to know how Allegro sets up the mode-X screen bitmaps, here goes...
The line pointers are still present, and they contain planar addresses, ie. the actual location at which you access the first pixel in the line. These addresses are guaranteed to be quad aligned, so you can just set the write plane, divide your x coordinate by four, and add it to the line pointer. For example, a mode-X putpixel is:
void modex_putpixel(BITMAP *b, int x, int y, int color) { outportw(0x3C4, (0x100<<(x&3))|2); bmp_select(bmp); bmp_write8((unsigned long)bmp->line[y]+(x>>2), color); }
Oh yeah: the DJGPP nearptr hack. Personally I don't like this very much because it disables memory protection and isn't portable to other platforms, but a lot of people swear by it because it can give you direct access to the screen memory via a normal C pointer. Warning: this method will only work with the DJGPP library, when using VGA 13h or a linear framebuffer modes!
In your setup code:
Then:#include <sys/nearptr.h> unsigned char *screenmemory; unsigned long screen_base_addr; __djgpp_nearptr_enable(); __dpmi_get_segment_base_address(screen->seg, &screen_base_addr); screenmemory = (unsigned char *)(screen_base_addr + screen->line[0] - __djgpp_base_address);
void nearptr_putpixel(int x, int y, int color) { screenmemory[x + y*VIRTUAL_W] = color; }
There are two high level functions for playing FLI/FLC animations: play_fli(), which reads the data directly from disk, and play_memory_fli(), which uses data that has already been loaded into RAM. Apart from the different sources of the data, these two functions behave identically. They draw the animation onto the specified bitmap, which should normally be the screen. Frames will be aligned with the top left corner of the bitmap: if you want to position them somewhere else you will need to create a sub-bitmap for the FLI player to draw onto.
If the callback function is not NULL it will be called once for each frame, allowing you to perform background tasks of your own. This callback should normally return zero: if it returns non-zero the player will terminate (this is the only way to stop an animation that is playing in looped mode).
The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR if something went wrong, and the value returned by the callback function if that was what stopped it. If you need to distinguish between different return values, your callback should return positive integers, since FLI_OK is zero and FLI_ERROR is negative.
Note that the FLI player will only work when the timer module is installed, and that it will alter the palette according to whatever palette data is present in the animation file.
Occasionally you may need more detailed control over how an FLI is played, for example if you want to superimpose a text scroller on top of the animation, or to play it back at a different speed. You could do both of these with the lower level functions described below.
/* Let users skip looped animations. */ int check_escape_key(void) { if (key[KEY_ESC]) return 1; else return 0; } ... int ret = play_fli("animlogo.fli", screen, 1, check_escape_key); if (ret == FLI_ERROR) abort_on_error("Error playing intro!");
Return value: The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR if something went wrong, and the value returned by the callback function if that was what stopped it.
See also: play_memory_fli, install_timer, fli_frame.
Playing animations from memory is obviously faster than cuing them directly from disk, and is particularly useful with short, looped FLI's. Animations can easily get very large, though, so in most cases you will probably be better just using play_fli(). You can think of this function as a wrapper on top of open_memory_fli(), next_fli_frame() and close_fli(). Example:
int ret = play_memory_fli(anim_data, screen, 0, NULL); if (ret == FLI_ERROR) abort_on_error("Corrupted animation data?");
Return value: The FLI player returns FLI_OK if it reached the end of the file, FLI_ERROR if something went wrong, and the value returned by the callback function if that was what stopped it.
See also: play_fli, install_timer, fli_frame.
if (open_fli("intro.fli") == FLI_ERROR) abort_on_error("Error playing intro");
Return value: Returns FLI_OK on success, FLI_ERROR if something went wrong, like trying to open another FLI file without closing the previous one.
See also: close_fli, next_fli_frame, fli_bitmap, fli_palette.
See also: open_fli.
while (next_fli_frame(0) == FLI_OK) { /* Do stuff, like play audio stream or check keys to skip animation. */ /* Rest some time until next frame... */ }
Return value: Returns FLI_OK on success, FLI_ERROR or FLI_NOT_OPEN on error, and FLI_EOF on reaching the end of the file.
See also: open_fli, fli_bitmap, fli_palette, fli_timer, fli_frame.
See also: next_fli_frame, fli_bmp_dirty_from, fli_palette.
See also: next_fli_frame, fli_pal_dirty_from, fli_bitmap.
if (fli_bmp_dirty_from <= fli_bmp_dirty_to) blit(fli_bitmap, screen, 0, fli_bmp_dirty_from, 0, fli_bmp_dirty_from, fli_bitmap->w, fli_bmp_dirty_to - fli_bmp_dirty_from + 1);
See also: fli_bitmap, reset_fli_variables.
if (fli_pal_dirty_from <= fli_pal_dirty_to) set_palette_range(fli_palette, fli_pal_dirty_from, fli_pal_dirty_to, 1);
See also: fli_palette, reset_fli_variables.
See also: fli_bmp_dirty_from, fli_pal_dirty_from.
while (next_fli_frame(0) == FLI_OK) { if (fli_frame == 345) play_sample(trumpet_sound, 255, 128, 1000, 0); /* Rest some time until next frame... */ }
See also: play_fli, play_memory_fli, next_fli_frame.
while (next_fli_frame(0) == FLI_OK) { /* Do stuff, like play audio stream or check keys to skip animation. */ /* Rest some time until next frame... */ while (fli_timer <= 0) rest(0); }
See also: install_timer, next_fli_frame.
Allegro allows you to use the sound hardware in two ways: automatic, or manual. Usually you should try the automatic version first. This means calling install_sound() with the autodetection parameters and using the rest of the sound functions to play samples or music. In this situation, Allegro will handle the sound devices and mix the samples and/or music the best way it can.
However, sound hardware has a limitation on the number of samples it may play all at the same time (from now on, called hardware voices). When you exceed this limit, Allegro will cut off one of the samples being played and reproduce the new one. Depending on the type of sounds you are playing, how many of them you need at the same time and their nature (e.g: vital audio feedback to the user or useless "ping" when some shrapnel hits a rock in the scenery) you will want to specify more carefully how hardware voices are reserved and which samples have priority over others.
The hardware voice reservation phase has to be done before the call to install_sound(), since it directly affects how Allegro talks to the sound drivers.
Return value: Returns the maximum number of voices that the driver can provide, or zero if the hardware is not present.
See also: install_sound, reserve_voices, DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS, DIGI_*/QNX, DIGI_*/MacOSX.
Return value: Returns the maximum number of voices that the driver can provide, or zero if the hardware is not present.
There are two special-case return values that you should watch out for: if this function returns -1 it is a note-stealing driver (eg. DIGMID) that shares voices with the current digital sound driver, and if it returns 0xFFFF it is an external device like an MPU-401 where there is no way to determine how many voices are available.
See also: install_sound, reserve_voices, MIDI_*/DOS, MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX, MIDI_*/MacOSX.
See also: set_volume_per_voice, install_sound, detect_digi_driver, detect_midi_driver, get_mixer_voices.
If clipping is a problem - or if the output is too quiet - this function can be used to adjust the volume of each voice. You should first check that your speakers are at a reasonable volume, Allegro's global volume is at maximum (see set_volume() below), and any other mixers such as the Windows Volume Control are set reasonably. Once you are sure that Allegro's output level is unsuitable for your application, use this function to adjust it.
Each time you increase the parameter by one, the volume of each voice will halve. For example, if you pass 4, you can play up to 16 centred samples at maximum volume without distortion.
If you pass 0 to this function, each centred sample will play at the maximum volume possible without distortion, as will all samples played through a mono driver. Samples at the extreme left and right will distort if played at full volume. If you wish to play panned samples at full volume without distortion, you should pass 1 to this function. Note: this is different from the function's behaviour in WIPs 3.9.34, 3.9.35 and 3.9.36. If you used this function under one of these WIPs, you will have to increase your parameter by one to get the same volume.
Note: The default behaviour has changed as of Allegro 4.1.15. If you would like the behaviour of earlier versions of Allegro, pass -1 to this function. Allegro will choose a value dependent on the number of voices, so that if you reserve n voices, you can play up to n/2 normalised samples with centre panning without risking distortion. The exception is when you have fewer than 8 voices, where the volume remains the same as for 8 voices. Here are the values, dependent on the number of voices:
Of course this function does not override the volume you specify with play_sample() or voice_set_volume(). It simply alters the overall output of the program. If you play samples at lower volumes, or if they are not normalised, then you can play more of them without distortion.1-8 voices - set_volume_per_voice(2) 16 voices - set_volume_per_voice(3) 32 voices - set_volume_per_voice(4) 64 voices - set_volume_per_voice(5)
It is recommended that you hard-code the parameter into your program, rather than offering it to the user. The user can alter the volume with the configuration file instead, or you can provide for this with set_volume().
To restore volume per voice to its default behaviour, pass 1.
See also: reserve_voices, set_volume, install_sound, detect_digi_driver, detect_midi_driver.
Return value: Returns zero if the sound is successfully installed, and -1 on failure. If it fails it will store a description of the problem in allegro_error.
See also: remove_sound, reserve_voices, detect_digi_driver, detect_midi_driver, set_volume, play_sample, Voice control, play_midi, play_audio_stream, install_sound_input, allegro_error, Standard config variables, set_mixer_quality, DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS, DIGI_*/QNX, DIGI_*/MacOSX, MIDI_*/DOS, MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX, MIDI_*/MacOSX.
Examples using this: exmidi, exsample, exsprite, exstream.
See also: install_sound, allegro_exit.
See also: install_sound, set_hardware_volume.
See also: install_sound, set_volume.
See also: set_volume, get_hardware_volume.
See also: set_hardware_volume, get_volume.
See also: get_mixer_quality, Standard config variables.
See also: set_mixer_quality, Standard config variables.
See also: Standard config variables.
See also: Standard config variables.
See also: Standard config variables.
See also: reserve_voices.
See also: Standard config variables.
SAMPLE *sample = load_sample(user_input); if (!sample) abort_on_error("Couldn't load sample!");
Return value: Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks.
See also: destroy_sample, load_voc, load_wav, play_sample, save_sample, register_sample_file_type, Voice control.
Examples using this: exsample.
SAMPLE *sample = load_wav("scream.wav"); if (!sample) abort_on_error("Couldn't scare user!");
Return value: Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks.
See also: load_sample, register_sample_file_type.
PACKFILE *packfile; SAMPLE *sample; packfile = pack_fopen("sound.wav", F_READ); if (!packfile) abort_on_error("Couldn't open sound.wav"); sample = load_wav_pf(packfile); if (!sample) abort_on_error("Error loading sound.wav");
Return value: Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks.
See also: load_wav.
SAMPLE *sample = load_voc("alarm.voc"); if (!sample) abort_on_error("Couldn't alert user!");
Return value: Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks.
See also: load_sample, register_sample_file_type.
PACKFILE *packfile; SAMPLE *sample; packfile = pack_fopen("sound.wav", F_READ); if (!packfile) abort_on_error("Couldn't open sound.wav"); sample = load_wav_pf(packfile); if (!sample) abort_on_error("Error loading sound.wav");
Return value: Returns a pointer to the SAMPLE or NULL on error. Remember to free this sample later to avoid memory leaks.
See also: load_voc.
if (save_sample("sound.wav", sample) != 0) abort_on_error("Couldn't save sample!");
Return value: Returns zero on success, non-zero otherwise.
See also: load_sample, register_sample_file_type.
Return value: Returns a pointer to the created sample, or NULL if the sample could not be created. Remember to free this sample later to avoid memory leaks.
See also: load_sample, destroy_sample, Structures and types defined by Allegro.
See also: load_sample.
Examples using this: exsample.
See also: load_sample, create_sample.
SAMPLE *load_mp3(const char *filename) { ... } register_sample_file_type("mp3", load_mp3, NULL);
See also: load_sample, save_sample.
/* Scream from the left speaker, twice the freq. */ int sound = play_sample(scream, 255, 0, 2000, 0);
Return value: Returns the voice number that was allocated for the sample or negative if no voices were available.
See also: install_sound, load_sample, adjust_sample, stop_sample, Voice control.
Examples using this: exsample, exsprite.
See also: play_sample.
Examples using this: exsample.
See also: play_sample, destroy_sample.
If you need more detailed control over how samples are played, you can use the lower level voice functions rather than just calling play_sample(). This is rather more work, because you have to explicitly allocate and free the voices rather than them being automatically released when they finish playing, but allows far more precise specification of exactly how you want everything to sound. You may also want to modify a couple of fields from the SAMPLE structure. Read chapter "Structures and types defined by Allegro" for its definition.
See also: install_sound, allocate_voice, deallocate_voice, reallocate_voice, release_voice, voice_start, voice_set_priority, voice_check, voice_set_position, voice_set_playmode, voice_set_volume, voice_set_frequency, voice_set_pan, SAMPLE.
Return value: Returns the voice number, or -1 if no voices are available.
See also: Voice control, deallocate_voice, reallocate_voice, release_voice, load_sample.
See also: allocate_voice, voice_stop.
deallocate_voice(voice); voice = allocate_voice(sample);
See also: allocate_voice, deallocate_voice, load_sample.
See also: allocate_voice, deallocate_voice.
See also: Voice control, allocate_voice, voice_stop, release_voice.
Examples using this: exstream.
See also: voice_start, deallocate_voice, release_voice.
Examples using this: exstream.
See also: Voice control.
Return value: Returns a pointer to the sample that the voice is using, or NULL if the voice is inactive (ie. it has been deallocated, or the release_voice() function has been called and the sample has then finished playing).
See also: allocate_voice, voice_start, voice_get_position.
See also: Voice control, voice_set_position.
See also: Voice control, voice_get_position, voice_set_playmode.
See also: Voice control.
See also: Voice control, voice_set_volume.
See also: Voice control, voice_get_volume, voice_ramp_volume.
See also: Voice control, voice_set_volume.
See also: voice_ramp_volume.
See also: Voice control, voice_set_frequency.
See also: Voice control, voice_get_frequency, voice_sweep_frequency.
See also: Voice control, voice_set_frequency.
See also: voice_sweep_frequency.
See also: Voice control, voice_set_pan.
See also: Voice control, voice_get_pan, voice_sweep_pan.
See also: Voice control, voice_set_pan.
See also: voice_sweep_pan.
See also: Voice control.
See also: Voice control.
See also: Voice control.
Allegro allows you to play MIDI files. MIDI files basically contain notes and the type of instrument that is meant to play them, so they are usually very small in size. However, it's up to the sound card of the end user to play the notes, and sound cards have been historically known to have poor MIDI performance (at least those oriented to the consumer market). Few consumer cards feature decent MIDI playback. Still, as a game creator you can never be sure if the music of your game will be played as you meant it, because it totally depends on the hardware of the user.
For this reason Allegro also provides a DIGMID driver. This is a software implementation of the so called Wavetable synthesis. Sound cards featuring this store digital samples of real instruments at different pitches, interpolating those that are not recorded, thus achieving a high sound quality. Implementing this in software makes you sure that the quality you hear on your computer is that which will be heard by end users using the same driver.
The disadvantage of the DIGMID driver is that it uses more CPU than simple MIDI playback, and it steals some hardware voices from the sound card, which might be more critical for the end user experience than the background music. At the Allegro homepage (http://alleg.sourceforge.net/) you can find more information about DIGMID and where to download digital samples for your MIDI files.
MIDI *music; music = load_midi("backmus.mid"); if (!music) abort_on_error("Couldn't load background music!");
Return value: Returns a pointer to a MIDI structure, or NULL on error. Remember to free this MIDI file later to avoid memory leaks.
See also: destroy_midi, play_midi, get_midi_length.
Examples using this: exmidi.
See also: load_midi.
Examples using this: exmidi.
See also: load_midi.
Return value: Returns non-zero if an error occurs (this may happen if a patch-caching wavetable driver is unable to load the required samples, or at least it might in the future when somebody writes some patch-caching wavetable drivers :-)
See also: install_sound, load_midi, play_looped_midi, stop_midi, midi_pause, midi_seek, midi_pos, midi_time, midi_msg_callback.
Examples using this: exmidi.
Return value: The return value has the same meaning as that of play_midi(): non-zero if an error occurs, zero otherwise.
See also: play_midi, midi_pos, midi_loop_start.
See also: play_midi, midi_pause.
See also: play_midi, stop_midi, midi_resume, midi_seek.
Examples using this: exmidi.
See also: midi_pause.
Examples using this: exmidi.
Return value: Returns zero if it could successfully seek to the requested position. Otherwise, a return value of 1 means it stopped playing, and midi_pos is set to the negative length of the MIDI file (so you can use this function to determine the length of a MIDI file). A return value of 2 means the MIDI file looped back to the start.
See also: play_midi, midi_pos.
Note that any currently playing midi is stopped when you call this function. Usually you would call it before play_midi, to get the length of the midi to be played, like in this example:
length = get_midi_length(my_midi); play_midi(my_midi); do { pos = midi_time; textprintf_ex(screen, font, 0, 0, c, -1, "%d:%02d / %d:%02d\n", pos / 60, pos % 60, length / 60, length % 60); rest(100); } while(pos <= length);
Return value: Returns the value of midi_time, the length of the midi.
See also: load_midi, midi_time, midi_pos.
Examples using this: exmidi.
See also: install_sound, load_midi_patches, midi_recorder.
Return value: Returns non-zero if an error occurred.
See also: install_sound, midi_out.
See also: play_midi, midi_msg_callback.
Examples using this: exmidi.
See also: play_midi, midi_pos, get_midi_length.
Examples using this: exmidi.
See also: play_looped_midi.
See also: play_midi.
Return value: Returns non-zero on error.
See also: install_sound.
The audio stream functions are for playing digital sounds that are too big to fit in a regular SAMPLE structure, either because they are huge files that you want to load in pieces as the data is required, or because you are doing something clever like generating the waveform on the fly.
You can think of an AUDIOSTREAM structure as a wrapper around two audio buffers. The first thing you do is fill both buffers with sound data and let Allegro play them. Once the first buffer has been played, the second starts, and Allegro lets you know you have to fill the other one (i.e. graphics double buffering applied to sounds too big to fit into memory).
The implementation of the sound buffers uses normal SAMPLE structures, so you can use all the voice_*() functions to modify the audio streams. Read chapter "Digital sample routines", section "Voice control" for a list of additional functions you can use. Read chapter "Structures and types defined by Allegro" for the internals of the AUDIOSTREAM structure.
The `bits' parameter must be 8 or 16. `freq' is the sample rate of the data in Hertz. The `vol' and `pan' values use the same 0-255 ranges as the regular sample playing functions. The `stereo' parameter should be set to 1 for stereo streams, or 0 otherwise.
If you want to adjust the pitch, volume, or panning of a stream once it is playing, you can use the regular voice_*() functions with stream->voice as a parameter. The format of the sample data is described in the SAMPLE entry of the "Structures and types defined by Allegro" chapter. The formula to get the size of the buffers in bytes could be:
Example:bytes = length * (bits / 8) * (stereo ? 2 : 1)
/* Create a 22KHz 8bit mono audio stream. */ stream = play_audio_stream(1024, 8, FALSE, 22050, 255, 128); if (!stream) abort_on_error("Error creating audio stream!\n");
Return value: This function returns a pointer to the audio stream or NULL if it could not be created.
See also: install_sound, get_audio_stream_buffer, stop_audio_stream, AUDIOSTREAM, Voice control.
Examples using this: exstream.
See also: play_audio_stream.
Examples using this: exstream.
void *mem_chunk; ... while (TRUE) { ... mem_chunk = get_audio_stream_buffer(buffer); if (mem_chunk != NULL) { /* Refill the stream buffer. */ } }
Return value: If it returns NULL, the stream is still playing the previous lot of data, so you don't need to do anything. If it returns a value, that is the location of the next buffer to be played, and you should load the appropriate number of samples (however many you specified when creating the stream) to that address, for example using an fread() from a disk file. After filling the buffer with data, call free_audio_stream_buffer() to indicate that the new data is now valid.
See also: play_audio_stream, free_audio_stream_buffer.
Examples using this: exstream.
mem_chunk = get_audio_stream_buffer(buffer); if (mem_chunk != NULL) { /* Refill the stream buffer. */ ... free_audio_stream_buffer(buffer); }
See also: get_audio_stream_buffer.
Examples using this: exstream.
Allegro provides routines to capture sound from the sound card, be it digital samples or MIDI notes. Ideally this would allow you to create games where basic speech recognition could be implemented, or voice messages in multiplayer games over a network. However, many old sound cards are not full duplex. This means, that the sound device can only be playing or recording, but not both at the same time.
Any Windows 2000 or better machine comes with a full duplex sound card and updated drivers. All MacOS X machines allow full duplex recording. Under Unix your mileage may vary: you can have the right hardware for the task, but the drivers might not support this feature. Under DOS you should forget about full duplex altogether.
To find out if your system allows this feature, use the akaitest program, distributed along with Allegro, in the `tests' directory.
Return value: This function returns zero on success, and any other value if the machine or driver doesn't support sound recording.
See also: install_sound, start_sound_input, midi_recorder, Standard config variables, DIGI_*/DOS, DIGI_*/Windows, DIGI_*/Unix, DIGI_*/BeOS, DIGI_*/QNX, DIGI_*/MacOSX, MIDI_*/DOS, MIDI_*/Windows, MIDI_*/Unix, MIDI_*/BeOS, MIDI_*/QNX, MIDI_*/MacOSX.
See also: install_sound_input, remove_sound, allegro_exit.
Example:0 = audio input not supported 8 = eight bit audio input is supported 16 = sixteen bit audio input is supported 24 = both eight and sixteen bit audio input are supported
cap = get_sound_input_cap_bits(); if (cap == 0) { /* Ugh, no audio input supported? */ } else { if (cap & 8) { /* We have eight bit audio input. */ } if (cap & 16) { /* We have sixteen bit audio input. */ } }
See also: start_sound_input, get_sound_input_cap_parm, get_sound_input_cap_rate, get_sound_input_cap_stereo.
Return value: Returns non-zero if the driver is capable of stereo recording.
See also: start_sound_input, get_sound_input_cap_parm, get_sound_input_cap_bits, get_sound_input_cap_rate.
int max_freq; ... /* What frequency can we record 8 bits mono at? */ max_freq = get_sound_input_cap_rate(8, 0); if (max_freq > 22000) { /* Ok, 22KHz and above is good enough. */ }
See also: start_sound_input, get_sound_input_cap_parm, get_sound_input_cap_bits, get_sound_input_cap_stereo.
Return value: The function returns one of the following possible values:
0 = It is impossible to record in this format. 1 = Recording is possible, but audio output will be suspended. 2 = Recording is possible at the same time as playing other sounds (full duplex sound card). -n = Sampling rate not supported, but rate 'n' would work instead.
See also: start_sound_input, get_sound_input_cap_bits, get_sound_input_cap_rate, get_sound_input_cap_stereo.
SOUND_INPUT_MIC SOUND_INPUT_LINE SOUND_INPUT_CD
Return value: The function returns zero on success, or -1 if the hardware does not provide an input select register (ie. you have no control over the input source).
See also: start_sound_input.
Return value: Returns the buffer size in bytes if successful, or zero on error.
See also: install_sound_input, read_sound_input, stop_sound_input, digi_recorder, set_sound_input_source, get_sound_input_cap_parm, get_sound_input_cap_bits, get_sound_input_cap_rate, get_sound_input_cap_stereo.
See also: start_sound_input.
Note: many cards produce a click or popping sound when switching between record and playback modes, so it is often a good idea to discard the first buffer after you start a recording. The waveform is always stored in unsigned format, with stereo data consisting of alternate left/right samples.
Return value: The function will return non-zero if a buffer has been copied or zero if no new data is yet available (you were too fast checking the input).
See also: start_sound_input.
See also: install_sound_input, start_sound_input.
See also: install_sound_input, midi_out.
The following routines implement a fast buffered file I/O system, which supports the reading and writing of compressed files using a ring buffer algorithm based on the LZSS compressor by Haruhiko Okumura. This does not achieve quite such good compression as programs like zip and lha, but unpacking is very fast and it does not require much memory. Packed files always begin with the 32-bit value F_PACK_MAGIC, and autodetect files with the value F_NOPACK_MAGIC.
The following FA_* flags are guaranteed to work:
Do not use any other flags from DOS/Windows or your code will not compile on another platform. FA_RDONLY is for directory entries with read-only flag on DOS-like systems or unwritable by current user on Unix-like systems. Hidden files are directory entries that have the hidden flag set (DOS/Windows) or have names starting with '.' (UNIX, excluding '.' and '..'). Flags can be combined using '|' (binary OR operator).FA_NONE - Exclude files that have any attribute set FA_RDONLY - Directory entries that are unwritable for current user FA_HIDDEN - Hidden flag FA_DIREC - Directories FA_SYSTEM - Files with system flag set (DOS/Windows only) FA_LABEL - Files with volume label flag set (DOS/Windows only) FA_ARCH - Files with archive flag set (DOS/Windows only) FA_ALL - Match all attributes
When passed to the functions as the 'attrib' parameter, these flags represent an upper set in which the actual flag set of a matching file must be included. That is, in order for a file to be matching, its attributes may contain any of the specified flags but must not contain any of the unspecified flags. In other words, you explicitly exclude the flags that you do not specify. Thus if you pass 'FA_DIREC | FA_RDONLY', normal files and directories will be included as well as read-only files and directories, but not hidden files and directories. Similarly, if you pass 'FA_ARCH' then both archived and non-archived files will be included. If FA_NONE is passed all attributes are excluded and only files with no attributes are returned. Conversely, if you pass FA_ALL, no attributes are excluded so all files are returned (which is what you would usually want).
Functions which accept wildcards as file names support the meta characters `*' (which means, zero or any quantity of characters) and `?' (which means any character, but only one).
char name[200]; ... get_executable_name(name, sizeof(name)); allegro_message("Running `%s'\n", name);
get_executable_name(name, sizeof(name)); fix_filename_case(name); allegro_message("Running `%s'\n", name);
Return value: Returns a copy of the `path' parameter.
See also: fix_filename_slashes, canonicalize_filename.
char buf[200] = "c:/dos\\backup/weirdo\\test"; ... fix_filename_slashes(buf); /* Under DOS we would have c:\dos\backup\weirdo\test. Under Unix we would have c:/dos/backup/weirdo/test. */
Return value: Returns a copy of the `path' parameter.
See also: fix_filename_case, canonicalize_filename.
Note that this function won't work as expected if the path to canonicalize comes from another platform (eg. a "c:\something" path will canonicalize into something really wrong under Unix: "/current/path/c:/something").char buf[256]; ... canonicalize_filename(buf, "~/../s22/..\\t3st///hi.c", sizeof(buf)); /* Running this under Unix would return: /home/t3st/hi.c */
Return value: Returns a copy of the `dest' parameter.
See also: fix_filename_case, fix_filename_slashes.
char buf[256]; ... make_absolute_filename(buf, "/usr/games/", "../temp.txt", sizeof(buf)); /* This would create /usr/temp.txt */
Return value: Returns a copy of the `dest' parameter.
See also: make_relative_filename, is_relative_filename, replace_filename, canonicalize_filename.
char base[] = "/long/absolute/path/program.exe"; char user_input[] = "/nice/and/short.txt"; ... make_relative_filename(buf, base, user_input, sizeof(buf)); /* Under Unix buf would contain: ../../../nice/and/short.txt */
Return value: Returns a copy of the `dest' parameter if it succeeds or NULL if it fails (eg. under DOS, one path starts with "C:\" and another with "A:\").
See also: make_absolute_filename, is_relative_filename, canonicalize_filename.
See also: make_absolute_filename, make_relative_filename.
char name[200]; ... get_executable_name(name, sizeof(name)); replace_filename(name, name, "sound.dat", sizeof(name));
Return value: Returns a copy of the `dest' parameter.
See also: get_filename, replace_extension, append_filename.
Examples using this: Available Allegro examples.
replace_extension(buf, "C:\\game\\prog.exe", "dat", sizeof(buf));
Return value: Returns a copy of the `dest' parameter.
See also: get_extension, replace_filename.
append_filename(buf, "/home/user", "prog.bin", sizeof(buf));
Return value: Returns a copy of the `dest' parameter.
See also: replace_filename.
Note that Allegro won't perform any IO operations during the verification. This means that if you have `/a/path/like/this/', which doesn't have a filename, the function will return a pointer to the trailing null character. However, if you have `/a/path/like/this', Allegro will return a pointer to `this', even if it is a valid directory.get_executable_name(name, sizeof(name)); allegro_message("Running `%s'\n", get_filename(name));
Return value: Returns a pointer to the portion of `path' where the filename starts, or the beginning of `path' if no valid filename is found (eg. you are processing a path with backslashes under Unix).
See also: get_extension, put_backslash, replace_filename.
Examples using this: exmidi.
get_executable_name(name, sizeof(name)); allegro_message("The binary has the extension `%s'\n", get_extension(name));
Return value: Returns a pointer to the portion of `filename' where the extension starts, or a pointer to the trailing null character if there is no filename or it doesn't have extension.
See also: get_filename, put_backslash, replace_extension.
See also: get_extension, get_filename.
/* Check for a normal file. */ if (file_exists("franken.dat", 0, NULL)) allegro_message("It is alive!\n");
Return value: Returns non-zero if the file exists, or zero if it doesn't or the specified attributes mask it out.
See also: exists, file_size_ex, file_time.
Return value: Returns non-zero if the file exists, or zero if it doesn't.
See also: file_exists, file_size_ex, file_time.
See also: file_exists, file_time.
Examples using this: expackf.
See also: file_exists, file_size_ex.
Return value: Returns zero on success, non-zero on failure.
The callback function will be passed three arguments: the first is a string which contains the completed filename (exactly the same string you passed to for_each_file_ex() but with meta characters), the second is the actual attributes of the file, and the third is a void pointer which is simply a copy of `param' (you can use this for whatever you like). The callback must return zero to let the enumeration proceed, or any non-zero value to stop it. If an error occurs, the error code will be stored in `errno' but the enumeration won't stop. Example:
int show_name(const char *filename, int attrib, void *param) { allegro_message("Caught `%s', attribs %d\n", filename, attrib); return 0; } ... count = for_each_file_ex("data/level*", FA_DIREC, 0, show_name, 0); allegro_message("%d game directories\n", count);
Return value: Returns the number of successful calls made to callback(), that is, the number of times callback() was called and returned 0.
See also: al_findfirst, al_findnext, al_findclose.
There is some other stuff in the structure as well, but it is there for internal use only. Example:struct al_ffblk { int attrib; - actual attributes of the file found time_t time; - modification time of file char name[512]; - name of file };
struct al_ffblk info; if (al_findfirst("*.pcx", &info, FA_ALL) != 0) { /* Tell user there are no PCX files. */ return; }
Return value: The function returns non-zero if no match is found or if an error occurred and, in the latter case, sets `errno' accordingly. It returns zero if a match is found, allocating some memory for internal use in the structure. Therefore you have to close your search when you are finished to avoid memory leaks in your program.
See also: al_findnext, al_findclose, al_ffblk_get_size.
if (al_findfirst("*.pcx", &info, 0) != 0) return; do { /* Do something useful here with info.name. */ } while (al_findnext(&info) == 0); al_findclose(&info);
Return value: Returns zero if a match is found, non-zero if none is found or if an error occurred and, in the latter case, sets errno accordingly.
See also: al_findfirst, al_findclose.
See also: al_findfirst, al_findnext.
See also: al_findfirst, al_findnext, al_ffblk.
Check the documentation chapter specific to your platform for information on additional paths this function might search for. Also, don't forget about set_allegro_resource_path() to extend the searches. Example:
char path[256]; int ret; ret = find_allegro_resource(path, "scores.cfg", NULL, NULL, NULL, NULL, NULL, sizeof(path)); if (ret == 0) { /* Found system wide scores file. */ } else { /* No previous scores, create our own file. */ }
Return value: Returns zero on success, and stores a full path to the file (at most size bytes) into the dest buffer.
See also: set_allegro_resource_path.
These custom paths will be valid until you call allegro_exit(). You can call this function before install_allegro(), but after set_uformat() if you want to use a text encoding format other than the default.set_allegro_resource_path(10, "my_game/configs"); set_allegro_resource_path(0, "users/configs/"); set_allegro_resource_path(-45, "temp");
Return value: Returns non-zero on success, zero if the path could not be added or you wanted to remove a path and the priority used didn't have any associated path. Modification of existing paths always succeeds.
See also: find_allegro_resource.
Note #1: when writing a packfile, you can change the password to whatever you want after opening the file, without affecting the write operation. On the contrary, when writing a sub-chunk of a packfile, you must make sure that the password that was active at the time the sub-chunk was opened is still active before closing the sub-chunk. This is guaranteed to be true if you didn't call the packfile_password() routine in the meantime. Read operations, either on packfiles or sub-chunks, have no such restriction.
Note #2: as explained above, the password is used for all read/write operations on files, including for several functions of the library that operate on files without explicitly using packfiles (e.g. load_bitmap()). The unencrypted mode is mandatory in order for those functions to work. Therefore remember to call packfile_password(NULL) before using them if you previously changed the password. As a rule of thumb, always call packfile_password(NULL) when you are done with operations on packfiles. The only exception to this is custom packfiles created with pack_fopen_vtable().
See also: pack_fopen, load_datafile, pack_fopen_vtable.
The packfile functions also understand several "magic" filenames that are used for special purposes. These are:
Finally, be aware that the special Allegro object types aren't the same format as the files you import the data from. When you import data like bitmaps or samples into the grabber, they are converted into a special Allegro-specific format, but the `#' marker file syntax reads the objects as raw binary chunks. This means that if, for example, you want to use load_pcx() to read an image from a datafile, you should import it as a binary block rather than as a BITMAP object.
Example:
PACKFILE *input_file; input_file = pack_fopen("scores.dat", "rp"); if (!input_file) abort_on_error("Couldn't read `scores.dat'!");
Return value: On success, pack_fopen() returns a pointer to a PACKFILE structure, and on error it returns NULL and stores an error code in `errno'. An attempt to read a normal file in packed mode will cause `errno' to be set to EDOM.
See also: pack_fclose, pack_fopen_chunk, packfile_password, pack_fread, pack_getc, file_select_ex, pack_fopen_vtable.
Examples using this: expackf.
While the created packfile structure can be used with other Allegro functions, there are two limitations. First, opening chunks using pack_fopen_chunk() on top of the returned packfile is not possible at this time. And packfile_password() does not have any effect on packfiles opened with pack_fopen_vtable().
Return value: On success, it returns a pointer to a PACKFILE structure, and on error it returns NULL and stores an error code in `errno'.
See also: pack_fopen, pack_fopen_chunk, packfile_password.
Examples using this: expackf.
Return value: Returns zero on success. On error, returns an error code which is also stored in `errno'. This function can fail only when writing to files: if the file was opened in read mode, it will always succeed.
See also: pack_fopen, pack_fopen_vtable, packfile_password.
Examples using this: expackf.
input_file = pack_fopen("data.bin", "r"); if (!input_file) abort_on_error("Couldn't open binary data!"); /* Skip some useless header before reading data. */ pack_fseek(input_file, 32);
Return value: Returns zero on success or a negative number on error, storing the error code in `errno'.
See also: pack_fopen, pack_fopen_chunk.
Examples using this: expackf.
Return value: Returns non-zero if you are at the end of the file, zero otherwise.
See also: pack_fopen, pack_fopen_chunk, pack_ferror.
Return value: Returns nonzero if the error indicator for the stream is set, meaning that an error has occurred during a previous operation on the stream.
See also: pack_fopen, pack_fopen_chunk.
See also: pack_fopen, pack_fopen_chunk.
Note: pack_fgets internally uses pack_ungetc, so never use pack_ungetc directly after using pack_fgets on a PACKFILE.
Return value: Returns c on success, or EOF on error.
See also: pack_getc, pack_fgets.
Return value: Returns the character written on success, or EOF on error.
See also: pack_fopen, pack_fopen_chunk.
See also: pack_getc.
See also: pack_putc.
See also: pack_getc.
See also: pack_putc.
See also: pack_getc.
See also: pack_putc.
See also: pack_getc.
See also: pack_putc.
unsigned char buf[256]; ... if (pack_fread(buf, 256, input_file) != 256) abort_on_error("Truncated input file!");
Return value: Returns the number of bytes read, which will be less than `n' if EOF is reached or an error occurs. Error codes are stored in errno.
See also: pack_fopen, pack_fopen_chunk, pack_feof.
Examples using this: expackf.
Return value: Returns the number of bytes written, which will be less than n if an error occurs. Error codes are stored in errno.
See also: pack_fopen, pack_fopen_chunk, pack_feof.
Note: This function internally may make calls to pack_ungetc, so you cannot use pack_ungetc directly afterwards.
Example:
char buf[256]; ... while (pack_fgets(buf, sizeof(buf), input_file)) { /* Process input line. */ } fclose(input_file);
Return value: Returns the pointer `p' on success, or NULL on error.
See also: pack_fopen, pack_fopen_chunk, pack_fread, pack_getc, pack_ungetc.
Return value: Returns zero on success or a negative number on error.
See also: pack_fopen, pack_fopen_chunk, pack_fwrite, pack_putc.
The data written to the chunk will be prefixed with two length counts (32-bit, a.k.a. big-endian). For uncompressed chunks these will both be set to the size of the data in the chunk. For compressed chunks (created by setting the `pack' flag), the first length will be the raw size of the chunk, and the second will be the negative size of the uncompressed data.PACKFILE *output = pack_fopen("out.raw", "w!"); ... /* Create a sub-chunk with compression. */ output = pack_fopen(chunk(output, 1); if (!output) abort_on_error("Error saving data!"); /* Write some data to the sub-chunk. */ ... /* Close the sub-chunk, recovering parent file. */ output = pack_fclose_chunk(output);
To read the chunk, use the following code:
This sequence will read the length counts created when the chunk was written, and automatically decompress the contents of the chunk if it was compressed. The length will also be used to prevent reading past the end of the chunk (Allegro will return EOF if you attempt this), and to automatically skip past any unread chunk data when you call pack_fclose_chunk().PACKFILE *input = pack_fopen("out.raw", "rp"); ... input = pack_fopen_chunk(input, 1); /* Read data from the sub-chunk and close it. */ ... input = pack_fclose_chunk(input);
Chunks can be nested inside each other by making repeated calls to pack_fopen_chunk(). When writing a file, the compression status is inherited from the parent file, so you only need to set the pack flag if the parent is not compressed but you want to pack the chunk data. If the parent file is already open in packed mode, setting the pack flag will result in data being compressed twice: once as it is written to the chunk, and again as the chunk passes it on to the parent file.
Return value: Returns a pointer to the sub-chunked PACKFILE, or NULL if there was some error (eg. you are using a custom PACKFILE vtable).
See also: pack_fclose_chunk, pack_fopen.
Return value: Returns a pointer to the parent of the sub-chunk you just closed. Returns NULL if there was some error (eg. you tried to close a PACKFILE which wasn't sub-chunked).
See also: pack_fopen_chunk.
Return value: Returns a pointer to the structure, or NULL if there was an error.
See also: free_lzss_pack_data.
See also: create_lzss_pack_data.
Return value: Returns 0 on success, or EOF if there was an error.
See also: create_lzss_pack_data, free_lzss_pack_data.
Return value: Returns a pointer to the structure, or NULL if there was an error.
See also: free_lzss_unpack_data.
See also: create_lzss_unpack_data.
Return value: Returns the number of bytes added to the buffer `buf'.
See also: free_lzss_unpack_data.
Datafiles are created by the grabber utility (see grabber.txt for more information), and have a `.dat' extension. They can contain bitmaps, palettes, fonts, samples, MIDI music, FLI/FLC animations, and any other binary data that you import. You could distribute your bitmaps and samples in a myriad of separate files, but packing them in a few `.dat' binaries has a few advantages:
On some platforms you can attach datafiles to your binary, potentially reducing your game distribution down to a single executable file. Try the example exexedat on your platform to see if this is possible. However, this is not recommended for big programs: a single update to your code or binary data would force end users to download again a potentially big file, no matter how small your change is. The same warning goes for the tools dat2s or dat2c, which convert datafiles into assembler and C code respectively, prepared to be included directly in your binary.
Remember that with Allegro truecolor images can only be loaded after you have set a graphics mode. This is true for datafiles too. Load all your data after you have set the graphics mode, otherwise the pixel format (RGB or BGR) will not be known and the datafile may be converted wrongly. Oh, and read carefully the warning of fixup_datafile() if you plan on switching resolutions during runtime.
Note: even though Allegro datafiles provide encryption, you should consider it weak, so don't plan on hiding there the plans for a Death Star or something. Determinate knowledgeable users will be able to rip your resources no matter how hard you try to hide them! Use the encryption only as a slight deterrent towards unwanted tampering of your data. How to crack an encrypted datafile is left as an exercise to the reader, though.
Using datafiles once they are loaded is quite simple: you access the elements of the DATAFILE as a normal array. Read below the section "Using datafiles" below for several examples on how to access their data.
/* Load the resources for our game. */ DATAFILE *dat = load_datafile("game.dat"); if (!dat) abort_on_error("Couldn't load sound resources!"); /* Use resources. */ ... /* Destroy them when we don't need them any more. */ unload_datafile(dat);
Return value: Returns a pointer to the DATAFILE, or NULL on error. Remember to free this DATAFILE later to avoid memory leaks.
See also: load_datafile_callback, unload_datafile, load_datafile_object, set_color_conversion, fixup_datafile, packfile_password, find_datafile_object, register_datafile_object, Using datafiles.
Examples using this: excustom, exdata, exexedat, exgui, exsprite, exunicod.
void load_callback(DATAFILE *dat_obj) { static const char indicator[] = "-\\|/-.oOXOo."; static int current = 0; /* Show a different character every time. */ textprintf_ex(screen, font, 0, 0, makecol(0, 0, 0), makecol(255, 255, 255), "%c Loading %c", indicator[current], indicator[current]); /* Increase index and check if we need to reset it. */ current++; if (!indicator[current]) current = 0; } ... dat = load_datafile_callback("data.dat", load_callback);
Return value: Returns a pointer to the DATAFILE or NULL on error. Remember to free this DATAFILE later to avoid memory leaks.
See also: load_datafile, unload_datafile, load_datafile_object, set_color_conversion, fixup_datafile, packfile_password, find_datafile_object, register_datafile_object.
See also: load_datafile.
Examples using this: excustom, exdata, exexedat, exgui, exsprite, exunicod.
/* Load only the music from the datafile. */ music_object = load_datafile_object("datafile.dat", "MUSIC"); /* Play it and wait a moment for it. */ play_midi(music_object->dat); ... /* Destroy unneeded music. */ unload_datafile_object(music_object);
Return value: Returns a pointer to a single DATAFILE element whose `dat' member points to the object, or NULL if there was an error or there was no object with the requested name. Remember to free this DATAFILE later to avoid memory leaks, but use the correct unloading function!
See also: unload_datafile_object, load_datafile, set_color_conversion, find_datafile_object, register_datafile_object, Using datafiles.
See also: load_datafile_object.
char level_name[10]; DATAFILE *dat, *level; ... uszprintf(level_name, sizeof(buffer), "LEVEL_%02d", level_number); level = find_datafile_object(dat, level_name); if (!level) abort_on_error("That level doesn't exist!");
Return value: Returns a pointer to a single DATAFILE element whose `dat' member points to the object, or NULL if the object could not be found.
See also: load_datafile, load_datafile_object.
Note: If the datafile uses global compression, there is no performance gain from using an index, because seeking to the offset still requires to uncompress the whole datafile up to that offset. Example:
DATAFILE_INDEX *index = create_datafile_index("huge.dat"); DATAFILE *object = load_datafile_object_indexed(index, 1234); ... unload_datafile_object(object); destroy_datafile_index(index);
Return value: A pointer value which you can pass to load_datafile_object_indexed.
See also: destroy_datafile_index, load_datafile_object_indexed, Using datafiles.
Return value: Returns a pointer to a single DATAFILE element whose "dat" member points to the object, or NULL if the object could not be loaded.
See also: create_datafile_index, load_datafile_object, unload_datafile_object.
See also: create_datafile_index.
const char *name; ... name = get_datafile_property(game_data, DAT_ID('N','A','M','E')); if (name == empty_string) abort_on_error("Object doesn't have a name!");
Return value: Returns a pointer to the text string for the object, or a pointer to the variable empty_string if the property isn't present.
See also: Using datafiles, DAT_ID, empty_string.
See also: load_datafile, load_datafile_object, DAT_ID, Custom datafile objects.
Note that you can only call this once and expect it to work correctly, because after the call the DATAFILE you fixed up is permanently converted to whatever is the current component ordering for your screen mode. If you call fixup_datafile again, the function assumes you have a freshly loaded datafile. It cannot "undo" the previous conversion.
If your program supports changing resolution and/or color depth during runtime, you have two choices: either call fixup_datafile() just once and hope that the component ordering and bit depth doesn't change when the screen mode changes (unlikely). Or, you can reload your datafiles when the screen mode changes.
See also: set_gfx_mode, set_color_conversion, Differences between platforms.
get_datafile_property(datob, DAT_ID('N','A','M','E'));
See also: register_datafile_object, get_datafile_property, Custom datafile objects, Using datafiles.
In order to access the contents of a datafile, you will need to know where each object is located. The easiest way to do this is by integer index, using an automatically generated header file. With the grabber, type a name into the "Header:" field, and the object indexes will be written to this file whenever the datafile is saved. With the dat utility, use the '-h' option, eg. "dat filename.dat -h filename.h". The header will define C preprocessor symbols for each object in the datafile, for example:
To prevent name conflicts, you can specify a prefix string for these definitions by typing it into the "Prefix:" field in the grabber or using the '-p' option to dat.#define SOME_DATA 0 /* DATA */ #define SOME_MORE_DATA 1 /* DATA */
To load a datafile into memory, call the function:
This will load the entire file, returning a pointer to it, or NULL on error. When the data is no longer required, the entire thing can be destroyed by calling:DATAFILE *load_datafile(char *filename);
When you load a datafile, you will obtain a pointer to an array of DATAFILE structures:void unload_datafile(DATAFILE *dat);
typedef struct DATAFILE { void *dat; - pointer to the actual data int type; - object type ID long size; - size of the data, in bytes DATAFILE_PROPERTY *prop; - list of object properties } DATAFILE;
The only really important piece of information here is the `dat' field, which points to the contents of the object. What type of data this is will depend on the type of object: for bitmaps it will be an Allegro BITMAP structure, for RLE sprites an RLE_SPRITE, for fonts a FONT structure, etc. If you are programming in C you can pass this pointer directly to the relevant Allegro library functions, but if you are using C++ you will need to cast it to the appropriate type to prevent the compiler giving a warning.
For example, if you have a datafile called `myfile.dat', which contains a bitmap called COOL_PICTURE, and you have used it to produce a header called `myfile.h', you could display the bitmap with the code:
#include "myfile.h" void show_the_bitmap() { DATAFILE *dat; BITMAP *bmp; dat = load_datafile("myfile.dat"); if (!dat) { /* report an error! */ return; } bmp = (BITMAP *)dat[COOL_PICTURE].dat; blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h); unload_datafile(dat); }
If a datafile contains nested child datafiles, the header will prefix the names of objects in the sub-files with the name of their parent datafile. It will also define a count of the number of objects in the child file, which may be useful if for example the child datafile contains several bitmaps which form a 'run' animation, and you want your code to automatically adjust to the number of frames in the datafile.
For example, the following datafile:
Will produce the header:"FILE" - NESTED_FILE |- "BMP" - A_BITMAP |- "FONT" - A_FONT "DATA" - SOME_DATA "DATA" - SOME_MORE_DATA
The main datafile contains three objects (NESTED_FILE, SOME_DATA, and SOME_MORE_DATA) with consecutive indexes, while the child datafile contains the two objects A_BITMAP and A_FONT. To access these objects you need to reference both the parent and child datafiles, eg:#define NESTED_FILE 0 /* FILE */ #define NESTED_FILE_A_BITMAP 0 /* BMP */ #define NESTED_FILE_A_FONT 1 /* FONT */ #define NESTED_FILE_COUNT 2 #define SOME_DATA 1 /* DATA */ #define SOME_MORE_DATA 2 /* DATA */
If you need to access object property strings from within your program, you can use the function:DATAFILE *dat = load_datafile("whatever.dat"); DATAFILE *nested = (DATAFILE *)dat[NESTED_FILE].dat; FONT *thefont = (FONT *)nested[NESTED_FILE_A_FONT].dat;
This will return a pointer to the property string if it can be found, and an empty string (not null!) if it does not exist. One possible use of this function is to locate objects by name, rather than using the indexes from a header file. The datafile array is ended by an object of type DAT_END, so to search the datafile dat for the object "my_object" you could use the code:char *get_datafile_property(DATAFILE *dat, int type);
If you prefer to access objects by name rather than index number, you can use the function:const int name_type = DAT_ID('N','A','M','E'); for (i=0; dat[i].type != DAT_END; i++) { if (stricmp(get_datafile_property(dat+i, name_type), "my_object") == 0) { /* found the object at index i */ } } /* not found... */
This will search an already loaded datafile for an object with the specified name, returning a pointer to it, or NULL if the object cannot be found. It understands '/' and '#' separators for nested datafile paths.DATAFILE *find_datafile_object(DATAFILE *dat, char *objectname);
It is also possible to selectively load individual objects from a datafile, with the function:
This searches the datafile for an object with the specified name, so obviously it won't work if you strip the name properties out of the file. Because this function needs to seek through the data, it will be extremely slow if you have saved the file with global compression. If you are planning to load objects individually, you should save the file uncompressed or with individual compression per-object. Because the returned datafile points to a single object rather than an array of objects, you should access it with the syntax datafile->dat, rather than datafile[index].dat, and when you are done you should free the object with the function:DATAFILE *load_datafile_object(char *filename, char *objectname);
Example:void unload_datafile_object(DATAFILE *dat);
Alternatively, the packfile functions can open and read directly from the contents of a datafile object. You do this by calling pack_fopen() with a fake filename in the form "filename.dat#object_name". The contents of the object can then be read in an identical way to a normal disk file, so any of the file access functions in Allegro (eg. load_pcx() and set_config_file()) can be used to read from datafile objects. Note that you can't write to datafiles in this way: the fake file is read only. Also, you should save the file uncompressed or with per-object compression if you are planning on using this feature. Finally, be aware that the special Allegro object types aren't the same format as the files you import the data from, so if for example you want to use load_pcx to read an image from a datafile, you should import it as a binary data chunk rather than as a BITMAP object.music_object = load_datafile_object("datafile.dat", "MUSIC"); play_midi(music_object->dat); ... unload_datafile_object(music_object);
If you have appended a datafile to the end of your executable with the exedat utility, use load_datafile("#") to read the entire thing into memory, load_datafile_object("#", "object_name") to load a specific object, and pack_fopen("#object_name", F_READ) to read one of the objects directly with your own code. Note that unless you use the previous functions to load the appended data, the OS will not load it into memory just because you are running the program, so you shouldn't have problems attaching datafiles to your binary larger than the available system memory.
By default, all graphic objects loaded from a datafile will be converted into the current color depth. This conversion may be both lossy and very slow, particularly when reducing from truecolor to 256 color formats, so you may wish to disable it by calling set_color_conversion(COLORCONV_NONE) or set_color_conversion(COLORCONV_PARTIAL) before your call to load_datafile().
Some of the objects in a datafile, for example palettes and FLI animations, are simply treated as blocks of binary data, but others are loaded into special formats such as bitmap structures or compiled sprites. It is possible to extend the datafile system to support your own custom object types, eg. map objects for a tile based engine, or level data for a platform game. Obviously the grabber has no way of understanding this data, but it will allow you to import binary data from external files, so you can grab information produced by your own utilities. If you are happy with the data being loaded as a simple binary block, that is all you need to do, but if you need to load it into a specific structure, read on...
Your custom objects must be given a unique type ID, which is formed from four ASCII characters (by convention all uppercase A-Z). If you don't use all four characters, the string should be padded with spaces (ASCII 32). You should use this ID when creating the objects in the grabber (select New/Other and type in the ID string), and in your code you should define an identifier for the type, eg:
You then need to write functions for loading and destroying objects of this type, in the form:#define DAT_MAPDATA DAT_ID('M','A','P','D')
Finally, before you load your datafile you must tell Allegro about the custom format, by calling:void *load_mapdata(PACKFILE *f, long size) { /* Allegro will call this function whenever an object of your custom * type needs to be loaded from a datafile. It will be passed a * pointer to the file from which the data is to be read, and the size * of the object in bytes. It should return a pointer to the loaded * data, which will be stored in the dat field of the datafile object * structure, or NULL if an error occurs. The file will have been * opened as a sub-chunk of the main datafile, so it is safe to read * past the end of the object (if you attempt this, Allegro will * return EOF), and it is also safe to return before reading all the * data in the chunk (if you do this, Allegro will skip any unused * bytes before starting to read the next object). You should _not_ * close the file when you are done: this will be handled by the * calling function. To clarify how all this works, here's an example * implementation of a null-terminated string object: */ #define MAX_LEN 256 char buf[MAX_LEN]; char *p; int i, c; for (i=0; i<;MAX_LEN-1; i++) { if ((c = pack_getc(f)) == EOF) break; buf[i] = c; } buf[i] = 0; p = malloc(i+1); strcpy(p, buf); return p; } void destroy_mapdata(void *data) { /* Allegro will call this function whenever an object of your custom * type needs to be destroyed. It will be passed a pointer to the * object (as returned by the load function), and should free whatever * memory the object is using. For example, the simple string object * returned by the above loader could be destroyed with the code: */ if (data) free(data); }
It is also possible to integrate support for custom object types directly into the grabber and dat utilities, by copying some special files into the tools/plugins directory. This can be used to add whole new object types and menu commands, or to provide additional import/export routines for the existing formats. See `tools/plugins/plugins.txt' for an overview of how to write your own grabber plugins.register_datafile_object(DAT_MAPDATA, load_mapdata, destroy_mapdata);
Allegro provides some routines for working with fixed point numbers, and defines the type `fixed' to be a signed 32-bit integer. The high word is used for the integer part and the low word for the fraction, giving a range of -32768 to 32767 and an accuracy of about four or five decimal places. Fixed point numbers can be assigned, compared, added, subtracted, negated and shifted (for multiplying or dividing by powers of two) using the normal integer operators, but you should take care to use the appropriate conversion routines when mixing fixed point with integer or floating point values. Writing `fixed_point_1 + fixed_point_2' is OK, but `fixed_point + integer' is not.
Unfortunately the only advantage of fixed point math routines is that you don't require a floating point coprocessor to use them. This was great in the time period of i386 and i486 machines, but stopped being so useful with the coming of the Pentium class of processors. From Pentium onwards, CPUs have increased their strength in floating point operations, equaling or even surpassing integer math performance.
Depending on the type of operations your program may need, using floating point types may be faster than fixed types if you are targeting a specific machine class. Allegro comes with a test program in the `allegro/tests' directory. Its `Misc' menu contains a basic profile test which can give you an idea of the speed difference between fixed and float types for a few basic operations on your machine. However, don't forget to profile your program in real life conditions, tight loop benchmarks are after all artificial.
Fixed point math is considered "add-on" material and is kept only for backwards compatibility. Whenever a future release of Allegro breaks backwards compatibility, fixed point math will likely be moved to a separate add-on package for the very few users who still find it convenient and useful, and Allegro functions using fixed point math will use other types.
fixed number; /* This conversion is OK. */ number = itofix(100); ASSERT(fixtoi(number) == 100); number = itofix(64000); /* This check will fail in debug builds. */ ASSERT(fixtoi(number) == 64000);
Return value: Returns the value of the integer converted to fixed point ignoring overflows.
See also: fixtoi, ftofix, fixtof.
Examples using this: ex12bit, ex3buf, ex3d, exblend, excustom, exfixed, exlights, exspline, exsprite, exstars.
int result; /* This will put 33 into `result'. */ result = fixtoi(itofix(100) / 3); /* But this will round up to 17. */ result = fixtoi(itofix(100) / 6);
See also: itofix, ftofix, fixtof, fixfloor, fixceil.
Examples using this: ex12bit, ex3buf, ex3d, exblend, excustom, exlights, exspline, exstars, exupdate.
int result; /* This will put 33 into `result'. */ result = fixfloor(itofix(100) / 3); /* And this will round down to 16. */ result = fixfloor(itofix(100) / 6);
See also: fixtoi, fixceil.
int result; /* This will put 34 into `result'. */ result = fixceil(itofix(100) / 3); /* This will round up to 17. */ result = fixceil(itofix(100) / 6);
See also: fixtoi, fixfloor.
fixed number; number = itofix(-40000); ASSERT(fixfloor(number) == -32768); number = itofix(64000); ASSERT(fixfloor(number) == 32767); ASSERT(!errno); /* This will fail. */
Return value: Returns the value of the floating point value converted to fixed point clamping overflows (and setting `errno').
See also: fixtof, itofix, fixtoi.
Examples using this: exfixed, exspline, exupdate.
float result; /* This will put 33.33333 into `result'. */ result = fixtof(itofix(100) / 3); /* This will put 16.66666 into `result'. */ result = fixtof(itofix(100) / 6);
See also: ftofix, itofix, fixtoi.
Examples using this: exfixed, exspline, exstars.
If an overflow occurs, `errno' will be set and the maximum possible value will be returned, but `errno' is not cleared if the operation is successful. This means that if you are going to test for overflow you should set `errno=0' before calling fixmul(). Example:
fixed result; /* This will put 30000 into `result'. */ result = fixmul(itofix(10), itofix(3000)); /* But this overflows, and sets `errno'. */ result = fixmul(itofix(100), itofix(3000)); ASSERT(!errno);
Return value: Returns the clamped result of multiplying `x' by `y', setting `errno' to ERANGE if there was an overflow.
See also: fixadd, fixsub, fixdiv.
Examples using this: ex3buf, excustom, exfixed, exspline, exstars, exupdate.
fixed result; /* This will put 0.06060 `result'. */ result = fixdiv(itofix(2), itofix(33)); /* This will put 0 into `result'. */ result = fixdiv(0, itofix(-30)); /* Sets `errno' and puts -32768 into `result'. */ result = fixdiv(itofix(-100), itofix(0)); ASSERT(!errno); /* This will fail. */
Return value: Returns the result of dividing `x' by `y'. If `y' is zero, returns the maximum possible fixed point value and sets `errno' to ERANGE.
See also: fixadd, fixsub, fixmul.
Examples using this: exfixed.
fixed result; /* This will put 5035 into `result'. */ result = fixadd(itofix(5000), itofix(35)); /* Sets `errno' and puts -32768 into `result'. */ result = fixadd(itofix(-31000), itofix(-3000)); ASSERT(!errno); /* This will fail. */
Return value: Returns the clamped result of adding `x' to `y', setting `errno' to ERANGE if there was an overflow.
See also: fixsub, fixmul, fixdiv.
fixed result; /* This will put 4965 into `result'. */ result = fixsub(itofix(5000), itofix(35)); /* Sets `errno' and puts -32768 into `result'. */ result = fixsub(itofix(-31000), itofix(3000)); ASSERT(!errno); /* This will fail. */
Return value: Returns the clamped result of subtracting `y' from `x', setting `errno' to ERANGE if there was an overflow.
See also: fixadd, fixmul, fixdiv.
The fixed point square root, sin, cos, tan, inverse sin, and inverse cos functions are implemented using lookup tables, which are very fast but not particularly accurate. At the moment the inverse tan uses an iterative search on the tan table, so it is a lot slower than the others. Note that on machines with very good floating point processors using these functions could be slower in real life code due to cache misses: it may be faster to wait a few extra cycles for a floating point sine result rather than wait for the CPU to fetch the precalculated table from main memory. Always profile your code.
Angles are represented in a binary format with 256 equal to a full circle, 64 being a right angle and so on. This has the advantage that a simple bitwise 'and' can be used to keep the angle within the range zero to a full circle, eliminating all those tiresome 'if (angle >= 360)' checks.
fixed rad_angle, binary_angle; /* Set the binary angle to 90 degrees. */ binary_angle = 64; /* Now convert to radians (about 1.57). */ rad_angle = fixmul(binary_angle, fixtorad_r);
See also: fixmul, radtofix_r.
fixed rad_angle, binary_angle; ... binary_angle = fixmul(rad_angle, radtofix_r);
See also: fixmul, fixtorad_r.
fixed angle; int result; /* Set the binary angle to 90 degrees. */ angle = itofix(64); /* The sine of 90 degrees is one. */ result = fixtoi(fixsin(angle)); ASSERT(result == 1);
Return value: Returns the sine of a fixed point binary format angle. The return value will be in radians.
See also: Fixed point trig.
Examples using this: ex12bit, ex3buf, exblend, excustom, exspline, exupdate.
fixed angle; float result; /* Set the binary angle to 45 degrees. */ angle = itofix(32); /* The cosine of 45 degrees is about 0.7071. */ result = fixtof(fixcos(angle)); ASSERT(result > 0.7 && result < 0.71);
Return value: Returns the cosine of a fixed point binary format angle. The return value will be in radians.
See also: Fixed point trig.
Examples using this: ex12bit, ex3buf, exblend, excustom, exspline, exupdate.
fixed angle, res_a, res_b; float dif; angle = itofix(37); /* Prove that tan(angle) == sin(angle) / cos(angle). */ res_a = fixdiv(fixsin(angle), fixcos(angle)); res_b = fixtan(angle); dif = fixtof(fixsub(res_a, res_b)); allegro_message("Precision error: %f\n", dif);
Return value: Returns the tangent of a fixed point binary format angle. The return value will be in radians.
See also: Fixed point trig.
float angle; fixed val; /* Sets `val' to a right binary angle (`64'). */ val = fixasin(itofix(1)); /* Sets `angle' to 0.2405. */ angle = fixtof(fixmul(fixasin(ftofix(0.238)), fixtorad_r)); /* This will trigger the assert. */ val = fixasin(ftofix(-1.09)); ASSERT(!errno);
Return value: Returns the inverse sine of a fixed point value, measured as fixed point binary format angle, or zero if the input was out of the range. All return values of this function will be in the range `-64' to `64'.
See also: Fixed point trig.
fixed result; /* Sets `result' to binary angle 128. */ result = fixacos(itofix(-1));
Return value: Returns the inverse sine of a fixed point value, measured as fixed point binary format angle, or zero if the input was out of range. All return values of this function will be in the range `0' to `128'.
See also: Fixed point trig.
fixed result; /* Sets `result' to binary angle 13. */ result = fixatan(ftofix(0.326));
Return value: Returns the inverse tangent of a fixed point value, measured as a fixed point binary format angle.
See also: Fixed point trig.
fixed result; /* Sets `result' to binary angle 64. */ result = fixatan2(itofix(1), 0); /* Sets `result' to binary angle -109. */ result = fixatan2(itofix(-1), itofix(-2)); /* Fails the assert. */ result = fixatan2(0, 0); ASSERT(!errno);
Return value: Returns the arc tangent of `y / x' in fixed point binary format angle, from `-128' to `128'. If both `x' and `y' are zero, returns zero and sets `errno' to EDOM.
See also: Fixed point trig.
Examples using this: exlights, exspline.
See also: Fixed point trig.
Examples using this: exfixed, exlights, exspline.
See also: Fixed point trig.
If you are programming in C++ you can ignore all the above and use the fix class instead, which overloads a lot of operators to provide automatic conversion to and from integer and floating point values, and calls the above routines as they are required. You should not mix the fix class with the fixed typedef though, because the compiler will mistake the fixed values for regular integers and insert unnecessary conversions. For example, if x is an object of class fix, calling fixsqrt(x) will return the wrong result. You should use the overloaded sqrt(x) or x.sqrt() instead.
On top of that, the Fix class may be slower than using directly the C functions because of implicit internal conversions from one type to another which you otherwise could avoid or minimise. Finally, this is the only bit of C++ in the whole Allegro library, and the developers are certainly going to move it into add-on space in the next version of Allegro which breaks source backwards compatibility.
Allegro contains some 3d helper functions for manipulating vectors, constructing and using transformation matrices, and doing perspective projections from 3d space onto the screen. It is not, and never will be, a fully fledged 3d library (the goal is to supply generic support routines, not shrink-wrapped graphics code :-) but these functions may be useful for developing your own 3d code.
Allegro uses a right-handed coordinate system, i.e. if you point the thumb of your right hand along the x axis, and the index finger along the y axis, your middle finger points in the direction of the z axis.
Allegro's world coordinate system typically has the positive x axis right, the positive y axis up, and the positive z axis out of the screen. What all this means is this: Assume, the viewer is located at the origin (0/0/0) in world space, looks along the negative z axis (0/0/-1), and is oriented so up is along the positive y axis (0/1/0). Then something located at (100/200/-300) will be 100 to the right, 200 above, and 300 in front of the viewer. Just like in OpenGL. (Of course, both OpenGL and Allegro allow to use a different system.) Here's a short piece of code demonstrating the transformation pipeline of a point from world space to the screen.
/* First, set up the projection viewport. */ set_projection_viewport (0, 0, SCREEN_W, SCREEN_H); /* Next, get a camera matrix, depending on the * current viewer position and orientation. */ get_camera_matrix_f (&m, 0, 0, 0, /* Viewer position, in this case, 0/0/0. */ 0, 0, -1, /* Viewer direction, in this case along negative z. */ 0, 1, 0, /* Up vector, in this case positive y. */ 32, /* The FOV, here 45°. */ (float)SCREEN_W / (float)SCREEN_H)); /* Aspect ratio. */ /* Applying the matrix transforms the point 100/200/-300 * from world space into camera space. The transformation * moves and rotates the point so it is relative to the * camera, scales it according to the FOV and aspect * parameters, and also flips up and front direction - * ready to project the point to the viewport. */ apply_matrix_f (&m, 100, 200, -300, &x, &y, &z); /* Finally, the point is projected from * camera space to the screen. */ persp_project_f (cx, cy, cz, &sx, &sy);
For more details, look at the function descriptions of set_projection_viewport(), get_camera_matrix(), and persp_project(), as well as the relevant example programs.
All the 3d math functions are available in two versions: one which uses fixed point arithmetic, and another which uses floating point. The syntax for these is identical, but the floating point functions and structures are postfixed with '_f', eg. the fixed point function cross_product() has a floating point equivalent cross_product_f(). If you are programming in C++, Allegro also overloads these functions for use with the 'fix' class.
3d transformations are accomplished by the use of a modelling matrix. This is a 4x4 array of numbers that can be multiplied with a 3d point to produce a different 3d point. By putting the right values into the matrix, it can be made to do various operations like translation, rotation, and scaling. The clever bit is that you can multiply two matrices together to produce a third matrix, and this will have the same effect on points as applying the original two matrices one after the other. For example, if you have one matrix that rotates a point and another that shifts it sideways, you can combine them to produce a matrix that will do the rotation and the shift in a single step. You can build up extremely complex transformations in this way, while only ever having to multiply each point by a single matrix.
Allegro actually cheats in the way it implements the matrix structure. Rotation and scaling of a 3d point can be done with a simple 3x3 matrix, but in order to translate it and project it onto the screen, the matrix must be extended to 4x4, and the point extended into 4d space by the addition of an extra coordinate, w=1. This is a bad thing in terms of efficiency, but fortunately an optimisation is possible. Given the 4x4 matrix:
a pattern can be observed in which parts of it do what. The top left 3x3 grid implements rotation and scaling. The three values in the top right column (d, h, and l) implement translation, and as long as the matrix is only used for affine transformations, m, n and o will always be zero and p will always be 1. If you don't know what affine means, read Foley & Van Damme: basically it covers scaling, translation, and rotation, but not projection. Since Allegro uses a separate function for projection, the matrix functions only need to support affine transformations, which means that there is no need to store the bottom row of the matrix. Allegro implicitly assumes that it contains (0,0,0,1), and optimises the matrix manipulation functions accordingly. Read chapter "Structures and types defined by Allegro" for an internal view of the MATRIX/_f structures.( a, b, c, d ) ( e, f, g, h ) ( i, j, k, l ) ( m, n, o, p )
See also: apply_matrix, get_transformation_matrix, qtranslate_matrix.
Examples using this: exstars.
See also: apply_matrix, get_transformation_matrix, qscale_matrix.
See also: apply_matrix, get_rotation_matrix, get_y_rotate_matrix, get_z_rotate_matrix.
See also: apply_matrix, get_rotation_matrix, get_x_rotate_matrix, get_z_rotate_matrix.
See also: apply_matrix, get_rotation_matrix, get_x_rotate_matrix, get_y_rotate_matrix.
See also: apply_matrix, get_transformation_matrix, get_vector_rotation_matrix, get_x_rotate_matrix, get_y_rotate_matrix, get_z_rotate_matrix, get_align_matrix.
Examples using this: ex12bit, exquat, exstars.
See also: apply_matrix, get_camera_matrix.
See also: get_align_matrix.
See also: apply_matrix, get_rotation_matrix, get_align_matrix.
Examples using this: excamera.
See also: apply_matrix, get_rotation_matrix, get_scaling_matrix, get_translation_matrix.
Examples using this: ex3d, exstars.
See also: get_transformation_matrix.
Examples using this: exzbuf.
The fov parameter specifies the field of view (ie. width of the camera focus) in binary, 256 degrees to the circle format. For typical projections, a field of view in the region 32-48 will work well. 64 (90°) applies no extra scaling - so something which is one unit away from the viewer will be directly scaled to the viewport. A bigger FOV moves you closer to the viewing plane, so more objects will appear. A smaller FOV moves you away from the viewing plane, which means you see a smaller part of the world.
Finally, the aspect ratio is used to scale the Y dimensions of the image relative to the X axis, so you can use it to adjust the proportions of the output image (set it to 1 for no scaling - but keep in mind that the projection also performs scaling according to the viewport size). Typically, you will pass (float)w/(float)h, where w and h are the parameters you passed to set_projection_viewport.
Note that versions prior to 4.1.0 multiplied this aspect ratio by 4/3.
See also: apply_matrix, get_align_matrix, set_projection_viewport, persp_project.
See also: get_camera_matrix.
Examples using this: excamera, exquat.
See also: get_translation_matrix.
See also: get_scaling_matrix.
See also: apply_matrix.
Examples using this: exquat, exscn3d.
See also: normalize_vector.
See also: vector_length, dot_product, cross_product.
Examples using this: exstars.
See also: cross_product, normalize_vector.
Examples using this: exstars.
See also: dot_product, polygon_z_normal, normalize_vector.
Examples using this: exstars.
However, this method of culling back-faces must only be used once the X and Y coordinates have been projected into screen space using persp_project() (or if an orthographic (isometric) projection is being used). Note that this function will fail if the three vertices are co-linear (they lie on the same line) in 3D space.
See also: cross_product.
Examples using this: ex3d.
See also: matrix_mul.
Examples using this: ex12bit, ex3d, exstars.
See also: persp_project, get_camera_matrix.
Examples using this: ex3d, excamera, exquat, exscn3d, exstars, exzbuf.
See also: set_projection_viewport, get_camera_matrix.
Examples using this: ex3d, exstars.
Quaternions are an alternate way to represent the rotation part of a transformation, and can be easier to manipulate than matrices. As with a matrix, you can encode a geometric transformations in one, concatenate several of them to merge multiple transformations, and apply them to a vector, but they can only store pure rotations. The big advantage is that you can accurately interpolate between two quaternions to get a part-way rotation, avoiding the gimbal problems of the more conventional Euler angle interpolation.
Quaternions only have floating point versions, without any _f suffix. Other than that, most of the quaternion functions correspond with a matrix function that performs a similar operation.
Quaternion means 'of four parts', and that's exactly what it is. Here is the structure:
You will have lots of fun figuring out what these numbers actually mean, but that is beyond the scope of this documentation. Quaternions do work -- trust me.typedef struct QUAT { float w, x, y, z; }
Examples using this: exquat.
Examples using this: exquat.
Examples using this: exquat.
QUAT_SHORT - like quat_interpolate(), use shortest path QUAT_LONG - rotation will be greater than 180 degrees QUAT_CW - rotate clockwise when viewed from above QUAT_CCW - rotate counterclockwise when viewed from above QUAT_USER - the quaternions are interpolated exactly as given
Allegro contains an object-oriented dialog manager, which was originally based on the Atari GEM system (form_do(), objc_draw(), etc: old ST programmers will know what we are talking about :-) You can use the GUI as-is to knock out simple interfaces for things like the test program and grabber utility, or you can use it as a basis for more complicated systems of your own. Allegro lets you define your own object types by writing new dialog procedures, so you can take complete control over the visual aspects of the interface while still using Allegro to handle input from the mouse, keyboard, joystick, etc.
A GUI dialog is stored as an array of DIALOG objects, read chapter "Structures and types defined by Allegro" for an internal description of the DIALOG structure. The array should end with an object which has the proc pointer set to NULL. Each object has a flags field which may contain any combination of the bit flags:
Each object is controlled by a dialog procedure, which is stored in the proc pointer. This will be called by the dialog manager whenever any action concerning the object is required, or you can call it directly with the object_message() function. The dialog procedure should follow the form:D_EXIT - this object should close the dialog when it is clicked D_SELECTED - this object is selected D_GOTFOCUS - this object has got the input focus D_GOTMOUSE - the mouse is currently on top of this object D_HIDDEN - this object is hidden and inactive D_DISABLED - this object is greyed-out and inactive D_DIRTY - this object needs to be redrawn D_INTERNAL - don't use this! It is for internal use by the library... D_USER - any powers of two above this are free for your own use
It will be passed a flag (msg) indicating what action it should perform, a pointer to the object concerned (d), and if msg is MSG_CHAR or MSG_XCHAR, the key that was pressed (c). Note that d is a pointer to a specific object, and not to the entire dialog.int foo(int msg, DIALOG *d, int c);
The dialog procedure should return one of the values:
Dialog procedures may be called with any of the messages:D_O_K - normal return status D_CLOSE - tells the dialog manager to close the dialog D_REDRAW - tells the dialog manager to redraw the entire dialog D_REDRAWME - tells the dialog manager to redraw the current object D_WANTFOCUS - requests that the input focus be given to this object D_USED_CHAR - MSG_CHAR and MSG_XCHAR return this if they used the key
MSG_START:
Tells the object to initialise itself. The dialog manager sends this to
all the objects in a dialog just before it displays the dialog.
MSG_END:
Sent to all objects when closing a dialog, allowing them to perform
whatever cleanup operations they require.
MSG_DRAW:
Tells the object to draw itself onto the screen. The mouse pointer will
be turned off when this message is sent, so the drawing code does not
need to worry about it.
MSG_CLICK:
Informs the object that a mouse button has been clicked while the mouse
was on top of the object. Typically an object will perform its own mouse
tracking as long as the button is held down, and only return from this
message handler when it is released.
If you process this message, use the functions gui_mouse_*() to read the state of the mouse.
MSG_DCLICK:
Sent when the user double-clicks on an object. A MSG_CLICK will be sent
when the button is first pressed, then MSG_DCLICK if it is released and
pressed again within a short space of time.
If you process this message, use the functions gui_mouse_*() to read the state of the mouse.
MSG_KEY:
Sent when the keyboard shortcut for the object is pressed, or if enter,
space, or a joystick button is pressed while it has the input focus.
MSG_CHAR:
When a key is pressed, this message is sent to the object that has the
input focus, with a readkey() format character code (ASCII value in the
low byte, scancode in the high byte) as the c parameter. If the object
deals with the keypress it should return D_USED_CHAR, otherwise it should
return D_O_K to allow the default keyboard interface to operate. If you
need to access Unicode character input, you should use MSG_UCHAR instead
of MSG_CHAR.
MSG_UCHAR:
If an object ignores the MSG_CHAR input, this message will be sent
immediately after it, passed the full Unicode key value as the c
parameter. This enables you to read character codes greater than 255, but
cannot tell you anything about the scancode: if you need to know that,
use MSG_CHAR instead. This handler should return D_USED_CHAR if it
processed the input, or D_O_K otherwise.
MSG_XCHAR:
When a key is pressed, Allegro will send a MSG_CHAR and MSG_UCHAR to the
object with the input focus. If this object doesn't process the key (ie.
it returns D_O_K rather than D_USED_CHAR), the dialog manager will look
for an object with a matching keyboard shortcut in the key field, and
send it a MSG_KEY. If this fails, it broadcasts a MSG_XCHAR to all
objects in the dialog, allowing them to respond to special keypresses
even when they don't have the input focus. Normally you should ignore
this message (return D_O_K rather than D_USED_CHAR), in which case
Allegro will perform default actions such as moving the focus in response
to the arrow keys and closing the dialog if ESC is pressed.
MSG_WANTFOCUS:
Queries whether an object is willing to accept the input focus. It should
return D_WANTFOCUS if it does, or D_O_K if it isn't interested in getting
user input.
MSG_GOTFOCUS:
MSG_LOSTFOCUS:
Sent whenever an object gains or loses the input focus. These messages
will always be followed by a MSG_DRAW, to let objects display themselves
differently when they have the input focus. If you return D_WANTFOCUS in
response to a MSG_LOSTFOCUS event, this will prevent your object from
losing the focus when the mouse moves off it onto the screen background
or some inert object, so it will only lose the input focus when some
other object is ready to take over the focus (this trick is used by the
d_edit_proc() object).
MSG_GOTMOUSE:
MSG_LOSTMOUSE:
Sent when the mouse moves on top of or away from an object. Unlike the
focus messages, these are not followed by a MSG_DRAW, so if the object is
displayed differently when the mouse is on top of it, it is responsible
for redrawing itself in response to these messages.
MSG_IDLE:
Sent whenever the dialog manager has nothing better to do.
MSG_RADIO:
Sent by radio button objects to deselect other buttons in the same group
when they are clicked. The group number is passed in the c message
parameter.
MSG_WHEEL:
Sent to the focused object whenever the mouse wheel moves. The c message
parameter contains the number of clicks.
MSG_LPRESS, MSG_MPRESS, MSG_RPRESS:
Sent when the corresponding mouse button is pressed.
MSG_LRELEASE, MSG_MRELEASE, MSG_RRELEASE:
Sent when the corresponding mouse button is released.
MSG_USER:
The first free message value. Any numbers from here on (MSG_USER,
MSG_USER+1, MSG_USER+2, ... MSG_USER+n) are free to use for whatever you
like.
Allegro provides several standard dialog procedures. You can use these as they are to provide simple user interface objects, or you can call them from within your own dialog procedures, resulting in a kind of OOP inheritance. For instance, you could make an object which calls d_button_proc to draw itself, but handles the click message in a different way, or an object which calls d_button_proc for everything except drawing itself, so it would behave like a normal button but could look completely different.
Since the release of Allegro version 3.9.33 (CVS), some GUI objects and menus are being drawn differently unlike in previous Allegro versions. The changes are the following:
When you want to convert old dialogs to look equally when compiling with the new Allegro version, just increase the size of the mentioned objects by one pixel in both width and height fields.d_box_proc, d_shadow_box_proc, d_button_proc, d_check_proc, d_radio_proc, d_list_proc, d_text_list_proc and d_textbox_proc.
Menus had been forgotten during the changes for 3.9.33 (CVS), so they were still drawn too large until version 4.1.0.
Examples using this: excustom, exgui.
Examples using this: exgui, exrgbhsv.
Examples using this: exgui, exrgbhsv.
Examples using this: exgui, exrgbhsv.
Examples using this: excustom, exgui.
Note: the object width should allow space for the text as well as the check box (which is square, with sides equal to the object height).
Examples using this: excustom, exgui.
Examples using this: exgui.
Examples using this: exgui.
Examples using this: exgui.
Note: dp must point to a buffer at least (d1 + 1) * 4 bytes long because, depending on the encoding format in use, a single character can occupy up to 4 bytes and room must be reserved for the terminating null character.
Examples using this: excustom, exgui.
If index is zero or positive, the function should return a pointer to the string which is to be displayed at position index in the list. If index is negative, it should return NULL and list_size should be set to the number of items in the list.char *foobar(int index, int *list_size);
To create a multiple selection listbox, set the dp2 field to an array of byte flags indicating the selection state of each list item (non-zero for selected entries). This table must be at least as big as the number of objects in the list!
Examples using this: exgui.
Examples using this: exgui.
Examples using this: exgui.
The d_slider_proc object will return the value of the callback function.int function(void *dp3, int d2);
Examples using this: exgui, exrgbhsv.
See also: GUI menus, active_menu, gui_menu_draw_menu.
Examples using this: exgui.
See also: rest.
Examples using this: exgui.
The behaviour of the dialog manager can be controlled by the following global variables.
See also: gui_mg_color, set_dialog_color.
Examples using this: exgui.
See also: gui_fg_color, set_dialog_color.
Examples using this: exgui.
You can change the global 'font' pointer to make the GUI objects use something other than the standard 8x8 font. The standard dialog procedures, menus, and alert boxes, will work with fonts of any size, but the gfx_mode_select() dialog will look wrong with anything other than 8x8 fonts.
See also: gui_strlen.
See also: gui_textout_ex.
BITMAP *page[2]; /* Allocate two pages of video memory */ page[0] = create_video_bitmap(SCREEN_W, SCREEN_H); page[1] = create_video_bitmap(SCREEN_W, SCREEN_H); /* Page flip */ show_video_bitmap(page[0]); gui_set_screen(page[0]);
See also: gui_get_screen.
See also: gui_set_screen.
See also: centre_dialog.
Examples using this: exgui.
See also: position_dialog, set_dialog_color.
See also: gui_fg_color, gui_mg_color, centre_dialog.
Examples using this: exgui.
See also: do_dialog, init_dialog, offer_focus.
See also: find_dialog_focus.
The function will take care of scaring and unscaring the mouse if the message is MSG_DRAW.object_message(&dialog[1], MSG_DRAW, 0);
See also: dialog_message, scare_mouse, scare_mouse_area, unscare_mouse.
Examples using this: excustom, exrgbhsv.
See also: object_message, broadcast_dialog_message.
See also: dialog_message, active_dialog.
See also: popup_dialog, init_dialog, centre_dialog, set_dialog_color, find_dialog_focus.
Examples using this: excustom, exgui, exrgbhsv.
See also: do_dialog.
DIALOG_PLAYER *player = init_dialog(dialog, focus_obj); while (update_dialog(player)) ; return shutdown_dialog(player);
Note that you are responsible for showing and hiding the mouse cursor, which do_dialog would otherwise do for you, or saving and restoring the screen contents, as popup_dialog would do for you.
See also: update_dialog, shutdown_dialog, do_dialog.
See also: init_dialog.
See also: init_dialog.
See also: do_dialog, init_dialog, broadcast_dialog_message.
Popup or pulldown menus are created as an array of MENU structures. Read chapter "Structures and types defined by Allegro" for an internal description of the MENU structure.
Each menu item contains a text string. This can use the '&' character to indicate keyboard shortcuts, or can be an zero-length string to display the item as a non-selectable splitter bar. If the string contains a "\t" tab character, any text after this will be right-justified, eg. for displaying keyboard shortcut information. The proc pointer is a function which will be called when the menu item is selected, and child points to another menu, allowing you to create nested menus. Both proc and child may be NULL. The proc function returns an integer which is ignored if the menu was brought up by calling do_menu(), but which is passed back to the dialog manager if it was created by a d_menu_proc() object. The array of menu items is terminated by an entry with a NULL text pointer.
Menu items can be disabled (greyed-out) by setting the D_DISABLED bit in the flags field, and a check mark can be displayed next to them by setting the D_SELECTED bit. With the default alignment and font this will usually overlap the menu text, so if you are going to use checked menu items it would be a good idea to prefix all your options with a space or two, to ensure there is room for the check.
See also: do_menu, d_menu_proc, gui_menu_draw_menu.
See also: GUI menus, d_menu_proc, active_menu, gui_menu_draw_menu, update_menu.
MENU_PLAYER *player = init_menu(menu, x, y); while (update_menu(player)) ; return shutdown_menu(player);
See also: update_menu, shutdown_menu, do_menu.
See also: init_menu, shutdown_menu, do_menu.
See also: init_menu, update_menu.
See also: GUI menus.
Examples using this: exgui.
gui_menu_draw_menu() is passed the position and size of the menu. It should draw the background of the menu onto screen.
gui_menu_draw_menu_item() is called once for each menu item that is to be drawn. bar will be set if the item is part of a top-level horizontal menu bar, and sel will be set if the menu item is selected. It should also draw onto screen.
See also: GUI menus.
if (!exists(CONFIG_FILE)) alert(CONFIG_FILE, "not found.", "Using defaults.", "&Continue", NULL, 'c', 0);
Return value: Returns 1 or 2 depending on which button was clicked. If the alert is dismissed by pressing ESC when ESC is not one of the keyboard shortcuts, it treats it as a click on the second button (this is consistent with the common "Ok", "Cancel" alert).
See also: alert3, gui_fg_color.
Examples using this: exgui, expackf, exspline.
See also: alert, gui_fg_color.
See also: gui_fg_color.
The initial values of card, w, h are not used.
See also: gfx_mode_select_ex, gfx_mode_select_filter, set_gfx_mode, gui_fg_color.
This version of the function reads the initial values from the parameters when it activates so you can specify the default values. In fact, you should be sure not to pass in uninitialised values.
See also: gfx_mode_select, gfx_mode_select_filter, set_color_depth, set_gfx_mode, gui_fg_color.
Examples using this: ex3d, exscn3d, exswitch, exupdate, exzbuf.
This version of the function reads the initial values from the parameters when it activates so you can specify the default values. In fact, you should be sure not to pass in uninitialised values.
See also: gfx_mode_select, gfx_mode_select_ex, set_color_depth, set_gfx_mode, gui_fg_color.
See also: alert, alert3, file_select_ex, gfx_mode_select, gui_fg_color.
There are four Allegro files which you should redistribute along your program. These are the files `keyboard.dat', `language.dat', `allegro.cfg' and `setup.exe'.
The first two contain internationalisation information for keyboard mappings and system messages to show up localised on the user's computer. The `setup.exe' program, which comes in Allegro's `setup' directory, is a standalone tool which you can graphically customise and even embed into your main binary. The user can generate a configuration file with this tool, to store special settings or avoid Allegro's autodetection failing on specific hardware. Even if you distribute `setup.exe', you are recommended to copy too the empty `allegro.cfg' file, in case the setup program itself is unable to run and the user has to edit manually the configuration with a text editor.
If you are using get_config_text() in your program to localise text strings, merge your xxtext.cfg files with the ones provided by Allegro in the `resource' directory before creating `language.dat', and redistribute this with your program. This file will contain then both Allegro's system messages and the strings of your program.
See also: install_joystick.
Triple buffering is only possible with certain drivers: it will work in any DOS mode-X resolution if the timer retrace simulator is active (but this doesn't work correctly under Windows 95), plus it is supported by the VBE 3.0 and VBE/AF drivers for a limited number graphics cards.
See also: set_gfx_mode.
DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_SB - Sound Blaster (autodetect type) DIGI_SB10 - SB 1.0 (8-bit mono single shot DMA) DIGI_SB15 - SB 1.5 (8-bit mono single shot DMA) DIGI_SB20 - SB 2.0 (8-bit mono auto-initialised DMA) DIGI_SBPRO - SB Pro (8-bit stereo) DIGI_SB16 - SB16 (16-bit stereo) DIGI_AUDIODRIVE - ESS AudioDrive DIGI_SOUNDSCAPE - Ensoniq Soundscape DIGI_WINSOUNDSYS - Windows Sound System
See also: detect_digi_driver, install_sound, install_sound_input.
MIDI_AUTODETECT - let Allegro pick a MIDI sound driver MIDI_NONE - no MIDI sound MIDI_ADLIB - Adlib or SB FM synth (autodetect type) MIDI_OPL2 - OPL2 synth (mono, used in Adlib and SB) MIDI_2XOPL2 - dual OPL2 synths (stereo, used in SB Pro-I) MIDI_OPL3 - OPL3 synth (stereo, SB Pro-II and above) MIDI_SB_OUT - SB MIDI interface MIDI_MPU - MPU-401 MIDI interface MIDI_DIGMID - sample-based software wavetable player MIDI_AWE32 - AWE32 (EMU8000 chip)
See also: detect_midi_driver, install_sound, install_sound_input.
See also: install_timer, allegro_init, os_type.
In terms of file redistribution, the Windows platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this.
A Windows program that uses the Allegro library is only required to include one or more header files from the include/allegro tree, or allegro.h; however, if it also needs to directly call non portable Win32 API functions, it must include the Windows-specific header file winalleg.h after the Allegro headers, and before any Win32 API header file. By default winalleg.h includes the main Win32 C API header file windows.h. If instead you want to use the C++ interface to the Win32 API (a.k.a. the Microsoft Foundation Classes), define the preprocessor symbol ALLEGRO_AND_MFC before including any Allegro header so that afxwin.h will be included. Note that, in this latter case, the Allegro debugging macros ASSERT() and TRACE() are renamed AL_ASSERT() and AL_TRACE() respectively.
Windows GUI applications start with a WinMain() entry point, rather than the standard main() entry point. Allegro is configured to build GUI applications by default and to do some magic in order to make a regular main() work with them, but you have to help it out a bit by writing END_OF_MAIN() right after your main() function. If you don't want to do that, you can just include winalleg.h and write a WinMain() function. Note that this magic may bring about conflicts with a few programs using direct calls to Win32 API functions; for these programs, the regular WinMain() is required and the magic must be disabled by defining the preprocessor symbol ALLEGRO_NO_MAGIC_MAIN before including Allegro headers.
If you want to build a console application using Allegro, you have to define the preprocessor symbol ALLEGRO_USE_CONSOLE before including Allegro headers; it will instruct the library to use console features and also to disable the special processing of the main() function described above.
When creating the main window, Allegro searches the executable for an ICON resource named "allegro_icon". If it is present, Allegro automatically loads it and uses it as its application icon; otherwise, Allegro uses the default IDI_APPLICATION icon. See the manual of your compiler for a method to create an ICON resource, or use the wfixicon utility from the tools/win directory.
DirectX requires that system and video bitmaps (including the screen) be locked before you can draw onto them. This will be done automatically, but you can usually get much better performance by doing it yourself: see the acquire_bitmap() function for details.
Due to a major oversight in the design of DirectX, there is no way to preserve the contents of video memory when the user switches away from your program. You need to be prepared for the fact that your screen contents, and the contents of any video memory bitmaps, may be destroyed at any point. You can use the set_display_switch_callback() function to find out when this happens.
On the Windows platform, the only return values for the desktop_color_depth() function are 8, 16, 24 and 32. This means that 15-bit and 16-bit desktops cannot be differentiated and are both reported as 16-bit desktops. See below for the consequences for windowed and overlay DirectX drivers.
See also: install_joystick.
Note that, mainly for performance reasons, this driver requires the width of the screen to be a multiple of 4. This driver is capable of displaying a hardware cursor, but there are size restrictions. Typically, the cursor image cannot be more than 32x32 pixels.if (desktop_color_depth() == 16) { set_color_depth(16); if (set_gfx_mode(GFX_DIRECTX_WIN, 640, 480, 0, 0) != 0) { set_color_depth(15); if (set_gfx_mode(GFX_DIRECTX_WIN, 640, 480, 0, 0) != 0) { /* 640x480 direct drawing mode not supported */ goto Error; } } /* ok, we are in direct drawing mode */ }
if (desktop_color_depth() == 16) { set_color_depth(16); if (set_gfx_mode(GFX_DIRECTX_OVL, 640, 480, 0, 0) != 0) { set_color_depth(15); if (set_gfx_mode(GFX_DIRECTX_OVL, 640, 480, 0, 0) != 0) { /* 640x480 overlay driver not supported */ goto Error; } } /* ok, the 640x480 overlay driver is running */ }
See also: set_gfx_mode.
DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_DIRECTX(n) - use DirectSound device #n (zero-based) with direct mixing DIGI_DIRECTAMX(n) - use DirectSound device #n (zero-based) with Allegro mixing DIGI_WAVOUTID(n) - high (n=0) or low (n=1) quality WaveOut device
See also: detect_digi_driver, install_sound, install_sound_input.
MIDI_AUTODETECT - let Allegro pick a MIDI sound driver MIDI_NONE - no MIDI sound MIDI_WIN32MAPPER - use win32 MIDI mapper MIDI_WIN32(n) - use win32 device #n (zero-based) MIDI_DIGMID - sample-based software wavetable player
See also: detect_midi_driver, install_sound, install_sound_input.
The following functions provide a platform specific interface to seamlessly integrate Allegro into general purpose Win32 programs. To use these routines, you must include winalleg.h after other Allegro headers.
However you can also call it after the library has been initialised, provided that no graphics mode is set. In this case the keyboard, mouse, joystick, sound and sound recording modules will be restarted.
Passing NULL instructs Allegro to switch back to its built-in window if an user-created window was registered, or to request a new handle from Windows for its built-in window if this was already in use.
The following GDI routines are a very platform specific thing, to allow drawing Allegro memory bitmaps onto a Windows device context. When you want to use this, you'll have to install the neutral system driver (SYSTEM_NONE) or attach Allegro to an external window with win_set_window().
There are two ways to draw your Allegro bitmaps to the Windows GDI. When you are using static bitmaps (for example just some pictures loaded from a datafile), you can convert them to DDB (device-dependent bitmaps) with convert_bitmap_to_hbitmap() and then just use Win32's BitBlt() to draw it.
When you are using dynamic bitmaps (for example some things which react to user input), it's better to use set_palette_to_hdc() and blit_to_hdc() functions, which work with DIB (device-independent bitmaps).
There are also functions to blit from a device context into an Allegro BITMAP, so you can do things like screen capture.
All the drawing and conversion functions use the current palette as a color conversion table. You can alter the current palette with the set_palette_to_hdc() or select_palette() functions. Warning: when the GDI system color palette is explicitly changed, (by another application, for example) the current Allegro palette is not updated along with it!
To use these routines, you must include winalleg.h after Allegro headers.
See also: convert_hpalette_to_palette.
See also: convert_palette_to_hpalette.
See also: convert_hbitmap_to_bitmap.
See also: convert_bitmap_to_hbitmap.
See also: blit_to_hdc, stretch_blit_to_hdc, draw_sprite.
See also: draw_to_hdc, stretch_blit_to_hdc, blit_from_hdc, blit.
See also: draw_to_hdc, blit_to_hdc, stretch_blit_from_hdc, stretch_blit.
See also: stretch_blit_from_hdc, blit_to_hdc, blit.
See also: blit_from_hdc, stretch_blit_to_hdc, stretch_blit.
Under Unix you usually have two ways of redistributing your binaries. You either pack everything in a single directory, even providing Allegro in binary or source form for the user to compile. Or your program is being packaged separately from Allegro and stored in different paths. For the first case of redistribution, read section "Files shared by Allegro" from the "Dos specifics" chapter to learn more about this.
For the second type, you can ignore redistributing the setup, keyboard mappings and language datafiles, because they will be already installed in the system. This, however, is problematic if you are using get_config_text() to localise your program's text strings.
The problem is that on other platforms you usually mix your program's text strings with those of Allegro (found in the `resources' directory) to create a special language.dat. And it is likely that the Allegro library installed on the user's system already contains a datafile.dat. You can go ahead and still provide your own language.dat file, but this will mean that if Allegro is updated, your language.dat file may not contain all the text strings used by the new version.
Given the slow paced release cycle of Allegro, this might not be a concern. However, if you want to make it easy on system administrators, instead of providing your own `language.dat', you should provide the separate `xxtext.cfg' files it in a separate directory. Then, before showing the strings to the user you can detect the language setting and use override_config_file() with the appropriate localisation file and call reload_config_texts().
In order to locate things like the config and translation files, Allegro needs to know the path to your executable. Since there is no standard way to find that, it needs to capture a copy of your argv[] parameter, and it does this with some preprocessor macro trickery. Unfortunately it can't quite pull this off without a little bit of your help, so you will have to write END_OF_MAIN() right after your main() function. Pretty easy, really, and if you forget, you'll get a nice linker error about a missing _mangled_main function to remind you :-)
Under Unix resources are searched for in many different paths (see above). When a configuration resource is looked for, it is usually tried with the variations `name.cfg' or `.namerc' in multiple paths: the current directory, the directory pointed to by the ALLEGRO environment variable, the user's home directory, one or more global system directories which usually only the root user has access to and any custom paths set up with set_allegro_resource_path(). Text files, like the main allegro config file or a language text translation files are looked for in the following places:
Binary resources like the language translation files packfile (language.dat) are looked for in:./allegro.cfg $ALLEGRO/allegro.cfg ~/allegro.cfg ~/.allegrorc /etc/allegro.cfg /etc/allegrorc
Note that if you have installed Allegro from the source distribution with the typical `make install', global files like `language.dat' and `allegro.cfg' will not have been installed. As a system administrator you are required to install them manually wherever you prefer to have them. If you suspect that an Allegro program is somehow not finding the correct configuration file, you could try using the following command:./language.dat $ALLEGRO/language.dat ~/language.dat /etc/language.dat /usr/share/allegro/language.dat /usr/local/share/allegro/language.dat
The strace program traces system calls and signals. By default it outputs the information to stderr, so that's why we redirect it to stdin with `2>&1'. Since we are interested only in files being (un)successfully opened, we restrict the output of the log to stat or open calls with the extended grep command. You could add another grep to filter only lines with text like `language' or `allegro'.strace program 2>&1|egrep "(open|stat)"
See also: install_joystick.
See also: set_gfx_mode, GFX_*/X.
See also: set_gfx_mode, GFX_*/Linux.
DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_OSS - Open Sound System DIGI_ESD - Enlightened Sound Daemon DIGI_ARTS - aRts (Analog Real-Time Synthesizer) DIGI_ALSA - ALSA sound driver DIGI_JACK - JACK sound driver
See also: detect_digi_driver, install_sound, install_sound_input.
MIDI_AUTODETECT - let Allegro pick a MIDI sound driver MIDI_NONE - no MIDI sound MIDI_OSS - Open Sound System MIDI_DIGMID - sample-based software wavetable player MIDI_ALSA - ALSA RawMIDI driver
See also: detect_midi_driver, install_sound, install_sound_input.
See also: set_window_title.
In terms of file redistribution, the BeOS platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this.
See also: set_gfx_mode.
DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_BEOS - BeOS digital output
See also: detect_digi_driver, install_sound, install_sound_input.
MIDI_AUTODETECT - let Allegro pick a MIDI sound driver MIDI_NONE - no MIDI sound MIDI_BEOS - BeOS MIDI output MIDI_DIGMID - sample-based software wavetable player
See also: detect_midi_driver, install_sound, install_sound_input.
In terms of file redistribution, the QNX platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this.
See also: set_gfx_mode.
DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_ALSA - ALSA sound driver
See also: detect_digi_driver, install_sound, install_sound_input.
MIDI_AUTODETECT - let Allegro pick a MIDI sound driver MIDI_NONE - no MIDI sound MIDI_ALSA - ALSA RawMIDI driver MIDI_DIGMID - sample-based software wavetable player
See also: detect_midi_driver, install_sound, install_sound_input.
The following functions provide a platform specific interface to seamlessly integrate Allegro into general purpose QNX programs. To use these routines, you must include qnxalleg.h after other Allegro headers.
In terms of file redistribution, the MacOS X platform behaves practically the same as the DOS platform. Read section chapter "Dos specifics" in the manual to learn more about this.
Allegro programs under MacOS X are Cocoa applications; in order to hide all the Cocoa interfacing to the end-user, you need to add the END_OF_MAIN() macro right after your main() function. This is a necessary step: if you omit it, your program will not compile.
The END_OF_MAIN() macro simply does some magic to make sure your program executes another function before your main(); this function is defined into the liballeg-main.a static library, which is automatically linked if you use the allegro-config script when linking. Otherwise be sure you link against it unless you want to get undefined symbol errors.
To behave nicely with the MacOS X user interface, Allegro apps will provide a standard application menu with the "Quit" menu item in it. The default behaviour when the user hits Command-Q or selects "Quit" is to do nothing. To override this behaviour you must call the set_close_button_callback() function; under MacOS X the supplied callback will be used either if the user clicks the window close button either on Command-Q or "Quit" selection. In this last case the application will not shutdown, but you are supposed to set some quit flag in your callback and check for it on a regular basis in your main program loop.
If you would like to use InterfaceBuilder to design a more fully-featured menu, Allegro will automatically load it if you create a bundle for your application. The use of InterfaceBuilder is beyond the scope of this document. Briefly, you need to create a Nib, called MainMenu.nib, containing a main menu and a controller. Then, when you create the bundle, install MainMenu.nib into the Contents/Resources subdirectory. Note that the actions attached to the menu items will be called from a different thread than the one in which your Allegro code is running. Therefore you should not do any work there (especially, don't call Allegro functions.) Instead, set a variable, and test it in your main loop.
See also: set_gfx_mode.
DIGI_AUTODETECT - let Allegro pick a digital sound driver DIGI_NONE - no digital sound DIGI_CORE_AUDIO - CoreAudio digital output (OS >= X.2 required) DIGI_SOUND_MANAGER - Carbon Sound Manager digital output
See also: detect_digi_driver, install_sound, install_sound_input.
MIDI_AUTODETECT - let Allegro pick a MIDI sound driver MIDI_NONE - no MIDI sound MIDI_CORE_AUDIO - CoreAudio MIDI synthesizer (OS >= X.2 required) MIDI_QUICKTIME - QuickTime Music Note Allocator MIDI output MIDI_DIGMID - sample-based software wavetable player
See also: detect_midi_driver, install_sound, install_sound_input.
Here's a quick summary of things that may cause problems when moving your code from one platform to another (you can find a more detailed version of this in the docs section of the Allegro website).
The Windows, Unix and MacOS X versions require you to write END_OF_MAIN() after your main() function. This is used to magically turn an ISO C style main() into a Windows style WinMain(), or by the Unix code to grab a copy of your argv[] parameter, or by the MacOS X code to shell the user main() inside a Cocoa application.
On many platforms Allegro runs very slowly if you rely on it in order to automatically lock bitmaps when drawing onto them. For good performance, you need to call acquire_bitmap() and release_bitmap() yourself, and try to keep the amount of locking to a minimum.
The Windows version may lose the contents of video memory if the user switches away from your program, so you need to deal with that.
None of the currently supported platforms require input polling, but it is possible that some future ones might, so if you want to ensure 100% portability of your program, you should call poll_mouse() and poll_keyboard() in all the relevant places.
On Unix the shared files by Allegro (like `language.dat') may require a special use due to the nature of distributing the resources in separate paths instead of putting everything in the same directory. Check the beginning of your platform's specific chapter to learn more about this.
Allegro defines a number of standard macros that can be used to check various attributes of the current platform:
ALLEGRO_PLATFORM_STR
Text string containing the name of the current platform.
ALLEGRO_DOS
ALLEGRO_DJGPP
ALLEGRO_WATCOM
ALLEGRO_WINDOWS
ALLEGRO_MSVC
ALLEGRO_MINGW32
ALLEGRO_BCC32
ALLEGRO_UNIX
ALLEGRO_LINUX
ALLEGRO_BEOS
ALLEGRO_QNX
ALLEGRO_DARWIN
ALLEGRO_MACOSX
ALLEGRO_GCC
Defined if you are building for a relevant system. Often several of these
will apply, eg. DOS+Watcom, or Windows+GCC+MinGW.
Note that ALLEGRO_LINUX is a misnomer. It will only be defined if Linux console support is enabled. It is not a reliable way to check if the program is being built on a Linux system.
ALLEGRO_AMD64
ALLEGRO_I386
ALLEGRO_BIG_ENDIAN
ALLEGRO_LITTLE_ENDIAN
Defined if you are building for a processor of the relevant type.
ALLEGRO_MULTITHREADED
Defined if the library is internally multi-threaded on this system.
ALLEGRO_USE_CONSTRUCTOR
Defined if the compiler supports constructor/destructor functions.
ALLEGRO_VRAM_SINGLE_SURFACE
Defined if the screen is a single large surface that is then partitioned
into multiple video sub-bitmaps (eg. DOS), rather than each video bitmap
being a totally unique entity (eg. Windows).
ALLEGRO_CONSOLE_OK
Defined if when you are not in a graphics mode, there is a text mode
console that you can printf() to, and from which the user could
potentially redirect stdout to capture it even while you are in a
graphics mode. If this define is absent, you are running in an
environment like Windows that has no stdout at all.
ALLEGRO_MAGIC_MAIN
Defined if Allegro uses a magic main, i.e takes over the main() entry
point and turns it into a secondary entry point suited to its needs.
ALLEGRO_LFN
Non-zero if long filenames are supported, or zero if you are limited to
8.3 format (in the DJGPP version, this is a variable depending on the
runtime environment).
LONG_LONG
Defined to whatever represents a 64-bit "long long" integer for the
current compiler, or not defined if that isn't supported.
OTHER_PATH_SEPARATOR
Defined to a path separator character other than a forward slash for
platforms that use one (eg. a backslash under DOS and Windows), or
defined to a forward slash if there is no other separator character.
DEVICE_SEPARATOR
Defined to the filename device separator character (a colon for DOS and
Windows), or to zero if there are no explicit devices in paths (Unix).
Allegro can be customized at compile time to a certain extent with the following macros:
ALLEGRO_NO_MAGIC_MAIN
If you define this prior to including Allegro headers, Allegro won't
touch the main() entry point. This effectively removes the requirement
on a program to be linked against the Allegro library when it includes
the allegro.h header file. Note that the configuration and file routines
are not guaranteed to work on Unix systems when this symbol is defined.
Moreover, on Darwin/MacOS X systems, this symbol simply prevents the
program from being linked against the Allegro library! This highly non
portable feature is primarily intended to be used under Windows.
ALLEGRO_USE_CONSOLE
If you define this prior to including Allegro headers, Allegro will be
set up for building a console application rather than the default GUI
program on some platforms (especially Windows).
ALLEGRO_NO_STD_HEADER
If you define this prior to including Allegro headers, Allegro will not
automatically include some standard headers (eg <stddef.h>) its own
headers depend upon.
ALLEGRO_NO_KEY_DEFINES
If you define this prior to including Allegro headers, Allegro will omit
the definition of the KEY_* constants, which may clash with other headers.
ALLEGRO_NO_FIX_ALIASES
The fixed point functions used to be named with an "f" prefix instead of
"fix", eg. fixsqrt() used to be fsqrt(), but were renamed due to conflicts
with some libc implementations. So backwards compatibility aliases are
provided as static inline functions which map the old names to the new
names, eg. fsqrt() calls fixsqrt(). If you define this symbol prior to
including Allegro headers, the aliases will be turned off.
ALLEGRO_NO_FIX_CLASS
If you define this symbol prior to including Allegro headers in a C++
source file, the 'fix' class will not be made available. This mitigates
problems with the 'fix' class's overloading getting in the way.
ALLEGRO_NO_VHLINE_ALIAS
The `curses' API also defines functions called vline() and hline().
To avoid a linker conflict when both libraries are used, we have
internally renamed our functions and added inline function aliases which
remap vline() and hline(). This should not be noticeable to most users.
If you define ALLEGRO_NO_VHLINE_ALIAS prior to including Allegro headers, Allegro will not define the vline() and hline() aliases, e.g. so you can include curses.h and allegro.h in the same module.
ALLEGRO_NO_CLEAR_BITMAP_ALIAS
If you define this prior to including Allegro headers, Allegro will not
define the clear() backwards compatibility alias to clear_bitmap().
ALLEGRO_NO_COMPATIBILITY
If you define this prior to including Allegro headers, Allegro will not
include the backward compatibility layer. It is undefined by default so
old programs can still be compiled with the minimum amount of issues,
but you should define this symbol if you intend to maintain your code
up to date with the latest versions of Allegro. It automatically turns
off all backwards compatibility aliases.
Allegro also defines a number of standard macros that can be used to insulate you from some of the differences between systems:
INLINE
Use this in place of the regular "inline" function modifier keyword, and
your code will work correctly on any of the supported compilers.
RET_VOLATILE
Use this to declare a function with a volatile return value.
ZERO_SIZE_ARRAY(type, name)
Use this to declare zero-sized arrays in terminal position inside
structures, like in the BITMAP structure. These arrays are effectively
equivalent to the flexible array members of ISO C99.
AL_CONST
Use this in place of the regular "const" object modifier keyword, and
your code will work correctly on any of the supported compilers.
AL_RAND()
On platforms that require it, this macro does a simple shift
transformation of the libc rand() function, in order to improve the
perceived randomness of the output series in the lower 16 bits.
Where not required, it directly translates into a rand() call.
Some people complain that Allegro produces very large executables. This is certainly true: with the DJGPP version, a simple "hello world" program will be about 200k, although the per-executable overhead is much less for platforms that support dynamic linking. But don't worry, Allegro takes up a relatively fixed amount of space, and won't increase as your program gets larger. As George Foot so succinctly put it, anyone who is concerned about the ratio between library and program code should just get to work and write more program code to catch up :-)
Having said that, there are several things you can do to make your programs smaller:
where the driver names are any of the defines:BEGIN_GFX_DRIVER_LIST driver1 driver2 etc... END_GFX_DRIVER_LIST
This construct must be included in only one of your C source files. The ordering of the names is important, because the autodetection routine works down from the top of the list until it finds the first driver that is able to support the requested mode. I suggest you stick to the default ordering given above, and simply delete whatever entries you aren't going to use.GFX_DRIVER_VBEAF GFX_DRIVER_VGA GFX_DRIVER_MODEX GFX_DRIVER_VESA3 GFX_DRIVER_VESA2L GFX_DRIVER_VESA2B GFX_DRIVER_XTENDED GFX_DRIVER_VESA1
where the color depth names are any of the defines:BEGIN_COLOR_DEPTH_LIST depth1 depth2 etc... END_COLOR_DEPTH_LIST
Removing any of the color depths will save quite a bit of space, with the exception of the 15 and 16-bit modes: these share a great deal of code, so if you are including one of them, there is no reason not to use both. Be warned that if you try to use a color depth which isn't in this list, your program will crash horribly!COLOR_DEPTH_8 COLOR_DEPTH_15 COLOR_DEPTH_16 COLOR_DEPTH_24 COLOR_DEPTH_32
using the digital sound driver defines:BEGIN_DIGI_DRIVER_LIST driver1 driver2 etc... END_DIGI_DRIVER_LIST
and for the MIDI music:DIGI_DRIVER_SOUNDSCAPE DIGI_DRIVER_AUDIODRIVE DIGI_DRIVER_WINSOUNDSYS DIGI_DRIVER_SB
using the MIDI driver defines:BEGIN_MIDI_DRIVER_LIST driver1 driver2 etc... END_MIDI_DRIVER_LIST
If you are going to use either of these sound driver constructs, you must include both.MIDI_DRIVER_AWE32 MIDI_DRIVER_DIGMID MIDI_DRIVER_ADLIB MIDI_DRIVER_MPU MIDI_DRIVER_SB_OUT
using the joystick driver defines:BEGIN_JOYSTICK_DRIVER_LIST driver1 driver2 etc... END_JOYSTICK_DRIVER_LIST
The standard driver includes support for the dual joysticks, increased numbers of buttons, Flightstick Pro, and Wingman Extreme, because these are all quite minor variations on the basic code.JOYSTICK_DRIVER_WINGWARRIOR JOYSTICK_DRIVER_SIDEWINDER JOYSTICK_DRIVER_GAMEPAD_PRO JOYSTICK_DRIVER_GRIP JOYSTICK_DRIVER_STANDARD JOYSTICK_DRIVER_SNESPAD JOYSTICK_DRIVER_PSXPAD JOYSTICK_DRIVER_N64PAD JOYSTICK_DRIVER_DB9 JOYSTICK_DRIVER_TURBOGRAFX JOYSTICK_DRIVER_IFSEGA_ISA JOYSTICK_DRIVER_IFSEGA_PCI JOYSTICK_DRIVER_IFSEGA_PCI_FAST
If you comment out any of these definitions and then rebuild the library, you will get a version without any support for the absent color depths, which will be even smaller than using the DECLARE_COLOR_DEPTH_LIST() macro. Removing the ALLEGRO_COLOR16 define will get rid of the support for both 15 and 16-bit hicolor modes, since these share a lot of the same code.#define ALLEGRO_COLOR8 #define ALLEGRO_COLOR16 #define ALLEGRO_COLOR24 #define ALLEGRO_COLOR32
If you are distributing a copy of the setup program along with your game, you may be able to get a dramatic size reduction by merging the setup code into your main program, so that only one copy of the Allegro routines will need to be linked. See setup.txt for details. In the DJGPP version, after compressing the executable, this will probably save you about 200k compared to having two separate programs for the setup and the game itself.
There are three versions of the Allegro library: the normal optimised code, one with extra debugging support, and a profiling version. See the platform specific readme files for information about how to install and link with these alternative libs. Although you will obviously want to use the optimised library for the final version of your program, it can be very useful to link with the debug lib while you are working on it, because this will make debugging much easier, and includes assert tests that will help to locate errors in your code at an earlier stage. Allegro also contains some debugging helper functions:
#define DEBUGMODE #include... void my_blitter(BITMAP *source, int flags) { int some_variables; ASSERT(source != NULL); ASSERT(flags & GAME_RUNNING); ... }
See also: al_assert, TRACE, register_assert_handler.
Examples using this: expackf.
#define DEBUGMODE #include... void my_blitter(BITMAP *source, int flags) { static int count_call = 0; TRACE("my_blitter() called %d times.\n", count_call++); ... }
See also: al_trace, ASSERT, register_trace_handler.
int show_but_continue(const char *text) { alert("Uh oh...", "Fasten your seat belts.", text, "&Go on!", NULL, 'g', 0); return 1; } ... register_assert(show_but_continue); ASSERT(0); /* This won't crash the program now. */
See also: al_assert, ASSERT, register_trace_handler.
int network_broadcaster(const char *text) { int f; for (int f = 0; f < connected_clients; f++) send_msg_to_client(client[f], text); return 0; /* Let normal tracing occur. */ } ... register_trace_handler(network_broadcaster); TRACE("Networked tracing activated\n");
See also: al_trace, TRACE, register_assert_handler.
You will usually want to use the ASSERT() macro instead of calling this function directly.
See also: ASSERT, al_trace, register_assert_handler.
See also: TRACE, al_assert, register_trace_handler.
There are a number of options that you can use to control exactly how Allegro will be compiled. On Unix platforms, you do this by passing arguments to the configure script (run "configure --help" for a list), but on other platforms you can set the following environment variables:
With Allegro comes quite a bunch of examples, which go from the simple introductory `Hello world' to more complicated programs featuring truecolor blending effects. This chapter describes these examples which you can find in the allegro/examples folder. You don't have to go through them in the same order as this documentation, but doing so you will learn the basic functions and avoid missing any important bit of information.
See also: END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, clear_to_color, desktop_palette, font, install_keyboard, key, makecol, readkey, release_screen, screen, set_gfx_mode, set_palette, textout_centre_ex.
See also: BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, blit, circle, clear_bitmap, create_bitmap, desktop_palette, destroy_bitmap, install_keyboard, palette_color, readkey, release_screen, screen, set_gfx_mode, set_palette.
See also: END_OF_MAIN, PALETTE, RGB, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, black_palette, circlefill, install_keyboard, install_mouse, keypressed, release_screen, screen, set_gfx_mode, set_palette, show_mouse.
See also: BITMAP, END_OF_MAIN, acquire_bitmap, allegro_error, allegro_init, allegro_message, bitmap_mask_color, blit, clear_to_color, create_bitmap, create_sub_bitmap, desktop_palette, destroy_bitmap, drawing_mode, font, install_keyboard, makecol, masked_blit, palette_color, readkey, rectfill, release_bitmap, screen, set_gfx_mode, set_palette, solid_mode, text_height, text_length, textout_ex.
See also: END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, bmp_read_line, bmp_unwrite_line, bmp_write_line, clear_keybuf, font, getpixel, install_keyboard, keypressed, line, makecol, putpixel, release_screen, screen, set_gfx_mode, set_palette, textout_ex.
See also: BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, blit, circlefill, clear_keybuf, clear_to_color, create_bitmap, desktop_palette, destroy_bitmap, font, install_keyboard, install_timer, keypressed, makecol, release_screen, retrace_count, screen, set_gfx_mode, set_palette, textprintf_ex.
See also: BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, circlefill, clear_keybuf, clear_to_color, create_bitmap, create_video_bitmap, desktop_palette, destroy_bitmap, font, install_keyboard, install_timer, keypressed, makecol, retrace_count, screen, set_gfx_mode, set_palette, show_video_bitmap, textprintf_ex.
See also: END_OF_MAIN, allegro_init, allegro_message, fixdiv, fixed, fixmul, fixsqrt, fixtof, ftofix, itofix.
See also: END_OF_MAIN, FONT, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, clear_to_color, desktop_palette, destroy_font, extract_font_range, font, install_keyboard, key, load_font, makecol, merge_fonts, readkey, release_screen, screen, set_gfx_mode, set_palette, textout_centre_ex.
See also: BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, bitmap_mask_color, circle, clear_keybuf, clear_to_color, create_bitmap, desktop_palette, destroy_bitmap, font, get_mouse_mickeys, install_keyboard, install_mouse, install_timer, key, keypressed, makecol, mouse_b, mouse_w, mouse_x, mouse_y, mouse_z, palette_color, poll_mouse, readkey, release_screen, screen, set_gfx_mode, set_mouse_sprite, set_mouse_sprite_focus, set_palette, show_mouse, textout_centre_ex, textout_ex, textprintf_centre_ex, textprintf_ex, textprintf_right_ex, vsync.
See also: END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE, SCREEN_W, allegro_error, allegro_init, allegro_message, clear_to_color, desktop_palette, font, install_int, install_int_ex, install_keyboard, install_timer, key, keypressed, makecol, readkey, rest, screen, set_gfx_mode, set_palette, textprintf_centre_ex.
See also: END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, SCREEN_H, SCREEN_W, acquire_screen, allegro_error, allegro_init, allegro_message, blit, clear_keybuf, clear_to_color, desktop_palette, font, install_keyboard, install_timer, key, key_shifts, keyboard_lowlevel_callback, keypressed, makecol, readkey, rectfill, release_screen, rest, scancode_to_name, screen, set_gfx_mode, set_palette, textprintf_centre_ex, textprintf_ex, ureadkey, usprintf, ustrzncpy.
See also: BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, calibrate_joystick, calibrate_joystick_name, circle, clear_bitmap, clear_keybuf, create_bitmap, default_palette, destroy_bitmap, drawing_mode, font, install_joystick, install_keyboard, joy, key, keypressed, num_joysticks, palette_color, poll_joystick, putpixel, readkey, screen, set_gfx_mode, set_palette, textout_centre_ex, textprintf_centre_ex, textprintf_ex.
See also: END_OF_MAIN, SAMPLE, SCREEN_H, SCREEN_W, adjust_sample, allegro_error, allegro_init, allegro_message, clear_to_color, desktop_palette, destroy_sample, font, install_keyboard, install_sound, install_timer, key, load_sample, makecol, play_sample, poll_keyboard, rest, screen, set_gfx_mode, set_palette, textprintf_centre_ex.
See also: END_OF_MAIN, MIDI, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, clear_to_color, desktop_palette, destroy_midi, font, get_filename, get_midi_length, install_keyboard, install_sound, install_timer, key, keypressed, load_midi, makecol, midi_pause, midi_pos, midi_resume, midi_time, play_midi, readkey, rectfill, rest, screen, set_display_switch_mode, set_gfx_mode, set_palette, text_height, text_length, textprintf_centre_ex.
See also: DATAFILE, DIALOG, END_OF_MAIN, MENU, active_menu, alert, allegro_error, allegro_init, allegro_message, d_bitmap_proc, d_box_proc, d_button_proc, d_check_proc, d_clear_proc, d_ctext_proc, d_edit_proc, d_icon_proc, d_keyboard_proc, d_list_proc, d_menu_proc, d_radio_proc, d_rtext_proc, d_shadow_box_proc, d_slider_proc, d_text_list_proc, d_text_proc, d_textbox_proc, d_yield_proc, do_dialog, gui_bg_color, gui_fg_color, gui_mg_color, install_keyboard, install_mouse, install_timer, key, load_datafile, makecol, position_dialog, replace_filename, screen, set_dialog_color, set_gfx_mode, set_palette, unload_datafile, ustrtok, ustrzcat, ustrzcpy, uszprintf.
See also: BITMAP, DATAFILE, DIALOG, END_OF_MAIN, FONT, allegro_error, allegro_init, allegro_message, blit, circle, circlefill, clear_to_color, create_bitmap, d_button_proc, d_check_proc, d_clear_proc, d_edit_proc, desktop_palette, destroy_bitmap, do_dialog, fixcos, fixed, fixmul, fixsin, fixtoi, font, install_keyboard, install_mouse, install_timer, itofix, key, line, load_datafile, makecol, object_message, replace_filename, screen, set_gfx_mode, set_palette, unload_datafile.
Note how the Allegro unicode string functions resemble the functions you can find in the standard C library, only these handle Unicode on all platforms.
See also: BITMAP, DATAFILE, END_OF_MAIN, FONT, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, clear_to_color, create_bitmap, destroy_bitmap, font, install_int_ex, install_keyboard, install_timer, keypressed, load_datafile, replace_filename, rest, screen, set_gfx_mode, set_uformat, set_window_title, text_height, text_length, textout_ex, uconvert_ascii, unload_datafile, ustrcat, ustrcpy, ustrsize, ustrsizez.
See also: BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, destroy_bitmap, install_keyboard, load_bitmap, readkey, screen, set_gfx_mode, set_palette.
See also: BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, destroy_bitmap, install_keyboard, keypressed, load_pcx, replace_filename, screen, set_gfx_mode, set_palette, stretch_blit, vsync.
See also: BITMAP, END_OF_MAIN, RGB, SCREEN_H, SCREEN_W, allegro_init, allegro_message, blit, clear_bitmap, font, get_config_argv, get_config_int, get_config_string, install_keyboard, line, load_bitmap, makecol, pop_config_state, push_config_state, readkey, screen, set_color_depth, set_config_file, set_gfx_mode, set_palette, stretch_blit, textout_centre_ex, textprintf_centre_ex, ustrdup, ustricmp.
See also: DATAFILE, END_OF_MAIN, allegro_error, allegro_init, allegro_message, blit, font, install_keyboard, load_datafile, makecol, readkey, replace_filename, screen, set_color_conversion, set_gfx_mode, set_palette, textout_ex, unload_datafile.
Why is the animate() routine coded in that way? As you probably know, VIDEO RAM is much slower than "normal" RAM, so it's advisable to reduce VRAM blits to a minimum. Drawing sprite on the screen (meaning in VRAM) and then clearing a background for it is not very fast. This example uses a different method which is much faster, but require a bit more memory.
First the buffer is cleared (it's a normal BITMAP), then the sprite is drawn on it, and when the drawing is finished this buffer is copied directly to the screen. So the end result is that there is a single VRAM blit instead of blitting/clearing the background and drawing a sprite on it. It's a good method even when you have to restore the background. And of course, it completely removes any flickering effect.
When one uses a big (ie. 800x600 background) and draws something on it, it's wise to use a copy of background somewhere in memory and restore background using this "virtual background". When blitting from VRAM in SVGA modes, it's probably, that drawing routines have to switch banks on video card. I think, I don't have to remind how slow is it.
Note that on modern systems, the above isn't true anymore, and you usually get the best performance by caching all your animations in video ram and doing only VRAM->VRAM blits, so there is no more RAM->VRAM transfer at all anymore. And usually, such transfers can run in parallel on the graphics card's processor as well, costing virtually no main cpu time at all. See the exaccel example for an example of this.
See also: BITMAP, DATAFILE, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, circle, clear_bitmap, clear_keybuf, create_bitmap, destroy_bitmap, draw_sprite, draw_sprite_h_flip, draw_sprite_v_flip, draw_sprite_vh_flip, fixed, font, hline, install_int_ex, install_keyboard, install_sound, install_timer, itofix, key, keypressed, load_datafile, makecol, palette_color, pivot_sprite, pivot_sprite_v_flip, play_sample, rectfill, replace_filename, rest, screen, set_gfx_mode, set_palette, text_height, textout_centre_ex, unload_datafile, vsync.
You may ask: how do you compile, append and exec your program?
Answer: like this...
1) Compile your program like normal. Use the magic filenames with '#' to load your data where needed.
2) Once you compressed your program, run "exedat foo.exe data.dat"
3) Finally run your program.
Note that appending data to the end of binaries may not be portable across all platforms supported by Allegro.
See also: DATAFILE, END_OF_MAIN, allegro_error, allegro_init, allegro_message, blit, font, install_keyboard, line, load_datafile, makecol, readkey, screen, set_color_conversion, set_gfx_mode, set_palette, textout_ex, unload_datafile.
The translucency effect is easy to do in all color depths. However, the lighting effect has to be performed in a different way depending on whether the screen is in 8bit mode or another color depth. This is because additive drawing mode uses a different set of routines for truecolor modes.
See also: BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, RGB, RGB_MAP, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, bitmap_color_depth, blit, circlefill, clear_bitmap, clear_keybuf, color_map, create_bitmap, create_bitmap_ex, create_light_table, create_rgb_table, create_trans_table, destroy_bitmap, draw_trans_sprite, drawing_mode, install_keyboard, install_mouse, install_timer, keypressed, load_bitmap, mouse_x, mouse_y, poll_mouse, rectfill, replace_filename, rest, rgb_map, screen, set_alpha_blender, set_gfx_mode, set_palette, set_trans_blender, set_write_alpha_blender, stretch_blit.
See also: END_OF_MAIN, PALETTE, RGB, SCREEN_H, SCREEN_W, acquire_screen, allegro_init, clear_to_color, font, generate_332_palette, install_keyboard, key, makecol, readkey, release_screen, screen, set_color_depth, set_gfx_mode, set_palette, textout_centre_ex, textout_ex, textprintf_ex, vline.
See also: BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, RGB, RGB_MAP, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, circlefill, clear_keybuf, color_map, create_bitmap, create_color_table, create_rgb_table, destroy_bitmap, drawing_mode, font, generate_332_palette, install_keyboard, keypressed, makecol, rectfill, rgb_map, screen, set_gfx_mode, set_palette, textout_centre_ex, vsync.
Additionally this example also shows how to "inherit" the behaviour of a GUI object and extend it, here used to create the sliders.
See also: BITMAP, DIALOG, END_OF_MAIN, PALETTE, RGB, RGB_MAP, allegro_error, allegro_init, allegro_message, clear_to_color, create_bitmap_ex, create_rgb_table, d_bitmap_proc, d_box_proc, d_slider_proc, d_text_proc, destroy_bitmap, do_dialog, font, generate_332_palette, get_color_depth, hsv_to_rgb, install_keyboard, install_mouse, install_timer, key, makecol, makecol32, makecol8, object_message, rgb_map, rgb_to_hsv, screen, set_color, set_color_depth, set_gfx_mode, set_palette, textout_ex, vline, vsync.
See also: BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, RGB, RGB_MAP, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, clear_bitmap, color_map, create_bitmap, create_light_table, create_rgb_table, destroy_bitmap, draw_gouraud_sprite, font, install_keyboard, install_mouse, keypressed, line, load_bitmap, mouse_x, mouse_y, palette_color, poll_mouse, replace_filename, rgb_map, screen, set_gfx_mode, set_palette, set_trans_blender, show_mouse, textout_ex.
See also: BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, circle, clear_bitmap, clear_keybuf, create_bitmap, destroy_bitmap, draw_lit_sprite, draw_trans_sprite, fixcos, fixsin, fixtoi, font, install_keyboard, install_timer, itofix, keypressed, load_bitmap, makecol, replace_filename, retrace_count, screen, set_color_conversion, set_color_depth, set_gfx_mode, set_trans_blender, textprintf_ex, vsync.
See also: BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error, allegro_exit, allegro_init, allegro_message, blit, create_bitmap, destroy_bitmap, draw_trans_sprite, install_keyboard, keypressed, line, load_bitmap, readkey, screen, set_color_conversion, set_color_depth, set_gfx_mode, set_palette, set_trans_blender, vsync.
See also: BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, blit, clear_keybuf, create_bitmap, destroy_bitmap, draw_trans_sprite, drawing_mode, font, getb, getg, getpixel, getr, install_keyboard, install_mouse, install_timer, keypressed, load_bitmap, makecol, mouse_x, mouse_y, putpixel, rectfill, replace_filename, screen, set_alpha_blender, set_color_conversion, set_color_depth, set_gfx_mode, set_multiply_blender, set_write_alpha_blender, solid_mode, stretch_blit, textprintf_ex.
The basic approach is to select a 15 or 16 bit screen mode, but then draw onto 24 bit memory bitmaps. Since we only need the bottom 5 bits of each 8 bit color in order to store 15 bit data within a 24 bit location, we can fit a light level into the top 3 bits. The tricky bit is that these aren't actually 24 bit images at all: they are implemented as 8 bit memory bitmaps, and we just store the red level in one pixel, green in the next, and blue in the next, making the total image be three times wider than we really wanted. This allows us to use all the normal 256 color graphics routines for drawing onto our memory surfaces, most importantly the lookup table translucency, which can be used to combine the low 5 bits of color and the top 3 bits of light in a single drawing operation. Some trickery is needed to load 24 bit data into this fake 8 bit format, and of course it needs a custom routine to convert the resulting image while copying it across to the hardware screen.
This program chugs slightly on my p133, but not significantly worse than any double buffering in what amounts to a 1920x640, 256 color resolution. The light blending doesn't seem to slow it down too badly, so I think this technique would be quite usable on faster machines and in lower resolution hicolor modes. The biggest problem is that although you keep the full 15 bit color resolution, you only get 3 bits of light, ie. 8 light levels. You can do some nice colored light patches, but smooth gradients aren't going to work too well :-)
See also: BITMAP, COLOR_MAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, bitmap_color_depth, blit, bmp_unwrite_line, bmp_write_line, circlefill, clear_bitmap, clear_keybuf, color_map, create_bitmap_ex, destroy_bitmap, draw_trans_sprite, fixatan2, fixsqrt, fixtoi, getb_depth, getg_depth, getpixel, getr_depth, hsv_to_rgb, install_keyboard, install_mouse, install_timer, itofix, key, keypressed, line, load_bitmap, makecol, mouse_x, mouse_y, poll_mouse, replace_filename, retrace_count, screen, select_palette, set_color_conversion, set_color_depth, set_gfx_mode.
The example first shows a screen resolution selection dialog. Then, a number of bouncing 3d cubes are animated. Pressing a key modifies the rendering of the cubes, which can be wireframe, the more complex transparent perspective correct texture mapped version, and many other.
See also: BITMAP, COLOR_MAP, END_OF_MAIN, MATRIX, PALETTE, POLYTYPE_ATEX, POLYTYPE_ATEX_LIT, POLYTYPE_ATEX_MASK, POLYTYPE_ATEX_MASK_LIT, POLYTYPE_ATEX_MASK_TRANS, POLYTYPE_ATEX_TRANS, POLYTYPE_FLAT, POLYTYPE_GCOL, POLYTYPE_GRGB, POLYTYPE_PTEX, POLYTYPE_PTEX_LIT, POLYTYPE_PTEX_MASK, POLYTYPE_PTEX_MASK_LIT, POLYTYPE_PTEX_MASK_TRANS, POLYTYPE_PTEX_TRANS, RGB, RGB_MAP, SCREEN_H, SCREEN_W, V3D, allegro_error, allegro_exit, allegro_init, allegro_message, apply_matrix, bitmap_color_depth, bitmap_mask_color, blit, clear_bitmap, clear_to_color, color_map, create_bitmap, create_light_table, create_rgb_table, create_trans_table, desktop_palette, destroy_bitmap, fixed, fixtoi, font, get_transformation_matrix, gfx_mode_select_ex, install_keyboard, install_mouse, install_timer, itofix, key, keypressed, line, palette_color, persp_project, polygon_z_normal, quad3d, readkey, rect, retrace_count, rgb_map, screen, set_color_depth, set_gfx_mode, set_palette, set_projection_viewport, set_trans_blender, textout_ex, textprintf_ex, vsync.
See also: BITMAP, END_OF_MAIN, MATRIX_f, POLYTYPE_FLAT, SCREEN_H, SCREEN_W, V3D_f, allegro_error, allegro_init, allegro_message, apply_matrix_f, blit, clear_to_color, clip3d_f, create_bitmap, desktop_palette, destroy_bitmap, font, get_camera_matrix_f, get_vector_rotation_matrix_f, install_int_ex, install_keyboard, install_timer, key, key_shifts, makecol, persp_project_f, poll_keyboard, polygon, polygon3d_f, rect, screen, set_clip_rect, set_gfx_mode, set_palette, set_projection_viewport, textprintf_ex, vsync.
In this program, two cubes are rotated between random orientations. Notice that although they have the same beginning and ending orientations, they do not follow the same path between orientations.
One cube is being rotated by directly incrementing or decrementing the Euler angles from the starting point to the ending point. This is an intuitive notion, but it is incorrect because it does not cause the object to turn around a single unchanging axis of rotation. The axis of rotation wobbles resulting in the object spinning in strange ways. The object will eventually end up in the orientation that the user intended, but it gets there in a way that is unattractive. Imagine if this method was used to update the position of a camera in a game! Sometimes it would swing wildly and disorient the player.
The other cube is animated using quaternions. This results in a much more pleasing animation because the cube turns around a single axis of rotation.
See also: BITMAP, END_OF_MAIN, MATRIX_f, QUAT, acquire_bitmap, allegro_error, allegro_init, allegro_message, apply_matrix_f, blit, circle, clear_keybuf, clear_to_color, create_bitmap, desktop_palette, destroy_bitmap, font, get_camera_matrix_f, get_rotation_matrix, get_rotation_matrix_f, get_rotation_quat, install_keyboard, keypressed, line, matrix_mul_f, palette_color, persp_project_f, quat_interpolate, quat_to_matrix, readkey, release_bitmap, rest, screen, set_gfx_mode, set_palette, set_projection_viewport, textout_ex.
See also: BITMAP, END_OF_MAIN, MATRIX, PALETTE, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, apply_matrix, blit, clear_bitmap, create_bitmap, cross_product, destroy_bitmap, dot_product, fixed, fixmul, fixtof, fixtoi, font, get_rotation_matrix, get_transformation_matrix, get_translation_matrix, install_keyboard, install_timer, itofix, key, normalize_vector, palette_color, persp_project, poll_keyboard, putpixel, rectfill, screen, set_gfx_mode, set_palette, set_projection_viewport, textout_centre_ex, textprintf_centre_ex, triangle, vsync.
See also: BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE, MATRIX_f, PALETTE, POLYTYPE_GCOL, SCREEN_H, SCREEN_W, V3D_f, allegro_error, allegro_exit, allegro_init, allegro_message, apply_matrix_f, bitmap_color_depth, blit, clear_bitmap, clear_scene, clip3d_f, create_bitmap, create_scene, desktop_palette, destroy_bitmap, destroy_scene, font, get_rotation_matrix_f, get_translation_matrix_f, gfx_mode_select_ex, install_int, install_keyboard, install_mouse, install_timer, key, matrix_mul_f, palette_color, persp_project_f, polygon_z_normal_f, render_scene, scene_polygon3d_f, screen, set_color_depth, set_gfx_mode, set_palette, set_projection_viewport, textprintf_ex.
See also: BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE, MATRIX_f, PALETTE, POLYTYPE_GCOL, SCREEN_H, SCREEN_W, V3D_f, ZBUFFER, allegro_error, allegro_exit, allegro_init, allegro_message, apply_matrix_f, bitmap_color_depth, blit, clear_bitmap, clear_zbuffer, create_bitmap, create_zbuffer, desktop_palette, destroy_bitmap, destroy_zbuffer, font, get_transformation_matrix_f, gfx_mode_select_ex, install_int, install_keyboard, install_mouse, install_timer, keypressed, palette_color, persp_project_f, polygon_z_normal_f, quad3d_f, readkey, screen, set_color_depth, set_gfx_mode, set_palette, set_palette_range, set_projection_viewport, set_zbuffer, textprintf_ex, vsync.
See also: BITMAP, END_OF_MAIN, RGB, SCREEN_H, SCREEN_W, acquire_bitmap, allegro_init, allegro_message, clear_keybuf, create_sub_bitmap, desktop_palette, destroy_bitmap, install_keyboard, keypressed, rectfill, release_bitmap, screen, scroll_screen, set_color, set_gfx_mode, set_palette, vline.
See also: BITMAP, END_OF_MAIN, SCREEN_H, SCREEN_W, acquire_bitmap, allegro_error, allegro_init, allegro_message, clear_bitmap, clear_keybuf, create_video_bitmap, desktop_palette, destroy_bitmap, enable_triple_buffer, fixcos, fixed, fixmul, fixsin, fixtoi, font, gfx_capabilities, install_keyboard, install_mouse, install_timer, itofix, keypressed, poll_scroll, release_bitmap, request_video_bitmap, screen, set_gfx_mode, set_palette, textout_ex, triangle, ustrzcpy.
The example starts setting a normal 256 color mode, and construct a special palette for it. But then comes the trick: you need to write to a set of two adjacent pixels to form a single 12 bit dot. Two eight bit pixels is the same as one 16 bit pixel, so after setting the video mode you need to hack the screen bitmap about, halving the width and changing it to use the 16 bit drawing code. Then, once you have packed a color into the correct format (using the makecol12() function below), any of the normal Allegro drawing functions can be used with this 12 bit display!
Things to note:
See also: BITMAP, END_OF_MAIN, MATRIX, PALETTE, RGB, allegro_error, allegro_init, allegro_message, apply_matrix, blit, circle, clear_bitmap, clear_keybuf, clear_to_color, create_bitmap, create_bitmap_ex, destroy_bitmap, ellipsefill, fade_out, fixcos, fixed, fixsin, fixtoi, font, get_rotation_matrix, getpixel, install_keyboard, itofix, keypressed, line, makecol, masked_blit, putpixel, screen, set_clip_rect, set_color, set_gfx_mode, set_palette, text_height, text_length, textout_ex, textprintf_ex.
See also: BITMAP, END_OF_MAIN, PALETTE, SCREEN_H, SCREEN_W, acquire_bitmap, allegro_error, allegro_init, allegro_message, blit, clear_bitmap, create_video_bitmap, destroy_bitmap, font, gfx_capabilities, install_keyboard, install_timer, keypressed, load_bitmap, readkey, release_bitmap, replace_filename, screen, set_gfx_mode, set_palette, show_video_bitmap, textout_ex, textprintf_ex.
The technique is to connect the series of guide points p1..p(n) with spline curves from p1-p2, p2-p3, etc. Each spline must pass though both of its guide points, so they must be used as the first and fourth of the spline control points. The fun bit is coming up with sensible values for the second and third spline control points, such that the spline segments will have equal gradients where they meet. I came up with the following solution:
For each guide point p(n), calculate the desired tangent to the curve at that point. I took this to be the vector p(n-1) -> p(n+1), which can easily be calculated with the inverse tangent function, and gives decent looking results. One implication of this is that two dummy guide points are needed at each end of the curve, which are used in the tangent calculations but not connected to the set of splines.
Having got these tangents, it becomes fairly easy to calculate the spline control points. For a spline between guide points p(a) and p(b), the second control point should lie along the positive tangent from p(a), and the third control point should lie along the negative tangent from p(b). How far they are placed along these tangents controls the shape of the curve: I found that applying a 'curviness' scaling factor to the distance between p(a) and p(b) works well.
One thing to note about splines is that the generated points are not all equidistant. Instead they tend to bunch up nearer to the ends of the spline, which means you will need to apply some fudges to get an object to move at a constant speed. On the other hand, in situations where the curve has a noticeable change of direction at each guide point, the effect can be quite nice because it makes the object slow down for the curve.
See also: END_OF_MAIN, SCREEN_W, acquire_screen, alert, allegro_error, allegro_init, allegro_message, calc_spline, circlefill, clear_keybuf, clear_to_color, desktop_palette, fixatan2, fixcos, fixed, fixmul, fixsin, fixsqrt, fixtof, fixtoi, font, ftofix, install_keyboard, install_mouse, install_timer, itofix, key, keypressed, line, makecol, mouse_b, mouse_x, mouse_y, palette_color, poll_mouse, readkey, release_screen, screen, set_gfx_mode, set_palette, show_mouse, spline, textout_centre_ex, textprintf_centre_ex, textprintf_ex, vsync, xor_mode.
See also: END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, clear_to_color, enable_hardware_cursor, font, gfx_capabilities, install_keyboard, install_mouse, install_timer, makecol, readkey, screen, select_mouse_cursor, set_gfx_mode, show_mouse, text_height, textprintf_centre_ex.
See also: BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE, PALETTE, SCREEN_H, SCREEN_W, acquire_bitmap, allegro_error, allegro_init, allegro_message, bitmap_color_depth, blit, clear_bitmap, create_bitmap, create_system_bitmap, create_video_bitmap, desktop_palette, destroy_bitmap, enable_triple_buffer, fixcos, fixed, fixmul, fixsin, fixtoi, font, ftofix, generate_332_palette, gfx_capabilities, gfx_mode_select_ex, install_int_ex, install_keyboard, install_mouse, install_timer, keypressed, line, makecol, poll_scroll, release_bitmap, request_video_bitmap, screen, set_color_depth, set_gfx_mode, set_palette, show_video_bitmap, textout_ex, textprintf_ex, triangle, vsync, xor_mode.
Yes, I know the fractal drawing is very slow: that's the point! This is so you can easily check whether it goes on working in the background after you switch away from the app.
Depending on the type of selected switching mode, you will see whether the contents of the screen are preserved or not.
See also: BITMAP, END_OF_FUNCTION, END_OF_MAIN, LOCK_FUNCTION, LOCK_VARIABLE, PALETTE, SCREEN_H, SCREEN_W, acquire_bitmap, acquire_screen, allegro_error, allegro_exit, allegro_init, allegro_message, bitmap_color_depth, blit, clear_to_color, create_sub_bitmap, desktop_palette, destroy_bitmap, font, get_display_switch_mode, gfx_mode_select_ex, install_int, install_keyboard, install_mouse, install_timer, keypressed, makecol, palette_color, putpixel, readkey, rectfill, release_bitmap, release_screen, screen, set_color_depth, set_display_switch_callback, set_display_switch_mode, set_gfx_mode, set_palette, textout_centre_ex, textprintf_centre_ex.
See also: AUDIOSTREAM, END_OF_MAIN, SCREEN_H, SCREEN_W, allegro_error, allegro_init, allegro_message, clear_to_color, desktop_palette, font, free_audio_stream_buffer, get_audio_stream_buffer, install_keyboard, install_sound, install_timer, keypressed, makecol, play_audio_stream, readkey, screen, set_gfx_mode, set_palette, stop_audio_stream, textprintf_centre_ex, voice_start, voice_stop.
The first test uses the standard packfile functions to transfer a bitmap file into a block of memory, then reads the bitmap out of the block of memory, using a custom packfile vtable.
The second test reads in a bitmap with another custom packfile vtable, which uses libc's file stream functions.
The third test demonstrates seeking with a custom vtable.
The fourth test reads two bitmaps, and dumps them back into a single file, using a custom vtable again.
See also: ASSERT, BITMAP, END_OF_MAIN, PACKFILE, PACKFILE_VTABLE, SCREEN_H, SCREEN_W, alert, allegro_error, allegro_init, allegro_message, blit, clear_bitmap, destroy_bitmap, file_size_ex, font, install_keyboard, key, load_bmp_pf, load_pcx, load_pcx_pf, load_tga_pf, pack_fclose, pack_fopen, pack_fopen_vtable, pack_fread, pack_fseek, readkey, save_bmp_pf, save_tga_pf, screen, set_color_depth, set_gfx_mode, text_height, textprintf_centre_ex, textprintf_ex.
Allegro was originally created by Shawn Hargreaves. Published sometime between 1994 and 1995, it was just a simple lib for himself. At that time, many people were switching from Borland C to DJGPP and looking for a decent graphics library. Allegro was the first reasonably complete one to show up, so it attracted enough interest to keep growing, and a little contribution here, and some more encouragement there made it all light up like fire.
Some time after the latest 3.x stable release, though, Shawn was flooded with Allegro tasks and Real Life (TM) work, and chose the latter to focus his energies on. While this somehow stalled Allegro's development, it also attracted a lot of people who wanted Allegro to live longer. Also, by that time other people had started to work on Windows and Unix ports of Allegro, which suggested that Allegro had the potential to survive its only decaying main platform (DOS).
The current situation is that Shawn still keeps watching Allegro's progress from time to time, but is not involved with development any more. The community that grew over the years when Shawn was in charge of everything has stepped forward to continue improving Allegro. Transformed into a meritocratic community, users keep sending bug reports to the mailing lists, developers around the world keep sending patches to fix them, and a few carefully chosen have write access to the SVN repository, from which releases are built every now and then.
But, who decides when a build is stable enough? Who decides when somebody is granted write access to the SVN? Who chooses the lesser of two evils patching some obscure bug? And more importantly, who decides what's Allegro's mascot? For all these reasons, the community decided to replace Shawn's position with the Allegro Dictator.
In republican Rome, political power was with the Senate and the Consuls. However, if it was necessary that decisions were made very quickly then the senate could appoint a Dictator. The Dictator was appointed for a specified duration or charged with a specific task, after which he was expected to surrender his authority back to the Senate. Nowadays, the Allegro Dictator is a benevolent figure and rarely has to use his overwhelming fist of iron to put order into chaos.
The truth is that the Allegro Dictator is usually the person in charge of doing releases and all that unsexy work inside the community, like pestering users to test some obscure bugfix or rejecting incomplete patches.
Past Allegro dictators have been: Shawn Hargreaves, George Foot, Peter Wang and Eric Botcazou. At the moment of writing this, Evert Glebbeek is the active Allegro Dictator. Should you want to change Allegro in some illogical way, he's the guy you have to send your bribes too :-)
All good things must come to an end. Writing documentation is not a good thing, though, and that means it goes on for ever. There is always something we've forgotten to explain, or some essential detail we've left out, but for now you will have to make do with this. Feel free to ask if you can't figure something out.
Enjoy. We hope you find some of this stuff useful.
By Shawn Hargreaves and the Allegro development team.