⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demo.c

📁 用djgpp里allegro库编写的完整演示程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*         ______   ___    ___ 
 *        /\  _  \ /\_ \  /\_ \ 
 *        \ \ \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 + -