Skip to content

Instantly share code, notes, and snippets.

@arsaccol
Last active July 29, 2020 01:48
Show Gist options
  • Save arsaccol/5e8f71ab8713930a460c1112fa988865 to your computer and use it in GitHub Desktop.
Save arsaccol/5e8f71ab8713930a460c1112fa988865 to your computer and use it in GitHub Desktop.
Crappy Pong clone for Windows command line I did back in ~2012. Compiled and tested originally with MinGW.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include <conio.h>
#include <string.h>
#define PDLMAX 5
#define PDLCTR 9
#define XSIZ 80
#define YSIZ 24
#define XSPD 0
#define YSPD 1
#define FREE 0
#define BUSY 1
#define HORIZONTAL 1
#define VERTICAL 0
#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define DRAWTIME 0.04167
typedef struct {
int X;
int Y;
int velocity[2];
} BALL;
typedef struct {
int X[PDLMAX];
int Y[PDLMAX];
int length;
} PADDLE;
typedef struct {
int player1;
int player2;
} SCORE;
///////////////////////////////////////////
void gotoxy(int x, int y);
void wait(float seconds);
void initTable(int table[XSIZ][YSIZ]);
void drawTable(int table[XSIZ][YSIZ]);
int ballCollision(BALL* ball, int table[XSIZ][YSIZ]);
int wallHit(BALL* ball, int table[XSIZ][YSIZ]);
void ballBounce(BALL* ball, int table[XSIZ][YSIZ]);
void moveBall(BALL* ball);
void drawBall(BALL* ball);
void ballUpdate(BALL* ball, int table[XSIZ][YSIZ]);
PADDLE startPaddle(int X);
void paddleShrink(PADDLE* paddle, int table[XSIZ][YSIZ]);
int paddleCollision(PADDLE* paddle, int direction, int table[XSIZ][YSIZ]);
void paddleOccupyTable(PADDLE* paddle, int table[XSIZ][YSIZ]);
void paddleFreeTable(PADDLE* paddle, int table[XSIZ][YSIZ]);
void movePaddle(PADDLE* paddle, int direction, int table[XSIZ][YSIZ]);
int paddleInput();
void paddleUpdate(PADDLE* paddle, int player, int direction, int table[XSIZ][YSIZ]);
void paddleDraw(PADDLE* paddle);
void PaddleErase(PADDLE* paddle);
void startScore(SCORE* score);
void raiseScore(SCORE* score, int player);
void displayScore(SCORE* score);
void Konami();
char menuMain();
int gameAI(BALL* ball, PADDLE* paddle);
void gameTestVictory(SCORE* score, PADDLE* paddle1, PADDLE* paddle2);
void gameCheckRound(BALL* ball, PADDLE* paddle1, PADDLE* paddle2, int table[XSIZ][YSIZ], SCORE* score, float* difficulty);
void gameMain();
void gameLoop(float* difficulty, SCORE* score, BALL* ball, PADDLE* paddle1, PADDLE* paddle2, int table[XSIZ][YSIZ]);
///////////////////////////////////////////
///
int main()
{
static int k = 1;
while(1)
{
switch(menuMain())
{
case 'n':
gameMain();
case 'q':
system("cls");
gotoxy(0, YSIZ);
exit(0);
case 'k':
Konami();
}
}
gotoxy(0, YSIZ-1);
return 0;
}
///
//////////////////////////////////////////
void gotoxy(int x, int y)
{
COORD coord = {0, 0};
coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void wait(float seconds)
{
clock_t end = clock() + seconds * CLOCKS_PER_SEC;
while(clock() < end)
;
}
void initTable(int table[XSIZ][YSIZ])
{
int i, j;
for(i = 0; i < XSIZ; i++)
{
for(j = 0; j < YSIZ; j++)
{
if(i == 0 || j == 0 || i == XSIZ-1 || j == YSIZ-1)
table[i][j] = BUSY;
else
table[i][j] = FREE;
}
}
}
void drawTable(int table[XSIZ][YSIZ])
{
int i, j;
for(i = 0; i < XSIZ; i++)
{
for(j = 0; j < YSIZ; j++)
{
gotoxy(i, j);
switch(table[i][j])
{
case FREE:
printf(" ");
break;
case BUSY:
printf("%c", 219);
break;
}
}
}
}
int ballCollision(BALL* ball, int table[XSIZ][YSIZ])
{
return table[ ball->X + ball->velocity[XSPD] ]
[ ball->Y + ball->velocity[YSPD] ];
}
int wallHit(BALL* ball, int table[XSIZ][YSIZ])
{
if( (ball->X + ball->velocity[XSPD]) <= 0 ||
(ball->X + ball->velocity[XSPD] >= XSIZ-1) )
return VERTICAL;
else if( (ball->Y + ball->velocity[YSPD]) <= 0 ||
(ball->Y + ball->velocity[YSPD]) >= YSIZ-1 )
return HORIZONTAL;
}
void ballBounce(BALL* ball, int table[XSIZ][YSIZ])
{
if( table[ ball->X + ball->velocity[XSPD] ]
[ ball->Y + ball->velocity[YSPD] ] == BUSY )
{
if( wallHit(ball, table) == VERTICAL ) //If ball hits left or right wall
{
ball->velocity[XSPD] *= -1; //Horizontal component of speed is inverted
return;
}
if( wallHit(ball, table) == HORIZONTAL ) //If ball hits top or bottom wall
{
ball->velocity[YSPD] *= -1;//Vertical component of speed is inverted
return;
}
else
ball->velocity[XSPD] *= -1;
}
}
void moveBall(BALL* ball)
{
ball->X += ball->velocity[XSPD];
ball->Y += ball->velocity[YSPD];
}
void drawBall(BALL* ball)
{
gotoxy( (ball->X - ball->velocity[XSPD]),
(ball->Y - ball->velocity[YSPD]) );
printf(" ");
gotoxy(ball->X, ball->Y);
printf("o");
}
void ballUpdate(BALL* ball, int table[XSIZ][YSIZ])
{
static char sound;
if(kbhit())
sound = getch();
switch( ballCollision(ball, table) )
{
case FREE: //ball collided with a FREE table space
moveBall(ball);
break;
case BUSY: //ball collided with a BUSY table space
ballBounce(ball, table);
moveBall(ball);
break;
}
drawBall(ball);
}
PADDLE startPaddle(int X)
{
PADDLE paddle;
paddle.length = PDLMAX;
int i;
int initialY = PDLCTR;
for (i = 0; i < paddle.length; i++)
{
paddle.X[i] = X;
}
for(i = 0; i < paddle.length; i++)
{
paddle.Y[i] = initialY;
initialY++;
}
return paddle;
}
void paddleDraw(PADDLE* paddle)
{
int i;
for(i = 0; i < paddle->length; i++)
{
gotoxy(paddle->X[i], paddle->Y[i]);
printf("%c", 219);
}
}
void paddleErase(PADDLE* paddle)
{
int i;
for(i = 0; i < paddle->length; i++)
{
gotoxy(paddle->X[i], paddle->Y[i]);
printf(" ");
}
}
void paddleShrink(PADDLE* paddle, int table[XSIZ][YSIZ])
{
paddleErase(paddle);
paddleFreeTable(paddle, table);
paddle->length--;
paddleOccupyTable(paddle, table);
}
int paddleCollision(PADDLE* paddle, int direction, int table[XSIZ][YSIZ])
{
switch(direction)
{
case UP:
if( table[ paddle->X[0] ]
[ paddle->Y[0] - 1] == BUSY )
return BUSY;
else
return FREE;
case DOWN:
if( table[ paddle->X[paddle->length-1] ]
[ paddle->Y[paddle->length-1] + 1] == BUSY )
return BUSY;
else
return FREE;
}
} //returns 1 if collision, 0 otherwise
void paddleOccupyTable(PADDLE* paddle, int table[XSIZ][YSIZ])
{
int i;
for(i = 0; i < paddle->length; i++)
{
table[ paddle->X[i] ][ paddle->Y[i] ] = BUSY;
}
}
void paddleFreeTable(PADDLE* paddle, int table[XSIZ][YSIZ])
{
int i;
for(i = 0; i < paddle->length; i++)
{
table[ paddle->X[i] ][ paddle->Y[i] ] = FREE;
}
}
void movePaddle(PADDLE* paddle, int direction, int table[XSIZ][YSIZ])
{
int i;
switch(direction)
{
case UP:
for(i = 0; i < paddle->length; i++)
{
paddle->Y[i]--;
}
break;
case DOWN:
for(i = 0; i < paddle->length; i++)
{
paddle->Y[i]++;
}
break;
}
}
int paddleInput()
{
if(kbhit())
return getch();
else return 0;
}
void paddleUpdate(PADDLE* paddle, int player, int direction, int table[XSIZ][YSIZ])
{
paddleErase(paddle);
paddleOccupyTable(paddle, table);
switch(player)
{
case 1:
switch(direction)
{
case UP:
if(!paddleCollision(paddle, UP, table))
{
paddleFreeTable(paddle, table);
movePaddle(paddle, UP, table);
paddleOccupyTable(paddle, table);
if(!paddleCollision(paddle, UP, table)) //Repeat movement for better gameplay
{
paddleFreeTable(paddle, table);
movePaddle(paddle, UP, table);
paddleOccupyTable(paddle, table);
}
}
break;
case DOWN:
if(!paddleCollision(paddle, DOWN, table))
{
paddleFreeTable(paddle, table);
movePaddle(paddle, DOWN, table);
paddleOccupyTable(paddle, table);
if(!paddleCollision(paddle, DOWN, table)) //Repeat movement for better gameplay
{
paddleFreeTable(paddle, table);
movePaddle(paddle, DOWN, table);
paddleOccupyTable(paddle, table);
}
}
break;
}
/*case 2:
switch(direction)
{
case 'w':
if(!paddleCollision(paddle, UP, table))
{
paddleFreeTable(paddle, table);
movePaddle(paddle, UP, table);
paddleOccupyTable(paddle, table);
if(!paddleCollision(paddle, UP, table)) //Repeat movement for better gameplay
{
paddleFreeTable(paddle, table);
movePaddle(paddle, UP, table);
paddleOccupyTable(paddle, table);
}
}
break;
case 's':
if(!paddleCollision(paddle, DOWN, table))
{
paddleFreeTable(paddle, table);
movePaddle(paddle, DOWN, table);
paddleOccupyTable(paddle, table);
if(!paddleCollision(paddle, DOWN, table)) //Repeat movement for better gameplay
{
paddleFreeTable(paddle, table);
movePaddle(paddle, DOWN, table);
paddleOccupyTable(paddle, table);
}
}
break;
}*/
}
paddleDraw(paddle);
fflush(stdin);
}
void startScore(SCORE* score)
{
score->player1 = 0;
score->player2 = 0;
}
void raiseScore(SCORE* score, int player)
{
switch(player)
{
case 1:
score->player2++;
break;
case 2:
score->player1++;
}
}
void displayScore(SCORE* score)
{
gotoxy(XSIZ/2 - 10, 1);
printf("%d", score->player1);
gotoxy(XSIZ/2 + 12, 1);
printf("%d", score->player2);
}
void Konami()
{
wait(0.05);
system("cls");
gotoxy(20, 4); printf(" /oooooooooo+` ");
gotoxy(20, 5); printf(" .ooooooooooo. ");
gotoxy(20, 6); printf(" +oooooooooo. ");
gotoxy(20, 7); printf(" `/ooooooooo+. ");
gotoxy(20, 8); printf(" .:+oooooo+/:. ");
gotoxy(20, 9); printf(" `.-://+oooo/:-.` .yyyyyyyyyyy: ");
gotoxy(20, 10); printf(" ./ooooooooo:` ohhhhhhhhhho ");
gotoxy(20, 11); printf(" -oooooooooo- :hhhhhhhhhhs` ");
gotoxy(20, 12); printf(" -oooooooooo: -yhhhhhhhhho` ");
gotoxy(20, 13); printf(" .oooooooooo+ -ohhhhhhhhs+- ");
gotoxy(20, 14); printf(" :::::::::::` `-//+oshhhhs+:-.` ");
gotoxy(20, 15); printf(" :shhhhhhhhy/` ");
gotoxy(20, 16); printf(" `shhhhhhhhhy. ");
gotoxy(20, 17); printf(" `shhhhhhhhhy. ");
gotoxy(20, 18); printf(" shhhhhhhhhh/ ");
gotoxy(20, 19); printf(" :oooooooooo+ ");
wait(0.030);
system("cls");
wait(0.2);
gotoxy(40, 12);
printf("!!!");
gotoxy(0, 23);
wait(0.7);
system("cls");
gotoxy(40,12);
gotoxy(37, 12);
printf("."); wait(0.3);
printf("."); wait(0.3);
printf("."); wait(0.3);
//system("cls");
gotoxy(40, 12);
printf("Huh?!");
gotoxy(0, YSIZ);
wait(2);
//getch();
fflush(stdin);
}
char menuMain()
{
system("cls");
gotoxy(35, 10);
puts("(N)ew Game");
gotoxy(35, 11);
//puts("(L)oad Game");
//gotoxy(35, 12);
puts("(Q)uit");
gotoxy(38, 23);
//puts("(K)...?");
gotoxy(0, 24);
return getch();
}
int gameAI(BALL* ball, PADDLE* paddle)
{
if( ball->X > paddle->X[0] - 17)
{
if(paddle->Y[0] > ball->Y)
return UP;
if(paddle->Y[(paddle->length) - 1] < ball->Y)
return DOWN;
}
}
void gameTestVictory(SCORE* score, PADDLE* paddle1, PADDLE* paddle2)
{
if(score->player1 == 5)
{
paddleDraw(paddle2);
gotoxy(32, 12);
puts("IMPRESSIVE, SNAKE!");
wait(0.7);
gotoxy(32, 12);
puts("I mean, Player 1...");
gotoxy(0, YSIZ);
wait(1.5);
main();
}
else if(score->player2 == 5)
{
paddleDraw(paddle1);
wait(0.5);
gotoxy(30, 10);
puts("Player 1, what happened?");
wait(0.7);
gotoxy(38, 11);
puts("Player 1?!");
wait(0.7);
gotoxy(33, 12);
puts("PLAYER OOOOONE!!!!!!");
gotoxy(0, YSIZ-1);
wait(0.7);
getch();
main();
}
}
void gameCheckRound(BALL* ball, PADDLE* paddle1, PADDLE* paddle2, int table[XSIZ][YSIZ], SCORE* score, float* difficulty)
{
if(wallHit(ball, table) == VERTICAL)
{
printf("\a");
switch(ball->X)
{
case 1:
raiseScore(score, 1);
//paddleShrink(paddle1, table);
//paddleShrinkq(paddle2, table);
//*difficulty -= 0.1;
break;
case (XSIZ - 2):
raiseScore(score, 2);
/*if(score->player1 % 2)
{
paddleShrink(paddle1, table);
paddleShrink(paddle2, table);
}*/
*difficulty -= 0.1;
break;
}
}
}
void gameMain()
{
float difficulty = 1.0;
int table[XSIZ][YSIZ];
BALL ball;
PADDLE paddle1 = startPaddle(2);
PADDLE paddle2 = startPaddle(XSIZ-3);
SCORE score;
startScore(&score);
ball.X = XSIZ/2; ball.Y = YSIZ/2;
ball.velocity[XSPD] = -1;
ball.velocity[YSPD] = 1;
initTable(table);
drawTable(table);
while(1)
gameLoop(&difficulty, &score, &ball, &paddle1, &paddle2, table);
}
void gameLoop(float* difficulty, SCORE* score, BALL* ball, PADDLE* paddle1, PADDLE* paddle2, int table[XSIZ][YSIZ]) ///Will add PADDLE* later.
{
paddleUpdate(paddle2, 1, gameAI(ball, paddle2), table);
paddleUpdate(paddle1, 1, paddleInput(), table);
paddleUpdate(paddle1, 1, paddleInput(), table);
fflush(stdin);
ballUpdate(ball, table);
wait(*difficulty * DRAWTIME);
if(kbhit())
if(getch() == 'q')
main();
gameTestVictory(score, paddle1, paddle2);
gameCheckRound(ball, paddle1, paddle2, table, score, difficulty);
displayScore(score);
fflush(stdin);
gotoxy(0, YSIZ);
printf("Paddle 1: %2d,%2d \t Ball: %2d,%2d Vball = %2d,%2d \t\tPaddle 2: %2d,%2d", paddle1->X[0], paddle1->Y[0], ball->X, ball->Y, ball->velocity[XSPD], ball->velocity[YSPD], paddle2->X[0], paddle2->Y[0]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment