Metropoli BBS
VIEWER: tc-016.c MODE: TEXT (ASCII)
/*_______________________________________________________________

tc-016.c

Function:  This program demonstrates arcade animation
techniques.  The user can use the keyboard to control the
high-speed movement of a ricocheting ball on the screen.

Compatibility:  Supports all graphics adapters and monitors.
The software uses the 640x200 2-color mode on the VGA, EGA,
and CGA.  By changing a single line in the configuration
subroutine you can run this program in the 16-color mode.

Remarks:  Refer to the book for a description of keyboard
controls.

Copyright 1988 Lee Adams and TAB BOOKS Inc.

_________________________________________________________________


I N C L U D E    F I L E S                                       */

#include <stdio.h>               /* supports the printf function */
#include <graphics.h>         /* supports the graphics functions */
#include <process.h>             /* supports the exit() function */
#include <bios.h>            /* supports read of keyboard buffer */
#include <alloc.h>                 /* supports memory allocation */
#include <dos.h>                   /* supports port manipulation */

/*_______________________________________________________________


D E C L A R A T I O N S                                          */

void keyboard(void);void quit_pgm(void);
void notice(float x,float y);void graphics_setup(void);
void noise(int hertz,int duration);

int t1=1,t2=1,x1=220,y1=100,x2=270,y2=120,
sx=220,sy=100,sxmove=3,symove=-1,sx1,sy1;
int C0=0,C1=1,C2=2,C3=3,C4=4,C5=5,C6=6,C7=7,C8=8,C9=9,C10=10,
C11=11,C12=12,C13=13,C14=14,C15=15,mode_flag=0;
int hz=450;

char far *gr_array1;                 /* pointer to graphic array */

/*_______________________________________________________________


M A I N    R O U T I N E                                         */

main(){
graphics_setup();                     /* establish graphics mode */

/*                            create and store the graphic array */
setcolor(C7);circle(x1+25,y1+10,22);
setfillstyle(SOLID_FILL,C4);floodfill(x1+25,y1+10,C7);
gr_array1=(char far*)farmalloc((unsigned long)imagesize(x1,y1,x2,y2));
getimage(x1,y1,x2,y2,gr_array1);
setfillstyle(SOLID_FILL,C0);bar(x1,y1,x2,y2);

/*                   create background and install graphic array */
setcolor(C7);
rectangle(0,10,639,189);                 /* animation boundaries */
moveto(319,188);lineto(319,110);              /* central barrier */
notice(0,192);
putimage(sx,sy,gr_array1,COPY_PUT);     /* install block graphic */

/*_____________bitblt animation manager____________*/

ANIMATE:                           /* animation loop begins here */
if (sx1<=268) goto LEFT_ARENA;
if (sx1>=320) goto RIGHT_ARENA;
goto IN_BETWEEN;

LEFT_ARENA:
if (sx1>=266){                                 /* right boundary */
if (sy1>=81){noise(hz,300);sxmove=-3;}}          /* hits barrier */
if (sx1<=3) {noise(hz,300);sxmove=3;}           /* left boundary */
if (sy1>=168) {noise(hz,300);symove=-1;}      /* bottom boundary */
if (sy1<=11) {noise(hz,300);symove=1;}           /* top boundary */
sx1=sx+sxmove;sy1=sy+symove;           /* calculate new position */
putimage(sx1,sy1,gr_array1,COPY_PUT);       /* install new array */
sx=sx1;sy=sy1;                         /* update sx,sy variables */
keyboard();                     /* check for user keyboard input */
goto ANIMATE;                                   /* infinite loop */

RIGHT_ARENA:
if (sx1>=586) {noise(hz,300);sxmove=-3;}       /* right boundary */
if (sx1<=322){                                  /* left boundary */
if (sy1>=81){noise(hz,300);sxmove=3;}}           /* hits barrier */
if (sy1>=168) {noise(hz,300);symove=-1;}      /* bottom boundary */
if (sy1<=11) {noise(hz,300);symove=1;}           /* top boundary */
sx1=sx+sxmove;sy1=sy+symove;           /* calculate new position */
putimage(sx1,sy1,gr_array1,COPY_PUT);       /* install new array */
sx=sx1;sy=sy1;                         /* update sx,sy variables */
keyboard();                     /* check for user keyboard input */
goto ANIMATE;                                   /* infinite loop */

IN_BETWEEN:
if (sy1<=11) {noise(hz,300);symove=1;}           /* top boundary */
if (sy1>=89) {noise(hz,300);symove=-1;}      /* hits barrier tip */
sx1=sx+sxmove;sy1=sy+symove;           /* calculate new position */
putimage(sx1,sy1,gr_array1,COPY_PUT);       /* install new array */
sx=sx1;sy=sy1;                         /* update sx,sy variables */
keyboard();                     /* check for user keyboard input */
goto ANIMATE;                                   /* infinite loop */

quit_pgm();}                       /* make the code bullet-proof */

/*_______________________________________________________________


SUBROUTINE: dynamic keyboard input

The subroutine is called by the main routine on each pass
through the animation loop.  If the Esc key is pressed, the
arcade game will terminate.  Press <h> to move right; press
<f> to move left.  Press <t> to move up; press <b> to move
down.                                                            */

void keyboard(void){
union u_type{int a;char b[3];}keystroke;char inkey=0;

if (bioskey(1)==0) return;                  /* if no key, return */
keystroke.a=bioskey(0);                   /* fetch ASCII code... */
inkey=keystroke.b[0];          /* ...and load code into variable */
switch (inkey){          /* make decision based upon ASCII value */
case 27:  quit_pgm();                                 /* Esc key */
case 104: sxmove=3;return;                   /* h key move right */
case 102: sxmove=-3;return;                   /* f key move left */
case 116: symove=-1;return;                     /* t key move up */
case 98:  symove=1;return;                    /* b key move down */
default:  return;}                  /* make routine bullet-proof */
}
/*_______________________________________________________________


SUBROUTINE: GRACEFUL EXIT FROM THE PROGRAM                       */

void quit_pgm(void){
cleardevice();restorecrtmode();exit(0);}

/*_______________________________________________________________


SUBROUTINE: GENERATE A SOUND

Enter with frequency, expressed as hertz in the range
40 to 4660.  A comfortable frequency range for the human
ear is 40 to 2400.  Enter with duration, expressed as an
integer to be used in a simple for...next delay loop.            */

void noise(int hertz,int duration){
int t1=1,high_byte=0,low_byte=0;
short count=0;unsigned char old_port=0,new_port=0;

if (hertz<40) return;       /* avoid math overflow for int count */
if (hertz>4660) return;     /* avoid math underflow for low_byte */
count=1193180L/hertz;                   /* determine timer count */
high_byte=count/256;low_byte=count-(high_byte*256);
outportb(0x43,0xB6);                  /* prep the timer register */
outportb(0x42,low_byte);                    /* send the low byte */
outportb(0x42,high_byte);                  /* send the high byte */
old_port=inportb(0x61);         /* store the existing port value */
new_port=(old_port | 0x03);  /* use OR to set bits 0 and 1 to on */
outportb(0x61,new_port);                  /* turn on the speaker */
for (t1=1;t1<=duration;t1++);                            /* wait */
outportb(0x61,old_port);                 /* turn off the speaker */
return;}                                     /* return to caller */

/*_______________________________________________________________


SUBROUTINE: VGA/EGA/CGA/MCGA compatibility module                */

void graphics_setup(void){
int graphics_adapter,graphics_mode;
detectgraph(&graphics_adapter,&graphics_mode);goto CGA_mode;
if (graphics_adapter==VGA) goto VGA_EGA_mode;          /* if VGA */
if (graphics_mode==EGAHI) goto VGA_EGA_mode;   /* if EGA and ECD */
if (graphics_mode==EGALO) goto VGA_EGA_mode;   /* if EGA and SCD */
if (graphics_adapter==CGA) goto CGA_mode;              /* if CGA */
if (graphics_adapter==MCGA) goto CGA_mode;            /* if MCGA */
goto abort_message;              /* if no VGA, EGA, CGA, or MCGA */

VGA_EGA_mode:                 /* establish 640x200 16-color mode */
graphics_adapter=EGA;graphics_mode=EGALO;
initgraph(&graphics_adapter,&graphics_mode,"");
mode_flag=3;setcolor(C7);
outtextxy(176,192,"640x480 16-color VGA and EGA mode.");
outtextxy(192,0,"USING C FOR ARCADE-STYLE ANIMATION");
return;


CGA_mode:                      /* establish 640x200 2-color mode */
graphics_adapter=CGA;graphics_mode=CGAHI;
initgraph(&graphics_adapter,&graphics_mode,"");
C0=0;C1=1;C2=1;C3=1;C4=1;C5=1;C6=1;C7=1;C8=1;C9=1;C10=1;
C11=1;C12=1;C13=1;C14=1;C15=1;
mode_flag=4;setcolor(C7);
outtextxy(184,192,"640x200 2-color VGA, EGA, and CGA mode.");
outtextxy(192,0,"USING C FOR ARCADE-STYLE ANIMATION");
return;

abort_message:
printf("\n\nUnable to proceed.\n");
printf("Requires VGA, EGA, MCGA, or CGA adapter\n");
printf("   with appropriate monitor.\n");
printf("Please refer to the book.\n\n");
exit(0);
}
/*_______________________________________________________________


SUBROUTINE: Copyright Notice

This subroutine displays the standard copyright notice.
If you are typing in this program from the book you can
safely omit this subroutine, provided that you also remove
the instruction "notice()" from the main routine.                */

int copyright[][3]={0x7c00,0x0000,0x0000,0x8231,
0x819c,0x645e,0xba4a,0x4252,0x96d0,0xa231,0x8252,0x955e,0xba4a,
0x43d2,0xf442,0x8231,0x825c,0x945e,0x7c00,0x0000,0x0000};

void notice(float x, float y){
int a,b,c; int t1=0;
for (t1=0;t1<=6;t1++){a=copyright[t1][0];b=copyright[t1][1];
c=copyright[t1][2];
setlinestyle(USERBIT_LINE,a,NORM_WIDTH);
moveto(x,y);lineto(x+15,y);
setlinestyle(USERBIT_LINE,b,NORM_WIDTH);
moveto(x+16,y);lineto(x+31,y);
setlinestyle(USERBIT_LINE,c,NORM_WIDTH);
moveto(x+32,y);lineto(x+47,y);y=y+1;};
setlinestyle(USERBIT_LINE,0xFFFF,NORM_WIDTH);
return;}

/*_______________________________________________________________

End of source code                                               */



[ RETURN TO DIRECTORY ]