]> code.delx.au - pong/blob - pong.c
Don't let paddles go out of range
[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 #define SPEEDINC 1.15
14 #define PADDLESPEED 2.5
15 #define FRAME 40
16 #define PADDLESIZE 10
17 #define HEIGHT 100
18
19 static int AI = 0;
20 static int p1move = 0;
21 static int p2move = 0;
22 static int score1 = 0;
23 static int score2 = 0;
24 static GLdouble paddle1 = 0.0;
25 static GLdouble paddle2 = 0.0;
26 static GLdouble ballX = 0.0;
27 static GLdouble ballY = 0.0;
28 static GLdouble ballVecX = 0.0;
29 static GLdouble ballVecY = 0.0;
30
31
32 static void initball(void) {
33 ballX = 0.0;
34 ballY = 0.0;
35 if(ballVecX < 0)
36 ballVecX = -1.2;
37 else
38 ballVecX = 1.2;
39 ballVecY = 0.7;
40 }
41
42 static void run(void) {
43 // AI
44 if(AI) {
45 if(ballY < paddle2 - PADDLESIZE)
46 p2move = -1;
47 else if(ballY > paddle2 + PADDLESIZE)
48 p2move = 1;
49 else
50 p2move = 0;
51 }
52
53 // Move the paddles
54 paddle1 += p1move * PADDLESPEED;
55 paddle2 += p2move * PADDLESPEED;
56 if(paddle1 < -HEIGHT)
57 paddle1 = -HEIGHT;
58 if(paddle1 > HEIGHT)
59 paddle1 = HEIGHT;
60 if(paddle2 < -HEIGHT)
61 paddle2 = -HEIGHT;
62 if(paddle2 > HEIGHT)
63 paddle2 = HEIGHT;
64
65 // Check for collisions with paddles
66 if(ballVecX < 0 && ballX <= -HEIGHT + -ballVecX * 1.5) {
67 if(ballY >= paddle1 - PADDLESIZE && ballY <= paddle1 + PADDLESIZE) {
68 ballVecX *= -SPEEDINC;
69 ballVecY *= SPEEDINC;
70 }
71 }
72 if(ballVecX > 0 && ballX >= HEIGHT - ballVecX * 1.5) {
73 if(ballY >= paddle2 - PADDLESIZE && ballY <= paddle2 + PADDLESIZE) {
74 ballVecX *= -SPEEDINC;
75 ballVecY *= SPEEDINC;
76 }
77 }
78
79 // Check if it's past the top or bottom of the screen
80 if(ballY >= HEIGHT || ballY <= -HEIGHT) {
81 ballVecY = -ballVecY;
82 }
83
84 // Check if it's past the sides of the screen
85 if(ballX >= HEIGHT) {
86 ++score1;
87 initball();
88 }
89 if(ballX <= -HEIGHT) {
90 ++score2;
91 initball();
92 }
93
94 // Move the ball
95 ballX += ballVecX;
96 ballY += ballVecY;
97
98 // Check scores for winners..
99 if(score1 == 9) {
100 // Player 1 wins
101 score1 = score2 = 0;
102 }
103 if(score2 == 9) {
104 // Player 2 wins
105 score1 = score2 = 0;
106 }
107 }
108
109 static void display(void) {
110 glClear(GL_COLOR_BUFFER_BIT);
111 glColor3d(0.0, 0.0, 0.0);
112
113 // Draw the paddles
114 glLineWidth(2.0);
115 glBegin(GL_LINES);
116 glVertex2d(-HEIGHT + 1, paddle1 - PADDLESIZE);
117 glVertex2d(-HEIGHT + 1, paddle1 + PADDLESIZE);
118 glVertex2d( HEIGHT - 1, paddle2 + PADDLESIZE);
119 glVertex2d( HEIGHT - 1, paddle2 - PADDLESIZE);
120 glEnd();
121
122 // Draw the ball
123 glPointSize(5.0);
124 glBegin(GL_POINTS);
125 glVertex2d(ballX, ballY);
126 glEnd();
127
128 // Write the score
129 glRasterPos2d(-5.0, HEIGHT - 10.0);
130 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, '0' + score1);
131 glRasterPos2d( 5.0, HEIGHT - 10.0);
132 glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, '0' + score2);
133
134 glutSwapBuffers();
135 }
136
137 static void resize(int w, int h) {
138 glViewport(0, 0, w, h);
139 glLoadIdentity();
140 glOrtho(-HEIGHT, HEIGHT, -HEIGHT, HEIGHT, -1.0, 1.0);
141 }
142
143 static void keyboard(unsigned char key, int x, int y) {
144 (void)x;(void)y;
145
146 switch(key) {
147 case 'q':
148 case 'Q':
149 case '\033':
150 exit(0);
151
152 case 'w':
153 p1move = 1;
154 break;
155 case 's':
156 p1move = -1;
157 break;
158
159 case 'i':
160 p2move = 1;
161 break;
162 case 'k':
163 p2move = -1;
164 break;
165
166 default:
167 return;
168 }
169 glutPostRedisplay();
170 }
171
172 static void keyboardUp(unsigned char key, int x, int y) {
173 (void)x;(void)y;
174
175 switch(key) {
176 case 'w':
177 case 's':
178 p1move = 0;
179 break;
180
181 case 'i':
182 case 'k':
183 p2move = 0;
184 p2move = 0;
185 break;
186 }
187 }
188
189 static void timer(int lastTime) {
190 int curTime = glutGet(GLUT_ELAPSED_TIME);
191 do {
192 lastTime += FRAME;
193 run();
194 } while(lastTime + FRAME < curTime);
195 glutPostRedisplay();
196 glutTimerFunc(FRAME - (curTime - lastTime), timer, curTime);
197 }
198
199 static void init(void) {
200 glClearColor(1.0, 1.0, 1.0, 0.0);
201 initball();
202 }
203
204 int main(int argc, char *argv[]) {
205 if(argc == 2 && *argv[1] == '1') {
206 AI = 1;
207 }
208
209 glutInitWindowPosition(100, 100);
210 glutInitWindowSize(640, 480);
211 glutInit(&argc, argv);
212 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
213 glutCreateWindow(argv[0]);
214 glutDisplayFunc(display);
215 glutReshapeFunc(resize);
216 glutKeyboardFunc(keyboard);
217 glutKeyboardUpFunc(keyboardUp);
218 glutTimerFunc(FRAME, timer, glutGet(GLUT_ELAPSED_TIME));
219 init();
220 glutMainLoop();
221 return 0;
222 }
223