X-Git-Url: https://code.delx.au/pong/blobdiff_plain/892a3db8c3df3ef9fae4711a0d75d620956c36c3..6c1893c335f49f5a595e04b66c18dc88f8b5cff3:/pong.c diff --git a/pong.c b/pong.c index ad2abda..4ecaa8a 100644 --- a/pong.c +++ b/pong.c @@ -9,13 +9,23 @@ #include #include +#include -#define SPEEDINC 1.15 -#define PADDLESPEED 2.5 +// Amount to increase speed by on x, y axis, and when bouncing +#define SPEEDXINC 1.1 +#define SPEEDYINC 1.1 +#define SPEEDBINC 0.15 +#define PADDLESPEED 3.0 #define FRAME 40 #define PADDLESIZE 10 #define HEIGHT 100 +#define STATE_UI 0 +#define STATE_1P 1 +#define STATE_2P 2 + +static char* menu = ""; +static int state = 0; static int p1move = 0; static int p2move = 0; static int score1 = 0; @@ -28,7 +38,7 @@ static GLdouble ballVecX = 0.0; static GLdouble ballVecY = 0.0; -static void initball(void) { +static void initBall(void) { ballX = 0.0; ballY = 0.0; if(ballVecX < 0) @@ -39,21 +49,41 @@ static void initball(void) { } static void run(void) { + // AI is on + if(state == STATE_1P) { + if(ballY < paddle2 - PADDLESIZE) + p2move = -1; + else if(ballY > paddle2 + PADDLESIZE) + p2move = 1; + else + p2move = 0; + } + // Move the paddles paddle1 += p1move * PADDLESPEED; paddle2 += p2move * PADDLESPEED; + if(paddle1 < -HEIGHT) + paddle1 = -HEIGHT; + if(paddle1 > HEIGHT) + paddle1 = HEIGHT; + if(paddle2 < -HEIGHT) + paddle2 = -HEIGHT; + if(paddle2 > HEIGHT) + paddle2 = HEIGHT; // Check for collisions with paddles if(ballVecX < 0 && ballX <= -HEIGHT + -ballVecX * 1.5) { if(ballY >= paddle1 - PADDLESIZE && ballY <= paddle1 + PADDLESIZE) { - ballVecX *= -SPEEDINC; - ballVecY *= SPEEDINC; + GLdouble speedChange = fmax(1.0, fabs(paddle1 - ballY) * SPEEDBINC); + ballVecX *= -speedChange * SPEEDXINC; + ballVecY *= speedChange * SPEEDYINC; } } if(ballVecX > 0 && ballX >= HEIGHT - ballVecX * 1.5) { if(ballY >= paddle2 - PADDLESIZE && ballY <= paddle2 + PADDLESIZE) { - ballVecX *= -SPEEDINC; - ballVecY *= SPEEDINC; + GLdouble speedChange = fmax(1.0, fabs(paddle2 - ballY) * SPEEDBINC); + ballVecX *= -speedChange * SPEEDXINC; + ballVecY *= speedChange * SPEEDYINC; } } @@ -65,24 +95,66 @@ static void run(void) { // Check if it's past the sides of the screen if(ballX >= HEIGHT) { ++score1; - initball(); - return; + initBall(); } if(ballX <= -HEIGHT) { ++score2; - initball(); - return; + initBall(); } // Move the ball ballX += ballVecX; ballY += ballVecY; + + // Check scores for winners.. + if(score1 == 9) { + menu = "Player 1 wins!"; + state = STATE_UI; + score1 = score2 = 0; + } + if(score2 == 9) { + menu = "Player 2 wins!"; + state = STATE_UI; + score1 = score2 = 0; + } } -static void display(void) { - glClear(GL_COLOR_BUFFER_BIT); - glColor3d(0.0, 0.0, 0.0); +static void timer(int lastTime) { + if(state == STATE_UI) { + return; + } + + int curTime = glutGet(GLUT_ELAPSED_TIME); + do { + lastTime += FRAME; + run(); + } while(lastTime + FRAME < curTime); + glutPostRedisplay(); + glutTimerFunc(FRAME - (curTime - lastTime), timer, curTime); +} + +static void startGame(void) { + glutTimerFunc(FRAME, timer, glutGet(GLUT_ELAPSED_TIME)); + initBall(); +} + +static void drawText(double x, double y, char* str) { + glRasterPos2d(x, y); + while(*str) { + glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, *str); + ++str; + } +} + +static void menuDisplay(void) { + drawText(-20, 50, "Awesome PONG!"); + drawText(-50, -50, "Press 1 for a single player game."); + drawText(-50, -60, "Press 2 for a multi player game."); + drawText(-50, -70, "Keys: w/s and i/k"); + drawText(-20, 0, menu); +} +static void gameDisplay(void) { // Draw the paddles glLineWidth(2.0); glBegin(GL_LINES); @@ -93,9 +165,9 @@ static void display(void) { glEnd(); // Draw the ball - glPointSize(5.0); - glBegin(GL_POINTS); + glBegin(GL_LINES); glVertex2d(ballX, ballY); + glVertex2d(ballX - ballVecX, ballY - ballVecY); glEnd(); // Write the score @@ -103,6 +175,17 @@ static void display(void) { glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, '0' + score1); glRasterPos2d( 5.0, HEIGHT - 10.0); glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, '0' + score2); +} + +static void display(void) { + glClear(GL_COLOR_BUFFER_BIT); + glColor3d(0.0, 0.0, 0.0); + + if(state == STATE_UI) { + menuDisplay(); + } else { + gameDisplay(); + } glutSwapBuffers(); } @@ -113,15 +196,24 @@ static void resize(int w, int h) { glOrtho(-HEIGHT, HEIGHT, -HEIGHT, HEIGHT, -1.0, 1.0); } -static void keyboard(unsigned char key, int x, int y) { - (void)x;(void)y; - +static void menuKeyboard(unsigned char key) { switch(key) { - case 'q': - case 'Q': - case '\033': - exit(0); + case '1': + state = STATE_1P; + break; + + case '2': + state = STATE_2P; + break; + + default: + return; + } + startGame(); +} +static void gameKeyboard(unsigned char key) { + switch(key) { case 'w': p1move = 1; break; @@ -142,6 +234,24 @@ static void keyboard(unsigned char key, int x, int y) { glutPostRedisplay(); } +static void keyboard(unsigned char key, int x, int y) { + (void)x;(void)y; + + switch(key) { + case 'q': + case 'Q': + case '\033': + exit(0); + } + + + if(state == STATE_UI) { + menuKeyboard(key); + } else { + gameKeyboard(key); + } +} + static void keyboardUp(unsigned char key, int x, int y) { (void)x;(void)y; @@ -159,21 +269,6 @@ static void keyboardUp(unsigned char key, int x, int y) { } } -static void timer(int lastTime) { - int curTime = glutGet(GLUT_ELAPSED_TIME); - do { - lastTime += FRAME; - run(); - } while(lastTime + FRAME < curTime); - glutPostRedisplay(); - glutTimerFunc(FRAME - (curTime - lastTime), timer, curTime); -} - -static void init(void) { - glClearColor(1.0, 1.0, 1.0, 0.0); - initball(); -} - int main(int argc, char *argv[]) { glutInitWindowPosition(100, 100); glutInitWindowSize(640, 480); @@ -184,8 +279,7 @@ int main(int argc, char *argv[]) { glutReshapeFunc(resize); glutKeyboardFunc(keyboard); glutKeyboardUpFunc(keyboardUp); - glutTimerFunc(FRAME, timer, glutGet(GLUT_ELAPSED_TIME)); - init(); + glClearColor(1.0, 1.0, 1.0, 0.0); glutMainLoop(); return 0; }