📄 demo.c
字号:
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* A simple game demonstrating the use of the Allegro library.
*
* By Shawn Hargreaves.
*
* See readme.txt for copyright information.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#ifdef DJGPP
#include <conio.h>
#endif
#include "allegro.h"
#include "demo.h"
#define DOUBLE_BUFFER 1
#define PAGE_FLIP 2
#define RETRACE_FLIP 3
#define TRIPLE_BUFFER 4
#define DIRTY_RECTANGLE 5
int animation_type = 0;
int cheat = FALSE;
int turbo = FALSE;
DATAFILE *data;
BITMAP *s;
BITMAP *page1, *page2, *page3;
int current_page = 0;
int use_retrace_proc = FALSE;
PALLETE title_pallete;
volatile int score;
char score_buf[80];
int dead;
int pos;
int xspeed, yspeed, ycounter;
int ship_state;
int ship_burn;
int shot;
int skip_speed, skip_count;
volatile int frame_count, fps;
volatile int game_time;
#define MAX_SPEED 32
#define SPEED_SHIFT 3
#define MAX_STARS 128
volatile struct {
fixed x, y, z;
int ox, oy;
} star[MAX_STARS];
#define MAX_ALIENS 50
volatile struct {
int x, y;
int d;
int state;
int shot;
} alien[MAX_ALIENS];
volatile int alien_count;
volatile int new_alien_count;
#define EXPLODE_FLAG 100
#define EXPLODE_FRAMES 64
#define EXPLODE_SIZE 80
RLE_SPRITE *explosion[EXPLODE_FRAMES];
#define BULLET_SPEED 6
volatile int bullet_flag;
volatile int bullet_x, bullet_y;
typedef struct RECT {
int x, y, w, h;
} RECT;
typedef struct DIRTY_LIST {
int count;
RECT rect[2*(MAX_ALIENS+MAX_STARS+4)];
} DIRTY_LIST;
DIRTY_LIST dirty, old_dirty;
#define PAN(x) (((x) * 256) / SCREEN_W)
void game_timer()
{
game_time++;
}
END_OF_FUNCTION(game_timer);
void fps_proc()
{
fps = frame_count;
frame_count = 0;
score++;
}
END_OF_FUNCTION(fps_proc);
void move_everyone()
{
int c;
/* player dead? */
if (shot) {
if (skip_count <= 0) {
if (ship_state >= EXPLODE_FLAG+EXPLODE_FRAMES-1)
dead = TRUE;
else
ship_state++;
if (yspeed)
yspeed--;
}
}
else {
if (skip_count <= 0) {
/* moving left */
if ((key[KEY_LEFT]) || (joy[0].stick[0].axis[0].d1)) {
if (xspeed > -MAX_SPEED)
xspeed -= 2;
}
else {
/* moving right */
if ((key[KEY_RIGHT]) || (joy[0].stick[0].axis[0].d2)) {
if (xspeed < MAX_SPEED)
xspeed += 2;
}
else {
/* decelerate */
if (xspeed > 0)
xspeed -= 2;
else if (xspeed < 0)
xspeed += 2;
}
}
}
/* which ship sprite to use? */
if (xspeed < -24)
ship_state = SHIP1;
else if (xspeed < -2)
ship_state = SHIP2;
else if (xspeed <= 2)
ship_state = SHIP3;
else if (xspeed <= 24)
ship_state = SHIP4;
else
ship_state = SHIP5;
/* move player */
pos += xspeed;
if (pos < (32 << SPEED_SHIFT)) {
pos = (32 << SPEED_SHIFT);
xspeed = 0;
}
else
if (pos >= ((SCREEN_W-32) << SPEED_SHIFT)) {
pos = ((SCREEN_W-32) << SPEED_SHIFT);
xspeed = 0;
}
if (skip_count <= 0) {
/* fire thrusters? */
if ((key[KEY_UP]) || (joy[0].stick[0].axis[1].d1) || (turbo)) {
if (yspeed < MAX_SPEED) {
if (yspeed == 0) {
play_sample(data[ENGINE_SPL].dat, 0, PAN(pos>>SPEED_SHIFT),
1000, TRUE);
}
else
/* fade in sample while speeding up */
adjust_sample(data[ENGINE_SPL].dat, yspeed*64/MAX_SPEED,
PAN(pos>>SPEED_SHIFT), 1000, TRUE);
yspeed++;
}
else
/* adjust pan while the sample is looping */
adjust_sample(data[ENGINE_SPL].dat, 64, PAN(pos>>SPEED_SHIFT),
1000, TRUE);
ship_burn = TRUE;
score++;
}
else {
if (yspeed) {
yspeed--;
if (yspeed == 0)
stop_sample(data[ENGINE_SPL].dat);
else
/* fade out and reduce frequency when slowing down */
adjust_sample(data[ENGINE_SPL].dat, yspeed*64/MAX_SPEED,
PAN(pos>>SPEED_SHIFT), 500+yspeed*500/MAX_SPEED, TRUE);
}
ship_burn = FALSE;
}
}
}
/* going fast? move everyone else down to compensate */
if (yspeed) {
ycounter += yspeed;
while (ycounter >= (1 << SPEED_SHIFT)) {
if (bullet_flag)
bullet_y++;
for (c=0; c<MAX_STARS; c++)
if (++star[c].oy >= SCREEN_H)
star[c].oy = 0;
for (c=0; c<alien_count; c++)
alien[c].y++;
ycounter -= (1 << SPEED_SHIFT);
}
}
/* move bullet */
if (bullet_flag) {
bullet_y -= BULLET_SPEED;
if (bullet_y < 8)
bullet_flag = FALSE;
else {
/* shot an alien? */
for (c=0; c<alien_count; c++) {
if ((ABS(bullet_y - alien[c].y) < 20) &&
(ABS(bullet_x - alien[c].x) < 20) &&
(!alien[c].shot)) {
alien[c].shot = TRUE;
alien[c].state = EXPLODE_FLAG;
bullet_flag = FALSE;
score += 10;
play_sample(data[BOOM_SPL].dat, 255, PAN(bullet_x), 1000, FALSE);
break;
}
}
}
}
/* move stars */
for (c=0; c<MAX_STARS; c++) {
if ((star[c].oy += ((int)star[c].z>>1)+1) >= SCREEN_H)
star[c].oy = 0;
}
/* fire bullet? */
if (!shot) {
if ((key[KEY_SPACE]) || (joy[0].button[0].b) || (joy[0].button[1].b)) {
if (!bullet_flag) {
bullet_x = (pos>>SPEED_SHIFT)-2;
bullet_y = SCREEN_H-64;
bullet_flag = TRUE;
play_sample(data[SHOOT_SPL].dat, 100, PAN(bullet_x), 1000, FALSE);
}
}
}
/* move aliens */
for (c=0; c<alien_count; c++) {
if (alien[c].shot) {
/* dying alien */
if (skip_count <= 0) {
if (alien[c].state < EXPLODE_FLAG+EXPLODE_FRAMES-1) {
alien[c].state++;
if (alien[c].state & 1)
alien[c].x += alien[c].d;
}
else {
alien[c].x = 16 + random() % (SCREEN_W-32);
alien[c].y = -60 - (random() & 0x3f);
alien[c].d = (random()&1) ? 1 : -1;
alien[c].shot = FALSE;
alien[c].state = -1;
}
}
}
else {
/* move alien sideways */
alien[c].x += alien[c].d;
if (alien[c].x < -60)
alien[c].x = SCREEN_W;
else if (alien[c].x > SCREEN_W)
alien[c].x = -60;
}
/* move alien vertically */
alien[c].y += 1;
if (alien[c].y > SCREEN_H+30) {
if (!alien[c].shot) {
alien[c].x = random() % (SCREEN_W-32);
alien[c].y = -32 - (random() & 0x3f);
alien[c].d = (random()&1) ? 1 : -1;
}
}
else {
/* alien collided with player? */
if ((ABS(alien[c].x - (pos>>SPEED_SHIFT)) < 48) &&
(ABS(alien[c].y - (SCREEN_H-42)) < 32)) {
if (!shot) {
if (!cheat) {
ship_state = EXPLODE_FLAG;
shot = TRUE;
stop_sample(data[ENGINE_SPL].dat);
}
if ((!cheat) || (!alien[c].shot))
play_sample(data[DEATH_SPL].dat, 255, PAN(pos>>SPEED_SHIFT), 1000, FALSE);
}
if (!alien[c].shot) {
alien[c].shot = TRUE;
alien[c].state = EXPLODE_FLAG;
}
}
}
}
if (skip_count <= 0) {
skip_count = skip_speed;
/* make a new alien? */
new_alien_count++;
if ((new_alien_count > 600) && (alien_count < MAX_ALIENS)) {
alien_count++;
new_alien_count = 0;
}
}
else
skip_count--;
/* Yes, I know that isn't a very pretty piece of code :-) */
}
void add_to_list(DIRTY_LIST *list, int x, int y, int w, int h)
{
list->rect[list->count].x = x;
list->rect[list->count].y = y;
list->rect[list->count].w = w;
list->rect[list->count].h = h;
list->count++;
}
int rect_cmp(const void *p1, const void *p2)
{
RECT *r1 = (RECT *)p1;
RECT *r2 = (RECT *)p2;
return (r1->y - r2->y);
}
void draw_screen()
{
int c;
int i, j;
int x, y;
BITMAP *bmp;
RLE_SPRITE *spr;
char *animation_type_str;
if (animation_type == DOUBLE_BUFFER) {
/* for double buffering, draw onto the memory bitmap. The first step
* is to clear it...
*/
animation_type_str = "double buffered";
bmp = s;
clear(bmp);
}
else if ((animation_type == PAGE_FLIP) || (animation_type == RETRACE_FLIP)) {
/* for page flipping we draw onto one of the sub-bitmaps which
* describe different parts of the large virtual screen.
*/
if (animation_type == PAGE_FLIP)
animation_type_str = "page flipping";
else
animation_type_str = "synced flipping";
if (current_page == 0) {
bmp = page2;
current_page = 1;
}
else {
bmp = page1;
current_page = 0;
}
clear(bmp);
}
else if (animation_type == TRIPLE_BUFFER) {
/* triple buffering works kind of like page flipping, but with three
* pages (obvious, really :-) The benefit of this is that we can be
* drawing onto page a, while displaying page b and waiting for the
* retrace that will flip across to page c, hence there is no need
* to waste time sitting around waiting for retraces.
*/
animation_type_str = "triple buffered";
if (current_page == 0) {
bmp = page2;
current_page = 1;
}
else if (current_page == 1) {
bmp = page3;
current_page = 2;
}
else {
bmp = page1;
current_page = 0;
}
clear(bmp);
}
else {
/* for dirty rectangle animation we draw onto the memory bitmap, but
* we can use information saved during the last draw operation to
* only clear the areas that have something on them.
*/
animation_type_str = "dirty rectangles";
bmp = s;
for (c=0; c<dirty.count; c++) {
if ((dirty.rect[c].w == 1) && (dirty.rect[c].h == 1))
putpixel(bmp, dirty.rect[c].x, dirty.rect[c].y, 0);
else
rectfill(bmp, dirty.rect[c].x, dirty.rect[c].y,
dirty.rect[c].x + dirty.rect[c].w,
dirty.rect[c].y+dirty.rect[c].h, 0);
}
old_dirty = dirty;
dirty.count = 0;
}
/* draw the stars */
for (c=0; c<MAX_STARS; c++) {
y = star[c].oy;
x = ((star[c].ox-SCREEN_W/2)*(y/(4-star[c].z/2)+SCREEN_H)/SCREEN_H)+SCREEN_W/2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -