// Program to demonstrate how to open a window size and position it properly

#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
int wide=300, high=300;   // Global Variables for Length and Width
int winX=40, winY=40;	  // X and Y positions for window
double moveLength = 3.5;
double rightSize = 20.0;
double leftSize = -20.0;
double topSize = 20.0;
double bottomSize = -20.0;
double paddleLength = 5.0;
double paddleWidth = 1.0;

double xpos;
double ypos;
double vx;
double vy;
double rightY;
double leftY;
double rightX = 18.0;
double leftX = -18.0;

int leftScore=0;
int rightScore=0;

void DrawText(GLint x, GLint y, char* s, GLfloat r, GLfloat g, GLfloat b)
{
    int lines;
    char* p;

    glMatrixMode(GL_PROJECTION);
     glPushMatrix();
     glLoadIdentity();
     glOrtho(0.0, glutGet(GLUT_WINDOW_WIDTH), 
	    0.0, glutGet(GLUT_WINDOW_HEIGHT), -1.0, 1.0);
     glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glLoadIdentity();
      glColor3f(r,g,b);
      glRasterPos2i(x, y);
      for(p = s, lines = 0; *p; p++) {
	  if (*p == '\n') {
	      lines++;
	      glRasterPos2i(x, y-(lines*18));
	  }
	  glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *p);
      }
      glPopMatrix();
     glMatrixMode(GL_PROJECTION);
     glPopMatrix();
     glMatrixMode(GL_MODELVIEW);
}

void DrawGraph()  // The Drawing Routine
{ 
//    double x,y;
    char buffer[2];
    glColor3f(1.0, 1.0, 1.0);		// Set drawing color to yellow
    glPointSize(5.0);
    glBegin( GL_POINTS );		// Start drawing POINTS
    glVertex3f(xpos, ypos, 0.0);      // Plot point at (x,y) z=0 in 2D
    glEnd();				// End drawing points
    glColor3f(1.0, 1.0, 1.0);		// Set drawing color to yellow
    glBegin(GL_POLYGON);
       glVertex3f(rightX-paddleWidth/2.0,rightY-paddleLength/2.0, 0.0);
       glVertex3f(rightX+paddleWidth/2.0,rightY-paddleLength/2.0, 0.0);
       glVertex3f(rightX+paddleWidth/2.0,rightY+paddleLength/2.0, 0.0);
       glVertex3f(rightX-paddleWidth/2.0,rightY+paddleLength/2.0, 0.0);
    glEnd();
    glBegin(GL_POLYGON);
       glVertex3f(leftX-paddleWidth/2.0,leftY-paddleLength/2.0, 0.0);
       glVertex3f(leftX+paddleWidth/2.0,leftY-paddleLength/2.0, 0.0);
       glVertex3f(leftX+paddleWidth/2.0,leftY+paddleLength/2.0, 0.0);
       glVertex3f(leftX-paddleWidth/2.0,leftY+paddleLength/2.0, 0.0);
    glEnd();
    sprintf(buffer,"%i",leftScore);
    DrawText(wide/3,(int)(high-30),buffer,1.0,1.0,1.0);
    sprintf(buffer,"%i",rightScore);
    DrawText((2*wide)/3,(int)(high-30),buffer,1.0,1.0,1.0);
} 

void SpawnBall(int dir)
{
   if (leftScore >= 10 || rightScore >= 10)
      exit(0);
   xpos = (rightSize+leftSize)/2.0;
   ypos = (topSize+bottomSize)/2.0;
   vx = dir*(.02);
   vy = (rand()/(2147483647.0))*(.02);
}

void MoveBall()
{

   xpos = xpos + vx;
   ypos = ypos + vy;

   if (ypos > topSize)
   {
      ypos = 2*topSize - ypos;
      vy = -1 * vy;
   }
   if (ypos < bottomSize)
   {
      ypos = 2*bottomSize - ypos;
      vy = -1 * vy;
   }
   if (xpos > rightSize)
   {
      xpos = 2*rightSize - xpos;
      vx = -1 * vx;
   }
   if (xpos < leftSize)
   {
      xpos = 2*leftSize - xpos;
      vx = -1 * vx;
   }

   //Test for collision
   
   if (xpos > rightX-paddleWidth/2.0 && ypos < rightY + paddleLength/2.0 && ypos > rightY - paddleLength/2.0)
   {
      vx = -1 *vx;
   }
   if (xpos < leftX+paddleWidth/2.0 && ypos < leftY + paddleLength/2.0 && ypos > leftY - paddleLength/2.0)
   {
      vx = -1 *vx;
   }
   //Test for passed balls
		   
   if (xpos < leftX-paddleWidth/2.0)
   {
      rightScore += 1;
      SpawnBall(1);
   }
   if (xpos > rightX+paddleWidth/2.0)
   {
      leftScore += 1;
      SpawnBall(-1);
   }
}

void display(void)
{ /* clear all pixels */

   glClear(GL_COLOR_BUFFER_BIT);
   DrawGraph();
   MoveBall();
   glFlush();  // Force writing all pending OpenGL actions to the screen.
   glutSwapBuffers();
   glutPostRedisplay();
}

void myinit(void)
{ /* select clearing (background) color   */
   glClearColor(0.0, 0.0, 0.0, 0.0);     // These RGB values make gray
   
/* initialize viewing values */
   glMatrixMode(GL_PROJECTION);			// Select Matrix Mode
   glLoadIdentity();				// Provide Base Matrix 
   glOrtho(leftSize, rightSize, bottomSize, topSize, -1.0, 1.0);   	// Set window dimensions
   // Parameters:  glOrtho(Left, Right, Bottom, Top, Front, Back)
   SpawnBall(1);
   rightY = 0.0;
   leftY = 0.0;
   
}

void keyboard(unsigned char key, int x, int y)
{
    if (key == (unsigned char) 27)   //Press 'Esc' key, with mouse on window, 
      exit(0);	                     // to exit
    if (key == 'w') {
        leftY = leftY + moveLength;
	if (leftY + paddleLength/2.0 > topSize)
	{
		leftY = topSize - paddleLength/2.0;
	}
    }
    else if (key == 's') {
        leftY = leftY - moveLength;
  	if (leftY - paddleLength/2.0 < bottomSize)
	{
		leftY = bottomSize + paddleLength/2.0;
	}
   }

}


void specialKey(int key, int x, int y)
{
    if (key == GLUT_KEY_UP) {
        rightY = rightY + moveLength;
	if (rightY + paddleLength/2.0 > topSize)
	{
		rightY = topSize - paddleLength/2.0;
	}
    }
    else if (key == GLUT_KEY_DOWN) {
        rightY = rightY - moveLength;
  	if (rightY - paddleLength/2.0 < bottomSize)
	{
		rightY = bottomSize + paddleLength/2.0;
	}
   }
}    



/* Declare initial window size, position, and display mode */

int main(int argc, char* argv[])
{  
   //printf("Creating window %d pixels wide and %d pixels high", wide, high);
   //printf(" at (%d,%d).\n", winX, winY);
   glutInit(&argc, argv);   // Call glut's initialization routine
   glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);	// Set Single Buffer, RGB Color
   glutInitWindowSize(wide, high);  	// Initialize window size
   glutInitWindowPosition(winX,winY); 	// Position window
   glutCreateWindow("DSchafer PONG!");	// Actually create window with title
   glutKeyboardFunc(keyboard);
   glutSpecialFunc(specialKey);
   myinit();				// Call my initialization routine

   glutDisplayFunc(display);		// Call my display routine 
   glutMainLoop();			// Fall into glut's main event loop 
   return 0;
}








