📄 exsprite.c
字号:
/*
* Example program for the Allegro library, by Grzegorz Ludorowski.
*
* This example demonstrates how to use datafiles, various sprite
* drawing routines and flicker-free animation.
*
* 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.
*/
#include <math.h>
#include <allegro.h>
#include "running.h"
#define FRAMES_PER_SECOND 30
/* set up a timer for animation */
volatile int ticks = 0;
void ticker(void)
{
ticks++;
}
END_OF_FUNCTION(ticker)
/* pointer to data file */
DATAFILE *running_data;
/* current sprite frame number */
int frame, frame_number = 0;
/* pointer to a sprite buffer, where sprite will be drawn */
BITMAP *sprite_buffer;
/* a boolean - if true, skip to next part */
int next;
void animate(void)
{
/* Wait for animation timer. */
while (frame > ticks) {
/* Avoid busy wait. */
rest(1);
}
/* Ideally, instead of using a timer, we would set the monitor refresh rate
* to a multiple of the animation speed, and synchronize with the vertical
* blank interrupt (vsync) - to get a completely smooth animation. But this
* doesn't work on all setups (e.g. in X11 windowed modes), so should only
* be used after performing some tests first or letting the user enable it.
* Too much for this simple example
*/
frame++;
/* blits sprite buffer to screen */
blit(sprite_buffer, screen, 0, 0, (SCREEN_W - sprite_buffer->w) / 2,
(SCREEN_H - sprite_buffer->h) / 2, sprite_buffer->w, sprite_buffer->h);
/* clears sprite buffer with color 0 */
clear_bitmap(sprite_buffer);
/* if key pressed set a next flag */
if (keypressed())
next = TRUE;
else
next = FALSE;
if (frame_number == 0)
play_sample(running_data[SOUND_01].dat, 128, 128, 1000, FALSE);
/* increase frame number, or if it's equal 9 (last frame) set it to 0 */
if (frame_number == 9)
frame_number = 0;
else
frame_number++;
}
int main(int argc, char *argv[])
{
char datafile_name[256];
int angle = 0;
int x, y;
int text_y;
int color;
if (allegro_init() != 0)
return 1;
install_keyboard();
install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
install_timer();
LOCK_FUNCTION(ticker);
LOCK_VARIABLE(ticks);
install_int_ex(ticker, BPS_TO_TIMER(30));
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Unable to set any graphic mode\n%s\n",
allegro_error);
return 1;
}
}
/* loads datafile and sets user palette saved in datafile */
replace_filename(datafile_name, argv[0], "running.dat",
sizeof(datafile_name));
running_data = load_datafile(datafile_name);
if (!running_data) {
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
allegro_message("Error loading %s!\n", datafile_name);
return 1;
}
/* select the palette which was loaded from the datafile */
set_palette(running_data[PALETTE_001].dat);
/* create and clear a bitmap for sprite buffering, big
* enough to hold the diagonal(sqrt(2)) when rotating */
sprite_buffer = create_bitmap((int)(82 * sqrt(2) + 2),
(int)(82 * sqrt(2) + 2));
clear_bitmap(sprite_buffer);
x = (sprite_buffer->w - 82) / 2;
y = (sprite_buffer->h - 82) / 2;
color = makecol(0, 80, 0);
text_y = SCREEN_H - 10 - text_height(font);
frame = ticks;
/* write current sprite drawing method */
textout_centre_ex(screen, font, "Press a key for next part...",
SCREEN_W / 2, 10, palette_color[1], -1);
textout_centre_ex(screen, font, "Using draw_sprite",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y + 82, sprite_buffer->w - 1, color);
draw_sprite(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Using draw_sprite_h_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y + 82, sprite_buffer->w - 1, color);
draw_sprite_h_flip(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Using draw_sprite_v_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y - 1, sprite_buffer->w - 1, color);
draw_sprite_v_flip(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Using draw_sprite_vh_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
hline(sprite_buffer, 0, y - 1, sprite_buffer->w - 1, color);
draw_sprite_vh_flip(sprite_buffer, running_data[frame_number].dat, x, y);
animate();
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Now with rotating - pivot_sprite",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
/* The last argument to pivot_sprite() is a fixed point type,
* so I had to use itofix() routine (integer to fixed).
*/
circle(sprite_buffer, x + 41, y + 41, 47, color);
pivot_sprite(sprite_buffer, running_data[frame_number].dat, sprite_buffer->w / 2,
sprite_buffer->h / 2, 41, 41, itofix(angle));
animate();
angle -= 4;
} while (!next);
clear_keybuf();
rectfill(screen, 0, text_y, SCREEN_W, SCREEN_H, 0);
textout_centre_ex(screen, font, "Now using pivot_sprite_v_flip",
SCREEN_W / 2, text_y, palette_color[15], -1);
do {
/* The last argument to pivot_sprite_v_flip() is a fixed point type,
* so I had to use itofix() routine (integer to fixed).
*/
circle(sprite_buffer, x + 41, y + 41, 47, color);
pivot_sprite_v_flip(sprite_buffer, running_data[frame_number].dat,
sprite_buffer->w / 2, sprite_buffer->h / 2, 41, 41, itofix(angle));
animate();
angle += 4;
} while (!next);
unload_datafile(running_data);
destroy_bitmap(sprite_buffer);
return 0;
}
END_OF_MAIN()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -