home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 May
/
Pcwk5b98.iso
/
Gry
/
Breakout
/
MAIN1.C
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-24
|
56KB
|
1,698 lines
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <conio.h>
#include "allegro.h"
#include "breakout.h"
BITMAP *page1; // drawing screen
BITMAP *bg1; // display this between levels
BITMAP *startup; // main screen to show at start & between games
BITMAP *bl_block; // blue block
BITMAP *grn_block; // green block
BITMAP *prp_block; // purple block
BITMAP *red_block; // red block
BITMAP *laser_block; // laser block
BITMAP *explode_block; // explosion block
BITMAP *catch_block; // catch block
BITMAP *hit2_block; // hit this block twice to destroy
BITMAP *hit3_block; // hit this block three times to destroy
BITMAP *slow_block; // make ball go slow block
BITMAP *fast_block; // make ball go fast block
BITMAP *pwr_block; // power block (enables ball to explode blocks)
BITMAP *lrg_block; // enlarge bat block
BITMAP *sml_block; // shrink bat block
BITMAP *invinc_block; // invincible block
BITMAP *plus_block; // extra life block
BITMAP *next_block; // next level block
BITMAP *thru_block; // ball through blocks (doesn't bounce if this block collected)
BITMAP *explosion_frames; //explosion frames (10)
BITMAP *ball; // ball bitmap
BITMAP *pwr_ball; // power ball bitmap (explodes blocks on impact)
BITMAP *bat1; // bat 1 bitmap (normal size)
BITMAP *bat2; // bat 2 bitmap (large size)
BITMAP *bat3; // bat 3 bitmap (small size)
BITMAP *laser_bat; // laser bat
BITMAP *catch_bat; // catch bat
BITMAP *finish_screen; // exit screen
BITMAP *gameover_screen; // gameover screen
BITMAP *hiscore_screen; // hi score screen
BITMAP *help_screen; // help screen
PALLETE pallete1; // main game pallete
PALLETE pallete2; // pallete used for between level screen
PALLETE pal_startup; // main screen pallete (used at start of game ie main.bmp)
PALLETE pal_finish; // exit screen pallete
PALLETE pal_tmp;
PALLETE pal_gamover; // gameover screen pallete
PALLETE pal_hiscore; // hi score screen pallete
FILE *data; // set up file pointer for block data to load from disk
DATAFILE *fontfile; // file to hold fonts
SAMPLE *hit_block; // sound of ball hitting block
SAMPLE *explode; // explosion sound
SAMPLE *laser; // laser sound
SAMPLE *powerup; // power up sound
SAMPLE *bounce; // ball bounce off wall sound
SAMPLE *loose1; // loose a life sound
SAMPLE *newlevel; // new level music
SAMPLE *newlev2; // new level music
SAMPLE *catch; // catch ball sample (every time ball is catched)
SAMPLE *new_life; // play when a new life is obtained
SAMPLE *bat_sml; // small bat sound effect
SAMPLE *bat_lrg; // large bat sound effect
SAMPLE *half_amin; // half a minute music sample
SAMPLE *finish; // exit screen tune
SAMPLE *hiscore; // hiscore music
SAMPLE *ball_fast; // ball sppedup sound
SAMPLE *ball_slow; // ball slowdown sound
RGB col1={63,0,0}; // color for invincible box
RGB col2={63,63,0}; // used for pallete shifting
// global variable used for holding temporary characters
char ch_tmp[80]; // temp character string
int level; // game level
int ptr; // general pointer
int lives; // number of lives left
int score; // players score
int new_level; // set to 1 when all bricks have been destroyed.
int ball_out; // ball out of play flag (0= in play, 1= out of play)
int bat_type; // 1=normal bat, 2=large bat, 3=small bat
//
int laser_down; //|if set to '1' shifts laser block down screen
int laser_enable; //|if set to '1' turns bat into laser and enables firing
int las_x1,las_y1; //|laser beam x,y position
int las_x2,las_y2; //|laser beam x,y position
int las_firing1; //|set to '1' if laser beam is in process of firing
int laser_ptr; //|points to the laser block number just hit
int las_firing2; //|set to '1' if laser beam is in process of firing
//
int catch_down; //|if set to '1' shifts catch block down screen
int catch_enable; //|if set to '1' turns bat into catch bat
int catch_ptr; //|points to the catch block number just hit
//
int power_down; //|if set to '1 shifts power block down screen
int power_enable; //|if set to '1' turns ball into power ball
int power_ptr; //|points to the power block number just hit
int plus_down; //|if set to '1 shifts plus block down screen
int plus_enable; //|if set to '1' adds a life
int plus_ptr; //|points to the plus block number just hit
int next_down; //|if set to '1 shifts next block down screen
int next_enable; //|if set to '1' skips the level
int next_ptr; //|points to the next block number just hit
int thru_down; //|if set to '1 shifts thru block down screen
int thru_enable; //|if set to '1' ball will go through blocks (ie doesnt bounce)
int thru_ptr; //|points to the thru block number just hit
int bounces; // no of bounces ball has made (used to determine velocity)
int vel_x; // ball velocity
int vel_y;
int bounce_angle; // angle of bounce off ball (0=normal, 1=high)
int frame_tstart; // stores time for frames per second routine
int frame_ctr; // counts number of frames
int frame_fps;
int frame_delay; // used by fps routine to limit fps
int explde[10]; // array to hold tiles that are to be exploded
int explode_frame[10]; // up to 10 explosions at same time.
// holds the current frame to be displayed
int frame_skip; // used to skip frames
int pal_cycles; // used as counter for pallete cycling (see drawing_screen()
int bounce_time; //monitors time between ball hitting bat
int input_device; //The mouse is used for all menus, however
//the game game be played using the
//mouse, keyboard or joystick.
// 1=mouse, 2=keyboard, 3=joystick
// default is mouse
// define structure for holding block positions for each level
// bx,by : x,y position of block
// bw,bh : width & height of block
// b_show : 0 = not displayed, 1=displayed
// b_type : 1= blue block, 2= green, 3=purple, 4=red, 5=laser
// 6= explode 7=catch, 8=hit2 , 9=hit3 , A=slow
// B=fast, C=power ball, D=small bat, E=large bat
// F=extra life, G=next level, H=ball thru blocks
// hits : no of hits required to destroy block
struct {
int bx,by,bw,bh,b_show,b_type,hits;
}blocks[450];
// define structure for holding ball position
// bx,by : x,y position of ball
// dx,dy : direction of ball. eg. dx=-1 (left) dx=+1 (right)
struct {
int bx,by,dx,dy;
}balls[3];
// define structure for holding bat position data
// mx.my,mw : x,y,width of bat
// bb : last button pressed (1= left, 2=right)
struct {
int bx,by,bb,bw;
}bat[4];
// define structure for holding the hi-score table
struct {
char names[22];
int scores;
} hiscores[10];
void load_bitmaps()
{
// LOAD BITMAPS INTO MEMORY
// load background screen and set pallete
sprintf(ch_tmp,"backgnd.bmp"); // place string into ch_tmp array
page1=load_bitmap(ch_tmp,pallete1); // load background into drawing bitmap
set_pallete(pallete1); // set pallete
bg1=load_bitmap("newlevel.bmp",pallete2); // new level background
startup=load_bitmap("main.bmp",pal_startup); // load stratup screen
//load blocks
bl_block=load_bitmap("bk_blue.bmp",pal_tmp);
grn_block=load_bitmap("bk_grn.bmp",pal_tmp);
prp_block=load_bitmap("bk_prpl.bmp",pal_tmp);
red_block=load_bitmap("bk_red.bmp",pal_tmp);
laser_block=load_bitmap("bk_lsr.bmp",pal_tmp);
explode_block=load_bitmap("bk_exp.bmp",pal_tmp);
catch_block=load_bitmap("bk_cth.bmp",pal_tmp);
hit2_block=load_bitmap("bk_2ht.bmp",pal_tmp);
hit3_block=load_bitmap("bk_3ht.bmp",pal_tmp);
slow_block=load_bitmap("bk_slw.bmp",pal_tmp);
fast_block=load_bitmap("bk_fst.bmp",pal_tmp);
pwr_block=load_bitmap("bk_pwr.bmp",pal_tmp);
sml_block=load_bitmap("bk_sml.bmp",pal_tmp);
lrg_block=load_bitmap("bk_lrg.bmp",pal_tmp);
invinc_block=load_bitmap("bk_inv.bmp",pal_tmp);
plus_block=load_bitmap("bk_plus.bmp",pal_tmp);
next_block=load_bitmap("bk_next.bmp",pal_tmp);
thru_block=load_bitmap("bk_thru.bmp",pal_tmp);
finish_screen=load_bitmap("finish.bmp",pal_finish);
gameover_screen=load_bitmap("gameover.bmp",pal_gamover);
hiscore_screen=load_bitmap("hiscores.bmp",pal_hiscore);
help_screen=load_bitmap("help.bmp",pal_tmp);
// load balls
ball=load_bitmap("ball.bmp",pal_tmp);
pwr_ball=load_bitmap("ball1.bmp",pal_tmp);
// load bats
bat1=load_bitmap("bat1.bmp",pal_tmp);
bat2=load_bitmap("bat2.bmp",pal_tmp);
bat3=load_bitmap("bat3.bmp",pal_tmp);
laser_bat=load_bitmap("bat_lsr.bmp",pal_tmp);
catch_bat=load_bitmap("bat_cth.bmp",pal_tmp);
// load explosion frames
explosion_frames=load_bitmap("explode.bmp",pal_tmp);
// load font file
fontfile=load_datafile("breakout.dat");
}
void load_samples()
{
// Load sound samples
hit_block=load_sample("block.wav");
explode=load_sample("explode.wav");
laser=load_sample("laser.wav");
powerup=load_sample("powerup.wav");
bounce=load_sample("bounce.wav");
loose1=load_sample("loose1.wav");
newlevel=load_sample("newlev1.wav");
newlev2=load_sample("newlev2.wav");
catch=load_sample("catch.wav");
new_life=load_sample("newlife.wav");
bat_lrg=load_sample("bat_lrg.wav");
bat_sml=load_sample("bat_sml.wav");
half_amin=load_sample("half.wav");
finish=load_sample("finish.wav");
hiscore=load_sample("hiscore.wav");
ball_fast=load_sample("fast.wav");
ball_slow=load_sample("slow.wav");
}
// load blocks of data according to level
// data is loaded as ascii values into ch
// ch=48 block 0 dont display (0)
// ch=49 block 1 blue (1)
// ch=50 block 2 green (2)
// ch=51 block 3 purple (3)
// ch=52 block 4 red (4)
// ch=53 block 5 laser (5)
// ch=54 block 6 explosion (6)
// ch=55 block 7 catch (7)
// ch=56 block 8 hit 2 (8)
// ch=57 block 9 hit 3 (9)
// ch=65 block 10 slow ball (A)
// ch=66 block 11 fast ball (B)
// ch=67 block 12 power block (C)
// ch=68 block 13 shrink bat block (D)
// ch=69 block 14 enlarge bat block (E)
// ch=70 block 15 invincible block (F)
// ch=71 block 16 Extra life (G)
// ch=72 block 17 Skip to next level (H)
// ch=73 block 18 ball through blocks (I)
void load_data(level)
{
int ch,ptr,x,y;
x=80;
y=60;
// open block position data file (different for each level)
sprintf(ch_tmp,"level%d",level);
data=fopen(ch_tmp,"r");
for (ptr=0;ptr<303;ptr++){
ch=getc(data);
if (ch!=10){
blocks[ptr].bx=x;
blocks[ptr].by=y;
blocks[ptr].bw=31;
blocks[ptr].bh=12;
}
if (ch==48){
blocks[ptr].b_show=0;
blocks[ptr].b_type=0;
blocks[ptr].hits=0;
}
if (ch==49){
blocks[ptr].b_show=1;
blocks[ptr].b_type=1;
blocks[ptr].hits=1;
}
if (ch==50){
blocks[ptr].b_show=1;
blocks[ptr].b_type=2;
blocks[ptr].hits=1;
}
if (ch==51){
blocks[ptr].b_show=1;
blocks[ptr].b_type=3;
blocks[ptr].hits=1;
}
if (ch==52){
blocks[ptr].b_show=1;
blocks[ptr].b_type=4;
blocks[ptr].hits=1;
}
if (ch==53){
blocks[ptr].b_show=1;
blocks[ptr].b_type=5;
blocks[ptr].hits=1;
}
if (ch==54){
blocks[ptr].b_show=1;
blocks[ptr].b_type=6;
blocks[ptr].hits=1;
}
if (ch==55){
blocks[ptr].b_show=1;
blocks[ptr].b_type=7;
blocks[ptr].hits=1;
}
if (ch==56){
blocks[ptr].b_show=1;
blocks[ptr].b_type=8;
blocks[ptr].hits=2;
}
if (ch==57){
blocks[ptr].b_show=1;
blocks[ptr].b_type=9;
blocks[ptr].hits=3;
}
if (ch==65){
blocks[ptr].b_show=1;
blocks[ptr].b_type=10;
blocks[ptr].hits=1;
}
if (ch==66){
blocks[ptr].b_show=1;
blocks[ptr].b_type=11;
blocks[ptr].hits=1;
}
if (ch==67){
blocks[ptr].b_show=1;
blocks[ptr].b_type=12;
blocks[ptr].hits=1;
}
if (ch==68){
blocks[ptr].b_show=1;
blocks[ptr].b_type=13;
blocks[ptr].hits=1;
}
if (ch==69){
blocks[ptr].b_show=1;
blocks[ptr].b_type=14;
blocks[ptr].hits=1;
}
if (ch==70){
// b_show=2 means this block type is invincible
blocks[ptr].b_show=2;
blocks[ptr].b_type=15;
blocks[ptr].hits=1;
}
if (ch==71){
blocks[ptr].b_show=1;
blocks[ptr].b_type=16;
blocks[ptr].hits=1;
}
if (ch==72){
blocks[ptr].b_show=1;
blocks[ptr].b_type=17;
blocks[ptr].hits=1;
}
if (ch==73){
blocks[ptr].b_show=1;
blocks[ptr].b_type=18;
blocks[ptr].hits=1;
}
if (ch!=10){
x+=32;
if (x==560){
x=80;
y+=14;
}
}
}
fclose (data);
}
// draw to drawing screen
void drawing_screen()
{
int x,y,show,type,ptr;
// update drawing screen with blocks
for (ptr=0; ptr<303; ptr++) {
x=blocks[ptr].bx;
y=blocks[ptr].by;
show=blocks[ptr].b_show;
type=blocks[ptr].b_type;
if (show!=0){
if (type==1) blit(bl_block,page1,0,0,x,y,31,13); // blue
if (type==2) blit(grn_block,page1,0,0,x,y,31,13); // green
if (type==3) blit(prp_block,page1,0,0,x,y,31,13); // purple
if (type==4) blit(red_block,page1,0,0,x,y,31,13); // red
if (type==5) blit(laser_block,page1,0,0,x,y,31,13); // laser
if (type==6) blit(explode_block,page1,0,0,x,y,31,13); // explosion
if (type==7) blit(catch_block,page1,0,0,x,y,31,13); // catch
if (type==8) blit(hit2_block,page1,0,0,x,y,31,13); // 2 hit block
if (type==9) blit(hit3_block,page1,0,0,x,y,31,13); // 3 hit block
if (type==10) blit(slow_block,page1,0,0,x,y,31,13); // ball slow block
if (type==11) blit(fast_block,page1,0,0,x,y,31,13); // ball fast block
if (type==12) blit(pwr_block,page1,0,0,x,y,31,13); // power block
if (type==13) blit(sml_block,page1,0,0,x,y,31,13); // shrink bat block
if (type==14) blit(lrg_block,page1,0,0,x,y,31,13); // enlarge bat block
if (type==15) blit(invinc_block,page1,0,0,x,y,31,13); // invincible block
if (type==16) blit(plus_block,page1,0,0,x,y,31,13); // extra life block
if (type==17) blit(next_block,page1,0,0,x,y,31,13); // skip to next level block
if (type==18) blit(thru_block,page1,0,0,x,y,31,13); // ball thru blocks
}
}
// Shift the pallete for the invincible blocks
// swap colors 14 & 15
if (pal_cycles==20) {vsync();set_color(14,&col1);set_color(15,&col2);}
if (pal_cycles==40) {vsync();set_color(14,&col2);set_color(15,&col1);pal_cycles=0;}
pal_cycles++;
}
// copy drawing screen to output screen
void copy_drawing()
{
blit(page1,screen,0,0,0,0,640,480);
}
// copy background screen to drawing screen
void copy_backgrnd()
{
// replaced blit command with this
rectfill(page1,78,52,562,479,0);
rectfill(page1,78,5,562,30,1);
}
void show_score()
{
text_mode(-1);
sprintf(ch_tmp,"%d",score);
textout(page1,fontfile[SMALL].dat,ch_tmp,80,11,86);
textout(page1,fontfile[SMALL].dat,ch_tmp,81,12,129);
sprintf(ch_tmp,"LEVEL %d",level);
textout(page1,fontfile[SMALL].dat,ch_tmp,382,12,86);
textout(page1,fontfile[SMALL].dat,ch_tmp,383,13,129);
sprintf(ch_tmp,"LIVES %d",lives);
textout(page1,fontfile[SMALL].dat,ch_tmp,485,12,86);
textout(page1,fontfile[SMALL].dat,ch_tmp,486,13,129);
}
void initialise_variables()
{
int n;
frame_delay=1;
frame_fps=0;
score=0;
level=0;
lives=4;
bat_type=1; // 1= normal ball, 2=large ball, 3=small ball
ball_out=0; // 0=ball in play, 1= ball out of play
bounces=0; // set ball bounces counter to zero
vel_x=2; // ball velocity (used as a multiplier for dx & dy)
vel_y=2;
laser_down=0; //
laser_enable=0;// disable laser
laser_ptr=-1;
catch_down=0;
catch_enable=0;
catch_ptr=-1;
power_down=0;
power_enable=0;
power_ptr=-1;
if (input_device==0) input_device=1;
// ensure that nothing is exploded at start of game
for (n=1 ;n<11 ;n++) {
explde[n]=0;
explode_frame[n]=0;
}
}
void update_bat_position()
{
int x,b;
// get input
// get mouse input
if (input_device==1) {
{x=mouse_x; b=mouse_b;}
bat[bat_type].bx=x;
bat[bat_type].bb=b;
}
// get keyboard input if required
if (input_device==2) {
if (key[KEY_CONTROL]) bat[bat_type].bb=1;
if (key[KEY_CONTROL] ==FALSE) bat[bat_type].bb=0;
if (key[KEY_ALT]) bat[bat_type].bb=2;
if (key[KEY_LEFT]) bat[bat_type].bx-=8;
if (key[KEY_RIGHT]) bat[bat_type].bx+=8;
}
// get joystick input if required
if (input_device==3) {
poll_joystick();
if (joy_b1!=0) bat[bat_type].bb=1;
if (joy_b1==0) bat[bat_type].bb=0;
if (joy_b2!=0) bat[bat_type].bb=2;
if (joy_left) bat[bat_type].bx-=8;
if (joy_right) bat[bat_type].bx+=8;
}
// ensure bat is not off side of screen
if (bat[bat_type].bx+bat[bat_type].bw>563) {bat[bat_type].bx=563-bat[bat_type].bw; mouse_x=563;}
if (bat[bat_type].bx<78) bat[bat_type].bx=78;
// update drawing screen with new bat position
// if the laser enable flag is set draw a laser bat
if (laser_enable==1) draw_sprite(page1,laser_bat,bat[1].bx,bat[1].by);
// if the catch enable flag is set draw a catch bat
if (catch_enable==1) draw_sprite(page1,catch_bat,bat[1].bx,bat[1].by);
// If one of the above bats is not displayed, draw a normal bat
if ((laser_enable!=1) && (catch_enable!=1)){
if (bat_type==1) draw_sprite(page1,bat1,bat[bat_type].bx,bat[bat_type].by);
if (bat_type==2) draw_sprite(page1,bat2,bat[bat_type].bx,bat[bat_type].by);
if (bat_type==3) draw_sprite(page1,bat3,bat[bat_type].bx,bat[bat_type].by);
}
}
// if a special block has been hit, make it move down the screen
void move_blocks()
{
// only update the block position evey 8 frames out of 10
if (frame_skip>1) {
// has the move laser block down flag been set ?
if (laser_down==1) {
// as we want to see the laser block falling, re-enable block show
blocks[laser_ptr].b_show=1;
// move laser block down one pixel
blocks[laser_ptr].by+=2;
// has the laser block missed the bat and reached the bottom of the screen ?
if (blocks[laser_ptr].by>455) {
laser_down=0;
blocks[laser_ptr].b_show=0;
}
// Has the laser block hit the bat, if so set the enable laser flag
if (((blocks[laser_ptr].bx>bat[bat_type].bx)
&&(blocks[laser_ptr].bx<bat[bat_type].bx+bat[bat_type].bw))
||((blocks[laser_ptr].bx+blocks[laser_ptr].bw >bat[bat_type].bx)
&&(blocks[laser_ptr].bx+blocks[laser_ptr].bw <bat[bat_type].bx+bat[bat_type].bw))){
if (blocks[laser_ptr].by>450) {
bat[1].bx=bat[bat_type].bx;
bat_type=1;
laser_enable=1;
catch_enable=0;
play_sample(powerup,255,128,6000,FALSE);
score+=100;
blocks[laser_ptr].b_show=0;
}
}
}
// *******************************************************************************************
// has the move catch block down flag been set ?
if (catch_down==1) {
// as we want to see the catch block falling, re-enable block show
blocks[catch_ptr].b_show=1;
// move catch block down one pixel
blocks[catch_ptr].by+=2;
// has the catch block missed the bat and reached the bottom of the screen ?
if (blocks[catch_ptr].by>455) {
catch_down=0;
blocks[catch_ptr].b_show=0;
}
// Has the catch block hit the bat, if so set the enable catch flag
if (((blocks[catch_ptr].bx>bat[bat_type].bx)
&&(blocks[catch_ptr].bx<bat[bat_type].bx+bat[bat_type].bw))
||((blocks[catch_ptr].bx+blocks[catch_ptr].bw >bat[bat_type].bx)
&&(blocks[catch_ptr].bx+blocks[catch_ptr].bw <bat[bat_type].bx+bat[bat_type].bw))) {
if (blocks[catch_ptr].by>450) {
bat[1].bx=bat[bat_type].bx;
bat_type=1;
catch_enable=1;
laser_enable=0;
play_sample(powerup,255,128,6000,FALSE);
score+=100;
blocks[catch_ptr].b_show=0;
}
}
}
// *******************************************************************************************
// has the move power block down flag been set ?
if (power_down==1) {
// as we want to see the power block falling, re-enable block show
blocks[power_ptr].b_show=1;
// move power block down one pixel
blocks[power_ptr].by+=2;
// has the power block missed the bat and reached the bottom of the screen ?
if (blocks[power_ptr].by>455) {
power_down=0;
blocks[power_ptr].b_show=0;
}
// Has the power block hit the bat, if so set the enable power flag
if (((blocks[power_ptr].bx>bat[bat_type].bx)
&&(blocks[power_ptr].bx<bat[bat_type].bx+bat[bat_type].bw))
||((blocks[power_ptr].bx+blocks[power_ptr].bw >bat[bat_type].bx)
&&(blocks[power_ptr].bx+blocks[power_ptr].bw <bat[bat_type].bx+bat[bat_type].bw))) {
if (blocks[power_ptr].by>450) {
power_enable=1;
play_sample(powerup,255,128,6000,FALSE);
score+=100;
blocks[power_ptr].b_show=0;
}
}
}
// *******************************************************************************************
// has the move plus life block down flag been set ?
if (plus_down==1) {
// as we want to see the plus block falling, re-enable block show
blocks[plus_ptr].b_show=1;
// move plus block down one pixel
blocks[plus_ptr].by+=2;
// has the plus block missed the bat and reached the bottom of the screen ?
if (blocks[plus_ptr].by>455) {
plus_down=0;
blocks[plus_ptr].b_show=0;
}
// Has the plus block hit the bat, if so set the enable plus flag
if (((blocks[plus_ptr].bx>bat[bat_type].bx)
&&(blocks[plus_ptr].bx<bat[bat_type].bx+bat[bat_type].bw))
||((blocks[plus_ptr].bx+blocks[plus_ptr].bw >bat[bat_type].bx)
&&(blocks[plus_ptr].bx+blocks[plus_ptr].bw <bat[bat_type].bx+bat[bat_type].bw))) {
if (blocks[plus_ptr].by>450) {
plus_enable=1;
play_sample(new_life,255,128,1000,FALSE);
score+=100;
blocks[plus_ptr].b_show=0;
}
}
}
// *******************************************************************************************
// has the move next level block down flag been set ?
if (next_down==1) {
// as we want to see the next block falling, re-enable block show
blocks[next_ptr].b_show=1;
// move next block down one pixel
blocks[next_ptr].by+=2;
// has the next block missed the bat and reached the bottom of the screen ?
if (blocks[next_ptr].by>455) {
next_down=0;
blocks[next_ptr].b_show=0;
}
// Has the next block hit the bat, if so set the enable next flag
if (((blocks[next_ptr].bx>bat[bat_type].bx)
&&(blocks[next_ptr].bx<bat[bat_type].bx+bat[bat_type].bw))
||((blocks[next_ptr].bx+blocks[next_ptr].bw >bat[bat_type].bx)
&&(blocks[next_ptr].bx+blocks[next_ptr].bw <bat[bat_type].bx+bat[bat_type].bw))) {
if (blocks[next_ptr].by>450) {
next_enable=1;
play_sample(powerup,255,128,6000,FALSE);
score+=100;
blocks[next_ptr].b_show=0;
}
}
}
// *******************************************************************************************
// has the move thru level block down flag been set ?
if (thru_down==1) {
// as we want to see the thru block falling, re-enable block show
blocks[thru_ptr].b_show=1;
// move thru block down one pixel
blocks[thru_ptr].by+=2;
// has the thru block missed the bat and reached the bottom of the screen ?
if (blocks[thru_ptr].by>455) {
thru_down=0;
blocks[thru_ptr].b_show=0;
}
// Has the thru block hit the bat, if so set the enable thru flag
if (((blocks[thru_ptr].bx>bat[bat_type].bx)
&&(blocks[thru_ptr].bx<bat[bat_type].bx+bat[bat_type].bw))
||((blocks[thru_ptr].bx+blocks[thru_ptr].bw >bat[bat_type].bx)
&&(blocks[thru_ptr].bx+blocks[thru_ptr].bw <bat[bat_type].bx+bat[bat_type].bw))) {
if (blocks[thru_ptr].by>450) {
thru_enable=1;
play_sample(powerup,255,128,6000,FALSE);
score+=100;
blocks[thru_ptr].b_show=0;
}
}
}
}
}
void initial_ball_position()
{
int button,offset;
balls[1].bx=315;
balls[1].by=452;
balls[1].dx=1;
balls[1].dy=-1;
// initial bat position
bat[1].bx=310;
bat[1].by=460;
bat[1].bw=70;
bat[2].bx=215;
bat[2].by=460;
bat[2].bw=100;
bat[3].bx=315;
bat[3].by=460;
bat[3].bw=50;
offset=0;
// hold onto the ball until left mouse button is pressed
{show_score(); drawing_screen(); copy_drawing();}
if (lives!=0) {
if (ball_out==0) fade_in(pallete1,1);
poll_joystick();
while (((bat[bat_type].bb!=1)&&(key[KEY_CONTROL])!=TRUE)&&(joy_b1!=1)) {
poll_joystick();
update_bat_position();
show_score();
balls[1].bx=(bat[bat_type].bx+(bat[bat_type].bw/2)-3)+offset;
draw_sprite(page1,ball,balls[1].bx,balls[1].by);
{drawing_screen(); copy_drawing(); copy_backgrnd();}
if (bat[bat_type].bb==2) offset++;
if ((balls[1].bx+offset)-12>bat[bat_type].bx+bat[bat_type].bw) {
offset=1-(bat[bat_type].bw/2);
}
// if ball positioned on left side of bat start ball moving left
if (balls[1].bx+3<(bat[bat_type].bx+bat[bat_type].bw/2)) balls[1].dx=-1;
// if ball positioned on right side of bat start ball moving right
if (balls[1].bx+3>=(bat[bat_type].bx+bat[bat_type].bw/2)) balls[1].dx=+1;
move_blocks();
{frame_skip ++; if (frame_skip==10) frame_skip=1;}
}
}
// record time for fps routine
frame_tstart=rawclock();
frame_ctr=0;
}
void update_ball_position()
{
int bat_centre;
if (bounces>0) {vel_x=2+bounce_angle; vel_y=2;}
if (bounces>2000) {vel_x=3+bounce_angle*2; vel_y=3;}
if (bounces>4000) {vel_x=4+(bounce_angle*3); vel_y=4;}
// bounce ball around screen
balls[1].bx=balls[1].bx+(balls[1].dx)*vel_x;
balls[1].by=balls[1].by+(balls[1].dy)*vel_y;
if (balls[1].bx>550) {balls[1].dx= -balls[1].dx;play_sample(bounce,255,255,1000,FALSE);score++;}
if (balls[1].bx<85) {balls[1].dx= -balls[1].dx;play_sample(bounce,255,0,1000,FALSE);score++;}
if (balls[1].by<62) {balls[1].dy= -balls[1].dy;play_sample(bounce,255,128,1000,FALSE);score++;}
// increase ball bounce counter
bounces++;
// if ball drops below level of bat then it is out of play
if (balls[1].by>452) {
// check to see if it is over the bat
if ((balls[1].bx+10<bat[bat_type].bx)||(balls[1].bx-10>bat[bat_type].bx+bat[bat_type].bw)) ball_out=1;
else {
//bounce ball off bat
// if the ball bounces off the outer section of the bat
// increase the bounce angle
bat_centre=bat[bat_type].bx+(bat[bat_type].bw/2);
balls[1].dy=-balls[1].dy;
bounce_angle=0;
if (bat_type==1) {if ((balls[1].bx+5<bat_centre-15)|| (balls[1].bx+5>bat_centre+15)) bounce_angle=1;}
if (bat_type==2) {if ((balls[1].bx+5<bat_centre-30)|| (balls[1].bx+5>bat_centre+30)) bounce_angle=1;}
if (bat_type==3) {if ((balls[1].bx+5<bat_centre-10)|| (balls[1].bx+5>bat_centre+10)) bounce_angle=1;}
play_sample(bounce,255,128,1000,FALSE);score++;
// start monitoring time between ball hitting bat
bounce_time=rawclock();
if (mouse_b==2) balls[1].bx+=2;
}
}
// update drawing screen with new ball position
if ((power_enable==1)|| (thru_enable==1)) {
draw_sprite(page1,pwr_ball,balls[1].bx,balls[1].by);
} else draw_sprite(page1,ball,balls[1].bx,balls[1].by);
}
// Check for ball collision with brick
void ball_collide_brick()
{
int skip,ctr;
new_level=1;
for (ptr=0; ptr<303; ptr++) {
// if there is a brick on the screen, set new level flag to false.
if (blocks[ptr].b_show==1) new_level=0;
// is the ball over a displayed brick
// but not one which is moving
if ((balls[1].bx+vel_x+5+bounce_angle>=blocks[ptr].bx) && //LEFT
(balls[1].bx-vel_x-bounce_angle<=blocks[ptr].bx+blocks[ptr].bw) && //RIGHT
(balls[1].by+vel_y+5>=blocks[ptr].by) && //TOP
(balls[1].by-vel_y<=blocks[ptr].by+blocks[ptr].bh)&& //BOTTOM
(blocks[ptr].b_show!=0) &&
(ptr!=laser_ptr) && (ptr!=catch_ptr) && (ptr!=power_ptr)) {
// Yes, the ball is over a brick
// Play sound
play_sample(hit_block,255,(balls[1].bx),1000,FALSE);
// bounce ball
// only if the ball through flag is not set
// or if the block is invincible
if ((thru_enable==0)|| (blocks[ptr].b_type==15)){
skip=0;
// ball hits bottom of brick
for (ctr=0; ctr<=vel_y; ctr++) {
if (balls[1].by-ctr==blocks[ptr].by+blocks[ptr].bh) {
balls[1].dy=-balls[1].dy;
balls[1].by=balls[1].by+vel_y;
skip=1;
break;
}
}
// ball hits top of brick
for (ctr=0; ctr<=vel_y; ctr++) {
if ((balls[1].by+ctr+6==blocks[ptr].by)&& (skip==0)) {
balls[1].dy=-balls[1].dy;
balls[1].by=balls[1].by-vel_y;
skip=1;
break;
}
}
// ball hits left side of brick
for (ctr=0; ctr<=vel_x+bounce_angle; ctr++) {
if ((balls[1].bx+ctr+6+bounce_angle==blocks[ptr].bx)&&(skip==0)) {
balls[1].dx=-balls[1].dx;
balls[1].bx=balls[1].bx-vel_x;
skip=1;
break;
}
}
// ball hits right side of brick
for (ctr=0; ctr<=vel_x+bounce_angle+1; ctr++) {
if ((balls[1].bx-ctr-bounce_angle==blocks[ptr].bx+blocks[ptr].bw)&&(skip==0)) {
balls[1].dx=-balls[1].dx;
balls[1].bx=balls[1].bx+vel_x;
break;
}
}
// this is added insurance
if (balls[1].dy==0) balls[1].dy=1;
if (balls[1].dx==0) balls[1].dx=1;
}
// if the power ball is enabled, explode the surrounding bricks
if ((power_enable==1) && (blocks[ptr].b_show==1)) {
// Play sound
play_sample(explode,255,(blocks[ptr].bx),1000,FALSE);
// point to the bricks to explode
{explde[1]=ptr;blocks[ptr].b_show=0;score+=20;}
if (blocks[ptr+1].b_show==1) {explde[2]=ptr+1; blocks[ptr+1].b_show=0;score+=20;}
if (blocks[ptr-1].b_show==1) {explde[3]=ptr-1; blocks[ptr-1].b_show=0;score+=20;}
if (blocks[ptr-16].b_show==1){explde[4]=ptr-16;blocks[ptr-16].b_show=0;score+=20;}
if (blocks[ptr+16].b_show==1){explde[5]=ptr+16;blocks[ptr+16].b_show=0;score+=20;}
}
// erase the brick if the blocks hit value is zero
if ((blocks[ptr].hits >0)&& (blocks[ptr].b_show!=2)) blocks[ptr].hits--;
if (blocks[ptr].hits <1) {blocks[ptr].b_show=0;score+=20;}
// The ball has just bounced off an exploding brick
if (blocks[ptr].b_type==6) {
// Play sound
play_sample(explode,255,(blocks[ptr].bx),1000,FALSE);
// point to the bricks to explode
explde[1]=ptr;
if (blocks[ptr+1].b_show==1) {explde[2]=ptr+1; blocks[ptr+1].b_show=0;score+=20;}
if (blocks[ptr-1].b_show==1) {explde[3]=ptr-1; blocks[ptr-1].b_show=0;score+=20;}
if (blocks[ptr-16].b_show==1){explde[4]=ptr-16;blocks[ptr-16].b_show=0;score+=20;}
if (blocks[ptr+16].b_show==1){explde[5]=ptr+16;blocks[ptr+16].b_show=0;score+=20;}
}
// The ball has just bounced off a laser brick
// set flag to start laser blocks moving down the screen
// dont move the laser block down if one is already moving
if ((blocks[ptr].b_type==5) && (laser_down!=1)) {
laser_down=1;
laser_ptr=ptr;
score+=100;
}
// The ball has just bounced off a catch brick
// set flag to start catch block moving down the screen
// dont move the catch block down if one is already moving
if ((blocks[ptr].b_type==7) && (catch_down!=1)) {
catch_down=1;
catch_ptr=ptr;
}
// The ball has just bounced off a slow ball brick
// adjust 'bounce' variable so that the ball moves slowly
if (blocks[ptr].b_type==10) {
bounces=0;
play_sample(ball_slow,255,128,1000,FALSE);
}
// The ball has just bounced off a fast ball brick
// adjust 'bounce' variable so that the ball moves fast
if (blocks[ptr].b_type==11) {
bounces=8000;
play_sample(ball_fast,255,128,1000,FALSE);
}
// The ball has just bounced off a power ball brick
// set flag to start power block moving down the screen
// dont move the power block down if one is already moving
if ((blocks[ptr].b_type==12) && (power_down!=1)) {
power_down=1;
power_ptr=ptr;
}
// The ball has just bounced off a small bat brick
// set the bat type to small
if (blocks[ptr].b_type==13) {
bat[3].bx=bat[bat_type].bx; // copy x pos of last bat to new bat
bat_type=3;
play_sample(bat_sml,255,128,1000,FALSE);
{catch_enable=0;laser_enable=0;}
}
// The ball has just bounced off a large bat brick
// set the bat type to large
if (blocks[ptr].b_type==14) {
{catch_enable=0;laser_enable=0;}
bat[2].bx=bat[bat_type].bx; // copy x pos of last bat to new bat
bat_type=2;
play_sample(bat_lrg,255,128,1000,FALSE);
}
// The ball has just bounced off a plus 1 life brick
// set flag to start plus block moving down the screen
// dont move the plus block down if one is already moving
if ((blocks[ptr].b_type==16) && (plus_down!=1)) {
plus_down=1;
plus_ptr=ptr;
}
// The ball has just bounced off a next level brick
// set flag to start next level block moving down the screen
// dont move the next level block down if one is already moving
if ((blocks[ptr].b_type==17) && (next_down!=1)) {
next_down=1;
next_ptr=ptr;
}
// The ball has just bounced off a ball thru brick
// set flag to start ball thru block moving down the screen
// dont move the ball thru block down if one is already moving
if ((blocks[ptr].b_type==18) && (thru_down!=1)) {
thru_down=1;
thru_ptr=ptr;
}
}
}
}
void explode_bricks()
{
int n,x,y;
// array 'explode' hold the brick no. to explode
// array 'explode_frame' holds the animation frame to display.
// there are 10 animation frames per explosion.
for (n=0; n<10; n++) {
if (explde[n]>0) {
// advance frame every 10 frames of game
if (frame_skip>5) explode_frame[n]++;
x=blocks[explde[n]].bx;
y=blocks[explde[n]].by;
if (explode_frame[n]==1) blit (explosion_frames,page1,0,0,x,y,25,10);
if (explode_frame[n]==2) blit (explosion_frames,page1,24,0,x,y,25,10);
if (explode_frame[n]==3) blit (explosion_frames,page1,48,0,x,y,25,10);
if (explode_frame[n]==4) blit (explosion_frames,page1,72,0,x,y,25,10);
if (explode_frame[n]==5) blit (explosion_frames,page1,96,0,x,y,25,10);
if (explode_frame[n]==6) blit (explosion_frames,page1,120,0,x,y,25,10);
if (explode_frame[n]==7) blit (explosion_frames,page1,144,0,x,y,25,10);
if (explode_frame[n]==8) blit (explosion_frames,page1,168,0,x,y,25,10);
if (explode_frame[n]==9) blit (explosion_frames,page1,192,0,x,y,25,10);
if (explode_frame[n]==10) {
blit (explosion_frames,page1,279,0,x,y-10,31,31);
explde[n]=0;
explode_frame[n]=0;
}
}
}
}
void fire_laser()
{
// only fire the laser if the conditions below are true
// ie laser enabled, left mouse button pressed, laser not already firing
if((bat[1].bb==1) && (laser_enable==1) && (las_firing1==0)) {
las_x1=bat[1].bx+10;
las_y1=460;
las_firing1=1;
// Play sound
play_sample(laser,255,bat[1].bx,2000,FALSE);
}
// move laser beam up screen
if(las_firing1==1) {
if (frame_skip>1) las_y1-=12;
vline(page1,las_x1-1,las_y1,las_y1-5,32);
vline(page1,las_x1,las_y1,las_y1-10,178);
vline(page1,las_x1+1,las_y1,las_y1-5,32);
// if beam reaches top of screen set las_firing flag to false
if (las_y1<=70) {
las_firing1=0;
}
//check for laser beam hitting brick
// check every brick
for (ptr=0; ptr<303; ptr++) {
if ((las_x1>=blocks[ptr].bx) &&
(las_x1<=blocks[ptr].bx+blocks[ptr].bw) &&
(las_y1>=blocks[ptr].by) &&
(las_y1<=blocks[ptr].by+blocks[ptr].bh)&&
(blocks[ptr].b_show!=0)) {
// Yes, the laser is over a brick
// erase the brick
if (blocks[ptr].b_show==1) {blocks[ptr].b_show=0; blocks[ptr].hits=0; score+=20; las_firing1=0;}
if (blocks[ptr].b_show==2) {las_firing1=0;}
// The laser has just hit an exploding brick
// Play sound
play_sample(explode,255,(bat[1].bx),1000,FALSE);
// point to the bricks to explode
explde[1]=ptr;
if (blocks[ptr+1].b_show==1) {explde[2]=ptr+1; blocks[ptr+1].b_show=0;score+=20;}
if (blocks[ptr-1].b_show==1) {explde[3]=ptr-1; blocks[ptr-1].b_show=0;score+=20;}
if (blocks[ptr-16].b_show==1){explde[4]=ptr-16;blocks[ptr-16].b_show=0;score+=20;}
if (blocks[ptr+16].b_show==1){explde[5]=ptr+16;blocks[ptr+16].b_show=0;score+=20;}
}
}
}
if((bat[1].bb==1) && (laser_enable==1) && (las_firing2==0)) {
las_x2=bat[1].bx+50;
las_y2=460;
las_firing2=1;
// Play sound
play_sample(laser,255,bat[1].bx,2000,FALSE);
}
// move laser beam up screen
if(las_firing2==1) {
if (frame_skip>1) las_y2-=12;
vline(page1,las_x2-1,las_y2,las_y2-5,32);
vline(page1,las_x2,las_y2,las_y2-10,178);
vline(page1,las_x2+1,las_y2,las_y2-5,32);
// if beam reaches top of screen set las_firing flag to false
if (las_y2<=70) {
las_firing2=0;
}
//check for laser beam hitting brick
// check every brick
for (ptr=0; ptr<303; ptr++) {
if ((las_x2>=blocks[ptr].bx) &&
(las_x2<=blocks[ptr].bx+blocks[ptr].bw) &&
(las_y2>=blocks[ptr].by) &&
(las_y2<=blocks[ptr].by+blocks[ptr].bh)&&
(blocks[ptr].b_show!=0)) {
// Yes, the laser is over a brick
// erase the brick
if (blocks[ptr].b_show==1) {blocks[ptr].b_show=0; blocks[ptr].hits=0; score+=20; las_firing2=0;}
if (blocks[ptr].b_show==2) {las_firing2=0;}
// The laser has just hit an exploding brick
// Play sound
play_sample(explode,255,(bat[1].bx),1000,FALSE);
// point to the bricks to explode
explde[1]=ptr;
if (blocks[ptr+1].b_show==1) {explde[2]=ptr+1; blocks[ptr+1].b_show=0;score+=20;}
if (blocks[ptr-1].b_show==1) {explde[3]=ptr-1; blocks[ptr-1].b_show=0;score+=20;}
if (blocks[ptr-16].b_show==1){explde[4]=ptr-16;blocks[ptr-16].b_show=0;score+=20;}
if (blocks[ptr+16].b_show==1){explde[5]=ptr+16;blocks[ptr+16].b_show=0;score+=20;}
}
}
}
}
void catch_ball()
{
int temp1,temp2,button, offset;
// check to see if it is over the bat
// and the catch flag is set
if ((balls[1].bx+8>bat[1].bx)&&
(balls[1].bx-8<bat[1].bx+bat[1].bw)&&
(balls[1].by>452)&&
(next_enable!=1)&&
(catch_enable==1)) {
play_sample(catch,255,0,1000,FALSE);
// store position of ball and bat when ball hit the bat
temp1=balls[1].bx;
temp2=bat[1].bx;
offset=0;
// hold onto the ball until left mouse button is pressed
while (((bat[bat_type].bb!=1)&&(key[KEY_CONTROL])!=TRUE)&&(joy_b1!=1)) {
update_bat_position();
balls[1].bx=(bat[bat_type].bx+(bat[bat_type].bw/2)-3)+offset;
if (bat[bat_type].bb) offset++;
if ((balls[1].bx+offset)-12>bat[bat_type].bx+bat[bat_type].bw) {
offset=1-(bat[bat_type].bw/2);
}
if (power_enable==1) {
draw_sprite(page1,pwr_ball,balls[1].bx,balls[1].by);
} else draw_sprite(page1,ball,balls[1].bx,balls[1].by);
show_score();
{drawing_screen(); copy_drawing(); copy_backgrnd();}
button=mouse_b;
move_blocks();
{frame_skip ++; if (frame_skip==10) frame_skip=1;}
}
play_sample(catch,255,255,1000,FALSE);
//bounce ball off bat
// if ball positioned on left side of bat start ball moving left
if (balls[1].bx+3<(bat[bat_type].bx+bat[bat_type].bw/2)) balls[1].dx=-1;
// if ball positioned on right side of bat start ball moving right
if (balls[1].bx+3>=(bat[bat_type].bx+bat[bat_type].bw/2)) balls[1].dx=+1;
balls[1].by=451;
// record time for fps routine
frame_tstart=rawclock();
frame_ctr=0;
}
}
void next_level()
{
int n;
if (level!=0) {
show_score();drawing_screen(); copy_drawing(); copy_backgrnd();
n=rawclock()+18;
while (rawclock()<n);
play_sample(newlevel,255,128,1000,FALSE);
fade_out(1);
if (level==40) level=0;
bat_type=1; // set bat size back to normal size
bounces=0;
las_firing1=0;
laser_down=0; //
laser_enable=0;// disable laser
laser_ptr=-1;
catch_down=0;
catch_enable=0;
catch_ptr=-1;
power_down=0;
power_enable=0;
power_ptr=-1;
plus_down=0;
plus_enable=0;
plus_ptr=-1;
next_down=0;
next_enable=0;
next_ptr=-1;
thru_down=0;
thru_enable=0;
thru_ptr=-1;
// ensure that nothing is exploded at start of game
for (n=1 ;n<11 ;n++) {
explde[n]=0;
explode_frame[n]=0;
}
}
//set_pallete(pallete2); // set pallete
level ++;
clear(screen);
blit(bg1,screen,5,0,0,0,640,480);
text_mode(-1);
textout(screen,fontfile[LARGE].dat,"Get Ready !",160,220,97);
textout(screen,fontfile[LARGE].dat,"Get Ready !",162,222,98);
play_sample(newlev2,255,128,1000,FALSE);
fade_in(pallete2,1);
fade_out(1);
bounce_time=rawclock();
}
void out_of_play()
{
int n;
play_sample(loose1,255,128,1000,FALSE);
// remove any blocks that are falling
// by setting the 'y psn of the blocks to 186
// they will be removed the next time 'remove_blocks is called
if (laser_down==1) {blocks[laser_ptr].by=500;}
if (catch_down==1) {blocks[catch_ptr].by=500;}
if (power_down==1) {blocks[power_ptr].by=500;}
if (plus_down==1) {blocks[plus_ptr].by=500;}
if (next_down==1) {blocks[next_ptr].by=500;}
if (thru_down==1) {blocks[thru_ptr].by=500;}
lives--;
initial_ball_position();
ball_out=0;
bat_type=1; // set bat size back to narmal size
// return bat to normal bat
laser_down=0; //
laser_enable=0;// disable laser
laser_ptr=-1;
catch_down=0;
catch_enable=0;
catch_ptr=-1;
power_down=0;
power_enable=0;
power_ptr=-1;
plus_down=0;
plus_enable=0;
plus_ptr=-1;
next_down=0;
next_enable=0;
next_ptr=-1;
thru_down=0;
thru_enable=0;
thru_ptr=-1;
vel_x=2;
vel_y=2;
bounce_angle=0;
bounces=0;
bounce_time=rawclock();
// ensure that nothing is exploded at start of game
for (n=1 ;n<11 ;n++) {
explde[n]=0;
explode_frame[n]=0;
}
}
void extras()
{
int i,n;
// add a new life
if (plus_enable==1) {
plus_enable=0;
plus_down=0;
lives++;
blocks[plus_ptr].by=300;
}
// the next level block has been collected
// explode each block in turn and then go
// to the next level
if (next_enable==1) {
next_enable=0;
for (ptr=0;ptr<155;ptr++) {
if ((blocks[ptr].b_show!=0)||(blocks[302-ptr].b_show!=0)) {
play_sample(explode,255,128,1000,FALSE);
blocks[302-ptr].b_show=0;
blocks[ptr].b_show=0;
i=rawclock()+0;
while (rawclock()<i);
score+=20;
show_score();drawing_screen(); copy_drawing(); copy_backgrnd();
}
}
new_level=1;
}
// increase frame counter
frame_ctr++;
}
void test()
{
int ptr;
for (ptr=0;ptr<440;ptr++) {
{drawing_screen(); copy_drawing(); copy_backgrnd();}
sprintf(ch_tmp,"%d",ptr);
textout(screen,fontfile[SMALL].dat,ch_tmp,10,5,5);
sprintf(ch_tmp,"%d",blocks[ptr].b_show);
textout(screen,fontfile[SMALL].dat,ch_tmp,100,5,5);
readkey();
}
}
void fps()
{
int n;
// has one second elapsed
if (rawclock()-frame_tstart>18) {
frame_fps=frame_ctr;
frame_ctr=0;
frame_tstart=rawclock();
}
// delay to slow game down on fast machines
if (frame_fps>70) frame_delay+=2;
for (n=0;n<frame_delay;n++) vsync();
// DISPLAY THE FRAMES PER SECOND
//sprintf(ch_tmp,"%d",frame_fps);
//textout(page1,fontfile[SMALL].dat,ch_tmp,200,11,20);
//sprintf(ch_tmp,"%d",frame_delay);
//textout(page1,fontfile[SMALL].dat,ch_tmp,250,11,20);
}
void exit_screen()
{
fade_out(60);
blit(finish_screen,screen,0,0,0,0,640,480);
play_sample(finish,255,128,1000,FALSE);
fade_in(pal_finish,1);
readkey();
exit(0);
}
void display_gameover()
{
int i;
fade_out(2);
blit(gameover_screen,screen,0,0,0,0,640,480);
play_sample(finish,255,128,1000,FALSE);
fade_in(pal_gamover,2);
i=rawclock()+18;
while (rawclock()<i);
fade_out(2);
}
void display_hiscore()
{
int ptr,psn,i, sorted,k;
char ch[20], temp[80],name[22];
// load hiscore data
data=fopen("hiscore","r");
for (ptr=0;ptr<10;ptr++){
fgets(hiscores[ptr].names,20,data);
fscanf(data,"%d",&hiscores[ptr].scores);
fscanf(data,"%d",&i); // has to be done twice for some reason
}
fclose(data);
// display hi-score table
show_mouse(NULL);
blit(hiscore_screen,screen,0,0,0,0,640,480);
play_sample(hiscore,255,128,1000,TRUE);
fade_in(pal_hiscore,20);
text_mode(-1);
psn=0;
for (ptr=160;ptr<410;ptr+=25) {
// draw border around each score
rectfill(screen,29,ptr-3,598,ptr+18,101);
rectfill(screen,30,ptr-1,600,ptr+20,100);
// this is the name
textout(screen,fontfile[SMALL].dat,hiscores[psn].names,40,ptr,1);
textout(screen,fontfile[SMALL].dat,hiscores[psn].names,41,ptr+1,2);
// this is the score
sprintf(ch_tmp,"%d",hiscores[psn].scores);
textout(screen,fontfile[SMALL].dat,ch_tmp,470,ptr,1);
textout(screen,fontfile[SMALL].dat,ch_tmp,471,ptr+1,1);
psn++;
}
// set score
// clear keyboard buffer
clear_keybuf();
if (score>hiscores[9].scores) {
// Erase EXIT box for now
rectfill(screen,520,410,640,480,93);
// border around text
rectfill(screen,2,430,410,460,101);
rectfill(screen,415,430,630,460,102);
textout(screen,fontfile[SMALL].dat,"A TOP 10 SCORE ENTER YOUR NAME >",5,435,1);
// Enter player name
//read in each character individually
ptr=0;
do {
// GET KEYBOARD INPUT
k=readkey();
// CHECK FOR VALID ASCII CHARACTER
if (((k & 0xFF)>31) && ((k & 0xFF)<127) && (ptr<15)) {
// PLACE ASCII CHARACTER IN ARRAY name
name[ptr]=(k & 0xFF);
// THIS IS HERE TO SKIP A MISSING CHARACTER IN THE FONT TABLE
if (name[ptr]>96) name[ptr]++;
// CLEAR STRING name OF UNWANTED CHARACTERS (A BUG IN ALLEGRO ?)
for (i=ptr+1; i<15 ;i++) name[i]=32;
ptr++;
}
// BACKSPACE
if ((k&0xFF)==8) {ptr--; name[ptr]=32;}
// UPDATE TEXT ONTO THE SCREEN
//OUTPUT ARRAY name TO SCREEN
rectfill(screen,415,430,630,460,102);
sprintf(ch,"%s",name);
// convert characters to upper case
textout(screen,fontfile[SMALL].dat,ch,430,435,1);
} while ((k & 0xFF) !=13);
sprintf(hiscores[9].names,"%s \n",name);
hiscores[9].scores=score;
// sort hiscore table
sorted=0;
while(sorted==0) {
sorted=1;
for (ptr=0;ptr<9;ptr++) {
if (hiscores[ptr].scores<hiscores[ptr+1].scores){
i=hiscores[ptr].scores;
hiscores[ptr].scores=hiscores[ptr+1].scores;
hiscores[ptr+1].scores=i;
sprintf(temp,"%s",hiscores[ptr].names);
sprintf(hiscores[ptr].names,"%s",hiscores[ptr+1].names);
sprintf(hiscores[ptr+1].names,"%s",temp);
sorted=0;
}
}
}
// display hi-score table
show_mouse(NULL);
blit(hiscore_screen,screen,0,0,0,0,640,480);
fade_in(pal_hiscore,20);
text_mode(-1);
psn=0;
for (ptr=160;ptr<410;ptr+=25) {
// draw border around each score
rectfill(screen,29,ptr-3,598,ptr+18,101);
rectfill(screen,30,ptr-1,600,ptr+20,100);
// this is the name
textout(screen,fontfile[SMALL].dat,hiscores[psn].names,40,ptr,1);
textout(screen,fontfile[SMALL].dat,hiscores[psn].names,41,ptr+1,2);
// this is the score
sprintf(ch_tmp,"%d",hiscores[psn].scores);
textout(screen,fontfile[SMALL].dat,ch_tmp,470,ptr,1);
textout(screen,fontfile[SMALL].dat,ch_tmp,471,ptr+1,1);
psn++;
}
// save hiscore data
data=fopen("hiscore","w");
for (ptr=0;ptr<10;ptr++){
fputs(hiscores[ptr].names,data);
fprintf(data,"%d",hiscores[ptr].scores);
fputc(10,data);
fputc(13,data);
}
fclose(data);
score=0;
}
set_mouse_range(520,410,630,475);
position_mouse(520,410);
show_mouse(screen);
while ((mouse_b==0) || (mouse_x<520)) {
position_mouse(mouse_x,mouse_y);
show_mouse(screen);
i=rawclock()+1;
while (rawclock()<i);
show_mouse(screen);
}
// reduce volume to zero
for (ptr=0;ptr<255;ptr+=10) {
adjust_sample(hiscore,255-ptr,128,1000,FALSE);
// slight delay
i=rawclock()+1;
while (rawclock()<i);
}
stop_sample(hiscore);
fade_out(4);
clear(screen);
}
void help()
{
int i,exit_flag;
blit(help_screen,screen,0,0,100,150,414,202);
i=rawclock();
while ((rawclock()-i)<8);
clear_keybuf();
exit_flag=0;
while (exit_flag==0) {
// select input device 1=mouse, 2=keyboard, 3=joystick
if(key[KEY_M])input_device=1;
if(key[KEY_K])input_device=2;
if(key[KEY_J])input_device=3;
if(key[KEY_F12])exit_flag=1;
}
i=rawclock();
while ((rawclock()-i)<6);
}
void main_menu()
{
int ptr,i,box_selected;
while (box_selected!=1) {
box_selected=0;
clear(screen);
blit(startup,screen,0,0,0,0,640,480);
play_sample(half_amin,255,128,1000,TRUE);
fade_in(pal_startup,1);
set_mouse_range(10,350,630,440);
position_mouse(360,400);
while ((mouse_b !=1)|| (box_selected ==0)) {
position_mouse(mouse_x,mouse_y);
show_mouse(screen);
i=rawclock()+1;
while (rawclock()<i);
show_mouse(screen);
// erase option boxes
{rect(screen,2,345,210,425,123); rect(screen,225,345,440,425,123); rect(screen,470,345,625,425,123);}
// draw box around option if mouse is over it
if ((mouse_x>0)&&(mouse_x<210)) {rect(screen,2,345,210,425,129);box_selected=1;}
if ((mouse_x>225)&&(mouse_x<440)) {rect(screen,225,345,440,425,129);box_selected=2;}
if ((mouse_x>470)&&(mouse_x<625)) {rect(screen,470,345,625,425,129);box_selected=3;}
if (mouse_b!=1) box_selected=0;
if(key[KEY_F12]) {
help();
blit(startup,screen,0,0,0,0,640,480);
}
}
// reduce volume to zero
for (ptr=0;ptr<255;ptr+=10) {
adjust_sample(half_amin,255-ptr,128,1000,FALSE);
// slight delay
i=rawclock()+1;
while (rawclock()<i);
}
fade_out(4);
if (box_selected==3) exit_screen();
if (box_selected==2) display_hiscore();
stop_sample(half_amin);
show_mouse(NULL);
}
}
void ball_stuck()
{
int between_bounces;
between_bounces=(rawclock()-bounce_time)/18;
if (between_bounces>40) {next_enable=1; between_bounces=rawclock();}
}
void pause()
{
int flag,i;
flag=0;
rectfill(screen,210,195,420,270,1);
textout(screen,fontfile[LARGE].dat,"PAUSE",220,200,213);
textout(screen,fontfile[LARGE].dat,"PAUSE",222,202,210);
i=rawclock();
while ((rawclock()-i)<8);
readkey();
while (flag==0){
if(key[KEY_P]) flag=1;
}
i=rawclock();
while ((rawclock()-i)<6);
}
void main()
{
int ptr,exit_flag;
/* you should always do this at the start of Allegro programs */
allegro_init();
/* set up the keyboard handler */
install_keyboard();
/* set VGA graphics mode 13h (sized 320x200) */
set_gfx_mode(GFX_AUTODETECT, 640,480, 0, 0);
/* install mouse driver */
install_mouse();
/* initialise joystick driver */
initialise_joystick();
/* install sound driver */
install_sound(DIGI_AUTODETECT,MIDI_NONE,NULL);
// Initalise program
// load various bitmaps into memory
load_bitmaps();
load_samples();
while (TRUE==TRUE) {
exit_flag=0;
// Display startup screen
initialise_variables();
main_menu();
next_level();
// MAIN GAME LOOP
while ((lives !=0)&&(exit_flag==0)) {
load_data(level);
initial_ball_position();
new_level=0;
while ((new_level==0) && (exit_flag==0) && (lives!=0)) {
show_score();
update_ball_position();
update_bat_position();
ball_collide_brick();
explode_bricks();
move_blocks();
fire_laser();
catch_ball();
extras();
fps();
drawing_screen();
copy_drawing();
copy_backgrnd();
ball_stuck();
// Is the ball out of play (ie missed bat)
if (ball_out==1) out_of_play();
// allow frame skipping for some procedures
// ie only call procedure when 'frame_skip equals a certain value
{frame_skip ++; if (frame_skip==10) frame_skip=1;}
// Space button or right mouse to exit
if (key[KEY_F1]) save_pcx("scrnshot.pcx",screen,pallete1);
if (key[KEY_P]) pause();
if (key[KEY_0]) exit(0);
}
if (lives==0) {display_gameover();display_hiscore();}
if ((exit_flag==0)&&(lives>0)) next_level();
}
}
}