Jump to content
  • Advertisement
Sign in to follow this  

Pong AI, and some advice on the code I've managed to cobble together

This topic is 4745 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I started working on this thing a couple of days ago. Not much planning on my part has led to a bunch of code that feels "improvised." Ugliness and redundancy are my biggest worries. I could use some advice on cleaning up the code. Plus, I need to add some AI. Right now I just got a "dumb" paddle going up and down randomly (at least 5 lines in a row). I'm almost afraid to post the code. But here it is:
#include <iostream>

using std::cout;
using std::cin;
using std::endl;

#include <iomanip>

using std::setw;

#include <ctime>
#include <cmath>
#include <conio.h>
#include <windows.h>

const int SCREEN_HEIGHT = 25;
const int SCREEN_WIDTH  = 80;
const int GAME_OBJECT_STR_LENGTH = 4;
enum { pLEFT = 10, pRIGHT = 70, pMIDDLE = 39 };
enum { pTOP = 3, pBOTTOM = 22, pCENTER = 12 };
enum DIRECTION { d_LEFT = -1, d_NONE = 0, d_RIGHT = 1, d_UP = -1, d_DOWN = 1 };
enum { LOSE_LINE_LEFT = 8, LOSE_LINE_RIGHT = 72 };

// forward declarations/prototypes
void gotoxy( int, int );
void delay( int );
void print_interface();
void ai_move( int & );

int player1score = 0;
int player2score = 0;
int speedfactor = 100;
bool flag1 = false; // a flag because I'm lazy

// game object struct
struct game_object {
    char str_top[4];     // all game objects will consist of three (or less) char
    char str_middle[4];  // arrays of length 3 or less
    char str_bottom[4];
    int oldx, oldy;
    int tempx, tempy;
    int x, y;
};

// engine class
class pong {
    
    public:
        void draw_object( game_object & );
        void get_input( int & );
        void ball_move( game_object &, game_object &, game_object & );
        bool check_ball( game_object & );
        
} engine;

void pong::draw_object( game_object &object )
{
    // delete object at old location
    for ( int i = 0; i < GAME_OBJECT_STR_LENGTH - 1; i++ ) {
        if ( object.str_top[ i ] )
            gotoxy( object.oldx + i, object.oldy ), cout << " ";
    
        if ( object.str_middle[ i ] )
            gotoxy( object.oldx + i, object.oldy + 1 ), cout << " ";
        
        if ( object.str_bottom[ i ] )
            gotoxy( object.oldx + i, object.oldy + 2), cout << " ";
    }
    
    // draw object at new location
    if ( object.str_top )
        gotoxy( object.x, object.y ), cout << object.str_top;
    
    if ( object.str_middle )
        gotoxy( object.x, object.y + 1 ), cout << object.str_middle;
        
    if ( object.str_bottom[ 0 ] )
        gotoxy( object.x, object.y + 2), cout << object.str_bottom;
}

void pong::get_input( int &y )
{       
    if ( GetAsyncKeyState( 38 ) && y != pTOP ) // if the "up" key is pressed...
        y--;
    
    if ( GetAsyncKeyState( 40 ) && y != pBOTTOM - 2 ) // if the "down" key is pressed...
        y++;
}

void pong::ball_move( game_object &ball, game_object &p1, game_object &p2 )
{
    static DIRECTION Y_DIR = d_NONE;
    static DIRECTION X_DIR = d_LEFT;
    
    if ( flag1 == true ) {
        Y_DIR = d_NONE;
        X_DIR = rand() % 2 == 0 ? d_LEFT : d_RIGHT;
        flag1 = false;
    }
    
    if ( ball.x == pLEFT + 1 ) { // if the ball hits the line...
       
        if ( ball.y == p1.y - 1 ) { // if it hits the top of the paddle, reflect
            Y_DIR = d_UP;           // along x+ and y+
            X_DIR = d_RIGHT;
            if ( speedfactor >= 25 )
                speedfactor -= 5;
        }
        
        else if ( ball.y == p1.y ) { // if it hits the middle, reflect along
            Y_DIR = d_NONE;          // x+ only
            X_DIR = d_RIGHT;
            if ( speedfactor >= 25 )
                speedfactor -= 5;
        }
        
        else if ( ball.y == p1.y + 1 ) {
            Y_DIR = d_DOWN;
            X_DIR = d_RIGHT;
            if ( speedfactor >= 25 )
                speedfactor -= 5;
        }
    } else if ( ball.x == pRIGHT - 1 ) { // if the ball hits the line...
       
        if ( ball.y == p2.y - 1  ) { // if it hits the top of the paddle, reflect
            Y_DIR = d_UP;            // along x+ and y+
            X_DIR = d_LEFT;
            if ( speedfactor >= 25 )
                speedfactor -= 5;
        }
        
        else if ( ball.y == p2.y ) { // if it hits the middle, reflect along
            Y_DIR = d_NONE;          // x+ only
            X_DIR = d_LEFT;
            if ( speedfactor >= 25 )
                speedfactor -= 5;
        }
        
        else if ( ball.y == p2.y + 1 ) {
            Y_DIR = d_DOWN;
            X_DIR = d_LEFT;
            if ( speedfactor >= 25 )
                speedfactor -= 5;
        }
    }
    
    if ( ball.y == pTOP )
        Y_DIR = d_DOWN;
    else if ( ball.y == pBOTTOM - 2 )
        Y_DIR = d_UP;
    
    ball.oldx = ball.x;
    ball.oldy = ball.y;
    
    ball.x += X_DIR;
    ball.y += Y_DIR;
}

bool pong::check_ball( game_object &ball )
{
    if ( ball.x == LOSE_LINE_RIGHT ) {
        player1score++;
        if ( speedfactor - 1 < 100 )
            speedfactor += 2;
        flag1 = true;
        return true;
    }
    
    if ( ball.x == LOSE_LINE_LEFT ) {
        player2score++;
        if ( speedfactor - 1 < 100 )
            speedfactor += 2;
        flag1 = true;
        return true;
    }
    
    return false;
}

int main()
{
    game_object paddle1, paddle2, ball;
    
    // paddle 1 initialization
    paddle1.x = pLEFT, paddle1.y = pCENTER;
    paddle1.oldx = paddle1.x, paddle1.oldy = paddle1.y;
    
    paddle1.str_top[ 0 ] = '|', paddle1.str_top[ 1 ] = '\0',
        paddle1.str_top[ 2 ] = '\0';
    
    paddle1.str_middle[ 0 ] = '|', paddle1.str_middle[ 1 ] = '\0',
        paddle1.str_middle[ 2 ] = '\0';
    
    paddle1.str_bottom[ 0 ] = '|', paddle1.str_bottom[ 1 ] = '\0',
        paddle1.str_bottom[ 1 ] = '\0';

    // paddle 2 initialization
    paddle2.x = pRIGHT, paddle2.y = pCENTER;
    paddle2.oldx = paddle2.x, paddle2.oldy = paddle2.y;
    
    paddle2.str_top[ 0 ] = '|', paddle2.str_top[ 1 ] = '\0',
        paddle2.str_top[ 2 ] = '\0';
    
    paddle2.str_middle[ 0 ] = '|', paddle2.str_middle[ 1 ] = '\0',
        paddle2.str_middle[ 2 ] = '\0';
    
    paddle2.str_bottom[ 0 ] = '|', paddle2.str_bottom[ 1 ] = '\0',
        paddle2.str_bottom[ 1 ] = '\0';
    
    // ball initialization
    ball.x = pMIDDLE, ball.y = pCENTER;
    ball.oldx = ball.x, ball.oldy = ball.y;
    
    ball.str_top[ 0 ] = '\0', ball.str_top[ 1 ] = '\0',
        ball.str_top[ 2 ] = '\0';
    
    ball.str_middle[ 0 ] = 219, ball.str_middle[ 1 ] = '\0',
        ball.str_middle[ 2 ] = '\0';
    
    ball.str_bottom[ 0 ] = '\0', ball.str_bottom[ 1 ] = '\0',
        ball.str_bottom[ 1 ] = '\0';
        
    while( 1 ) {
        delay( speedfactor );
        print_interface();
        engine.draw_object( paddle1 );
        engine.draw_object( paddle2 );
        engine.draw_object( ball );
        
        if ( kbhit() ) {
            paddle1.oldy = paddle1.y;
            paddle2.oldy = paddle2.y;
            engine.get_input( paddle1.y );
        }
        
        ai_move( paddle2.y );
        
        engine.ball_move( ball, paddle1, paddle2 );
        
        if ( engine.check_ball( ball ) ) {
            paddle1.x = pLEFT, paddle1.y = pCENTER;
            paddle1.oldx = paddle1.x, paddle1.oldy = paddle1.y;
            
            paddle2.x = pRIGHT, paddle2.y = pCENTER;
            paddle2.oldx = paddle2.x, paddle2.oldy = paddle2.y;
            
            ball.x = pMIDDLE, ball.y = pCENTER;
            ball.oldx = ball.x, ball.oldy = ball.y;
            
            gotoxy( pMIDDLE - 10, pCENTER - 1 );
            cout << "                                     ";
            
            gotoxy( pMIDDLE - 10, pCENTER );
            cout << "Oops! Score is " << player1score << " - " << player2score << endl;
            
            gotoxy( pMIDDLE - 10, pCENTER + 1 );
            cout << "                                     ";
            
            delay( 3000 );
            system( "cls" );
        } 
    }
}

// a couple of functions for utility purposes
void gotoxy( int x, int y )
{
    COORD pos;
    HANDLE screen = GetStdHandle( STD_OUTPUT_HANDLE );

    pos.X = x;
    pos.Y = y;

    SetConsoleCursorPosition( screen, pos );
}

void delay( int milliseconds )
{
    time_t now = clock();
    time_t end = now + milliseconds;
    
    while( now = clock() < end );
}

void print_interface()
{
    gotoxy( 0, 0 );
    cout << "Player 1: " << player1score << "\tPlayer 2: " << player2score
            << "\t\tGamespeed is currently: "
               << setw( 2 ) << abs( speedfactor - 100 ) << "/80\n\n"
         << "        _________________________________________________________________\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |                                |                                |\n"
         << "       |________________________________|________________________________|\n";
}

void ai_move( int &y )
{   
    static DIRECTION dir = d_UP;
    static int dcounter = 0;
    
    if ( y == pTOP )
        dir = d_DOWN;
    else
        if ( y == pBOTTOM - 2 )
            dir = d_UP;
        else
            if ( dcounter > 5 )
                dir = rand() % 2 == 0 ? d_UP : d_DOWN;
    y += dir;
    dcounter++;
    if ( dcounter > 6 )
        dcounter = 0;
}




Please excuse any n00bish-ness. I started off ok. I had an engine class, but after some time it just devolved into a collection of public functions, pointless to have as a class. I can make this hideous beast work, but I want to make it work right. Hints, tips, AI ideas, anything will be appreciated. Thanks in advance. The main thing is AI, though. Edit: Oh yeah, and it's an ASCII pong, but you already knew that [looksaround]

Share this post


Link to post
Share on other sites
Advertisement
Putting everything into a class is not necessarily a good thing - it doesn't make your code more 'object oriented.' Some functions are naturally suited to being public globals. So don't worry about that.

My issues with your code would be:

  1. Personally, I tend to group all my includes together and put them in alphabetical order (when dependencies are not a problem).
  2. Those enums need commenting.
  3. 'flag1' is a terrible variable name. You could change it, or you could fix up the comment to tell us something useful.
  4. You say that game objects will require arrays of length 3 or less, yet your arrays are of length 4. I think you want to change the comment to say 'strings of three characters or less, not including the null terminator.'
  5. What's 'tempx' and 'tempy'?
  6. Using commas like that is a fairly nasty idea, because you're doing two things with one statement. It looks like an attempt to avoid using curly braces after the if - that's a really bad habit to get into, because at first glance there is only one thing being done by that line of code, a misleading way to leave things. Add curly braces and split the gotoxy/cout into seperate statements.
  7. It's often a good idea to bracket out seperate clauses in an if statement to avoid any potential problems with operator precedence (the get_input function's ifs are what I'm looking at).
  8. Don't you want to be copying paddle2.y to paddle2.oldy regardless of whether the user has hit a key, because your AI is going to be moving the paddle?
  9. gotoxy, delay, and ai_move need commenting.


Other than that, it's a fairly nice system you've got there.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I agree with superpig's comments. I also wrote a pong clone as my first game, if you want the source code it's here:

http://www.freewebs.com/crazyballsgame/

It uses directdraw, but the AI could be used in a text-game. Basically, check whether the ball is higher or lower than the AI paddle, and move the paddle a set number of spaces up or down accordingly.

If you scroll down the page ^ there's english underneath.

Share this post


Link to post
Share on other sites
Thanks for the tips, superpig. Using your suggestions, and some from PMs and other forums (and of course, looking at other people's code), I think I have managed to clean it up and make it much prettier and easier to understand. As far as the AI, I can't believe how simple it was. I should have been able to figure it out on my own. To the AP, I took a look at your game. It was nice. I like the AI, even if it was a bit easy. Thanks for the good example.

Without further ado:
// ASCII Pong
// Programmed by Muhammad al-Haider

// pong.cpp
#include <conio.h>
#include <cmath>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <windows.h>

using namespace std;

/*** global variables ***/
const int str_length = 4; // length for game object strings
int p1score = 0;
int p2score = 0;
int speed = 100; // gamespeed (length of delay for the main game loop)
bool randomize = true; // flag to randomize the direction the ball is moving

/*** enumerations ***/
enum { pLEFT = 10, pRIGHT = 70, pMIDDLE = 39 }; // horizontal(x) positions
enum { pTOP = 3, pBOTTOM = 22, pCENTER = 12 }; // vertical(y) positions
enum { LOSE_LINE_LEFT = 8, LOSE_LINE_RIGHT = 72 }; // the ball is out if it crosses
// one of these lines
enum DIRECTION { d_LEFT = -1, d_FLAT = 0, d_RIGHT = 1, // Direction an object is
d_UP = -1, d_DOWN = 1 }; // travelling

/*** structs ***/
struct game_object {
char szTop[ str_length ]; // all game objects will consist of three (or less)
char szMiddle[ str_length ]; // char strings of length 3 or less
char szBottom[ str_length ];
COORD old;
COORD current;
};

/*** prototypes/forward declarations ***/
void print_title();
void draw_object( game_object & );
void draw_interface();
void print_point_message();
void ball_move( game_object &, COORD, COORD );
void get_input( short & );
void ai_move( short &, game_object &, short );
bool check_ball( game_object & );
void gotoxy( int, int );
void delay( int );

/*******************************************************************************
* Main *
*******************************************************************************/


int main()
{
srand( time( NULL ) ); // seed random number generator

/*** initialize game_objects ***/

game_object paddle1, paddle2, ball;
short dir; // direction the ball is traveling

/**********
| paddle1 |
**********/

paddle1.old.X = paddle1.current.X = pLEFT;
paddle1.old.Y = paddle1.current.Y = pCENTER;

// top string
paddle1.szTop[ 0 ] = '|';
paddle1.szTop[ 1 ] = 0;
paddle1.szTop[ 2 ] = 0;

// middle string
paddle1.szMiddle[ 0 ] = '|';
paddle1.szMiddle[ 1 ] = 0;
paddle1.szMiddle[ 2 ] = 0;

// bottom string
paddle1.szBottom[ 0 ] = '|';
paddle1.szBottom[ 1 ] = 0;
paddle1.szBottom[ 2 ] = 0;

/**********
| paddle2 |
**********/

paddle2.old.X = paddle2.current.X = pRIGHT;
paddle2.old.Y = paddle2.current.Y = pCENTER;

// top string
paddle2.szTop[ 0 ] = '|';
paddle2.szTop[ 1 ] = 0;
paddle2.szTop[ 2 ] = 0;

// middle string
paddle2.szMiddle[ 0 ] = '|';
paddle2.szMiddle[ 1 ] = 0;
paddle2.szMiddle[ 2 ] = 0;

// bottom string
paddle2.szBottom[ 0 ] = '|';
paddle2.szBottom[ 1 ] = 0;
paddle2.szBottom[ 2 ] = 0;

/*******
| ball |
*******/

ball.old.X = ball.current.X = pMIDDLE;
ball.old.Y = ball.current.Y = pCENTER;

// top string
ball.szTop[ 0 ] = 0;
ball.szTop[ 1 ] = 0;
ball.szTop[ 2 ] = 0;

// middle string
ball.szMiddle[ 0 ] = 219;
ball.szMiddle[ 1 ] = 0;
ball.szMiddle[ 2 ] = 0;

// bottom string
ball.szBottom[ 0 ] = 0;
ball.szBottom[ 1 ] = 0;
ball.szBottom[ 2 ] = 0;

print_title();

while( 1 ) {
delay( speed );
draw_interface();
draw_object( paddle1 );
draw_object( paddle2 );
draw_object( ball );

paddle1.old.Y = paddle1.current.Y;
paddle2.old.Y = paddle2.current.Y;

// determine whether ball is moving left or right
if ( ball.old.X < ball.current.X )
dir = d_RIGHT;
if ( ball.old.X > ball.current.X )
dir = d_LEFT;

// move the game objects
if ( kbhit() ) get_input( paddle1.current.Y );
ai_move( paddle2.current.Y, ball, dir );
ball_move( ball, paddle1.current, paddle2.current );

if ( check_ball( ball ) ) { // if one of the players misses the ball

// reset the game objects
paddle1.old.X = paddle1.current.X = pLEFT;
paddle1.old.Y = paddle1.current.Y = pCENTER;
paddle2.old.X = paddle2.current.X = pRIGHT;
paddle2.old.Y = paddle2.current.Y = pCENTER;
ball.old.X = ball.current.X = pMIDDLE;
ball.old.Y = ball.current.Y = pCENTER;
randomize = true; // randomize horizontal direction of the ball

print_point_message(); // print a message that the score has changed
delay( 3000 ); // wait three seconds
system( "cls" ); // clear the board and continue
}
}
}

/*******************************************************************************
* "Drawing" Functions *
*******************************************************************************/


/*** prints the title and some short information ***/
void print_title()
{
cout << "\n\n\n\n\n\n\n\n\n\t\t\tASCII Pong version 1.0\n\t\t\tby Muhammad al-Haider"
<< "\n\t\t\tskulldrudgery@hotmail.com";
delay( 4000 );
system( "cls" );
}

/*** prints an object to the screen and clears the object's former position ***/
void draw_object( game_object &object )
{
// delete object at old location
for ( int i = 0; i < str_length - 1; i++ ) {
if ( object.szTop[ i ] )
gotoxy( object.old.X + i, object.old.Y ), cout << " ";

if ( object.szMiddle[ i ] )
gotoxy( object.old.X + i, object.old.Y + 1 ), cout << " ";

if ( object.szBottom[ i ] )
gotoxy( object.old.X + i, object.old.Y + 2), cout << " ";
}

// draw object at new location
if ( object.szTop[ 0 ] )
gotoxy( object.current.X, object.current.Y ), cout << object.szTop;

if ( object.szMiddle[ 0 ] )
gotoxy( object.current.X, object.current.Y + 1 ), cout << object.szMiddle;

if ( object.szBottom[ 0 ] )
gotoxy( object.current.X, object.current.Y + 2), cout << object.szBottom;
}

/*** prints the "interface" of the game: the board, score and gamespeed ***/
void draw_interface()
{
gotoxy( 0, 0 ); // reset the cursor, to begin printing from upper-left corner

cout << " Player 1: " << setw( 2 ) << p1score << " Player 2: " << setw( 2 )
<< p2score << "\t Gamespeed is currently: " << setw( 2 ) << abs( speed - 100 )
<< "/80\n\n";

cout << " _________________________________________________________________\n"
<< " | | |\n"
<< " A | | |\n"
<< " | | |\n"
<< " S | | |\n"
<< " | | |\n"
<< " C | | |\n"
<< " | | |\n"
<< " I | | |\n"
<< " | | |\n"
<< " I | | |\n"
<< " | | |\n"
<< " | | |\n"
<< " P | | |\n"
<< " | | |\n"
<< " O | | |\n"
<< " | | |\n"
<< " N | | |\n"
<< " | | |\n"
<< " G | | |\n"
<< " |________________________________|________________________________|\n";
}

/*** prints a message that the score has changed ***/
void print_point_message()
{
gotoxy( pMIDDLE - 10, pCENTER - 1 );
cout << " ";

gotoxy( pMIDDLE - 10, pCENTER + 1 );
cout << " ";

gotoxy( pMIDDLE - 10, pCENTER );
cout << "Oops! Score is " << p1score << " - " << p2score;
}


/*******************************************************************************
* "Moving" Functions *
*******************************************************************************/


/*** moves the ball and reflects it off the surfaces (paddles and borders) ***/
void ball_move( game_object &ball, COORD p1, COORD p2 )
{
static DIRECTION Y_DIR = d_FLAT; // y direction of the ball
static DIRECTION X_DIR = d_LEFT; // x direction of the ball

// if the randomize flag is set, randomly choose directions and reset flag
if ( randomize ) {
X_DIR = rand() % 100 < 50 ? d_LEFT : d_RIGHT;
Y_DIR = rand() % 100 < 50 ? d_UP : d_DOWN;
randomize = false;
}

// if the ball reaches the x coordinates (+1) of the left paddle...
if ( ball.current.X == pLEFT + 1 ) {

// ...check if any part of the paddle would "hit" it, if it hits the...
if ( ball.current.Y == p1.Y - 1 ) { // ...top, reflect along y+ and x+
Y_DIR = d_UP;
X_DIR = d_RIGHT;
if ( speed >= 25 ) speed -= 3;
} else
if ( ball.current.Y == p1.Y ) { // ...middle, reflect along x+ only
Y_DIR = d_FLAT;
X_DIR = d_RIGHT;
if ( speed >= 25 ) speed -= 3;
} else
if ( ball.current.Y == p1.Y + 1 ) { // ...bottom, reflect along y- and x+
Y_DIR = d_DOWN;
X_DIR = d_RIGHT;
if ( speed >= 25 ) speed -= 3; // speed increases each time the ball is hit
}
} // end if ( ball.current.X == pLEFT + 1 )

// if the ball reaches the x coordinates (-1) of the right paddle...
if ( ball.current.X == pRIGHT - 1 ) {

// ...check if any part of the paddle would "hit" it, if it hits the...
if ( ball.current.Y == p2.Y - 1 ) { // ...top, reflect along y+ and x-
Y_DIR = d_UP;
X_DIR = d_LEFT;
if ( speed >= 25 ) speed -= 3;
} else
if ( ball.current.Y == p2.Y ) { // ...middle, reflect along x- only
Y_DIR = d_FLAT;
X_DIR = d_LEFT;
if ( speed >= 25 ) speed -= 3;
} else
if ( ball.current.Y == p2.Y + 1 ) { // ...bottom, reflect along y- and x-
Y_DIR = d_DOWN;
X_DIR = d_LEFT;
if ( speed >= 25 ) speed -= 3;
}
} // end if ( ball.current.Y == p2.current.Y - 1 )

// if the ball hits the top border...
if ( ball.current.Y == pTOP ) Y_DIR = d_DOWN; // reflect along y-

// if the ball hits the bottom border...
if ( ball.current.Y == pBOTTOM - 2 ) Y_DIR = d_UP; // reflect along y+

// update the old coordinates to the current ones
ball.old.X = ball.current.X;
ball.old.Y = ball.current.Y;

// update the coordinates of the ball according to the directions the it's moving
ball.current.X += X_DIR;
ball.current.Y += Y_DIR;
}

/*** moves the computer paddle according to the ai routine ***/
void ai_move( short &y, game_object &ball, short h_direction )
{
static DIRECTION dir = d_UP; // vertical direction
static int dcounter = 0; // number of lines moved in one direction

// if the ball is close to the right paddle and is traveling that way...
if ( ball.current.X > 60 && h_direction == d_RIGHT ) {
dcounter = 0; // reset counter

if ( y > ball.current.Y ) // if the paddle is lower than the ball, move up
y--;

else if ( y < ball.current.Y ) // if higher, move down
y++;
} else if ( h_direction == d_RIGHT ) {
// if the ball is not close, the paddle moves randomly


if ( y == pTOP ) dir = d_DOWN;
else
if ( y == pBOTTOM - 2 ) dir = d_UP;
else // if the dcounter is more than five, change to a random direction
if ( dcounter == 8 ) dir = rand() % 2 == 0 ? d_UP : d_DOWN;

dcounter++;
y += dir;

// reset the counter for the number of lines moved
if ( dcounter > 8 ) dcounter = 0;
}
}

/*******************************************************************************
* Input Functions *
*******************************************************************************/


/*** get direction input from player, and change y coordinate appropriately ***/
void get_input( short &y )
{
if ( GetAsyncKeyState( 38 ) && y != pTOP ) y--; // "up" key, ignore if paddle is at top
if ( GetAsyncKeyState( 40 ) && y != pBOTTOM - 2 ) y++; // "down" key, ignore if paddle is
// at bottom (- 2 to account for
// paddle length)
}

/*******************************************************************************
* Winning Condition Functions *
*******************************************************************************/


/*** check if the ball has gone "out" ***/
bool check_ball( game_object &ball )
{
if ( ball.current.X == LOSE_LINE_RIGHT ) { // if player 2 misses the ball...
p1score++; // ...player one scores
if ( speed - 1 < 100 ) speed += 2; // if the game speed is over 0, decrease by 2
randomize = true; // choose a random direction for the ball ( left or right)
return true; // the ball was missed
}

if ( ball.current.X == LOSE_LINE_LEFT ) { // if player 1 misses the ball...
p2score++; // ...player two scores
if ( speed - 1 < 100 ) speed += 2; // if the game speed is over 0, decrease by 2
randomize = true; // choose a random direction for the ball ( left or right)
return true; // the ball was missed
}

return false; // the ball was not missed
}

/*******************************************************************************
* Utility Functions *
*******************************************************************************/


// move the cursor to the given coordinates
void gotoxy( int x, int y )
{
COORD pos;
HANDLE screen = GetStdHandle( STD_OUTPUT_HANDLE );

pos.X = x;
pos.Y = y;

SetConsoleCursorPosition( screen, pos );
}

// delay for a given number of milliseconds - busy waiting
inline void delay( int m )
{
for ( time_t end = clock() + m; clock() < end; );
}





@ superpig feel the impotent force of my ratings++ on you

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!