home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Programming Black Book (Special Edition)
/
BlackBook.bin
/
disk1
/
source
/
chapter49
/
l49-5.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-06-18
|
10KB
|
241 lines
/* Sample mode X VGA animation program. Portions of this code first appeared
in PC Techniques.
Tested with Borland C++ 4.02 in small model by Jim Mischel 12/16/94.
*/
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <math.h>
#include "maskim.h"
#define SCREEN_SEG 0xA000
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240
#define PAGE0_START_OFFSET 0
#define PAGE1_START_OFFSET (((long)SCREEN_HEIGHT*SCREEN_WIDTH)/4)
#define BG_START_OFFSET (((long)SCREEN_HEIGHT*SCREEN_WIDTH*2)/4)
#define DOWNLOAD_START_OFFSET (((long)SCREEN_HEIGHT*SCREEN_WIDTH*3)/4)
static unsigned int PageStartOffsets[2] =
{PAGE0_START_OFFSET,PAGE1_START_OFFSET};
static char GreenAndBrownPattern[] =
{2,6,2,6, 6,2,6,2, 2,6,2,6, 6,2,6,2};
static char PineTreePattern[] = {2,2,2,2, 2,6,2,6, 2,2,6,2, 2,2,2,2};
static char BrickPattern[] = {6,6,7,6, 7,7,7,7, 7,6,6,6, 7,7,7,7,};
static char RoofPattern[] = {8,8,8,7, 7,7,7,7, 8,8,8,7, 8,8,8,7};
#define SMOKE_WIDTH 7
#define SMOKE_HEIGHT 7
static char SmokePixels[] = {
0, 0,15,15,15, 0, 0,
0, 7, 7,15,15,15, 0,
8, 7, 7, 7,15,15,15,
8, 7, 7, 7, 7,15,15,
0, 8, 7, 7, 7, 7,15,
0, 0, 8, 7, 7, 7, 0,
0, 0, 0, 8, 8, 0, 0};
static char SmokeMask[] = {
0, 0, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1,
0, 1, 1, 1, 1, 1, 0,
0, 0, 1, 1, 1, 0, 0};
#define KITE_WIDTH 10
#define KITE_HEIGHT 16
static char KitePixels[] = {
0, 0, 0, 0,45, 0, 0, 0, 0, 0,
0, 0, 0,46,46,46, 0, 0, 0, 0,
0, 0,47,47,47,47,47, 0, 0, 0,
0,48,48,48,48,48,48,48, 0, 0,
49,49,49,49,49,49,49,49,49, 0,
0,50,50,50,50,50,50,50, 0, 0,
0,51,51,51,51,51,51,51, 0, 0,
0, 0,52,52,52,52,52, 0, 0, 0,
0, 0,53,53,53,53,53, 0, 0, 0,
0, 0, 0,54,54,54, 0, 0, 0, 0,
0, 0, 0,55,55,55, 0, 0, 0, 0,
0, 0, 0, 0,58, 0, 0, 0, 0, 0,
0, 0, 0, 0,59, 0, 0, 0, 0,66,
0, 0, 0, 0,60, 0, 0,64, 0,65,
0, 0, 0, 0, 0,61, 0, 0,64, 0,
0, 0, 0, 0, 0, 0,62,63, 0,64};
static char KiteMask[] = {
0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
0, 0, 0, 0, 1, 0, 0, 1, 0, 1,
0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 1, 1, 0, 1};
static MaskedImage KiteImage;
#define NUM_OBJECTS 20
typedef struct {
int X,Y,Width,Height,XDir,YDir,XOtherPage,YOtherPage;
MaskedImage *Image;
} AnimatedObject;
AnimatedObject AnimatedObjects[] = {
{ 0, 0,KITE_WIDTH,KITE_HEIGHT, 1, 1, 0, 0,&KiteImage},
{ 10, 10,KITE_WIDTH,KITE_HEIGHT, 0, 1, 10, 10,&KiteImage},
{ 20, 20,KITE_WIDTH,KITE_HEIGHT,-1, 1, 20, 20,&KiteImage},
{ 30, 30,KITE_WIDTH,KITE_HEIGHT,-1,-1, 30, 30,&KiteImage},
{ 40, 40,KITE_WIDTH,KITE_HEIGHT, 1,-1, 40, 40,&KiteImage},
{ 50, 50,KITE_WIDTH,KITE_HEIGHT, 0,-1, 50, 50,&KiteImage},
{ 60, 60,KITE_WIDTH,KITE_HEIGHT, 1, 0, 60, 60,&KiteImage},
{ 70, 70,KITE_WIDTH,KITE_HEIGHT,-1, 0, 70, 70,&KiteImage},
{ 80, 80,KITE_WIDTH,KITE_HEIGHT, 1, 2, 80, 80,&KiteImage},
{ 90, 90,KITE_WIDTH,KITE_HEIGHT, 0, 2, 90, 90,&KiteImage},
{100,100,KITE_WIDTH,KITE_HEIGHT,-1, 2,100,100,&KiteImage},
{110,110,KITE_WIDTH,KITE_HEIGHT,-1,-2,110,110,&KiteImage},
{120,120,KITE_WIDTH,KITE_HEIGHT, 1,-2,120,120,&KiteImage},
{130,130,KITE_WIDTH,KITE_HEIGHT, 0,-2,130,130,&KiteImage},
{140,140,KITE_WIDTH,KITE_HEIGHT, 2, 0,140,140,&KiteImage},
{150,150,KITE_WIDTH,KITE_HEIGHT,-2, 0,150,150,&KiteImage},
{160,160,KITE_WIDTH,KITE_HEIGHT, 2, 2,160,160,&KiteImage},
{170,170,KITE_WIDTH,KITE_HEIGHT,-2, 2,170,170,&KiteImage},
{180,180,KITE_WIDTH,KITE_HEIGHT,-2,-2,180,180,&KiteImage},
{190,190,KITE_WIDTH,KITE_HEIGHT, 2,-2,190,190,&KiteImage},
};
void main(void);
void DrawBackground(unsigned int);
void MoveObject(AnimatedObject *);
extern void Set320x240Mode(void);
extern void FillRectangleX(int, int, int, int, unsigned int, int);
extern void FillPatternX(int, int, int, int, unsigned int, char*);
extern void CopySystemToScreenMaskedX(int, int, int, int, int, int,
char *, unsigned int, int, int, char *);
extern void CopyScreenToScreenX(int, int, int, int, int, int,
unsigned int, unsigned int, int, int);
extern unsigned int CreateAlignedMaskedImage(MaskedImage *,
unsigned int, char *, int, int, char *);
extern void CopyScreenToScreenMaskedX(int, int, int, int, int, int,
MaskedImage *, unsigned int, int);
extern void ShowPage(unsigned int);
void main()
{
int DisplayedPage, NonDisplayedPage, Done, i;
union REGS regset;
Set320x240Mode();
/* Download the kite image for fast copying later */
if (CreateAlignedMaskedImage(&KiteImage, DOWNLOAD_START_OFFSET,
KitePixels, KITE_WIDTH, KITE_HEIGHT, KiteMask) == 0) {
regset.x.ax = 0x0003; int86(0x10, ®set, ®set);
printf("Couldn't get memory\n"); exit();
}
/* Draw the background to the background page */
DrawBackground(BG_START_OFFSET);
/* Copy the background to both displayable pages */
CopyScreenToScreenX(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0,
BG_START_OFFSET, PAGE0_START_OFFSET, SCREEN_WIDTH,
SCREEN_WIDTH);
CopyScreenToScreenX(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0,
BG_START_OFFSET, PAGE1_START_OFFSET, SCREEN_WIDTH,
SCREEN_WIDTH);
/* Move the objects and update their images in the nondisplayed
page, then flip the page, until Esc is pressed */
Done = DisplayedPage = 0;
do {
NonDisplayedPage = DisplayedPage ^ 1;
/* Erase each object in nondisplayed page by copying block from
background page at last location in that page */
for (i=0; i<NUM_OBJECTS; i++) {
CopyScreenToScreenX(AnimatedObjects[i].XOtherPage,
AnimatedObjects[i].YOtherPage,
AnimatedObjects[i].XOtherPage +
AnimatedObjects[i].Width,
AnimatedObjects[i].YOtherPage +
AnimatedObjects[i].Height,
AnimatedObjects[i].XOtherPage,
AnimatedObjects[i].YOtherPage, BG_START_OFFSET,
PageStartOffsets[NonDisplayedPage], SCREEN_WIDTH,
SCREEN_WIDTH);
}
/* Move and draw each object in the nondisplayed page */
for (i=0; i<NUM_OBJECTS; i++) {
MoveObject(&AnimatedObjects[i]);
/* Draw object into nondisplayed page at new location */
CopyScreenToScreenMaskedX(0, 0, AnimatedObjects[i].Width,
AnimatedObjects[i].Height, AnimatedObjects[i].X,
AnimatedObjects[i].Y, AnimatedObjects[i].Image,
PageStartOffsets[NonDisplayedPage], SCREEN_WIDTH);
}
/* Flip to the page into which we just drew */
ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
/* See if it's time to end */
if (kbhit()) {
if (getch() == 0x1B) Done = 1; /* Esc to end */
}
} while (!Done);
/* Restore text mode and done */
regset.x.ax = 0x0003; int86(0x10, ®set, ®set);
}
void DrawBackground(unsigned int PageStart)
{
int i,j,Temp;
/* Fill the screen with cyan */
FillRectangleX(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, PageStart, 11);
/* Draw a green and brown rectangle to create a flat plain */
FillPatternX(0, 160, SCREEN_WIDTH, SCREEN_HEIGHT, PageStart,
GreenAndBrownPattern);
/* Draw blue water at the bottom of the screen */
FillRectangleX(0, SCREEN_HEIGHT-30, SCREEN_WIDTH, SCREEN_HEIGHT,
PageStart, 1);
/* Draw a brown mountain rising out of the plain */
for (i=0; i<120; i++)
FillRectangleX(SCREEN_WIDTH/2-30-i, 51+i, SCREEN_WIDTH/2-30+i+1,
51+i+1, PageStart, 6);
/* Draw a yellow sun by overlapping rects of various shapes */
for (i=0; i<=20; i++) {
Temp = (int)(sqrt(20.0*20.0 - (float)i*(float)i) + 0.5);
FillRectangleX(SCREEN_WIDTH-25-i, 30-Temp, SCREEN_WIDTH-25+i+1,
30+Temp+1, PageStart, 14);
}
/* Draw green trees down the side of the mountain */
for (i=10; i<90; i += 15)
for (j=0; j<20; j++)
FillPatternX(SCREEN_WIDTH/2+i-j/3-15, i+j+51,SCREEN_WIDTH/2+i+j/3-15+1,
i+j+51+1, PageStart, PineTreePattern);
/* Draw a house on the plain */
FillPatternX(265, 150, 295, 170, PageStart, BrickPattern);
FillPatternX(265, 130, 270, 150, PageStart, BrickPattern);
for (i=0; i<12; i++)
FillPatternX(280-i*2, 138+i, 280+i*2+1, 138+i+1, PageStart, RoofPattern);
/* Finally, draw puffs of smoke rising from the chimney */
for (i=0; i<4; i++)
CopySystemToScreenMaskedX(0, 0, SMOKE_WIDTH, SMOKE_HEIGHT, 264,
110-i*20, SmokePixels, PageStart, SMOKE_WIDTH,SCREEN_WIDTH, SmokeMask);
}
/* Move the specified object, bouncing at the edges of the screen and
remembering where the object was before the move for erasing next time */
void MoveObject(AnimatedObject * ObjectToMove) {
int X, Y;
X = ObjectToMove->X + ObjectToMove->XDir;
Y = ObjectToMove->Y + ObjectToMove->YDir;
if ((X < 0) || (X > (SCREEN_WIDTH - ObjectToMove->Width))) {
ObjectToMove->XDir = -ObjectToMove->XDir;
X = ObjectToMove->X + ObjectToMove->XDir;
}
if ((Y < 0) || (Y > (SCREEN_HEIGHT - ObjectToMove->Height))) {
ObjectToMove->YDir = -ObjectToMove->YDir;
Y = ObjectToMove->Y + ObjectToMove->YDir;
}
/* Remember previous location for erasing purposes */
ObjectToMove->XOtherPage = ObjectToMove->X;
ObjectToMove->YOtherPage = ObjectToMove->Y;
ObjectToMove->X = X; /* set new location */
ObjectToMove->Y = Y;
}