// Pong by Konstantinos Egarhos (aka konsnos) edited by sergio
/*
Requiere
sudo apt-get install build-essential
sudo apt-get install freeglut3 freeglut3-dbg freeglut3-dev
##sudo apt-get install freeglut3-dev
gcc -o opengl opengl.c -lglut -lGLU -lGL
*/
#include <GL/freeglut.h> // OpenGL toolkit
#include <stdio.h>
// Function Initialising
void drawRect(GLfloat, GLfloat, int, int, float, float, float);
void update();
// Window dimensions
const int Width = 400;
const int Height = 300;
// Dimensions
#define paddleHeight 80
#define paddleWidth 10
#define zAxis 0
float p1 = 220;
float p2 = 220;
float p3 = 000;
float p4 = 150;
float p5 = 300;
float p6 = 450;
// GLfloat player1[4][2] = { 10, p1, 10, p1+paddleHeight, 10+paddleWidth, p1+paddleHeight, 10+paddleWidth, p1 };
// GLfloat player2[4][2] = { 480, p2, 480, p2+paddleHeight, 480+paddleWidth, p2+paddleHeight, 480+paddleWidth, p2 };
const float pspeed = 20;
int score[2];// = {0, 0}; // Score for players 1 and 2
#define bsize 10
GLdouble bpos[2] = {235,235};
GLfloat bvx = 1; // ball vector in left-right axis
GLfloat bvy = 1; // ball vector in top-bottom axis
// GLfloat ball[4][2] = { pos[0], pos[1], pos[0], pos[1]+bsize, pos[0]+bsize, pos[1]+bsize, pos[0]+bsize, pos[1] };
float bspeed = 2;
// Time variables for the speed calculation of the objects
GLdouble time;
GLdouble prtime;
GLdouble timeDiff;
GLdouble runtime;
// Text variable
static char str[200];
void * font = GLUT_BITMAP_9_BY_15;
void inicio()
{
char linea[5];
printf("Pong!!!.\n\n");
printf("/*************************/\n\n");
//printf("Utiliza la tecla p para hacer una pausa.\n\n");//
printf("mueve el jugador 1con w s.\n\n");
printf("mueve el jugador 2 con las flechas.\n\n");
printf("/*************************/\n\n");
printf("Teclea la velocitat de la bola i pulsa intro.\n");
printf("--------------------------------------------------\n");
printf("a - Rapido.\n");
printf("b - Normal.\n");
printf("c - Lento.\n\n");
fflush(stdin);
printf("Opcion:");
fgets(linea,2,stdin);
if(!strcmp(linea,"a")) bspeed=3;
if(!strcmp(linea,"b")) bspeed=2;
if(!strcmp(linea,"c")) bspeed=1;
fflush(stdin);
system("cls");
} /* fin inicio */
/*********************************************
Drawing
*********************************************/
void renderScene(void)
{
// Elapsed time from the initiation of the game.
time = glutGet(GLUT_ELAPSED_TIME);
timeDiff = time - prtime; // Elapsed time from the previous frame.
prtime = time;
runtime = timeDiff / 10.0;
update(); // Update the game.
// Clear the screen.
glClear(GL_COLOR_BUFFER_BIT);
sprintf(str, "%d %d", score[0], score[1] );
glRasterPos2f(205, 450);
glutBitmapString(font,(unsigned char*)str);
// Draws the 1st paddle and the 2nd.
drawRect(10.0, p1, paddleHeight, paddleWidth, 0, 0, 1); // Left blue paddle.
drawRect(480.0, p2, paddleHeight, paddleWidth, 1, 0, 0); // Right red paddle.
drawRect(250.0, p3, paddleHeight, paddleWidth, 1, 0, 0); // center line1.
drawRect(250.0, p4, paddleHeight, paddleWidth, 1, 0, 0); // center line2.
drawRect(250.0, p5, paddleHeight, paddleWidth, 1, 0, 0); // center line3.
drawRect(250.0, p6, paddleHeight, paddleWidth, 1, 0, 0); // center line4.
drawRect(bpos[0], bpos[1], bsize, bsize, 1, 1, 0); // Yellow ball.
glutSwapBuffers(); // Draw the new frame of the game.
}
/*********************************************
Update
*********************************************/
void update()
{
// Ball collision with the border of the window.
if(bpos[0] + bspeed > 500-bsize)
{
bvx = -1;
score[0]++;
}
else if (bpos[0] - bspeed < 0)
{
bvx = 1;
score[1]++;
}
if(bpos[1] + bspeed > 500-bsize)
bvy = -1;
else if (bpos[1] - bspeed < 0)
bvy = 1;
/******** Collision with the paddles ********/
// Collision with left paddle.
if(bpos[0] <= 10 + paddleWidth && bpos[1] >= p1 && bpos[1] + bsize <= p1 + paddleHeight)
{
bvx *= -1;
// bspeed *= 1.01;
}
// Collision with right paddle.
if(bpos[0] + bsize >= 480 && bpos[1] >= p2 && bpos[1] + bsize <= p2 + paddleHeight)
{
bvx *= -1;
// bspeed *= 1.01;
}
// New position of the ball dependent to the speed ***************
// Because frame rate isn't always the same that might affect objects speed.
// That's why we multiply the frame speed and multiply it with the object speed.
// In that way the object speed is always the same.
bpos[0] += bspeed * bvx * runtime;
bpos[1] += bspeed * bvy * runtime;
}
/*********************************************
Create and draw a rectangle.
Generally, we are only interested in the height(y) of the paddle.
*********************************************/
void drawRect(GLfloat x, GLfloat y, int height, int width, float R, float G, float B)
{
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glVertex2f( x, y); // Top Left
glVertex2f( x, y + height); // Bottom Left
glVertex2f( x + width, y + height); // Bottom Right
glVertex2f( x + width, y); // Top Right
glEnd();
}
/*********************************************
User Input (keyboard)
I don't calculate frame speed, since it doesn't affect much.
*********************************************/
void keyPress(unsigned char key, int x, int y)
{
switch (key)
{
case 'w':
case 'W':
if(420>=p1+pspeed)
{p1 += pspeed;}
break;
case 's':
case 'S':
if(0<=p1-pspeed)
{p1 -= pspeed;}
break;
case 27 :
exit(0);
}
}
/*********************************************
Special Keys Input (keyboard arrows)
I don't calculate frame speed, since it doesn't affect much.
*********************************************/
void specialKeyPress(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
if(420>=p2+pspeed)
{p2 += pspeed;}
break;
case GLUT_KEY_DOWN:
if(0<=p2-pspeed)
{p2 -= pspeed;}
break;
}
}
/*********************************************
Let there be initial variables.
*********************************************/
void init(void)
{
// The color the windows will redraw. Its done to erase the previous frame.
glClearColor(0.4f, 0.4f, 0.4f, 0.4f); // Black, no opacity(alpha).
// Orthographic projection matrix (initiating 2D window).
gluOrtho2D(0,500,0,500);
// Initialize time.
prtime = time = glutGet(GLUT_ELAPSED_TIME);
// Initialize score.
score[0] = score[1] = 0;
}
/* Main function */
int main(int argc, char *argv[])
{
inicio();
// Initialize openGL with Double buffer and RGB color without transparency.
// Its interesting to try GLUT_SINGLE instead of GLUT_DOUBLE.
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
// Create the window.
glutInitWindowSize(Width, Height);
glutInitWindowPosition(150,50);
glutCreateWindow("Pong");
// Define the draw function.
glutDisplayFunc(renderScene);
// Define the keyboard input function.
glutKeyboardFunc(keyPress);
// Define the keyboards' special keys input function.
glutSpecialFunc(specialKeyPress);
// Define which function to execute when nothing except the gameplay is updating.
glutIdleFunc(renderScene);
init();
glutMainLoop();
return 0;
}