C Programming Reference

C Programming Reference >> C Games Programming Tutorials >> 

PING PONG 1.0 

27/12/06 -  Views - Ratings :   4.84 of 5 / 153 Votes

Level - Intermediate

Here you will learn how to create a game called Ping Pong through C . Ping Pong was the second video game ever created (First was Asteroids). This game at that time hit people like hell and whole world was playing it non-stop for hours. Ping Pong in C is a simple game to play but not easy to program especially for beginners but dont worry stay with tutorial, do what it says and you will be done in no time. If you are unable to flow please read basic tutorials and then come back to desing your very own ping pong using C. Read last coloumn for source code, executable and copyright.

Graphic Library Used - Turbo C/C++ BGI

Operating System Used - Windows XP Professional

Contents -

1. Requirements
2. Getting Started
3. Coding Main
4. Intializing Graphics
5. Game Data
6. Game Intilization
7. Game Engine
8. Moving Bats
9. Move The Ball
10. Physics Processor
11. Final Words
12. What Next?

1. Requirements

From Programming point of view i am assuming you have some knowledge of C and we will build this program from scratch for better understanding . If you absolute beginner check this out if you dont understand go through basic tutorials first.

But before you start you need some tools. You must install Turbo C++ 3.0 IDE and install it in folder C:\TC (Please Choose same directory name and drive if you are beginner). Thats all now you are all done to start your games programming fantasies.

Back To Top

2. Getting Started

Go to C:\TC\Bin there you will find a executable file called TC execute it and IDE will load itself.

Now go to File Menu and choose New.

Now Press F2 to save the file. Give it name pingpong.c.

Now you are all set to rock. The screen should be something like this -

 

Back To Top

3. Coding Main

First Thing a program should do is to include header files and code main only header we will be needing is graphics.h . Including unnecessary header files increase the size of the code and compile time. Next we create an parameterless int returning main with no code at present. Your Code should look like this -

#include <conio.h>
int main ()
{
            
return 0;

}
            
 

Back To Top

4. Intializing Graphics

Now we intialise graphics in main, stop for a key press and then close the graphics. When we stop you should se a blank page and not any error. If you face an error make sure your installation path is correct. All our game activity occurs in this opening and closing of graphics. It will generally give you a 640*480 mode with VGA graphics. These graphics are good enough to code any descent looking games. If you get different settings try to set them as above. Your code should be now -

#include <graphics.h>
int main ()
{
int gdriver = DETECT, gmode;
initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); // Intializes Graphics
getch (); // Key Press
closegraph (); // Close Graphics
return 0;
}
 

Back To Top

5. Game Data

Now we create data your game needs . In this game we need following data -

Score : Player A Score & Player B Score.

Bats : Length, Width, X Coordinate, Old Y Coordinate, New Y Coordinate (Since bat moves only up and down)

Ball : Radius,Speed in X Direction, Speed in Y Direction, Old X center , Old Y center, New X centre, New Y centre

You can change these parameters as you wish to modify your game but changing them may need a alteration in code otherwise it could lead to preety stupid behaviour of game and severe cases a crash (very unlikely).

Now we use structure to store data and code will be as follow -

#include <graphics.h>
struct bat
{
 int length;
 int width;
 int xcoordinate;
 int new_ycoordinate;
 int old_ycoordinate;
}batA, batB; // Create Two Bats For Each User.
struct ball
{
 int radius;
 int speedx;
 int speedy;
 int old_xcenter;
 int old_ycenter;
 int new_xcenter;
 int new_ycenter;
}ball1;
struct score
{
  int score_A;
  int score_B;
}score_game;
int main ()
{
 int gdriver = DETECT, gmode;
 initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); // Intializes Graphics
 getch (); // Key Press
 closegraph (); // Close Graphics
 return 0;
}
 

Back To Top

6. Game Initializaton

Now we create a function which intializes all your data and create a board with non moving or static elements permanently and dynamic or moving elements to intial postion. We call this function through main only once. You can modify parameters here to see the changes. If you are unable to understand what function does press SHIFT + F1 and see in index or you are free to contanct us..

You screen should now look like this -

Ping Pong

Code Now Becomes -

#include <graphics.h>
struct bat
{
 int length;
 int width;
 int xcoordinate;
 int new_ycoordinate;
 int old_ycoordinate;
}batA, batB; // Create Two Bats For Each User.
struct ball
{
 int radius;
 int speedx;
 int speedy;
 int old_xcenter;
 int old_ycenter;
 int new_xcenter;
 int new_ycenter;
}ball1;
struct score
{
  int score_A;
  int score_B;
}score_game;
void initialize () // Initialize the game.
{
 char tempstring [10]; //This String holds score in char format temporarily
 
 //Initialise Bat A
 
 batA.length = 20;
 batA.width = 2;
 batA.xcoordinate = 20;
 batA.new_ycoordinate = 237;
 batA.old_ycoordinate = 237;
 
 // Intialise Bat B
 
 batB.length = 20;
 batB.width = 2;
 batB.xcoordinate = 620;
 batB.new_ycoordinate = 237;
 batB.old_ycoordinate = 237;
 
 // Intialise Ball
 ball1.radius = 3;
 ball1.speedx = 4;
 ball1.speedy = 0;
 ball1.old_xcenter = 320;
 ball1.old_ycenter = 250;
 ball1.new_xcenter = 320;
 ball1.new_ycenter = 250;
 
 // Intialise Score
 score_game.score_A = 0;
 score_game.score_B = 0;
 
 // Set Background to white
 setbkcolor (BLACK);


 // Draw Ball at Initial Position
 setfillstyle (1,15);
 fillellipse (ball1.new_xcenter,ball1.new_ycenter,ball1.radius,ball1.radius);


 // Draw Bats at Intial Position
 bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
 bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);


 // Display Score
 textcolor ();
 sprintf (tempstring,"A - %d",score_game.score_A);
 outtextxy (10,450,tempstring);
 sprintf (tempstring,"B - %d",score_game.score_A);
 outtextxy (590,450,tempstring);
}
int main ()
{
 int gdriver = DETECT, gmode;
 initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); // Intializes Graphics
 initialize ();
 getch (); // Key Press
 closegraph (); // Close Graphics
 return 0;
}
            
 

Back To Top

7. Game Engine

Now we take a big step forward. We move from static to dynamic and we design a game engine for us do that. Now lets take a overview what is changing.

1. Bats move up and down for both players on thier will.

2. Ball moves between the two bats controlled by computer.

3. Score Changes when a player miss.

We introduce this function in main and when this function returns the game exit.

All this occurs in our game engine function called play ( ). In this function there is a infinite while loop which exits only when player press exit command (Q Key). Now we discuss each part of game engine in details.

Back To Top

8. Moving Bats -

We pick four keys 2 for player A up and down and 2 for player B up and down . Let the keys be

A - Player A up

Z - Player A down

J - Player B up

M - Player B down

To check for input we use a function called inportb and for that we need header <dos.h>. We use 0X60 port designated to keyboard.

Then we use a switch case for action to be performed.

Action is performed by a function called movebat which removes the last picture of the bat and place a new one. It also calculate the new coordinates of bat after moving.

Here is a screen shot -

The Code Now becomes -

#include <graphics.h>
#include <dos.h>
struct bat

{
 int length;
 int width;
 int xcoordinate;
 int new_ycoordinate;
 int old_ycoordinate;
}batA, batB; // Create Two Bats For Each User.
struct ball
{
  int radius;
  int speedx;
  int speedy;
  int old_xcenter;
  int old_ycenter;
  int new_xcenter;
  int new_ycenter;
}ball1;
struct score
{
  int score_A;
  int score_B;
}score_game;
void initialize () // Initialize the game.
{
 char tempstring [10]; //This String holds score in char format temporarily
 
 //Initialise Bat A
 batA.length = 20;
 batA.width = 2;
 batA.xcoordinate = 20;
 batA.new_ycoordinate = 237;
 batA.old_ycoordinate = 237;
 
 // Intialise Bat B
 batB.length = 20;
 batB.width = 2;
 batB.xcoordinate = 620;
 batB.new_ycoordinate = 237;
 batB.old_ycoordinate = 237;
 
 // Intialise Ball
 ball1.radius = 3;
 ball1.speedx = 4;
 ball1.speedy = 0;
 ball1.old_xcenter = 320;
 ball1.old_ycenter = 250;
 ball1.new_xcenter = 320;
 ball1.new_ycenter = 250;
 
 // Intialise Score
 score_game.score_A = 0;
 score_game.score_B = 0;
 
 // Set Background to white
 setbkcolor (BLACK);
 
 // Draw Ball at Initial Position
 setfillstyle (1,15);
 fillellipse (ball1.new_xcenter,ball1.new_ycenter,ball1.radius,ball1.radius);
 
 // Draw Bats at Intial Position
 bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
 bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
 
 // Display Score
 textcolor ();
 sprintf (tempstring,"A - %d",score_game.score_A);
 outtextxy (10,450,tempstring);
 sprintf (tempstring,"B - %d",score_game.score_A);
 outtextxy (590,450,tempstring);
}
void movebat (char input)
{
 switch (input)
   {
     case 'A' : 
                if (batA.new_ycoordinate > 0) // Move only when bat is not touching the top so it doesnt jump out of screen.
                  {
                    batA.old_ycoordinate = batA.new_ycoordinate;
                    batA.new_ycoordinate --;
                    setfillstyle (1,0); // Remove last postion.
                    bar (batA.xcoordinate,batA.old_ycoordinate,batA.xcoordinate+batA.width,batA.old_ycoordinate+batA.length);
                    setfillstyle (1,15); // Display New postion.
                    bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
                    break;
                  }
     
     case 'Z' : 
               if (batA.new_ycoordinate+batA.length < 480) // Make sure bat doesnot go below the screen.
                  {
                    batA.old_ycoordinate = batA.new_ycoordinate;
                    batA.new_ycoordinate ++;
                    setfillstyle (1,0); // Remove last postion.
                    bar (batA.xcoordinate,batA.old_ycoordinate,batA.xcoordinate+batA.width,batA.old_ycoordinate+batA.length);
                    setfillstyle (1,15); // Display New postion.
                    bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
                    break;
                   }
     
     case 'J' : 
               if (batB.new_ycoordinate > 0) // Move only when bat is not touching the top so it doesnt jump out of screen.
                 {
                   batB.old_ycoordinate = batB.new_ycoordinate;
                   batB.new_ycoordinate --;
                   setfillstyle (1,0); // Remove last postion.
                   bar (batB.xcoordinate,batB.old_ycoordinate,batB.xcoordinate+batB.width,batB.old_ycoordinate+batB.length);
                   setfillstyle (1,15); // Display New postion.
                   bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
                   break;
                 }
    
    case 'M' : 
              if (batB.new_ycoordinate+batB.length < 480) // Make sure bat doesnot go below the screen.
                {
                  batB.old_ycoordinate = batB.new_ycoordinate;
                  batB.new_ycoordinate ++;
                  setfillstyle (1,0); // Remove last postion.
                  bar (batB.xcoordinate,batB.old_ycoordinate,batB.xcoordinate+batB.width,batB.old_ycoordinate+batB.length);
                  setfillstyle (1,15); // Display New postion.
                  bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
                  break;
                }
     
   }

}
void play ()\\ Our Budding Game Engine
{
   while (inportb (0X60) != 16) // Check wether key press is Q if so exit loop
    {
      delay (10); // Reduce game speed to human playable level
      if (inportb (0X60) == 30)  movebat ('A');
      if (inportb (0X60) == 44)  movebat ('Z');
      if (inportb (0X60) == 36)  movebat ('J');
      if (inportb (0X60) == 50)  movebat ('M');
    }
}
            
int main ()
{        
int gdriver = DETECT, gmode;
initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); // Intializes Graphics
initialize ();
play ();                                   // Game Engine
closegraph ();                            // Close Graphics
return 0;
}

Back To Top

9. Move The Ball

Now since we are done with bat lets move the ball.

If speed of the ball speedx is positive, ball moves in right direction and if speedx of the ball is negative ball moves in left direction.

If speed of the ball speedy is positive, ball moves in up direction and if speedy of the ball is negative ball moves in down direction.

If ball hits the top or bottom its speedy changes sign to bring reflection.

We do this in function called moveball and call this function in our game engine.

Also we need to make ball behaviour unpredictable so we use srand and rand to intialize ball speed y from 0 - 3 pixel per second and choose two of four adjacent direction to produce any possible direction.. We also need header time.h for this purpose.

Here are some screen shots -

Now code becomes even bigger, dont get scared its easy to understand.

 


#include <graphics.h>
#include <dos.h>
#include <time.h>
struct bat
{

 int length;
 int width;
 int xcoordinate;
 int new_ycoordinate;
 int old_ycoordinate;
}batA, batB; // Create Two Bats For Each User.
struct ball
{
  int radius;
  int speedx;
  int speedy;
  int old_xcenter;
  int old_ycenter;
  int new_xcenter;
  int new_ycenter;
}ball1;
struct score
{
  int score_A;
  int score_B;
}score_game;
void initialize () // Initialize the game.
{
 char tempstring [10]; //This String holds score in char format temporarily
 time_t t;             // Used to generate random number from system time.
        
 //Initialise Bat A
 batA.length = 20;
 batA.width = 2;
 batA.xcoordinate = 20;
 batA.new_ycoordinate = 237;
 batA.old_ycoordinate = 237;
 
 // Intialise Bat B
 batB.length = 20;
 batB.width = 2;
 batB.xcoordinate = 620;
 batB.new_ycoordinate = 237;
 batB.old_ycoordinate = 237;
 
 // Intialise Ball
 ball1.radius = 3;
 ball1.speedx = 2;
 srand((int) time(&t)); // Seed rand a random number
 ball1.speedy = rand ()%3;// Sets speed from 0 to 3 depending upon remainder.
 if (rand() % 2 == 0)
  {
    ball1.speedx = - ball1.speedx; // Generate Random X direction.
    ball1.speedy = - ball1.speedy; // Generate Random Y direction.
  }
 ball1.old_xcenter = 320;
 ball1.old_ycenter = 250;
 ball1.new_xcenter = 320;
 ball1.new_ycenter = 250;

 // Intialise Score
 score_game.score_A = 0;
 score_game.score_B = 0;
 
 // Set Background to white
 setbkcolor (BLACK);
 
 // Draw Ball at Initial Position
 setfillstyle (1,15);
 fillellipse (ball1.new_xcenter,ball1.new_ycenter,ball1.radius,ball1.radius);
 
 // Draw Bats at Intial Position
 bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
 bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
 
 // Display Score
 textcolor ();
 sprintf (tempstring,"A - %d",score_game.score_A);
 outtextxy (10,450,tempstring);
 sprintf (tempstring,"B - %d",score_game.score_A);
 outtextxy (590,450,tempstring);
 outtextxy (40,470,"Remove This Line by Learn Coding It yourself at www.cencyclopedia.com");
         
}
void movebat (char input)
{
  switch (input)
      {
         case 'A' : 
                   if (batA.new_ycoordinate > 0) // Move only when bat is not touching the top so it doesnt jump out of screen.
                    {
                      batA.old_ycoordinate = batA.new_ycoordinate;
                      batA.new_ycoordinate --;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batA.xcoordinate,batA.old_ycoordinate,batA.xcoordinate+batA.width,batA.old_ycoordinate+batA.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
                    }
                    break;
         case 'Z' : 
                   if (batA.new_ycoordinate+batA.length < 430) // Make sure bat doesnot go below the screen.
                    {
                      batA.old_ycoordinate = batA.new_ycoordinate;
                      batA.new_ycoordinate ++;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batA.xcoordinate,batA.old_ycoordinate,batA.xcoordinate+batA.width,batA.old_ycoordinate+batA.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
                    }
                    break;
         case 'J' : 
                   if (batB.new_ycoordinate > 0) // Move only when bat is not touching the top so it doesnt jump out of screen.
                    {
                      batB.old_ycoordinate = batB.new_ycoordinate;
                      batB.new_ycoordinate --;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batB.xcoordinate,batB.old_ycoordinate,batB.xcoordinate+batB.width,batB.old_ycoordinate+batB.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
                    }
                    break;
          case 'M' : 
                   if (batB.new_ycoordinate+batB.length < 430) // Make sure bat doesnot go below the screen.
                    {
                      batB.old_ycoordinate = batB.new_ycoordinate;
                      batB.new_ycoordinate ++;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batB.xcoordinate,batB.old_ycoordinate,batB.xcoordinate+batB.width,batB.old_ycoordinate+batB.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
                    }
                    break;
         }


}
void moveball ()
{
  ball1.old_xcenter = ball1.new_xcenter;
  ball1.old_ycenter = ball1.new_ycenter;
  ball1.new_xcenter = ball1.new_xcenter + ball1.speedx;
  ball1.new_ycenter = ball1.new_ycenter + ball1.speedy;
  setcolor (0);
  setfillstyle (1,0);// Remove last postion.
  fillellipse (ball1.old_xcenter,ball1.old_ycenter,ball1.radius,ball1.radius);
  setfillstyle (1,15); // Display New postion.
  fillellipse (ball1.new_xcenter,ball1.new_ycenter,ball1.radius,ball1.radius);
  if ( ball1.new_ycenter - ball1.radius < 0 ) ball1.speedy = -ball1.speedy; // Reflect From Top
  if ( ball1.new_ycenter + ball1.radius > 430 ) ball1.speedy = -ball1.speedy; // Reflect From Bottom
}
void play ()
{
  while (inportb (0X60) != 16) // Check wether key press is Q if so exit loop
    {
      delay (10); // Reduce game speed to human playable level
      if (inportb (0X60) == 30)  movebat ('A');
      if (inportb (0X60) == 44)  movebat ('Z');
      if (inportb (0X60) == 36)  movebat ('J');
      if (inportb (0X60) == 50)  movebat ('M');
      moveball ();
     }
}
            
int main ()
{ 
  int gdriver = DETECT, gmode;
  initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); // Intializes Graphics
  initialize ();
  play (); // Game Engine
  closegraph (); // Close Graphics
  return 0; 
}

 

Back To Top

10. Physics Processor

Another most important part of any game is physics processor . It calculates the physics in our game bring real world similarities.

In this Simple Game Physics is not this complicated but when we build 3D Game togther it is far more complicated than graphics.

Now we Analyse what physics do we need here -

1. When ball hit left or right of the screen it reflects itself if their is bat there or bring itself to the centre and increment the score.

Now we can modify our intialize function a little and little bit of main this can be achieved as a piece of cake without tough programming. What we do is we dont initialize score in intialize function but in main so that intialize function can be called again without reseting score. Also we need to a closegraph and renitialise graphic in initialize function.

Because of above we can now remove the burden of intializing graphics from main making program more efficient. Hence we hit two targets in one arrow.

We create a function called physics to do this for us.

Some Screen Shots -

Now we present the final code of this version -

#include <graphics.h>
#include <dos.h>
#include <time.h>
struct bat
{
 int length;
 int width;
 int xcoordinate;
 int new_ycoordinate;
 int old_ycoordinate;
}batA, batB; // Create Two Bats For Each User.
struct ball
{
 int radius;
 int speedx;
 int speedy;
 int old_xcenter;
 int old_ycenter;
 int new_xcenter;
 int new_ycenter;
}ball1;
struct score
{
  int score_A;
  int score_B;
}score_game;
            
void initialize () // Initialize the game.
{
  int gdriver = DETECT, gmode;
  char tempstring [10]; //This String holds score in char format temporarily
  time_t t;// Used to generate random number from system time.
  closegraph ();
  initgraph(&gdriver, &gmode, "c:\\tc\\bgi"); // Intializes Graphics
  
  //Initialise Bat A
  batA.length = 40;
  batA.width = 2;
  batA.xcoordinate = 20;
  batA.new_ycoordinate = 237;
  batA.old_ycoordinate = 237;
  
  // Intialise Bat B
  batB.length = 40;
  batB.width = 2;
  batB.xcoordinate = 620;
  batB.new_ycoordinate = 237;
  batB.old_ycoordinate = 237;
  
   // Intialise Ball
   ball1.radius = 3;
   ball1.speedx = 2;
   srand((int) time(&t)); // Seed rand a random number
   ball1.speedy = rand ()%1;// Sets speed from 0 to 2 depending upon remainder.
   if (rand() % 2 == 0)
     {
       ball1.speedx = - ball1.speedx; // Generate Random X direction.
       ball1.speedy = - ball1.speedy; // Generate Random Y direction.
      }
    ball1.old_xcenter = 320;
    ball1.old_ycenter = 250;
    ball1.new_xcenter = 320;
    ball1.new_ycenter = 250;
   
   // Set Background to white
   setbkcolor (BLACK);
   
   // Draw Ball at Initial Position
   setfillstyle (1,15);
   fillellipse (ball1.new_xcenter,ball1.new_ycenter,ball1.radius,ball1.radius);
  
   // Draw Bats at Intial Position
   bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
   bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
  
   // Display Score
   textcolor ();
   sprintf (tempstring,"A - %d",score_game.score_A);
   outtextxy (10,450,tempstring);
   sprintf (tempstring,"B - %d",score_game.score_B);
   outtextxy (590,450,tempstring);
   outtextxy (40,472,"Remove This Line by Learn Coding It yourself at www.cencyclopedia.com");
}
void movebat (char input)
{
  switch (input)
     {
       case 'A' : 
                  if (batA.new_ycoordinate > 0) // Move only when bat is not touching the top so it doesnt jump out of screen.
                    {
                      batA.old_ycoordinate = batA.new_ycoordinate;
                      batA.new_ycoordinate --;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batA.xcoordinate,batA.old_ycoordinate,batA.xcoordinate+batA.width,batA.old_ycoordinate+batA.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
                     }
                   break;

       case 'Z' : 
                  if (batA.new_ycoordinate+batA.length < 430) // Make sure bat doesnot go below the screen.
                    {
                      batA.old_ycoordinate = batA.new_ycoordinate;
                      batA.new_ycoordinate ++;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batA.xcoordinate,batA.old_ycoordinate,batA.xcoordinate+batA.width,batA.old_ycoordinate+batA.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batA.xcoordinate,batA.new_ycoordinate,batA.xcoordinate+batA.width,batA.new_ycoordinate+batA.length);
                    }
                  break;
       case 'J' : 
                  if (batB.new_ycoordinate > 0) // Move only when bat is not touching the top so it doesnt jump out of screen.
                     {
                      batB.old_ycoordinate = batB.new_ycoordinate;
                      batB.new_ycoordinate --;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batB.xcoordinate,batB.old_ycoordinate,batB.xcoordinate+batB.width,batB.old_ycoordinate+batB.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
                     }
                  break;
        case 'M' : 
                  if (batB.new_ycoordinate+batB.length < 430) // Make sure bat doesnot go below the screen.
                    {
                      batB.old_ycoordinate = batB.new_ycoordinate;
                      batB.new_ycoordinate ++;
                      setfillstyle (1,0); // Remove last postion.
                      bar (batB.xcoordinate,batB.old_ycoordinate,batB.xcoordinate+batB.width,batB.old_ycoordinate+batB.length);
                      setfillstyle (1,15); // Display New postion.
                      bar (batB.xcoordinate,batB.new_ycoordinate,batB.xcoordinate+batB.width,batB.new_ycoordinate+batB.length);
                    }
                   break;
         }
         
}
void moveball ()
{
   ball1.old_xcenter = ball1.new_xcenter;
   ball1.old_ycenter = ball1.new_ycenter;
   ball1.new_xcenter = ball1.new_xcenter + ball1.speedx;
   ball1.new_ycenter = ball1.new_ycenter + ball1.speedy;
   setcolor (0);
   setfillstyle (1,0); // Remove last postion.
   fillellipse (ball1.old_xcenter,ball1.old_ycenter,ball1.radius,ball1.radius);
   setfillstyle (1,15); // Display New postion.
   fillellipse (ball1.new_xcenter,ball1.new_ycenter,ball1.radius,ball1.radius);
   if ( ball1.new_ycenter - ball1.radius < 0 ) ball1.speedy = -ball1.speedy; // Reflect From Top
   if ( ball1.new_ycenter + ball1.radius > 430 ) ball1.speedy = -ball1.speedy; // Reflect From Bottom
}
void physics ()
{
  char tempstring [10];
  if ( ball1.new_xcenter - ball1.radius <= 20)
     {
         if (ball1.new_ycenter > batA.new_ycoordinate && ball1.new_ycenter < batA.new_ycoordinate+batA.length)
            {
               ball1.speedx = - ball1.speedx;
               ball1.speedy = rand () % 2;// Sets speed from 0 to 2 depending upon remainder.
               if (rand() % 2 == 0) ball1.speedy = - ball1.speedy; // Generate Random Y direction.
             }
          else // Reintialize entire game with new score
             {
               score_game.score_B ++;
               initialize ();
             }
          return;
      }
  if ( ball1.new_xcenter +  ball1.radius > 620)
     
      {
         if (ball1.new_ycenter > batB.new_ycoordinate && ball1.new_ycenter < batB.new_ycoordinate+batB.length)
          {
            ball1.speedx = - ball1.speedx;
            ball1.speedy = rand ()%2;// Sets speed from 0 to 2 depending upon remainder.
            if (rand() % 2 == 0) ball1.speedy = - ball1.speedy; // Generate Random Y direction.
           }
         else // Reintialize game with new score
          {
           score_game.score_A ++;
           initialize ();
          }
           return;
       }
}
void play ()
{
  while (inportb (0X60) != 16) // Check wether key press is Q if so exit loop
     {
       delay (10); // Reduce game speed to human playable level
       if (inportb (0X60) == 30)  movebat ('A');
       if (inportb (0X60) == 44)  movebat ('Z');
       if (inportb (0X60) == 36)  movebat ('J');
       if (inportb (0X60) == 50)  movebat ('M');
       moveball ();
       physics ();
      }
}
            
int main ()
{
  score_game.score_A = 0;// Intialise score in Main This Time
  score_game.score_B = 0;// It improves Efficiency
  initialize ();
  play (); // Game Engine
  closegraph (); // Close Graphics
  return 0;
}

 

 

Back To Top

11. Final Words

I Know what you must be thinking "Thats a hell lot of Code for a Ping Pong". Well if you written this code 30 years back you would have made more money than Blizzard Entertainement.

I know this is not easy but did you expected games programming it to be easy. Study some more game programming tutorials to hone your skills razor sharp.

Imagine 260 lines of Code for Ping Pong maybe 1000 for Mario and Millions for Age Of Empire. Its true big games do go into millions of lines of code but this dont mean you cannt make. They may take time but if you know C you are limited only by your imagination.

If you sincerely studied this tutorial and came out succesfull you deserve my appreciation because i believe only a pro C programmer can do that and now you are one of them. Congrats !!!.

If you are stuck somewhere you can surely contanct us.

Program has been checked many times and is 100% bugfree but you still experience problem you are free to contanct us.

Keep checking for next version of the game. Enjoy !!!

Back To Top

12. Whats Next ?

This is the first version of game and needs improvement. We will be getting back to it as soon as we can.

You have permission to copy this game executable and source code and modify it, Improve it, anything you want.

You can even publish this content on your website, we just ask you to pop us a mail and place a small link to us if you find this stuff worthy enough to be a part of your website!!!

IIf you have improved our Version of game contanct us and we will publish it on our website with proper credit given to you.

For All those programmers excited to get thier hands dirty heres where you can start -

1. AI Computer Player

2. Trendy Backgrounds

3. Menu For The Game

4. Multiple Balls

5. Sound Effects

6. Background Music

7. Difficulty levels

8. 2D moving Bats

9. 3D Pong and much more....

Next Version of Game will have this and much more. Contribute your share, get credited for it and become world famous ;-)

Now get started with this source code and executable file -

Source Code

Executable

 

 

Back To Top

Reader Comments -

Author Comments

 

Add Comments 


Name :    
Reply :   


Rating :

Code : Code

 

© 2006 cencyclopedia.com