Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C (http://www.go4expert.com/articles/c-tutorials/)
-   -   Basic Pong in BGI (http://www.go4expert.com/articles/basic-pong-bgi-t4504/)

rai_gandalf 31May2007 19:34

Basic Pong in BGI
 
1 Attachment(s)
Hello to one & all, I did a little bit of programming this weekend (I got myself a new Xbox 360!) .... but not satisfied with the Gaming monolith, I decided to do some game programming myself. So, I implemented that very famous game played by everyone who had access to a computer in the early 90's .... And the result is here .... Now, its no big deal as its already a standardized game which has been done & played & now occupies a place only in computer museums :D , but nonetheless here it is .... its still incomplete in some ways - User Interfaces need to be strengthened & more options need to be provided, but the basic math & functionality is all there .... Am currently working on a Object Oriented Version of this in C++ with more options.

Hope you enjoy this!

HAPPY CODING!



CODE for a Ball Bouncing off the boundaries of the Screen in Graphics Mode (Non-OOP)

Code: C

/* Program to Produce a continuously moving ball, which bounces on striking a wall */

/* SOURCE CODE */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <time.h>
#include <math.h>
#include <dos.h>

#define DEFDELAY 5

/* Global Variables */
// Symbolic Constants
const int xincr=1,yincr=1;
const int TRUE=1,FALSE=0;
const int FWD=0,BCK=1,UP=0,DWN=1;
const int LEFT=1,RIGHT=2,TOP=3,BOTTOM=4;

// Other Variables
int gd,gm,MAXX,MAXY;
int xstart,ystart,ballrad;
int xinst,yinst;
int xdir,ydir,cuttingbound;
int bounce=TRUE,linecol,fillcol;

/* Function Prototypes */
void initgraphics(void);
void testresolution(void);
void moveball(void);
int testboundary(void);
void rebound(void);
void drawball(void);
void showimpact(void);

void main()
{
    testresolution();
    printf("Please Enter XY Co-Ordinates of Starting Point :  ");
    scanf("%d%d",&xstart,&ystart);
    printf("\n\nEnter the Size of Ball (Radius) :  ");
    scanf("%d",&ballrad);
   
    printf("\n\n\nPress Any Key to Enter Graphics Mode ..... ");
    getch();
    moveball();
}

void initgraphics(void)
{
    int error;
    initgraph(&gd,&gm,"\\TC\\BGI");
    error=graphresult();
    if(error!=grOk)
    {
        printf("\n\n\aGRAPHICS ERROR! Error Code :  %d",error);
        getch();exit(1);
    }
}

void testresolution(void)
{
    clrscr();
    printf("Testing System Resolution! Press Any Key to enter Graphics Mode ....");
    getch();
   
    initgraphics();
    MAXX=getmaxx();
    MAXY=getmaxy();
    closegraph();
   
    printf("System Resolution Detected!\n");
    printf("\nHORIZONTAL PIXEL SPAN :  %d  (0 to %d)",MAXX+1,MAXX);
    printf("\nVERTICAL   PIXEL SPAN :  %d  (0 to %d)",MAXY+1,MAXY);
    getch();
    clrscr();
}

void moveball(void)
{
    // Seeding Random Number Generator
    randomize();
    // Initializing the Graphics Mode
    initgraphics();
   
    // Initializing the Position of the Ball
    xinst=xstart;
    yinst=ystart;
    // Iterating Till User Hits a Key
    xdir=random(2);
    ydir=random(2);
    while(!kbhit())
    {
        if(testboundary())
        {
            // Drawing the Ball
            cleardevice();
            drawball();
            delay(DEFDELAY);
            // Making Changes
            if(xdir==FWD)
                xinst+=xincr;
            else
                xinst-=xincr;
            if(ydir==UP)
                yinst-=yincr;
            else
                yinst+=yincr;
        }
        else
            rebound();
    }
    closegraph();
}

int testboundary(void)
{
    if(bounce==TRUE)
        return TRUE;
    else
    {
        if((xinst+ballrad)>=MAXX || (xinst-ballrad)<=0 ||
            (yinst+ballrad)>=MAXY || (yinst-ballrad)<=0)
        {
            if((xinst+ballrad)>=MAXX)
                cuttingbound=RIGHT;
            else if((xinst-ballrad)<=0)
                cuttingbound=LEFT;
            else if((yinst+ballrad)>=MAXY)
                cuttingbound=BOTTOM;
            else
                cuttingbound=TOP;
            return FALSE;
        }
        else
            return TRUE;
    }
}

void rebound(void)
{
    bounce=TRUE;
    switch(cuttingbound)
    {
    case LEFT:xdir=FWD;break;
    case RIGHT:xdir=BCK;break;
    case TOP:ydir=DWN;break;
    case BOTTOM:ydir=UP;break;
    }
}

void drawball(void)
{
    if(bounce==TRUE)
    {
        bounce=FALSE;
        do{
            linecol=random(15);
            fillcol=random(15);
        }while(linecol==BLACK || fillcol==BLACK || linecol==fillcol);
    }
    setcolor(linecol);
    circle(xinst,yinst,ballrad);
    setfillstyle(1,fillcol);
    floodfill(xinst,yinst,linecol);
}

CODE for 2D Basic Tennis using BGI (Non-OOP):
Code: C

/* Program for a basic 2 player Pong match with no specialized shot/bounce physics */

      /*
      Programmed By:
      Rajiv Iyer,
      T.E. Computers,
      SIES GST, Nerul
      */

      
      /* SOURCE CODE */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <time.h>
#include <math.h>
#include <dos.h>
      
#define BARSIZE 4
#define DEFRAD 10
#define DEFDELAY 10
#define LONGDELAY 500
#define HFSND 70000
#define DEFPENALTY 50
#define DEFREWARD 25
      
      /* Global Variables */
      // Symbolic Constants
      const int BARYCH=10;
const int DXCH=3,DYCH=3;
const int TRUE=1,FALSE=0;
const int FWD=0,BCK=1,UP=0,DWN=1;
const int LEFT=1,RIGHT=2,TOP=3,BOTTOM=4;

// Other Variables
int gd,gm,MAXX,MAXY;
int bounce=TRUE,cuttingbound;
int linecol,fillcol;

/* Structure Declaration */
struct Player
{
    int num;
    int bar[BARSIZE];
    int points;
    int returned,missed;
}P1,P2;

struct Sphere
{
    int xinst,yinst;
    int xdir,ydir;
    int radius;
}Ball;

/* Function Prototypes */
void instructions(void);
void initGraphics(void);
void testResolution(void);
void moveBall(void);
int testBoundary(void);
int keyhit(void);
void rebound(void);
void drawBall(void);
void drawUserBars(void);
void pauseMenu(void);
void displayStats(void);

void main()
{
    testResolution();
    instructions();
    moveBall();
}

void instructions(void)
{
    clrscr();
    printf("Welcome to the Basic 2D Tennis Program!");
    printf("\n\nKeys for User I :-\n");
    printf("MOVE BAR UP   :  'W'  or  'w'\n");
    printf("MOVE BAR DOWN :  'S'  or  's'\n");
    printf("\n\nKeys for User II :-\n");
    printf("MOVE BAR UP   :  'P'  or  'p'\n");
    printf("MOVE BAR DOWN :  'L'  or  'l'\n");
   
    printf("\n\nCommon Keys:\n");
    printf("Terminate Game  :  'T'  or  't'\n");
    printf("Halt/Pause Game :  'H'  or  'h'\n");
   
    printf("\n\nAll Keys are Case Insensitive!");
    printf("\n\n\nPress Any Key to Enter Graphics Mode & PLAY ! ..... ");
    getch();
}

void initGraphics(void)
{
    int error;
    initgraph(&gd,&gm,"\\TC\\BGI");
    error=graphresult();
    if(error!=grOk)
    {
        printf("\n\n\aGRAPHICS ERROR! Error Code :  %d",error);
        getch();exit(1);
    }
}

void testResolution(void)
{
    clrscr();
    printf("Testing System Resolution! Press Any Key to enter Graphics Mode ....");
    getch();
   
    initGraphics();
    MAXX=getmaxx();
    MAXY=getmaxy();
    closegraph();
   
    printf("System Resolution Detected!\n");
    printf("\nHORIZONTAL PIXEL SPAN :  %d  (0 to %d)",MAXX+1,MAXX);
    printf("\nVERTICAL   PIXEL SPAN :  %d  (0 to %d)",MAXY+1,MAXY);
    getch();
    clrscr();
}

void moveBall(void)
{
    // Seeding Random Number Generator
    randomize();
    // Initializing the Graphics Mode
    initGraphics();
   
    // Initializing the Position of the Two Player Bars
    P1.bar[0]=20 ; P1.bar[1]=200; P1.bar[2]=30 ; P1.bar[3]=280;
    P2.bar[0]=610; P2.bar[1]=200; P2.bar[2]=620; P2.bar[3]=280;
    // Initializing the Marks Tally of Both Players to Zero
    P1.points=P2.points=0;
    P1.returned=P2.returned=0;
    P1.missed=P2.missed=0;
    // Initializing the Position of the Ball
    Ball.xinst=MAXX/2;
    Ball.yinst=MAXY/2;
    Ball.radius=DEFRAD;
    // Randomizing the Initial Direction of Travel of Ball
    Ball.xdir=random(2);
    Ball.ydir=random(2);
    // Iterating Till Either User Hits TERMINATE(T) Key
    while(!keyhit())
    {
        if(testBoundary())
        {
            // Drawing the Ball
            cleardevice();
            drawBall();
            drawUserBars();
            delay(DEFDELAY);
            // Making Changes
            if(Ball.xdir==FWD)
                Ball.xinst+=DXCH;
            else
                Ball.xinst-=DXCH;
            if(Ball.ydir==UP)
                Ball.yinst-=DYCH;
            else
                Ball.yinst+=DYCH;
        }
        else
            rebound();
    }
    closegraph();
    displayStats();
}

int keyhit(void)
{
    int i;
    char uch,tempch;
    if(kbhit())
    {
        uch=getch();
        switch(uch)
        {
        case 't':
        case 'T':
            // The TERMINATE (T) Key was hit - so Returning True
            return TRUE;
        case 'w':
        case 'W':
            // The UP-Direction Key for Player I has been pressed
            // Testing Whether Player Bar goes out of window with such a move
            if(P1.bar[1]-BARYCH<0)
            {
                sound(HFSND);
                nosound();
            }
            else
            {
                for(i=1;i<BARSIZE;i+=2)
                    P1.bar[i]-=BARYCH;
            }
            return FALSE;
        case 's':
        case 'S':
            // The DOWN-Direction Key for Player I has been pressed
            // Testing Whether Player Bar goes out of window with such a move
            if(P1.bar[3]+BARYCH>MAXY)
            {
                sound(HFSND);
                nosound();
            }
            else
            {
                for(i=1;i<BARSIZE;i+=2)
                    P1.bar[i]+=BARYCH;
            }
            return FALSE;
        case 'p':
        case 'P':
            // The UP-Direction Key for Player II has been pressed
            // Testing Whether Player Bar goes out of window with such a move
            if(P2.bar[1]-BARYCH<0)
            {
                sound(HFSND);
                nosound();
            }
            else
            {
                for(i=1;i<BARSIZE;i+=2)
                    P2.bar[i]-=BARYCH;
            }
            return FALSE;
        case 'l':
        case 'L':
            // The DOWN-Direction Key for Player II has been pressed
            // Testing Whether Player Bar goes out of window with such a move
            if(P2.bar[3]+BARYCH>MAXY)
            {
                sound(HFSND);
                nosound();
            }
            else
            {
                for(i=1;i<BARSIZE;i+=2)
                    P2.bar[i]+=BARYCH;
            }
            return FALSE;
           
        case 'h':
        case 'H':
            //do{
            pauseMenu();
            //tempch=getch();
            //}while(tempch!='h' && tempch!='H');
            return FALSE;
        default:
            return FALSE;
        }
    }
    else
        return FALSE;
}

int testBoundary(void)
{
    if(bounce==TRUE)
        return TRUE;
    else
    {
        if((Ball.xinst+Ball.radius)>=MAXX || (Ball.xinst-Ball.radius)<=0)
        {
            if((Ball.xinst+Ball.radius)>=MAXX)
            {
                cuttingbound=RIGHT;
                // Player 2 misses Shot => Hence Deducting Points
                P2.points-=DEFPENALTY;
                P2.missed++;
            }
            else if((Ball.xinst-Ball.radius)<=0)
            {
                cuttingbound=LEFT;
                // Player 1 misses Shot => Hence Deducting Points
                P1.points-=DEFPENALTY;
                P1.missed++;
            }
            // Resetting Ball to Center of Screen
            Ball.xinst=MAXX/2;
            Ball.yinst=MAXY/2;
            // Randomizing the Initial Direction of Travel
            Ball.xdir=random(2);
            Ball.ydir=random(2);
            // Delaying for Short Period before Graphically Resetting
            delay(LONGDELAY);
            return TRUE;
        }
        else if((Ball.yinst+Ball.radius)>=MAXY || (Ball.yinst-Ball.radius)<=0)
        {
            if((Ball.yinst+Ball.radius)>=MAXY)
                cuttingbound=BOTTOM;
            else if((Ball.yinst-Ball.radius)<=0)
                cuttingbound=TOP;
            return FALSE;
        }
        else if((Ball.xinst+Ball.radius)>=P2.bar[0] && (Ball.yinst>P2.bar[1] && Ball.yinst<P2.bar[3]) && Ball.xdir==FWD)
        {
            cuttingbound=RIGHT;
            // Player 2 Returns Shot Successfully => Hence Rewarding Points
            P2.points+=DEFREWARD;
            P2.returned++;
            return FALSE;
        }
        else if((Ball.xinst-Ball.radius)<=P1.bar[2] && (Ball.yinst>P1.bar[1] && Ball.yinst<P1.bar[3]) && Ball.xdir==BCK)
        {
            cuttingbound=LEFT;
            // Player 1 Returns Shot Successfully => Hence Rewarding Points
            P1.points+=DEFREWARD;
            P1.returned++;
            return FALSE;
        }
        else
            return TRUE;
    }
}

void rebound(void)
{
    bounce=TRUE;
    switch(cuttingbound)
    {
    case LEFT:Ball.xdir=FWD;break;
    case RIGHT:Ball.xdir=BCK;break;
    case TOP:Ball.ydir=DWN;break;
    case BOTTOM:Ball.ydir=UP;break;
    }
}

void drawBall(void)
{
    if(bounce==TRUE)
    {
        bounce=FALSE;
        do{
            linecol=random(15);
            fillcol=random(15);
        }while(linecol==BLACK || fillcol==BLACK || linecol==fillcol);
    }
    setcolor(linecol);
    circle(Ball.xinst,Ball.yinst,Ball.radius);
    setfillstyle(1,fillcol);
    floodfill(Ball.xinst,Ball.yinst,linecol);
}

void drawUserBars(void)
{
    // Drawing Player I Bar
    setcolor(linecol);
    rectangle(P1.bar[0],P1.bar[1],P1.bar[2],P1.bar[3]);
    setfillstyle(1,fillcol);
    floodfill(P1.bar[0]+5,P1.bar[1]+5,linecol);
    // Drawing Player I Bar
    setcolor(linecol);
    rectangle(P2.bar[0],P2.bar[1],P2.bar[2],P2.bar[3]);
    setfillstyle(1,fillcol);
    floodfill(P2.bar[0]+5,P2.bar[1]+5,linecol);
}

void pauseMenu(void)
{
    char pch;
   
    do{
        settextstyle(TRIPLEX_FONT,HORIZ_DIR,3);
        outtextxy(150,100,"1. Resume Game");
        outtextxy(150,200,"2. Display Statistics");
        outtextxy(150,300,"3. Controls");
       
        pch=getch();
        switch(pch)
        {
        case '1':
            break;
        case '2':
            closegraph();
            displayStats();
            initGraphics();
            break;
        case '3':
            closegraph();
            instructions();
            initGraphics();
            break;
        default:
            printf("\n\n\aInvalid Choice!\n\n\a");
        }
    }while(pch!='1');
}

void displayStats(void)
{
    // Printing All Collected Statistics
    printf("Statistics Score-Card :\n");
    printf("\n\nFor User I  :\nShots Taken :  %d\nShots Missed :  %d\nTotal Score :  %d",P1.returned,P1.missed,P1.points);
    printf("\n\nFor User II :\nShots Taken :  %d\nShots Missed :  %d\nTotal Score :  %d",P2.returned,P2.missed,P2.points);
    printf("\n\n\nWINNER :  ");
    if(P1.points>P2.points)
        printf("Player I !!");
    else if(P1.points<P2.points)
        printf("Player II !!");
    else
        printf("Undeterminable !!");
    getch();
}


shabbir 1Jun2007 10:11

Re: Basic 2D Tennis in BGI
 
I really like and appreciate your code snippets

rai_gandalf 1Jun2007 10:37

Re: Basic 2D Tennis in BGI
 
Quote:

Originally Posted by shabbir
I really like and appreciate your code snippets

Hey thanks a lot Shabbir! .... Its really not that big a deal, as this has been a standardized & done game from sometime in the early 90's .... but as I told you, it was pure love for logic & programming that drives me & no doubt even you & others to give it a try!

NJOY CODING!

Regards,
Rajiv

PS: Any Queries about any code-segment that is not clear (sorry I didnt comment extensively on this one as I usually do) are welcome

tailhook123 2Jun2007 03:20

Re: Basic 2D Tennis in BGI
 
Quote:

Originally Posted by rai_gandalf
Hey thanks a lot Shabbir! .... Its really not that big a deal, as this has been a standardized & done game from sometime in the early 90's .... but as I told you, it was pure love for logic & programming that drives me & no doubt even you & others to give it a try!

NJOY CODING!

Regards,
Rajiv

PS: Any Queries about any code-segment that is not clear (sorry I didnt comment extensively on this one as I usually do) are welcome

Aye.. good coding.. but this is Pong isn't it?

http://en.wikipedia.org/wiki/Pong

rai_gandalf 2Jun2007 13:22

Re: Basic 2D Tennis in BGI
 
Quote:

Originally Posted by tailhook123
Aye.. good coding.. but this is Pong isn't it?

http://en.wikipedia.org/wiki/Pong

Hey Tailhook,
Thanks for the link .... I didnt know the name of the game, but just knew that it was & still is a heck of a game .... and anyways, when I set out to code, I was plannin to code Tennis along with the court markings & stuff, but halfway I decided to revert to this "PONG" as the world calls it .... thx 4 the link - made an interesting read - especially Roddick playing Pong .... So, Pong it is .... will rename the thread if I can.

NJOY CODING

Regards,
Rajiv


PS: To use Shakespeare's quotation slightly distorted to suit the situation : "A Game by any other name would be just as enjoyable" :D

keith12125 4Jul2007 15:46

Re: Basic Pong in BGI
 
ok... I know I'm doing something wrong. I am using Visual C++ to compile this and I don't have a graphics.h file. Do i need to download it?

shabbir 4Jul2007 16:40

Re: Basic Pong in BGI
 
MS VC compiler does not support BGI graphics and so it does not have the graphics.h file.

You need to use the old days Turbo C++ 3.0 compiler for the BGI graphics program to compile

seeguna 5Jul2007 16:21

Re: Basic Pong in BGI
 
Good one................ Hats up..............

rai_gandalf 11Jul2007 13:18

Re: Basic Pong in BGI
 
Quote:

Originally Posted by seeguna
Good one................ Hats up..............


Hey thanks a lot. I am glad you liked it.


All times are GMT +5.5. The time now is 05:10.