]> code.delx.au - pong/blob - pong.c
Pong is cool
[pong] / pong.c
1 #if defined(WIN32)
2 #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
3 #include "glut.h"
4 #elif defined(__APPLE__) || defined(MACOSX)
5 #include <GLUT/glut.h>
6 #else
7 #include <GL/glut.h>
8 #endif
9
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 enum {
14 FRAME=40,
15 HEIGHT=100,
16 PADDLESIZE=10
17 };
18
19 static int score1;
20 static int score2;
21 static GLdouble paddle1;
22 static GLdouble paddle2;
23 static GLdouble ballX;
24 static GLdouble ballY;
25 static GLdouble ballVecX;
26 static GLdouble ballVecY;
27
28
29 static void initball(void) {
30 ballX = 0.0;
31 ballY = 0.0;
32 if(ballVecX < 0)
33 ballVecX = -1.0;
34 else
35 ballVecX = 1.0;
36 ballVecY = 1.0;
37 }
38
39 static void run(void) {
40 // Check for collisions with paddles
41 if(ballVecX < 0 && ballX <= -HEIGHT + -ballVecX * 1.5) {
42 if(ballY >= paddle1 - PADDLESIZE && ballY <= paddle1 + PADDLESIZE) {
43 ballVecX *= -1.15;
44 ballVecY *= 1.15;
45 }
46 }
47 if(ballVecX > 0 && ballX >= HEIGHT - ballVecX * 1.5) {
48 if(ballY >= paddle2 - PADDLESIZE && ballY <= paddle2 + PADDLESIZE) {
49 ballVecX *= -1.15;
50 ballVecY *= 1.15;
51 }
52 }
53
54 // Check if it's past the top or bottom of the screen
55 if(ballY >= HEIGHT || ballY <= -HEIGHT) {
56 ballVecY *= -1;
57 }
58
59 // Check if it's past the sides of the screen
60 if(ballX >= HEIGHT) {
61 ++score1;
62 initball();
63 return;
64 }
65 if(ballX <= -HEIGHT) {
66 ++score2;
67 initball();
68 return;
69 }
70
71 // Move the ball
72 ballX += ballVecX;
73 ballY += ballVecY;
74 }
75
76 static void display(void) {
77 glClear(GL_COLOR_BUFFER_BIT);
78 glColor3d(0.0, 0.0, 0.0);
79
80 // Draw the paddles
81 glLineWidth(2.0);
82 glBegin(GL_LINES);
83 glVertex2d(-HEIGHT + 1, paddle1 - PADDLESIZE);
84 glVertex2d(-HEIGHT + 1, paddle1 + PADDLESIZE);
85 glVertex2d( HEIGHT - 1, paddle2 + PADDLESIZE);
86 glVertex2d( HEIGHT - 1, paddle2 - PADDLESIZE);
87 glEnd();
88
89 // Draw the ball
90 glPointSize(5.0);
91 glBegin(GL_POINTS);
92 glVertex2d(ballX, ballY);
93 glEnd();
94
95 // Write the score
96 glRasterPos2d(-5.0, HEIGHT - 10.0);
97 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, '0' + score1);
98 glRasterPos2d( 5.0, HEIGHT - 10.0);
99 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, '0' + score2);
100
101 glutSwapBuffers();
102 }
103
104 static void resize(int w, int h) {
105 glViewport(0, 0, w, h);
106 glLoadIdentity();
107 glOrtho(-HEIGHT, HEIGHT, -HEIGHT, HEIGHT, -1.0, 1.0);
108 }
109
110 static void keyboard(unsigned char key, int x, int y) {
111 (void)x;(void)y;
112
113 switch(key) {
114 case 'q':
115 case 'Q':
116 case '\033':
117 exit(0);
118
119 case 'w':
120 if(paddle1 + PADDLESIZE < HEIGHT)
121 paddle1 += PADDLESIZE;
122 break;
123 case 's':
124 if(paddle1 - PADDLESIZE > -HEIGHT)
125 paddle1 -= PADDLESIZE;
126 break;
127
128 case 'i':
129 if(paddle2 + PADDLESIZE < HEIGHT)
130 paddle2 += PADDLESIZE;
131 break;
132 case 'k':
133 if(paddle2 - PADDLESIZE > -HEIGHT)
134 paddle2 -= PADDLESIZE;
135 break;
136
137 default:
138 return;
139 }
140 glutPostRedisplay();
141 }
142
143 static void timer(int lastTime) {
144 int curTime = glutGet(GLUT_ELAPSED_TIME);
145 do {
146 lastTime += FRAME;
147 run();
148 } while(lastTime + FRAME < curTime);
149 glutPostRedisplay();
150 glutTimerFunc(FRAME - (curTime - lastTime), timer, curTime);
151 }
152
153 static void init(void) {
154 glClearColor(1.0, 1.0, 1.0, 0.0);
155 initball();
156 }
157
158 int main(int argc, char *argv[]) {
159 glutInitWindowPosition(100, 100);
160 glutInitWindowSize(640, 480);
161 glutInit(&argc, argv);
162 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
163 glutCreateWindow(argv[0]);
164 glutDisplayFunc(display);
165 glutReshapeFunc(resize);
166 glutKeyboardFunc(keyboard);
167 glutTimerFunc(FRAME, timer, glutGet(GLUT_ELAPSED_TIME));
168 init();
169 glutMainLoop();
170 return 0;
171 }
172