#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 )
gotoxy( object.oldx + i, object.oldy ), cout << <span class="cpp-literal">" "</span>;
<span class="cpp-keyword">if</span> ( object.str_middle )
gotoxy( object.oldx + i, object.oldy + <span class="cpp-number">1</span> ), cout << <span class="cpp-literal">" "</span>;
<span class="cpp-keyword">if</span> ( object.str_bottom )
gotoxy( object.oldx + i, object.oldy + <span class="cpp-number">2</span>), cout << <span class="cpp-literal">" "</span>;
}
<span class="cpp-comment">// draw object at new location</span>
<span class="cpp-keyword">if</span> ( object.str_top )
gotoxy( object.x, object.y ), cout << object.str_top;
<span class="cpp-keyword">if</span> ( object.str_middle )
gotoxy( object.x, object.y + <span class="cpp-number">1</span> ), cout << object.str_middle;
<span class="cpp-keyword">if</span> ( object.str_bottom[ <span class="cpp-number">0</span> ] )
gotoxy( object.x, object.y + <span class="cpp-number">2</span>), cout << object.str_bottom;
}
<span class="cpp-keyword">void</span> pong::get_input( <span class="cpp-keyword">int</span> &y )
{
<span class="cpp-keyword">if</span> ( GetAsyncKeyState( <span class="cpp-number">38</span> ) && y != pTOP ) <span class="cpp-comment">// if the "up" key is pressed…</span>
y–;
<span class="cpp-keyword">if</span> ( GetAsyncKeyState( <span class="cpp-number">40</span> ) && y != pBOTTOM - <span class="cpp-number">2</span> ) <span class="cpp-comment">// if the "down" key is pressed…</span>
y++;
}
<span class="cpp-keyword">void</span> pong::ball_move( game_object &ball, game_object &p1, game_object &p2 )
{
<span class="cpp-keyword">static</span> DIRECTION Y_DIR = d_NONE;
<span class="cpp-keyword">static</span> DIRECTION X_DIR = d_LEFT;
<span class="cpp-keyword">if</span> ( flag1 == <span class="cpp-keyword">true</span> ) {
Y_DIR = d_NONE;
X_DIR = rand() % <span class="cpp-number">2</span> == <span class="cpp-number">0</span> ? d_LEFT : d_RIGHT;
flag1 = <span class="cpp-keyword">false</span>;
}
<span class="cpp-keyword">if</span> ( ball.x == pLEFT + <span class="cpp-number">1</span> ) { <span class="cpp-comment">// if the ball hits the line…</span>
<span class="cpp-keyword">if</span> ( ball.y == p1.y - <span class="cpp-number">1</span> ) { <span class="cpp-comment">// if it hits the top of the paddle, reflect</span>
Y_DIR = d_UP; <span class="cpp-comment">// along x+ and y+</span>
X_DIR = d_RIGHT;
<span class="cpp-keyword">if</span> ( speedfactor >= <span class="cpp-number">25</span> )
speedfactor -= <span class="cpp-number">5</span>;
}
<span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( ball.y == p1.y ) { <span class="cpp-comment">// if it hits the middle, reflect along</span>
Y_DIR = d_NONE; <span class="cpp-comment">// x+ only</span>
X_DIR = d_RIGHT;
<span class="cpp-keyword">if</span> ( speedfactor >= <span class="cpp-number">25</span> )
speedfactor -= <span class="cpp-number">5</span>;
}
<span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( ball.y == p1.y + <span class="cpp-number">1</span> ) {
Y_DIR = d_DOWN;
X_DIR = d_RIGHT;
<span class="cpp-keyword">if</span> ( speedfactor >= <span class="cpp-number">25</span> )
speedfactor -= <span class="cpp-number">5</span>;
}
} <span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( ball.x == pRIGHT - <span class="cpp-number">1</span> ) { <span class="cpp-comment">// if the ball hits the line…</span>
<span class="cpp-keyword">if</span> ( ball.y == p2.y - <span class="cpp-number">1</span> ) { <span class="cpp-comment">// if it hits the top of the paddle, reflect</span>
Y_DIR = d_UP; <span class="cpp-comment">// along x+ and y+</span>
X_DIR = d_LEFT;
<span class="cpp-keyword">if</span> ( speedfactor >= <span class="cpp-number">25</span> )
speedfactor -= <span class="cpp-number">5</span>;
}
<span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( ball.y == p2.y ) { <span class="cpp-comment">// if it hits the middle, reflect along</span>
Y_DIR = d_NONE; <span class="cpp-comment">// x+ only</span>
X_DIR = d_LEFT;
<span class="cpp-keyword">if</span> ( speedfactor >= <span class="cpp-number">25</span> )
speedfactor -= <span class="cpp-number">5</span>;
}
<span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( ball.y == p2.y + <span class="cpp-number">1</span> ) {
Y_DIR = d_DOWN;
X_DIR = d_LEFT;
<span class="cpp-keyword">if</span> ( speedfactor >= <span class="cpp-number">25</span> )
speedfactor -= <span class="cpp-number">5</span>;
}
}
<span class="cpp-keyword">if</span> ( ball.y == pTOP )
Y_DIR = d_DOWN;
<span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( ball.y == pBOTTOM - <span class="cpp-number">2</span> )
Y_DIR = d_UP;
ball.oldx = ball.x;
ball.oldy = ball.y;
ball.x += X_DIR;
ball.y += Y_DIR;
}
<span class="cpp-keyword">bool</span> pong::check_ball( game_object &ball )
{
<span class="cpp-keyword">if</span> ( ball.x == LOSE_LINE_RIGHT ) {
player1score++;
<span class="cpp-keyword">if</span> ( speedfactor - <span class="cpp-number">1</span> < <span class="cpp-number">100</span> )
speedfactor += <span class="cpp-number">2</span>;
flag1 = <span class="cpp-keyword">true</span>;
<span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;
}
<span class="cpp-keyword">if</span> ( ball.x == LOSE_LINE_LEFT ) {
player2score++;
<span class="cpp-keyword">if</span> ( speedfactor - <span class="cpp-number">1</span> < <span class="cpp-number">100</span> )
speedfactor += <span class="cpp-number">2</span>;
flag1 = <span class="cpp-keyword">true</span>;
<span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>;
}
<span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>;
}
<span class="cpp-keyword">int</span> main()
{
game_object paddle1, paddle2, ball;
<span class="cpp-comment">// paddle 1 initialization</span>
paddle1.x = pLEFT, paddle1.y = pCENTER;
paddle1.oldx = paddle1.x, paddle1.oldy = paddle1.y;
paddle1.str_top[ <span class="cpp-number">0</span> ] = '|', paddle1.str_top[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
paddle1.str_top[ <span class="cpp-number">2</span> ] = '\<span class="cpp-number">0</span>';
paddle1.str_middle[ <span class="cpp-number">0</span> ] = '|', paddle1.str_middle[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
paddle1.str_middle[ <span class="cpp-number">2</span> ] = '\<span class="cpp-number">0</span>';
paddle1.str_bottom[ <span class="cpp-number">0</span> ] = '|', paddle1.str_bottom[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
paddle1.str_bottom[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>';
<span class="cpp-comment">// paddle 2 initialization</span>
paddle2.x = pRIGHT, paddle2.y = pCENTER;
paddle2.oldx = paddle2.x, paddle2.oldy = paddle2.y;
paddle2.str_top[ <span class="cpp-number">0</span> ] = '|', paddle2.str_top[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
paddle2.str_top[ <span class="cpp-number">2</span> ] = '\<span class="cpp-number">0</span>';
paddle2.str_middle[ <span class="cpp-number">0</span> ] = '|', paddle2.str_middle[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
paddle2.str_middle[ <span class="cpp-number">2</span> ] = '\<span class="cpp-number">0</span>';
paddle2.str_bottom[ <span class="cpp-number">0</span> ] = '|', paddle2.str_bottom[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
paddle2.str_bottom[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>';
<span class="cpp-comment">// ball initialization</span>
ball.x = pMIDDLE, ball.y = pCENTER;
ball.oldx = ball.x, ball.oldy = ball.y;
ball.str_top[ <span class="cpp-number">0</span> ] = '\<span class="cpp-number">0</span>', ball.str_top[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
ball.str_top[ <span class="cpp-number">2</span> ] = '\<span class="cpp-number">0</span>';
ball.str_middle[ <span class="cpp-number">0</span> ] = <span class="cpp-number">219</span>, ball.str_middle[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
ball.str_middle[ <span class="cpp-number">2</span> ] = '\<span class="cpp-number">0</span>';
ball.str_bottom[ <span class="cpp-number">0</span> ] = '\<span class="cpp-number">0</span>', ball.str_bottom[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>',
ball.str_bottom[ <span class="cpp-number">1</span> ] = '\<span class="cpp-number">0</span>';
<span class="cpp-keyword">while</span>( <span class="cpp-number">1</span> ) {
delay( speedfactor );
print_interface();
engine.draw_object( paddle1 );
engine.draw_object( paddle2 );
engine.draw_object( ball );
<span class="cpp-keyword">if</span> ( kbhit() ) {
paddle1.oldy = paddle1.y;
paddle2.oldy = paddle2.y;
engine.get_input( paddle1.y );
}
ai_move( paddle2.y );
engine.ball_move( ball, paddle1, paddle2 );
<span class="cpp-keyword">if</span> ( 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 - <span class="cpp-number">10</span>, pCENTER - <span class="cpp-number">1</span> );
cout << <span class="cpp-literal">" "</span>;
gotoxy( pMIDDLE - <span class="cpp-number">10</span>, pCENTER );
cout << <span class="cpp-literal">"Oops! Score is "</span> << player1score << <span class="cpp-literal">" - "</span> << player2score << endl;
gotoxy( pMIDDLE - <span class="cpp-number">10</span>, pCENTER + <span class="cpp-number">1</span> );
cout << <span class="cpp-literal">" "</span>;
delay( <span class="cpp-number">3000</span> );
system( <span class="cpp-literal">"cls"</span> );
}
}
}
<span class="cpp-comment">// a couple of functions for utility purposes</span>
<span class="cpp-keyword">void</span> gotoxy( <span class="cpp-keyword">int</span> x, <span class="cpp-keyword">int</span> y )
{
COORD pos;
HANDLE screen = GetStdHandle( STD_OUTPUT_HANDLE );
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition( screen, pos );
}
<span class="cpp-keyword">void</span> delay( <span class="cpp-keyword">int</span> milliseconds )
{
time_t now = clock();
time_t end = now + milliseconds;
<span class="cpp-keyword">while</span>( now = clock() < end );
}
<span class="cpp-keyword">void</span> print_interface()
{
gotoxy( <span class="cpp-number">0</span>, <span class="cpp-number">0</span> );
cout << <span class="cpp-literal">"Player 1: "</span> << player1score << <span class="cpp-literal">"\tPlayer 2: "</span> << player2score
<< <span class="cpp-literal">"\t\tGamespeed is currently: "</span>
<< setw( <span class="cpp-number">2</span> ) << abs( speedfactor - <span class="cpp-number">100</span> ) << <span class="cpp-literal">"/80\n\n"</span>
<< <span class="cpp-literal">" _________________________________________________________________\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" | | |\n"</span>
<< <span class="cpp-literal">" |________________________________|________________________________|\n"</span>;
}
<span class="cpp-keyword">void</span> ai_move( <span class="cpp-keyword">int</span> &y )
{
<span class="cpp-keyword">static</span> DIRECTION dir = d_UP;
<span class="cpp-keyword">static</span> <span class="cpp-keyword">int</span> dcounter = <span class="cpp-number">0</span>;
<span class="cpp-keyword">if</span> ( y == pTOP )
dir = d_DOWN;
<span class="cpp-keyword">else</span>
<span class="cpp-keyword">if</span> ( y == pBOTTOM - <span class="cpp-number">2</span> )
dir = d_UP;
<span class="cpp-keyword">else</span>
<span class="cpp-keyword">if</span> ( dcounter > <span class="cpp-number">5</span> )
dir = rand() % <span class="cpp-number">2</span> == <span class="cpp-number">0</span> ? d_UP : d_DOWN;
y += dir;
dcounter++;
<span class="cpp-keyword">if</span> ( dcounter > <span class="cpp-number">6</span> )
dcounter = <span class="cpp-number">0</span>;
}
</pre></div><!–ENDSCRIPT–>
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]
Pong AI, and some advice on the code I've managed to cobble together
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:
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:
Other than that, it's a fairly nice system you've got there.
My issues with your code would be:
- Personally, I tend to group all my includes together and put them in alphabetical order (when dependencies are not a problem).
- Those enums need commenting.
- 'flag1' is a terrible variable name. You could change it, or you could fix up the comment to tell us something useful.
- 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.'
- What's 'tempx' and 'tempy'?
- 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.
- 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).
- 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?
- gotoxy, delay, and ai_move need commenting.
Other than that, it's a fairly nice system you've got there.
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.
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.
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:
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 stringsint 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 )<br> gotoxy( object.old.X + i, object.old.Y ), cout << <span class="cpp-literal">" "</span>;<br> <br> <span class="cpp-keyword">if</span> ( object.szMiddle )<br> gotoxy( object.old.X + i, object.old.Y + <span class="cpp-number">1</span> ), cout << <span class="cpp-literal">" "</span>;<br> <br> <span class="cpp-keyword">if</span> ( object.szBottom )<br> gotoxy( object.old.X + i, object.old.Y + <span class="cpp-number">2</span>), cout << <span class="cpp-literal">" "</span>;<br> }<br> <br> <span class="cpp-comment">// draw object at new location</span><br> <span class="cpp-keyword">if</span> ( object.szTop[ <span class="cpp-number">0</span> ] )<br> gotoxy( object.current.X, object.current.Y ), cout << object.szTop;<br> <br> <span class="cpp-keyword">if</span> ( object.szMiddle[ <span class="cpp-number">0</span> ] )<br> gotoxy( object.current.X, object.current.Y + <span class="cpp-number">1</span> ), cout << object.szMiddle;<br> <br> <span class="cpp-keyword">if</span> ( object.szBottom[ <span class="cpp-number">0</span> ] )<br> gotoxy( object.current.X, object.current.Y + <span class="cpp-number">2</span>), cout << object.szBottom;<br>}<br><br><span class="cpp-comment">/*** prints the "interface" of the game: the board, score and gamespeed ***/</span><br><span class="cpp-keyword">void</span> draw_interface()<br>{<br> gotoxy( <span class="cpp-number">0</span>, <span class="cpp-number">0</span> ); <span class="cpp-comment">// reset the cursor, to begin printing from upper-left corner</span><br> <br> cout << <span class="cpp-literal">" Player 1: "</span> << setw( <span class="cpp-number">2</span> ) << p1score << <span class="cpp-literal">" Player 2: "</span> << setw( <span class="cpp-number">2</span> )<br> << p2score << <span class="cpp-literal">"\t Gamespeed is currently: "</span> << setw( <span class="cpp-number">2</span> ) << abs( speed - <span class="cpp-number">100</span> )<br> << <span class="cpp-literal">"/80\n\n"</span>;<br> <br> cout << <span class="cpp-literal">" _________________________________________________________________\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" A | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" S | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" C | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" I | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" I | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" P | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" O | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" N | | |\n"</span><br> << <span class="cpp-literal">" | | |\n"</span><br> << <span class="cpp-literal">" G | | |\n"</span><br> << <span class="cpp-literal">" |________________________________|________________________________|\n"</span>;<br>}<br><br><span class="cpp-comment">/*** prints a message that the score has changed ***/</span><br><span class="cpp-keyword">void</span> print_point_message()<br>{<br> gotoxy( pMIDDLE - <span class="cpp-number">10</span>, pCENTER - <span class="cpp-number">1</span> );<br> cout << <span class="cpp-literal">" "</span>;<br> <br> gotoxy( pMIDDLE - <span class="cpp-number">10</span>, pCENTER + <span class="cpp-number">1</span> );<br> cout << <span class="cpp-literal">" "</span>;<br> <br> gotoxy( pMIDDLE - <span class="cpp-number">10</span>, pCENTER );<br> cout << <span class="cpp-literal">"Oops! Score is "</span> << p1score << <span class="cpp-literal">" - "</span> << p2score;<br>}<br> <br><br><span class="cpp-comment">/*******************************************************************************<br>* "Moving" Functions *<br>*******************************************************************************/</span><br><br><span class="cpp-comment">/*** moves the ball and reflects it off the surfaces (paddles and borders) ***/</span><br><span class="cpp-keyword">void</span> ball_move( game_object &ball, COORD p1, COORD p2 )<br>{<br> <span class="cpp-keyword">static</span> DIRECTION Y_DIR = d_FLAT; <span class="cpp-comment">// y direction of the ball</span><br> <span class="cpp-keyword">static</span> DIRECTION X_DIR = d_LEFT; <span class="cpp-comment">// x direction of the ball</span><br> <br> <span class="cpp-comment">// if the randomize flag is set, randomly choose directions and reset flag</span><br> <span class="cpp-keyword">if</span> ( randomize ) {<br> X_DIR = rand() % <span class="cpp-number">100</span> < <span class="cpp-number">50</span> ? d_LEFT : d_RIGHT;<br> Y_DIR = rand() % <span class="cpp-number">100</span> < <span class="cpp-number">50</span> ? d_UP : d_DOWN;<br> randomize = <span class="cpp-keyword">false</span>;<br> }<br> <br> <span class="cpp-comment">// if the ball reaches the x coordinates (+1) of the left paddle…</span><br> <span class="cpp-keyword">if</span> ( ball.current.X == pLEFT + <span class="cpp-number">1</span> ) {<br><br> <span class="cpp-comment">// …check if any part of the paddle would "hit" it, if it hits the…</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == p1.Y - <span class="cpp-number">1</span> ) { <span class="cpp-comment">// …top, reflect along y+ and x+</span><br> Y_DIR = d_UP;<br> X_DIR = d_RIGHT;<br> <span class="cpp-keyword">if</span> ( speed >= <span class="cpp-number">25</span> ) speed -= <span class="cpp-number">3</span>;<br> } <span class="cpp-keyword">else</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == p1.Y ) { <span class="cpp-comment">// …middle, reflect along x+ only</span><br> Y_DIR = d_FLAT;<br> X_DIR = d_RIGHT;<br> <span class="cpp-keyword">if</span> ( speed >= <span class="cpp-number">25</span> ) speed -= <span class="cpp-number">3</span>;<br> } <span class="cpp-keyword">else</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == p1.Y + <span class="cpp-number">1</span> ) { <span class="cpp-comment">// …bottom, reflect along y- and x+</span><br> Y_DIR = d_DOWN;<br> X_DIR = d_RIGHT;<br> <span class="cpp-keyword">if</span> ( speed >= <span class="cpp-number">25</span> ) speed -= <span class="cpp-number">3</span>; <span class="cpp-comment">// speed increases each time the ball is hit</span><br> }<br> } <span class="cpp-comment">// end if ( ball.current.X == pLEFT + 1 )</span><br> <br> <span class="cpp-comment">// if the ball reaches the x coordinates (-1) of the right paddle…</span><br> <span class="cpp-keyword">if</span> ( ball.current.X == pRIGHT - <span class="cpp-number">1</span> ) {<br> <br> <span class="cpp-comment">// …check if any part of the paddle would "hit" it, if it hits the…</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == p2.Y - <span class="cpp-number">1</span> ) { <span class="cpp-comment">// …top, reflect along y+ and x-</span><br> Y_DIR = d_UP;<br> X_DIR = d_LEFT;<br> <span class="cpp-keyword">if</span> ( speed >= <span class="cpp-number">25</span> ) speed -= <span class="cpp-number">3</span>;<br> } <span class="cpp-keyword">else</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == p2.Y ) { <span class="cpp-comment">// …middle, reflect along x- only</span><br> Y_DIR = d_FLAT;<br> X_DIR = d_LEFT;<br> <span class="cpp-keyword">if</span> ( speed >= <span class="cpp-number">25</span> ) speed -= <span class="cpp-number">3</span>;<br> } <span class="cpp-keyword">else</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == p2.Y + <span class="cpp-number">1</span> ) { <span class="cpp-comment">// …bottom, reflect along y- and x-</span><br> Y_DIR = d_DOWN;<br> X_DIR = d_LEFT;<br> <span class="cpp-keyword">if</span> ( speed >= <span class="cpp-number">25</span> ) speed -= <span class="cpp-number">3</span>;<br> }<br> } <span class="cpp-comment">// end if ( ball.current.Y == p2.current.Y - 1 )</span><br> <br> <span class="cpp-comment">// if the ball hits the top border…</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == pTOP ) Y_DIR = d_DOWN; <span class="cpp-comment">// reflect along y-</span><br> <br> <span class="cpp-comment">// if the ball hits the bottom border…</span><br> <span class="cpp-keyword">if</span> ( ball.current.Y == pBOTTOM - <span class="cpp-number">2</span> ) Y_DIR = d_UP; <span class="cpp-comment">// reflect along y+</span><br> <br> <span class="cpp-comment">// update the old coordinates to the current ones</span><br> ball.old.X = ball.current.X;<br> ball.old.Y = ball.current.Y;<br> <br> <span class="cpp-comment">// update the coordinates of the ball according to the directions the it's moving</span><br> ball.current.X += X_DIR;<br> ball.current.Y += Y_DIR;<br>}<br><br><span class="cpp-comment">/*** moves the computer paddle according to the ai routine ***/</span><br><span class="cpp-keyword">void</span> ai_move( <span class="cpp-keyword">short</span> &y, game_object &ball, <span class="cpp-keyword">short</span> h_direction )<br>{ <br> <span class="cpp-keyword">static</span> DIRECTION dir = d_UP; <span class="cpp-comment">// vertical direction</span><br> <span class="cpp-keyword">static</span> <span class="cpp-keyword">int</span> dcounter = <span class="cpp-number">0</span>; <span class="cpp-comment">// number of lines moved in one direction</span><br> <br> <span class="cpp-comment">// if the ball is close to the right paddle and is traveling that way…</span><br> <span class="cpp-keyword">if</span> ( ball.current.X > <span class="cpp-number">60</span> && h_direction == d_RIGHT ) {<br> dcounter = <span class="cpp-number">0</span>; <span class="cpp-comment">// reset counter</span><br> <br> <span class="cpp-keyword">if</span> ( y > ball.current.Y ) <span class="cpp-comment">// if the paddle is lower than the ball, move up</span><br> y–;<br> <br> <span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( y < ball.current.Y ) <span class="cpp-comment">// if higher, move down</span><br> y++;<br> } <span class="cpp-keyword">else</span> <span class="cpp-keyword">if</span> ( h_direction == d_RIGHT ) {<br> <span class="cpp-comment">// if the ball is not close, the paddle moves randomly</span><br><br> <br> <span class="cpp-keyword">if</span> ( y == pTOP ) dir = d_DOWN;<br> <span class="cpp-keyword">else</span><br> <span class="cpp-keyword">if</span> ( y == pBOTTOM - <span class="cpp-number">2</span> ) dir = d_UP;<br> <span class="cpp-keyword">else</span> <span class="cpp-comment">// if the dcounter is more than five, change to a random direction </span><br> <span class="cpp-keyword">if</span> ( dcounter == <span class="cpp-number">8</span> ) dir = rand() % <span class="cpp-number">2</span> == <span class="cpp-number">0</span> ? d_UP : d_DOWN;<br> <br> dcounter++;<br> y += dir;<br> <br> <span class="cpp-comment">// reset the counter for the number of lines moved</span><br> <span class="cpp-keyword">if</span> ( dcounter > <span class="cpp-number">8</span> ) dcounter = <span class="cpp-number">0</span>;<br> }<br>}<br><br><span class="cpp-comment">/*******************************************************************************<br>* Input Functions *<br>*******************************************************************************/</span><br><br><span class="cpp-comment">/*** get direction input from player, and change y coordinate appropriately ***/</span><br><span class="cpp-keyword">void</span> get_input( <span class="cpp-keyword">short</span> &y )<br>{ <br> <span class="cpp-keyword">if</span> ( GetAsyncKeyState( <span class="cpp-number">38</span> ) && y != pTOP ) y–; <span class="cpp-comment">// "up" key, ignore if paddle is at top</span><br> <span class="cpp-keyword">if</span> ( GetAsyncKeyState( <span class="cpp-number">40</span> ) && y != pBOTTOM - <span class="cpp-number">2</span> ) y++; <span class="cpp-comment">// "down" key, ignore if paddle is</span><br> <span class="cpp-comment">// at bottom (- 2 to account for</span><br> <span class="cpp-comment">// paddle length)</span><br>}<br><br><span class="cpp-comment">/*******************************************************************************<br>* Winning Condition Functions *<br>*******************************************************************************/</span><br><br><span class="cpp-comment">/*** check if the ball has gone "out" ***/</span><br><span class="cpp-keyword">bool</span> check_ball( game_object &ball )<br>{<br> <span class="cpp-keyword">if</span> ( ball.current.X == LOSE_LINE_RIGHT ) { <span class="cpp-comment">// if player 2 misses the ball…</span><br> p1score++; <span class="cpp-comment">// …player one scores</span><br> <span class="cpp-keyword">if</span> ( speed - <span class="cpp-number">1</span> < <span class="cpp-number">100</span> ) speed += <span class="cpp-number">2</span>; <span class="cpp-comment">// if the game speed is over 0, decrease by 2</span><br> randomize = <span class="cpp-keyword">true</span>; <span class="cpp-comment">// choose a random direction for the ball ( left or right)</span><br> <span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>; <span class="cpp-comment">// the ball was missed</span><br> }<br> <br> <span class="cpp-keyword">if</span> ( ball.current.X == LOSE_LINE_LEFT ) { <span class="cpp-comment">// if player 1 misses the ball…</span><br> p2score++; <span class="cpp-comment">// …player two scores</span><br> <span class="cpp-keyword">if</span> ( speed - <span class="cpp-number">1</span> < <span class="cpp-number">100</span> ) speed += <span class="cpp-number">2</span>; <span class="cpp-comment">// if the game speed is over 0, decrease by 2</span><br> randomize = <span class="cpp-keyword">true</span>; <span class="cpp-comment">// choose a random direction for the ball ( left or right)</span><br> <span class="cpp-keyword">return</span> <span class="cpp-keyword">true</span>; <span class="cpp-comment">// the ball was missed</span><br> }<br> <br> <span class="cpp-keyword">return</span> <span class="cpp-keyword">false</span>; <span class="cpp-comment">// the ball was not missed</span><br>}<br><br><span class="cpp-comment">/*******************************************************************************<br>* Utility Functions *<br>*******************************************************************************/</span><br><br><span class="cpp-comment">// move the cursor to the given coordinates</span><br><span class="cpp-keyword">void</span> gotoxy( <span class="cpp-keyword">int</span> x, <span class="cpp-keyword">int</span> y )<br>{<br> COORD pos;<br> HANDLE screen = GetStdHandle( STD_OUTPUT_HANDLE );<br><br> pos.X = x;<br> pos.Y = y;<br><br> SetConsoleCursorPosition( screen, pos );<br>}<br><br><span class="cpp-comment">// delay for a given number of milliseconds - busy waiting</span><br><span class="cpp-keyword">inline</span> <span class="cpp-keyword">void</span> delay( <span class="cpp-keyword">int</span> m )<br>{<br> <span class="cpp-keyword">for</span> ( time_t end = clock() + m; clock() < end; );<br>}<br><br><br><br></pre></div><!–ENDSCRIPT–><br><br>@ superpig feel the impotent force of my ratings++ on you
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement