Basic Pong in BGI

Discussion in 'C' started by rai_gandalf, May 31, 2007.

  1. rai_gandalf

    rai_gandalf New Member

    Joined:
    Nov 4, 2005
    Messages:
    46
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Final Year Comp Engg
    Location:
    Mumbai
    Home Page:
    http://mindpuncture.blogspot.com
    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:
    /* 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:
    /* 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();
    }
     

    Attached Files:

    Last edited: Jun 2, 2007
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Re: Basic 2D Tennis in BGI

    I really like and appreciate your code snippets
     
  3. rai_gandalf

    rai_gandalf New Member

    Joined:
    Nov 4, 2005
    Messages:
    46
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Final Year Comp Engg
    Location:
    Mumbai
    Home Page:
    http://mindpuncture.blogspot.com
    Re: Basic 2D Tennis in BGI

    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
     
  4. tailhook123

    tailhook123 New Member

    Joined:
    May 23, 2007
    Messages:
    30
    Likes Received:
    0
    Trophy Points:
    0
    Re: Basic 2D Tennis in BGI

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

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

    rai_gandalf New Member

    Joined:
    Nov 4, 2005
    Messages:
    46
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Final Year Comp Engg
    Location:
    Mumbai
    Home Page:
    http://mindpuncture.blogspot.com
    Re: Basic 2D Tennis in BGI

    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
     
  6. keith12125

    keith12125 New Member

    Joined:
    Jul 4, 2007
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    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?
     
  7. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    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
     
  8. seeguna

    seeguna New Member

    Joined:
    Jun 20, 2007
    Messages:
    31
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    Technical Consultant
    Location:
    Chennai
    Good one................ Hats up..............
     
  9. rai_gandalf

    rai_gandalf New Member

    Joined:
    Nov 4, 2005
    Messages:
    46
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Final Year Comp Engg
    Location:
    Mumbai
    Home Page:
    http://mindpuncture.blogspot.com

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

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice