1 /* This is "graphics.c", a part of the pool (billiards)-program
2
3 "Another Pool GL".
4
5 "graphics.c" uses the SDL graphics-library which is available at
6
7 http://www.libsdl.org and
8
9 Copyright (C) 1995,2002 by Gerrit Jahn (http://www.planetjahn.de)
10
11 This file ist part of Another Pool / Another Pool GL (apool, apoolGL).
12
13 "Another Pool" is free software; you can redistribute it
14 and/or modify it under the terms of the GNU General Public License
15 as published by the Free Software Foundation; either version 2 of
16 the License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ME CHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with GNU CC; see the file COPYING. If not, write to
25 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26
27 /* ------------------------------ graphics.c ----------------------------- */
28
29 #include <math.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <time.h>
33 #include <sys/time.h>
34 #include <string.h>
35 #include <SDL.h>
36 #include <GL/gl.h>
37 #include <GL/glu.h>
38 #include "apool.h"
39
40 #define GR_M_BUTTON_DOWN SDL_MOUSEBUTTONDOWN
41 #define GR_M_BUTTON_UP SDL_MOUSEBUTTONUP
42 #define GR_M_BUTTON_CHANGE SDL_MOUSEBUTTONDOWN|SDL_MOUSEBUTTONDOWN
43 #define GR_M_MOTION SDL_MOUSEMOTION
44 #define GR_M_KEYPRESS SDL_KEYDOWN
45
46 #define PAINT_ALL \
47 gl_plotall(-1);\
48 paint_spin( 1.0/10.0, 0.45, 0.36 );\
49 speed(spd, 1.0/10.0, 0.09, 0.36);\
50 gl_plot_target();\
51 msg(current_message);\
52 msg2(current_message2);\
53 SDL_GL_SwapBuffers()
54
55 int col[20][3] = {{0,0,0},{255,0,0},{255,255,0},{32,32,32},{0,127,0},
56 {124,224,224},{55,0,0},{255,0,255},{32,32,222},{0,255,0},
57 {255,255,255},{255,55,55},{0,0,0},{0,0,96},{0,0,255},
58 {0,0,127},{140,90,40},{0,0,196},{0,0,127},{0,0,127}};
59 #define TABLEGREEN 4
60 double oldalph=0.0, alph=0.0, spd=0.75, e_winkel, old_min;
61 int counter=0, oldx[BALLS], oldy[BALLS], olds[2];
62 int old_ball, old_hole, old_paint=5, mmouse = 0;
63 int SPINPOSX, SPINPOSY;
64
65 struct hole posl[6]; /* 6 L�cher */
66 struct bande banpixel[18], ban[18];
67
68 SDL_Event event;
69 SDL_Rect src_rect,dest_rect;
70
init_graphics(void)71 void init_graphics( void )
72 {
73 InitGL(SCREENRESX, SCREENRESY);
74 }
75
msg(char * out)76 void msg( char *out )
77 { /* Gibt einige Dinge unterhalb des Tisches aus */
78 glPrint(20,35,out,0,1.0,1.0,1.0,1.0,0.8);
79 }
80
gl_print_foul(void)81 void gl_print_foul( void )
82 { /* Fouls anzeigen */
83 glPrintCentered(600,foul_msg,0,1.0,0.0,0.0,0.8,1.5);
84 }
85
gl_print_err2(void)86 void gl_print_err2( void )
87 { /* freeball/extra shout anzeigen */
88 glPrintCentered(300,err2_msg1, 0, 1.0, 0.0, 0.0, 0.8,3.0);
89 glPrintCentered(220,err2_msg2, 0, 1.0, 0.0, 0.0, 0.8,3.0);
90 }
91
msg2(char * out)92 void msg2( char *out )
93 { /* Gibt einige Dinge unterhalb des Tisches aus */
94 glPrint(20,15,out,0,1.0,1.0,1.0,1.0,0.8);
95 }
96
plot_standings(void)97 void plot_standings( void )
98 {
99 char out[15];
100 sprintf(out,"%d : %d",(int)(ply[0].points)%10000+(int)(ply[1].points)/10000,
101 (int)(ply[1].points)%10000 + (int)(ply[0].points)/10000 );
102 /* GrDrawString(out,strlen(out), display->w - (15+strlen(out))*8, 10, 10); */
103 }
104
speed(double p,double scale,double posx,double posy)105 void speed( double p, double scale, double posx, double posy )
106 {
107 glDisable(GL_LIGHTING);
108 glEnable(GL_BLEND);
109 glDisable(GL_FOG);
110 glDisable(GL_DEPTH_TEST); /* Disables Depth Testing */
111
112 glMatrixMode(GL_PROJECTION);
113 glPushMatrix();
114 glLoadIdentity();
115 glOrtho(-0.5,0.5,-0.37,0.37,-0.5,1);
116 glMatrixMode(GL_MODELVIEW);
117 glPushMatrix();
118 glLoadIdentity();
119 glTranslated(posx, posy - 0.03 * (1.0 - scale), -0.0f);
120
121 glColor4d(0.0f,0.0f,1.0f,0.3f);
122
123 glBegin(GL_POLYGON);
124 glVertex3d( -0.2 - 0.2*scale, -(0.025 + 0.025*scale), 0.1);
125 glVertex3d( 0.2 + 0.2*scale, -(0.025 + 0.025*scale), 0.1);
126 glVertex3d( 0.2 + 0.2*scale, (0.01 + 0.04*scale), 0.1);
127 glVertex3d( -0.2 - 0.2*scale, (0.01 + 0.04*scale), 0.1);
128 glEnd();
129
130 glColor4d(0.0f,0.0f,1.0f,0.2f);
131 glBegin(GL_POLYGON);
132 glVertex3d( -0.2 -0.2*scale, -(0.025 + 0.025*scale), 0.1);
133 glVertex3d( (-0.2+spd*0.4) + (-0.2+spd*0.4)*scale, -(0.025 + 0.025*scale), 0.1);
134 glVertex3d( (-0.2+spd*0.4) + (-0.2+spd*0.4)*scale, (0.01 + 0.04*scale), 0.1);
135 glVertex3d( -0.2 -0.2*scale, (0.01 + 0.04*scale), 0.1);
136 glEnd();
137
138 glEnable(GL_DEPTH_TEST);
139 glDisable(GL_BLEND);
140 glEnable(GL_LIGHTING);
141 glEnable(GL_FOG);
142 glMatrixMode(GL_PROJECTION);
143 glPopMatrix();
144 glMatrixMode(GL_MODELVIEW);
145 glPopMatrix();
146 }
147
paint_spin(double scale,double posx,double posy)148 void paint_spin( double scale, double posx, double posy )
149 {
150 float rad_outer=0.3;
151 double angle;
152 float MatDifWhite[] = {1.0,1.0,1.0,0.75};
153
154 /* falls Textures ausgeschaltet muss die Spinkugel explizit
155 wei� sein, ansonsten hat sie die gleiche Farbe wie die
156 "next"-Kugel */
157 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDifWhite);
158
159 glDisable(GL_FOG);
160 glEnable(GL_BLEND);
161 glDisable(GL_LIGHT1);
162 glDisable(GL_LIGHT2);
163 glEnable(GL_LIGHT3);
164
165 glMatrixMode(GL_PROJECTION);
166 glPushMatrix();
167 glLoadIdentity();
168 glOrtho(-0.5,0.5,-0.4,0.4,1.0,0);
169
170 glMatrixMode(GL_MODELVIEW);
171 glPushMatrix();
172 glLoadIdentity();
173 glTranslated(posx, posy - 0.03 * (1.0 - scale) + 0.012, -1.0) ;
174
175 angle = sqrt( k[WHITE].e.x*90.0*k[WHITE].e.x*90.0 +
176 k[WHITE].e.y*90.0*k[WHITE].e.y*90.0 +
177 k[WHITE].e.z*90.0*k[WHITE].e.z*90.0 );
178 glRotated(angle, k[WHITE].e.y, k[WHITE].e.z, k[WHITE].e.x );
179
180 glMultMatrixd(k[WHITE].mrot);
181
182 glEnable(GL_TEXTURE_2D);
183 glBindTexture(GL_TEXTURE_2D, texture[0]); /* Wei�e Kugel */
184 if( scale <= 0.1 ) icosphere(ico320, 320, rad_outer*scale);
185 else icosphere(ico5120, 5120, rad_outer*scale);
186
187 glDisable(GL_TEXTURE_2D);
188
189 glMatrixMode(GL_PROJECTION);
190 glPopMatrix();
191 glMatrixMode(GL_MODELVIEW);
192 glPopMatrix();
193
194 glEnable(GL_DEPTH_TEST);
195 glDisable(GL_LIGHT3);
196 glEnable(GL_LIGHT1);
197 glEnable(GL_LIGHT2);
198 glDisable(GL_BLEND);
199 glEnable(GL_FOG);
200 }
201
test_spin(void)202 void test_spin( void )
203 { /* Mouse-Abfrage f�r das Setzen des lokalen Spins... */
204 int oldx, oldy, i, ende=0;
205 Uint8 *keys;
206 double sz, sp, dummy;
207 struct timeval tp_start,tp_cur;
208 double time_cur, time_start;
209 SDL_GetMouseState(&oldx, &oldy);
210 for( i=10;i>=1;i-- )
211 {
212 gettimeofday(&tp_start,NULL);
213 time_start = tp_start.tv_sec * 1000000 + tp_start.tv_usec;
214 glFogf(GL_FOG_DENSITY, 1.0-i/(100.0/5.0));
215 gl_plotall(-1);
216 paint_spin( 1.0/(double)i, 0.5 - 0.5 / (double)i, 0.4 - 0.4/(double)i );
217 speed(spd, 1.0/10.0, 0.09, 0.36);
218 glPrintCentered(0.85*768, "set spin", 0, 1.0, 1.0, 1.0, 1.0,4.0);
219 msg("move mouse to change spin. release middle button to leave...");
220 SDL_GL_SwapBuffers();
221 gettimeofday(&tp_cur,NULL);
222 time_cur = tp_cur.tv_sec * 1000000 + tp_cur.tv_usec;
223 if( time_cur - time_start < 10000 ) SDL_Delay(10+(time_cur - time_start)/1000);
224 }
225 keys=SDL_GetKeyState(NULL);
226 if( SDL_GetMouseState(&oldx, &oldy) & SDL_BUTTON(2) || keys[SDLK_e] )
227 {
228 do
229 {
230 do
231 {
232 while( SDL_PollEvent(&event) );
233 SDL_WaitEvent(&event);
234 }
235 while( event.type != SDL_MOUSEMOTION && event.type != SDL_KEYUP &&
236 (event.type != SDL_MOUSEBUTTONUP) &&
237 (event.type != SDL_MOUSEBUTTONDOWN) );
238 keys=SDL_GetKeyState(NULL);
239 if( event.type == SDL_MOUSEMOTION )
240 {
241 /* sollte vielleicht umgerechnet werden in einen Winkel !!! !!! !!! ??? */
242 sz = (event.motion.x - oldx)/50.0;
243 sp = (event.motion.y - oldy)/50.0;
244 SDL_WarpMouse( oldx, oldy );
245 dummy = sqrt( (k[WHITE].e.y+sp)*(k[WHITE].e.y+sp) + (k[WHITE].e.z+sz)*(k[WHITE].e.z+sz) );
246 if( dummy < 1.0 ) dummy = 1.0;
247 k[WHITE].e.x = 0.0; /* wird in translate_spin() entsprechend der Zielrichtung angepasst */
248 k[WHITE].e.y = (k[WHITE].e.y+sp) / dummy;
249 k[WHITE].e.z = (k[WHITE].e.z+sz) / dummy;
250 gl_plotall(-1);
251 paint_spin( 1.0, 0.0, 0.0 );
252 speed(spd, 1.0/10.0, 0.09, 0.36);
253 glPrintCentered(0.85*768, "set spin", 0, 1.0, 1.0, 1.0, 1.0,4.0);
254 msg("move mouse to change spin. release middle button to leave...");
255 SDL_GL_SwapBuffers();
256 }
257 else {mmouse=1;}
258 if( !(SDL_GetMouseState(NULL,NULL) & SDL_BUTTON(2)) && !keys[SDLK_e] ) ende = 1;
259 }
260 while( !ende && !(event.type == SDL_KEYDOWN) &&
261 !((event.button.button == SDL_BUTTON_MIDDLE) &&
262 (event.type == SDL_MOUSEBUTTONUP)) &&
263 !(mmouse && ((event.type == SDL_MOUSEBUTTONDOWN) ||
264 (event.type == SDL_MOUSEBUTTONUP))) );
265 }
266 for( i=1;i<=10;i++ )
267 {
268 gettimeofday(&tp_start,NULL);
269 time_start = tp_start.tv_sec * 1000000 + tp_start.tv_usec;
270 gl_plotall(-1);
271 paint_spin( 1.0/(double)i, 0.5 - 0.5 / (double)i, 0.4 - 0.4/(double)i );
272 speed(spd, 1.0/10.0, 0.09, 0.36);
273 msg(current_message);
274 msg2(current_message2);
275 glFogf(GL_FOG_DENSITY, 1.0-i/20.0);
276 SDL_GL_SwapBuffers();
277 gettimeofday(&tp_cur,NULL);
278 time_cur = tp_cur.tv_sec * 1000000 + tp_cur.tv_usec;
279 if( time_cur - time_start < 10000 ) SDL_Delay(10+(time_cur - time_start)/1000);
280 }
281 glFogf(GL_FOG_DENSITY, 0.5);
282 PAINT_ALL;
283 mmouse = 0;
284 }
285
wait_for_click(void)286 void wait_for_click( void )
287 /* wartet auf Mouse-Click oder Tasten-Druck */
288 {
289 SDL_Event event;
290 do
291 { SDL_WaitEvent(&event); }
292 while( ( event.type != SDL_KEYDOWN) && (event.type != SDL_MOUSEBUTTONUP) &&
293 (event.type != SDL_QUIT) );
294 if( (event.type == SDL_KEYDOWN) || (event.type == SDL_QUIT) )
295 {
296 Uint8 *keystate = SDL_GetKeyState(NULL);
297 if( (keystate[SDLK_ESCAPE]) || (event.type == SDL_QUIT) ) stop_it();
298 }
299 }
300
wait_for_click_up(void)301 void wait_for_click_up( void )
302 /* wartet auf Mouse-Click oder Tasten-Druck */
303 {
304 SDL_Event event;
305 do
306 { SDL_WaitEvent(&event); }
307 while( ( event.type != SDL_KEYUP) && (event.type != SDL_MOUSEBUTTONUP) &&
308 (event.type != SDL_QUIT) );
309 if( (event.type == SDL_KEYUP) || (event.type == SDL_QUIT) )
310 {
311 Uint8 *keystate = SDL_GetKeyState(NULL);
312 if( (keystate[SDLK_ESCAPE]) || (event.type == SDL_QUIT) ) stop_it();
313 }
314 }
315
wink(double a)316 void wink( double a ) /* Winkel zwischen Queue und Tisch darstellen */
317 { /* K�nnte mal einen dickeren Queue bekommen !!! !!! !!!*/
318 /* double b = a*M_PI/180.0; */
319 /* int posx = 0.5, posy=0.3; */
320 /* GrCircleArc(posx, posy, 6*PIXELRADIUS+1, 270, 362, GR_ARC_STYLE_OPEN, 9); */
321 /* GrFilledCircleArc(posx, posy, 6*PIXELRADIUS, 270, 362, */
322 /* GR_ARC_STYLE_CLOSE2, COL_WHITE); */
323 /* GrFilledCircle(posx+6.5*PIXELRADIUS*cos(oldalph), posy-6.5*PIXELRADIUS*sin(oldalph), */
324 /* PIXELRADIUS/2,0); */
325 /* GrFilledCircle(posx+6.5*PIXELRADIUS*cos(b), posy-6.5*PIXELRADIUS*sin(oldalph=b), */
326 /* PIXELRADIUS/2,16); */
327 /* SDL_UpdateRect(display,posx-1-PIXELRADIUS,posy-7.5*(PIXELRADIUS+1)-1, */
328 /* 12*(PIXELRADIUS+2)+2,7.5*(PIXELRADIUS+2)+2); */
329 }
330
err(char * out)331 void err( char *out )
332 { /* Ausgabe der normalen Texte w�hrend des Spiels */
333 glPrintCentered(768/2,out,0,1.0,0.5,0.5,1.0,1.45);
334 SDL_GL_SwapBuffers();
335 }
336
err2(char * out,char * out2)337 void err2( char *out, char *out2 )
338 { /* Ausgabe von z.B. Free- oder Extra-Ball ... */
339 strcpy(err2_msg1, out);
340 strcpy(err2_msg2, out2);
341 err2_endtime = timer() + 3000; /* Nachricht wird 2 Sekunden lang angezeigt */
342 }
343
foul(char * out,int time)344 void foul( char *out, int time )
345 { /* Ausgabe von z.B. Free- oder Extra-Ball ... */
346 strcpy(foul_msg, out);
347 foul_endtime = timer() + time; /* Nachricht wird time/1000 Sekunden lang angezeigt */
348 }
349
debug(char * out)350 void debug( char *out )
351 { /* Ausgabe der Kommentare beim Computer-Spieler */
352 /* char o[80]; */
353 /* sprintf(o,"%s",out); */
354 /* GrDrawString(out, strlen(out), 0, 35, TEXTCOL ); */
355 /* SDL_Flip(display); */
356 }
357
mouse_on(void)358 void mouse_on( void )
359 { SDL_ShowCursor(1); }
360
mouse_off(void)361 void mouse_off( void )
362 { SDL_ShowCursor(0); }
363
set_white_ball(void)364 void set_white_ball( void )
365 { /* Wei�e Kugel am Anfang oder nach Foul neu positionieren */
366 int i, j, okx,oky;
367 double old, old2, motionx,motiony, dummy;
368 int mousex, mousey;
369 struct vect v;
370 k[WHITE].p.z = RADIUS;
371 k[WHITE].v.z = 0.0;
372 k[WHITE].p.x = k[WHITE].p.y = 0.10;
373 k[WHITE].stat = (ONTABLE|MOVING);
374 if( (c_player == -1) || (cur != c_player ) )
375 {
376 k[WHITE].e.x = k[WHITE].e.y = k[WHITE].e.z = 0.0;
377 old2 = 0.25;
378 i = 225;
379 do
380 {
381 old = ((double)i) / 1000.0;
382 okx = 1;
383 for(j=0;j<BALLS;j++) /* Suche nach freiem Platz auf dem Tisch */
384 if( DIFF2( old-k[j].p.x, old2-k[j].p.y ) < 5.0*PIXELRADIUS*PIXELRADIUS )
385 {okx=0; break;}
386 }
387 while( !okx && (--i>50) );
388 k[WHITE].p.x = old; k[WHITE].p.y = old2;
389 gl_move_table(0.0f,0.0f,0.0f, 0.0f,0.0f,-0.985f, new_game ? 15.0 : 25.0f, 0, 0, 0);
390 do
391 {
392 gl_plotall(-1);
393 msg("move mouse to change the position of the cue-ball");
394 msg2("press left mouse button to set the position of the cue ball");
395 SDL_GL_SwapBuffers();
396 while( SDL_PollEvent(&event) );
397 SDL_WaitEvent( &event);
398 okx=oky=1;
399 if( event.type == SDL_MOUSEMOTION )
400 {
401 SDL_GetMouseState(&mousex, &mousey);
402 /* SDL_WarpMouse(SCREENRESX/2, SCREENRESY/2 ); */
403 motionx = (double)(mousex-SCREENRESX/2) / (double)SCREENRESX;
404 motiony = (double)(mousey-SCREENRESY/2) / (double)SCREENRESX;
405 k[WHITE].p.x += motionx * cos(angz * M_PI/180.0) - motiony * sin(angz * M_PI/180.0);
406 k[WHITE].p.y -= motionx * sin(angz * M_PI/180.0) + motiony * cos(angz * M_PI/180.0);
407 for(i=0;i<BALLS-1;i++)
408 {
409 if( ABST(k[i].p,k[WHITE].p) < RADIUS*RADIUS*4.0 )
410 {
411 v.x = k[i].p.x - k[WHITE].p.x;
412 v.y = k[i].p.y - k[WHITE].p.y;
413 dummy = BETR(v);
414 v.x /= dummy;
415 v.y /= dummy;
416 k[WHITE].p.y = k[i].p.y - 2*RADIUS * v.y;
417 k[WHITE].p.y = k[i].p.y - 2*RADIUS * v.y;
418 }
419 }
420 if( k[WHITE].p.x > 0.25 ) k[WHITE].p.x = 0.25;
421 if( k[WHITE].p.y > 0.5 - RADIUS ) k[WHITE].p.y = 0.5-RADIUS;
422 if( k[WHITE].p.x < RADIUS ) k[WHITE].p.x = RADIUS;
423 if( k[WHITE].p.y < RADIUS ) k[WHITE].p.y = RADIUS;
424 SDL_WarpMouse(SCREENRESX/2, SCREENRESY/2 );
425 }
426 }
427 while( event.type != SDL_MOUSEBUTTONUP && event.type != SDL_KEYDOWN && event.type != SDL_QUIT );
428 if( (event.type == SDL_KEYDOWN) || (event.type == SDL_QUIT) )
429 {
430 Uint8 *keystate = SDL_GetKeyState(NULL);
431 if( (keystate[SDLK_ESCAPE]) || (event.type == SDL_QUIT) ) stop_it();
432 }
433 }
434 else /* !!! !!! !!! !!! !!! !!! VERBESSERN! */
435 {
436 /* Computer kann Wei�e legen ... */
437 k[WHITE].e.x = k[WHITE].e.y = k[WHITE].e.z = 0.0;
438 old2 = 0.25;
439 i = 250;
440 do
441 {
442 old = ((double)i) / 1000.0;
443 okx = 1;
444 for(j=0;j<WHITE;j++) /* Suche nach freiem Platz auf dem Tisch */
445 if( DIFF2( old-k[j].p.x, old2-k[j].p.y ) < 5.0*PIXELRADIUS*PIXELRADIUS )
446 {okx=0; break;}
447 }
448 while( !okx && (--i>50) );
449 k[WHITE].p.x = old; k[WHITE].p.y = old2;
450 gl_plotall(1);
451 }
452 new_game = 0;
453 }
454
calc_player_v(void)455 void calc_player_v( void )
456 {
457 struct vect3 v;
458 double dummy;
459 v.x = target.x - k[WHITE].p.x;
460 v.y = target.y - k[WHITE].p.y;
461 if( fabs(v.x) > 1e-10 || fabs(v.y) > 1e-10 )
462 {
463 v.x /= (dummy = sqrt(v.x*v.x+v.y*v.y));
464 v.y /= dummy;
465 }
466 k[WHITE].e.x *= spd;
467 k[WHITE].e.y *= spd;
468 k[WHITE].e.z *= 1.0; /* *spd!!! ??*/
469 k[WHITE].v.x = spd * SPEED_FACTOR * v.x / DIFFX;
470 k[WHITE].v.y = spd * SPEED_FACTOR * v.y / DIFFX;
471 }
472
set_player_power(void)473 void set_player_power( void )
474 {
475 int oldx, oldy, i, ende = 0;
476 struct timeval tp_start,tp_cur;
477 double time_cur, time_start;
478 for( i=10;i>0;i-- )
479 {
480 gettimeofday(&tp_start,NULL);
481 time_start = tp_start.tv_sec * 1000000 + tp_start.tv_usec;
482 glFogf(GL_FOG_DENSITY, 1.0-i/(100.0/5.0));
483 gl_plotall(-1);
484 paint_spin( 1.0/10.0, 0.45, 0.36 );
485 speed(spd, 1.0/(double)i, 0.1 - 0.1/(double)i, 0.4 - 0.4/(double)i );
486 glPrintCentered(0.6*768, "set speed", 0, 1.0, 1.0, 1.0, 1.0,4.0);
487 msg("move mouse to change initial speed, release button to leave...");
488 SDL_GL_SwapBuffers();
489 gettimeofday(&tp_cur,NULL);
490 time_cur = tp_cur.tv_sec * 1000000 + tp_cur.tv_usec;
491 if( time_cur - time_start < 10000 ) SDL_Delay(10+(time_cur - time_start)/1000);
492 }
493 if( SDL_GetMouseState(&oldx, &oldy) & SDL_BUTTON(3) )
494 {
495 do
496 {
497 while( SDL_PollEvent(&event) );
498 SDL_WaitEvent(&event);
499 if( (event.type == SDL_MOUSEMOTION ) )
500 {
501 if( (event.button.x != oldx) || (event.button.y != oldy) )
502 {
503 spd += 1.0/500.0 * (double)(event.button.x - oldx);
504 spd += 1.0/500.0 * (double)(-event.button.y + oldy);
505 SDL_WarpMouse(oldx, oldy);
506 if( spd > 1.0 ) spd = 1.0;
507 if( spd < 0.0 ) spd = 0.0;
508 gl_plotall(-1);
509 paint_spin( 1.0/10.0, 0.45, 0.36 );
510 speed(spd, 1.0, 0.0, 0.0 );
511 glPrintCentered(0.6*768, "set speed", 0, 1.0, 1.0, 1.0, 1.0,4.0);
512 msg("move mouse to change initial speed, release button to leave...");
513 SDL_GL_SwapBuffers();
514 }
515 }
516 if( !(SDL_GetMouseState(NULL,NULL) & SDL_BUTTON(3)) ) ende = 1;
517 }
518 while( !ende && (event.type != SDL_MOUSEBUTTONUP) );
519 }
520 for( i=1;i<=10;i++ )
521 {
522 gettimeofday(&tp_start,NULL);
523 time_start = tp_start.tv_sec * 1000000 + tp_start.tv_usec;
524 glFogf(GL_FOG_DENSITY, 1.0-i/(100.0/5.0));
525 gl_plotall(-1);
526 paint_spin( 1.0/10.0, 0.45, 0.36 );
527 speed(spd, 1.0/(double)i, 0.1 - 0.1/(double)i, 0.4 - 0.4/(double)i );
528 msg(current_message);
529 msg2(current_message2);
530 SDL_GL_SwapBuffers();
531 gettimeofday(&tp_cur,NULL);
532 time_cur = tp_cur.tv_sec * 1000000 + tp_cur.tv_usec;
533 if( time_cur - time_start < 10000 ) SDL_Delay(10+(time_cur - time_start)/1000);
534 }
535 glFogf(GL_FOG_DENSITY, 0.5);
536 PAINT_ALL;
537 }
538
set_player_spin(void)539 void set_player_spin( void )
540 {
541 int oldx, oldy;
542 double oldalph_local;
543 oldalph=alph;
544 msg("move mouse to change spin, press right button to change angle");
545 test_spin();
546 SDL_GetMouseState(&oldx, &oldy);
547 return;
548 if( (event.type == SDL_MOUSEBUTTONDOWN) &&
549 ((event.button.button == SDL_BUTTON_MIDDLE) ||
550 (event.button.button == SDL_BUTTON_RIGHT)))
551 {
552 msg("move mouse to change angle between queue an table");
553 do
554 {
555 oldalph_local = alph;
556 while( SDL_PollEvent(&event) );
557 SDL_WaitEvent( &event );
558 if( event.type == GR_M_MOTION )
559 {
560 if( (oldx-event.motion.x) || (oldy-event.motion.y) )
561 {
562 alph += 0.1 * (oldx - event.motion.x + oldy - event.motion.y);
563 SDL_WarpMouse( oldx, oldy );
564 if( alph > 90.0 ) alph = 90.0;
565 if( alph < 0.0 ) alph = 0.0;
566 wink( alph );
567 }
568 }
569 }
570 while( !(event.type == GR_M_KEYPRESS) &&
571 !( (event.type == SDL_MOUSEBUTTONUP) &&
572 ((event.button.button == SDL_BUTTON_MIDDLE) ||
573 (event.button.button == SDL_BUTTON_RIGHT))) );
574 }
575 MSG2;
576 }
577
set_test_power(void)578 void set_test_power( void )
579 { /* Test-Prozedur, berechnet Geschw., die die Weisse haben mu�, um zur akt.
580 Maus-Position zu rollen */
581 struct vect3 v;
582 debug("press button, to play white to cur.pos. !");
583 do
584 { SDL_WaitEvent( &event ); }
585 while( !(event.type == GR_M_BUTTON_DOWN) );
586 v.x = (event.button.x-LEFT)/DIFFX - k[WHITE].p.x;
587 v.y = (event.button.y-UP)/DIFFX - k[WHITE].p.y;
588 set_c_speed( SET_V(BETR( v ), 0), v );
589 }
590
set_test_power2(void)591 int set_test_power2( void )
592 { /* Test-Prozedur, berechnet die Geschw., die die Weisse ben�tigt, um ein
593 best. Kugel in ein best. Loch zu schie�en; ohne jeden Test, ob andere
594 Kugeln im Weg liegen ... */
595 int i, puffer_ball;
596 struct vect3 v1, v2, v3, v4;
597 double dum1, dummy;
598 int dum2;
599 char outtext[80];
600 debug("ball ?");
601 do
602 { SDL_WaitEvent( &event ); }
603 while( !(event.type == GR_M_BUTTON_DOWN) );
604 v1.x = (event.button.x-LEFT) / DIFFX;
605 v1.y = (event.button.y-UP) / DIFFX;
606 dum1 = dum2 = 4;
607 for( i=0;i<WHITE;i++ )
608 if( DIFF( v1.x-k[i].p.x, v1.y-k[i].p.y ) < dum1 )
609 { dum1 = DIFF( v1.x-k[i].p.x, v1.y-k[i].p.y ); dum2 = i; }
610 v1.x = k[dum2].p.x; v1.y = k[dum2].p.y;
611 puffer_ball = dum2;
612 sprintf(outtext,"ball no: %d, hole ?", dum2 );
613 debug(outtext);
614 do
615 { SDL_WaitEvent( &event ); }
616 while( !(event.type == GR_M_BUTTON_DOWN) );
617 v2.x = (event.button.x-LEFT) / DIFFX;
618 v2.y = (event.button.y-UP) / DIFFX;
619 dum1 = 1000.0; dum2 = 0;
620 for( i=0;i<6;i++ )
621 if( DIFF( v2.x-posl[i].m.x, v2.y-posl[i].m.y ) < dum1 )
622 { dum1 = DIFF( v2.x-posl[i].m.x, v2.y-posl[i].m.y ); dum2 = i; }
623 sprintf(outtext,"hole: %d",dum2);
624 debug(outtext);
625 v2.x = posl[dum2].m.x; v2.y = posl[dum2].m.y;
626 v3 = calc_tp( v1, v2 );
627 dummy = sqrt( DIFF( k[WHITE].p.x-v3.x, k[WHITE].p.y-v3.y ));
628 /* geht so nat�rlich noch nicht wieder !!! */
629 v4.x = v2.x - v3.x; v4.y = v2.y - v3.y;
630 v1.x = v3.x - k[WHITE].p.x; v1.y = v3.y - k[WHITE].p.y;
631 if( COSV( v1, v4 ) > 0.0 )
632 {
633 v2.x = posl[dum2].p.x - posl[dum2].m.x;
634 v2.y = posl[dum2].p.y - posl[dum2].m.y;
635 v3.x = posl[dum2].m.x - k[puffer_ball].p.x;
636 v3.y = posl[dum2].m.y - k[puffer_ball].p.y;
637 if( ((dum2 == 2 || dum2 == 5) && COSV( v2, v3 ) > COS(e_winkel))
638 || (dum2 != 2 && dum2 != 5) )
639 {
640 if( (dum1=COSV( v1, v4 )) ) dummy += BETR(v4) / (dum1 * dum1);
641 else dummy = 1000000.0; /* =infinity */
642 set_c_speed( SET_V(dummy*sqrt(1.0/ROLL), 0), v1 );
643 return 1;
644 }
645 else
646 {
647 char out[80];
648 sprintf(out,"can't play this..(ew:%g/ pw:%g)", e_winkel,
649 180.0/M_PI * acos(COSV( v2, v3 )) );
650 debug(out);
651 return 0;
652 }
653 }
654 debug("can't play this...");
655 return 0;
656 }
657
gl_plot_target(void)658 void gl_plot_target( void )
659 {
660 float MatDif[] = {0.5f, 0.5f, 1.0f, 0.3f};
661 float MatAmb[] = {0.1f, 0.1f, 0.4f, 0.1f};
662 float MatSpc[] = {0.0f, 0.0f, 0.5f, 1.0f};
663 float MatEm[] = {0.9f, 0.0f, 0.9f, 0.5f};
664 float MatZero[] = {0.0f, 0.0f, 0.0f, 0.0f};
665 GLfloat LightEmission[] = { 1.0f, 0.5f, 1.0f, 1.0f };
666
667 glPushMatrix();
668 glLightfv(GL_LIGHT1, GL_EMISSION, LightEmission);
669 glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDif);
670 glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb);
671 glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);
672 glMaterialfv(GL_FRONT, GL_EMISSION, MatEm);
673
674 glTranslatef((double)target.x-0.5f, (double)target.y-0.25f, RADIUS);
675
676 glEnable(GL_BLEND);
677 glColor4d(0.2,0.2,1.0,0.3);
678
679 icosphere(ico320, 320, RADIUS);
680 glDisable(GL_BLEND);
681
682 glMaterialfv(GL_FRONT, GL_EMISSION, MatZero);
683 glLightfv(GL_LIGHT1, GL_EMISSION, MatZero);
684 glPopMatrix();
685 }
686
newstartpos(double sx,double sy,double sz,int key,int invoke,int button)687 void newstartpos( double sx, double sy , double sz, int key, int invoke, int button )
688 {
689 Uint8 *keys;
690 int ende=0;
691 do
692 {
693 startx += sx;
694 starty += sy;
695 startz += sz;
696 gl_plotall(-1);
697 gl_plot_target();
698 SDL_GL_SwapBuffers();
699 SDL_Delay(20);
700 SDL_PollEvent(NULL);
701 keys = SDL_GetKeyState(NULL);
702 if( keys[key] != SDL_PRESSED && invoke == 2 ) ende = 1;
703 if( !(SDL_GetMouseState(NULL,NULL) & SDL_BUTTON(button)) && invoke == 1 ) ende = 1;
704 }
705 while( !ende );
706 }
707
newtranspos(double sx,double sy,double sz,int key,int invoke)708 void newtranspos( double sx, double sy , double sz, int key, int invoke )
709 {
710 Uint8 *keys;
711 int ende=0;
712 do
713 {
714 transx += sx;
715 transy += sy;
716 transz += sz;
717 gl_plotall(1);
718 SDL_Delay(20);
719 SDL_PollEvent(NULL);
720 keys = SDL_GetKeyState(NULL);
721 if( keys[key] != SDL_PRESSED && invoke == 2 ) ende = 1;
722 if( !(SDL_GetMouseState(NULL,NULL) & SDL_BUTTON(1)) && invoke == 1 ) ende = 1;
723 }
724 while( !ende );
725 }
726
special_target_mode(void)727 void special_target_mode(void)
728 {
729 struct vect v,p;
730 v.x = target.x - k[WHITE].p.x;
731 v.y = target.y - k[WHITE].p.y;
732 p.x = 1.0;
733 p.y = 0.0;
734 newstartx = 0.0;
735 newstarty = 0.0;
736 newstartz = -0.2;
737 newangz = 90.0 + (v.y < 0 ? 1 : -1) * 180.0/M_PI * acos(COSV(p,v));
738 newangx = -70.0;
739 newangy = 0.0;
740 newtransx = -(k[WHITE].p.x-0.5);
741 newtransy = -(k[WHITE].p.y-0.25);
742 newtransz = -6*RADIUS;
743 }
744
745 /* berechnet den Schwerpunkt der Kugeln, die der aktuelle Spieler
746 zu spielen hat und setzt den Target-Ball dorthin, �berpr�ft
747 daraufhin, ob dort Platz ist und verschiebt den Target Ball
748 so lange bis es "passt" oder eine gewisse Anzahl vo
749 Verschiebungszyklen abgelaufen ist */
calc_target_pos(int cur)750 void calc_target_pos(int cur)
751 {
752 int i, count=0, ok;
753 double dummy;
754 struct vect a;
755 target.x = 0;
756 target.y = 0;
757
758 switch( ply[cur].col )
759 {
760 case COL_BLACK:
761 target.x = k[BLACK].p.x;
762 target.y = k[BLACK].p.y;
763 break;
764 case COL_RED:
765 for(i=0;i<BALLS;i++)
766 {
767 if( (k[i].stat & ONTABLE) && (k[i].col == COL_RED) )
768 {
769 count ++;
770 target.x += k[i].p.x;
771 target.y += k[i].p.y;
772 }
773 }
774 target.x /= count;
775 target.y /= count;
776 break;
777 case COL_YELLOW:
778 for(i=0;i<BALLS;i++)
779 {
780 if( (k[i].stat & ONTABLE) && (k[i].col == COL_YELLOW) )
781 {
782 count ++;
783 target.x += k[i].p.x;
784 target.y += k[i].p.y;
785 }
786 }
787 target.x /= count;
788 target.y /= count;
789 break;
790 default:
791 for(i=0;i<BALLS;i++)
792 {
793 if( k[i].stat & ONTABLE )
794 {
795 count ++;
796 target.x += k[i].p.x;
797 target.y += k[i].p.y;
798 }
799 }
800 target.x /= (double)(count-1);
801 target.y /= (double)(count-1);
802 break;
803 }
804
805 do
806 {
807 ok=1;
808 for(i=0;i<=BALLS;i++)
809 {
810 a.x = k[i].p.x - target.x;
811 a.y = k[i].p.y - target.y;
812 if( SKALP(a,a) < 4.0*RADIUS*RADIUS )
813 {
814 a.x = k[WHITE].p.x - target.x;
815 a.y = k[WHITE].p.y - target.y;
816 dummy = BETR(a);
817 a.x /= dummy;
818 a.y /= dummy;
819 target.x += a.x * 2.0*RADIUS;
820 target.y += a.y * 2.0*RADIUS;
821 ok=0; break;
822 }
823 }
824 }
825 while( !ok && ++counter < 30 );
826 }
827
menu(void)828 int menu( void )
829 {
830 int i, ok=0, ret_wert=0;
831 double motionx, motiony, dummy;
832 int mousex, mousey;
833 char out[255], out2[128];
834 struct vect v;
835 gamemode &= (0xffff ^ PLAY_MODE); /* ungeschickt, eigentlich sowas wie MAXINT */
836 gamemode &= (0xffff ^ FREELOOK_MODE); /* ungeschickt, eigentlich sowas wie MAXINT */
837 wink( alph = 0.0 );
838 for( i=0;i<BALLS;i++) /* alle Kugeln neu initialisieren */
839 {
840 k[i].v.x = k[i].v.y = 0;
841 k[i].e.x = k[i].e.y = k[i].e.z = 0.0;
842 }
843 clear_rotation_matrix(WHITE); /* damit der SPIN-BALL rechts oben nicht verdreht ist... */
844 /* k[WHITE].rot.x = 0 -0*angx; */
845 /* k[WHITE].rot.y = -90.0+0*angy; */
846 /* k[WHITE].rot.z = 0 +angz; */
847 k[WHITE].stat ^= GL_LISTED_NOT_MOVING; /* damit der Treffpunkt des Queues neu gemalt wird... */
848 /* calc_rotation_inkl_z(WHITE); */
849
850 if( new_game ) title_screen();
851 if( k[WHITE].stat & DELETED ) set_white_ball(); /* Wei�e neu setzen */
852 if( cur == c_player ) { computer_stoss(); return ret_wert; }
853 ok = 0;
854 MSG2;
855 if( simulation_flag ) {target.x = undo_target.x; target.y = undo_target.y;}
856 else calc_target_pos(cur);
857 simulation_flag=0;
858
859 if( gamemode == TARGET_MODE )
860 gl_move_table(0.0f,0.0f,0.0f, 0.0f,0.0f,-0.985f, 10.0f, 0,0,0);
861 else if( gamemode == SPECIAL_TARGET_MODE )
862 {
863 special_target_mode();
864 gl_move_table(newangx,newangy,newangz,newstartx,newstarty,newstartz, 20.0f, newtransx, newtransy, newtransz);
865 }
866
867 PAINT_ALL;
868 mouse_off();
869 SDL_WarpMouse(SCREENRESX/2, SCREENRESY/2 );
870 do
871 {
872 do
873 {
874 while( SDL_PollEvent(&event) ); /* versteht kein Mensch... */
875 SDL_WaitEvent(&event);
876 }
877 while( !( (event.type == SDL_KEYDOWN) || (event.type == SDL_MOUSEBUTTONDOWN) ||
878 (event.type == SDL_MOUSEBUTTONUP) || (event.type == SDL_QUIT) ||
879 (event.type == SDL_MOUSEMOTION) || (event.type == SDL_SYSWMEVENT) ||
880 (event.type == 1) || (event.type == 17) ) );
881 switch( event.type )
882 {
883 case 1: case 17: PAINT_ALL; break; /* Window-Refresh n�tig */
884 case SDL_MOUSEMOTION:
885 {
886 if( !(gamemode & FREELOOK_MODE) )
887 {
888 SDL_GetMouseState(&mousex, &mousey);
889 SDL_WarpMouse(SCREENRESX/2, SCREENRESY/2 );
890 motionx = (double)(mousex-SCREENRESX/2) / (double)SCREENRESX;
891 motiony = (double)(mousey-SCREENRESY/2) / (double)SCREENRESX;
892 target.x += motionx * cos(angz * M_PI/180.0) -motiony * sin(angz * M_PI/180.0);
893 target.y -= motionx * sin(angz * M_PI/180.0) + motiony * cos(angz * M_PI/180.0);
894 for(i=0;i<BALLS;i++)
895 {
896 if( ABST(k[i].p,target) < RADIUS*RADIUS*4.0 ) /* funktioniert meistens, sieht ganz lustig aus ;-) */
897 {
898 v.x = k[i].p.x - target.x;
899 v.y = k[i].p.y - target.y;
900 dummy = BETR(v);
901 v.x /= dummy;
902 v.y /= dummy;
903 target.x = k[i].p.x - 2*RADIUS * v.x;
904 target.y = k[i].p.y - 2*RADIUS * v.y;
905 }
906 }
907 if( target.x > 1.0 - RADIUS ) target.x = 1.0-RADIUS;
908 if( target.y > 0.5 - RADIUS ) target.y = 0.5-RADIUS;
909 if( target.x < RADIUS ) target.x = RADIUS;
910 if( target.y < RADIUS ) target.y = RADIUS;
911 /* Abfrage, ob target zu nahe an Kugel ist noch machen... */
912 SDL_WarpMouse(SCREENRESX/2, SCREENRESY/2 );
913 if( gamemode & SPECIAL_TARGET_MODE )
914 {
915 special_target_mode();
916 startx = newstartx;
917 starty = newstarty;
918 startz = newstartz;
919 angx = newangx;
920 angy = newangy;
921 angz = newangz;
922 transx = newtransx;
923 transy = newtransy;
924 transz = newtransz;
925 }
926 PAINT_ALL;
927 }
928 else if( gamemode & FREELOOK_MODE )
929 {
930 angz+=(double)event.motion.xrel;
931 angx+=(double)event.motion.yrel;
932 SDL_WarpMouse(SCREENRESX/2, SCREENRESY/2);
933 PAINT_ALL;
934 break;
935 }
936 }
937 break; /* �u�eres switch, Ende von event.type == MOUSE_MOTION */
938 case SDL_QUIT: ok = ret_wert = 1; stop_it(); break;
939 case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP:
940 {
941 switch(event.button.button)
942 {
943 case SDL_BUTTON_LEFT: /* Sto�: Geschw. berechnen */
944 switch(gamemode)
945 {
946 case FREELOOK_MODE: /* erstmal ;-) */
947 case SPECIAL_TARGET_MODE:
948 case TARGET_MODE:
949 if( event.type == SDL_MOUSEBUTTONUP ) { calc_player_v(); ok = 1; gamemode |= PLAY_MODE; }
950 else ok=0;
951 break;
952 }
953 break;
954 case SDL_BUTTON_RIGHT: /* Geschwindigkeits (Power)-Faktor verstellen */
955 if( event.type == SDL_MOUSEBUTTONDOWN ) set_player_power();
956 break;
957 case SDL_BUTTON_MIDDLE: /* Spin einstellen */
958 if( event.type == SDL_MOUSEBUTTONDOWN ) set_player_spin(); break;
959 case 4: alph = ((alph+=0.5) > 90 ? 90 : alph); wink( alph ); break;
960 case 5: alph = ((alph-=0.5) < 0 ? 0 : alph); wink( alph ); break;
961 }
962 }
963 break;
964 case SDL_KEYDOWN:
965 {
966 switch( event.key.keysym.sym )
967 {
968 case SDLK_SPACE:
969 gamemode ^= FREELOOK_MODE;
970 if( gamemode & FREELOOK_MODE )
971 {
972 sprintf(current_message, "free look mode - move mouse to change view, ...");
973 sprintf(current_message2,"F1: help; press SPACE to return to target mode, ...");
974 }
975 else if( gamemode & TARGET_MODE )
976 {
977 sprintf(current_message, "target mode - move mouse to change the position of the target ball");
978 sprintf(current_message2,"F1: help; left button: cue, right button speed, ...");
979 }
980 else if( gamemode & SPECIAL_TARGET_MODE )
981 {
982 sprintf(current_message, "special target mode; press w to toggle normal mode");
983 sprintf(current_message2,"F1: help; left button: cue, right button speed, ...");
984 }
985 PAINT_ALL;
986 break;
987 case SDLK_F9:
988 ball_env_map++;
989 if( ball_env_map > 2 ) ball_env_map = 0;
990 gl_init_lists();
991 PAINT_ALL;
992 switch(ball_env_map)
993 {
994 case 0: sprintf(out2,"off"); break;
995 case 1: sprintf(out2,"cube"); break;
996 case 2: sprintf(out2,"sphere"); break;
997 }
998 sprintf(out,"ball environment mapping is set to %s\n",out2);
999 err(out);
1000 SDL_GL_SwapBuffers();
1001 break;
1002 case SDLK_F8:
1003 env_map = 1 - env_map;
1004 gl_init_lists();
1005 PAINT_ALL;
1006 sprintf(out,"environment mapping is set to %s\n",env_map == 0 ? "off" : "on");
1007 err(out);
1008 SDL_GL_SwapBuffers();
1009 break;
1010 case SDLK_F7:
1011 if( ++txt_detail > TEXTURE_HIGH ) txt_detail = TEXTURE_LOW;
1012 switch(txt_detail)
1013 {
1014 case TEXTURE_LOW: sprintf(out2,"low"); break;
1015 case TEXTURE_HIGH: sprintf(out2,"high"); break;
1016 }
1017 gl_init_lists();
1018 PAINT_ALL;
1019 sprintf(out,"texture detail level is set to %s\n",out2);
1020 err(out);
1021 SDL_GL_SwapBuffers();
1022 break;
1023 case SDLK_F6:
1024 if( (++shadows) > 3 ) shadows = 0;
1025 gl_init_lists();
1026 PAINT_ALL;
1027 switch(shadows)
1028 {
1029 case 0: sprintf(out2,"off"); break;
1030 case 1: sprintf(out2,"planar"); break;
1031 case 2: sprintf(out2,"stencil (alpha)"); break;
1032 case 3: sprintf(out2,"stencil (multi)"); break;
1033 }
1034 sprintf(out,"shadows set to %s\n",out2);
1035 err(out);
1036 SDL_GL_SwapBuffers();
1037 break;
1038 case SDLK_F5:
1039 if( ++geo_detail > DETAIL_VERYHIGH ) geo_detail = DETAIL_VERYLOW;
1040 switch(geo_detail)
1041 {
1042 case DETAIL_VERYLOW: sprintf(out2,"very low"); txt_detail = TEXTURE_LOW; break;
1043 case DETAIL_LOW: sprintf(out2,"low"); txt_detail = TEXTURE_LOW; break;
1044 case DETAIL_MED: sprintf(out2,"medium"); txt_detail = TEXTURE_LOW; break;
1045 case DETAIL_HIGH: sprintf(out2,"high"); txt_detail = TEXTURE_HIGH; break;
1046 case DETAIL_VERYHIGH: sprintf(out2,"very high"); txt_detail = TEXTURE_HIGH; break;
1047 }
1048 gl_init_lists();
1049 PAINT_ALL;
1050 sprintf(out,"geometric detail level is set to %s\n",out2);
1051 err(out);
1052 SDL_GL_SwapBuffers();
1053 break;
1054 case SDLK_F3:
1055 display_floor_textures ^= 1;
1056 gl_init_lists();
1057 PAINT_ALL;
1058 sprintf(out,"display of floor texture is set to %s\n",display_floor_textures ? "on" : "off");
1059 err(out);
1060 SDL_GL_SwapBuffers();
1061 break;
1062 case SDLK_F4:
1063 display_textures ^= 1;
1064 gl_init_lists();
1065 PAINT_ALL;
1066 sprintf(out,"display textures is set to %s\n",display_textures ? "on" : "off");
1067 err(out);
1068 SDL_GL_SwapBuffers();
1069 break;
1070 case SDLK_h:
1071 calc_player_v();
1072 ok = 1;
1073 simulation_flag=1;
1074 gamemode |= (SIMULATION_MODE|PLAY_MODE);
1075 break;
1076 case SDLK_t:
1077 gl_move_table(0.0,0.0,0.0, 0.0,0.0,-0.985, 50.0, 0, 0, 0);
1078 break;
1079 case SDLK_s:
1080 gl_move_table(-55.0,0.0,-90.0, 0.0,0.1,-0.9, 50.0, 0, 0, 0);
1081 break;
1082 case SDLK_l:
1083 gl_move_table(oldang.x,oldang.y,oldang.z, oldstart.x,oldstart.y,oldstart.z, 50.0f,
1084 oldtrans.x, oldtrans.y, oldtrans.z);
1085 break;
1086 case SDLK_KP2: newtranspos( 0.0, 0.003, 0.0, SDLK_KP2, 2); break;
1087 case SDLK_KP8: newtranspos( 0.0, -0.003, 0.0, SDLK_KP8, 2); break;
1088 case SDLK_KP6: newtranspos( -0.003, 0.0, 0.0, SDLK_KP6, 2); break;
1089 case SDLK_KP4: newtranspos( 0.003, 0.0, 0.0, SDLK_KP4, 2); break;
1090 case SDLK_w:
1091 gamemode = (gamemode == TARGET_MODE) ? SPECIAL_TARGET_MODE : TARGET_MODE;
1092 if( gamemode == SPECIAL_TARGET_MODE )
1093 {
1094 sprintf(current_message, "special target mode; press w to toggle normal mode");
1095 special_target_mode();
1096 gl_move_table(newangx, newangy, newangz, newstartx, newstarty, newstartz, 50.0,
1097 newtransx, newtransy, newtransz);
1098 PAINT_ALL;
1099 }
1100 else if( gamemode == TARGET_MODE )
1101 {
1102 sprintf(current_message, "target mode - move mouse to change the position of the target ball");
1103 gl_move_table(0.0,0.0,0.0, 0.0,0.0,-0.985, 50.0, 0,0,0);
1104 PAINT_ALL;
1105 }
1106 break;
1107 case SDLK_DOWN: newstartpos( 0.0, 0.003, 0.0, SDLK_DOWN, 2, -1); break;
1108 case SDLK_UP: newstartpos( 0.0, -0.003, 0.0, SDLK_UP, 2, -1); break;
1109 case SDLK_RIGHT: newstartpos( -0.003, 0.0, 0.0, SDLK_RIGHT, 2, -1); break;
1110 case SDLK_LEFT: newstartpos( 0.003, 0.0, 0.0, SDLK_LEFT, 2, -1); break;
1111 case SDLK_PAGEUP: newstartpos( 0.0, 0.0, 0.005, SDLK_PAGEUP, 2, -1); break;
1112 case SDLK_PAGEDOWN: newstartpos( 0.0, 0.0, -0.005, SDLK_PAGEDOWN, 2, -1); break;
1113 case SDLK_ESCAPE: ok = ret_wert = 1; break;
1114 case SDLK_n: /* new game */
1115 mouse_off();
1116 ply[1-cur].points += 1;
1117 stats[cur].losses += 1;
1118 cur = 1 - cur;
1119 delete_ball(WHITE, -1);
1120 init_table();
1121 ok = 1;
1122 break;
1123 case SDLK_u: /* undo last shot */
1124 undo();
1125 debug("undo...");
1126 PAINT_ALL;
1127 break;
1128 case SDLK_d:
1129 demo = 1;
1130 msg("press space or mouse button to stop demo");
1131 c_player = cur;
1132 last_gamemode = gamemode;
1133 gamemode = TARGET_MODE;
1134 gl_move_table(0.0,0.0,0.0, 0.0,0.0,-0.985, 50.0, 0,0,0);
1135 computer_stoss();
1136 ok = 1;
1137 break;
1138 case SDLK_y: gl_plotall(1); /* to make nicer screenshots ;-) */
1139 break;
1140 case SDLK_c: /* computer plays every shot*/
1141 if( c_player == -1 )
1142 {
1143 c_player = cur;
1144 last_gamemode = gamemode;
1145 gamemode = TARGET_MODE;
1146 gl_move_table(0.0,0.0,0.0, 0.0,0.0,-0.985, 50.0, 0,0,0);
1147 }
1148 else { c_player = -1; break; }
1149 case SDLK_x: /* let computer play one shot */
1150 computer_stoss();
1151 ok = 1;
1152 break;
1153 case SDLK_F11: if( ++table_color > 2 ) table_color = 0;
1154 gl_init_lists();
1155 PAINT_ALL;
1156 break;
1157 case SDLK_F12: plot_statistics( 0, 1 ); break;
1158 case SDLK_F1: help(); break; /* F1 */
1159 case SDLK_F2: credits(); break; /* F2 */
1160 case SDLK_f: showfps = 1-showfps; break;
1161 case SDLK_p: /* put away every ball except of white and eight ball ;-) */
1162 for( i=BLACK+1;i<WHITE;i++ ) delete_ball( i, -1 );
1163 for( i=0;i<BLACK;i++ ) delete_ball( i, -1 );
1164 break;
1165 case SDLK_e: mmouse = 1;
1166 test_spin();
1167 break;
1168 case SDLK_PLUS: alph = ((alph+=1) > 90 ? 90 : alph); wink( alph ); break;
1169 case SDLK_MINUS: alph = ((alph-=1) < 0 ? 0 : alph); wink( alph ); break;
1170 default: {}
1171 }
1172 }
1173 default: break;
1174 }
1175 }
1176 while( !ok );
1177 if( !ret_wert && !(gamemode & SIMULATION_MODE) )
1178 {
1179 if( !( gamemode & SPECIAL_TARGET_MODE) ) gl_move_table(-55.0,0.0,-90.0, 0.0,0.1,-0.9, 10.0, 0, 0, 0);
1180 else gl_move_table(angx,angy,angz,startx,starty,startz*3.0,10.0,transx,transy,transz);
1181 }
1182 mouse_off();
1183 return ret_wert;
1184 }
1185
delete_ball(int n,int pocket)1186 void delete_ball( int n, int pocket )
1187 /* Kugel "n" f�llt in Tasche und wird gel�scht; au�erdem wird gepr�ft, ob
1188 ein Foul durch das Versenken begangen wurde... Hatte der Spieler vor dem
1189 Versenken noch keine Farbe (Anfang des Spiels) so bekommt er hier diese */
1190 {
1191 k[n].stat = FALLING;
1192 k[n].v.z = 0.0;
1193 if( pocket >= 0 ) k[n].pocket = pocket;
1194 if( k[n].col == COL_WHITE ) ply[cur].stat |= FOUL_WHITE_POCKETED;
1195 else if( (k[n].col == COL_BLACK) && (ply[cur].col != COL_BLACK) )
1196 ply[cur].stat |= FOUL_BLACK_ILLEGALY_POCKETED;
1197 else if( !ply[cur].col && (k[n].col != COL_WHITE) )
1198 { /* falls noch keine Spieler-Farbe festgelegt ist */
1199 if( (k[n].col != COL_BLACK) && (ply[1-cur].col != k[n].col) )
1200 ply[cur].col = k[n].col;
1201 ply[1-cur].col = 3 - k[n].col;
1202 ply[cur].stat |= FOUL_CORRECT_POT;
1203 col_in = k[n].col;
1204 new_col |= NEW_COL_NEW;
1205 }
1206 else if( !freeball && (k[n].col != ply[cur].col) ) /* falsche Farbe */
1207 {
1208 if( new_col & NEW_COL_NEW ) new_col |= NEW_COL_DOUBLE;
1209 else ply[cur].stat |= FOUL_WRONG_COLOR_POCKETED;
1210 }
1211 else if( freeball || (k[n].col == ply[cur].col)) /* OK */
1212 ply[cur].stat |= FOUL_CORRECT_POT;
1213 bande_hit = 1;
1214 last_pocketed_balls++;
1215 }
1216
print(char * out,int align,int x,int y)1217 void print( char *out, int align, int x, int y )
1218 {
1219 /* GrDrawString( out, strlen(out), x, y, TEXTCOL ); */
1220 /* SDL_Flip(display); */
1221 }
1222
print2(char * out,int align,int x,int y)1223 void print2( char *out, int align, int x, int y )
1224 {
1225 /* GrDrawString( out, strlen(out), x, y, TEXTCOL ); */
1226 /* SDL_Flip(display); */
1227 }
1228
close_graphics(void)1229 void close_graphics( void )
1230 {
1231 glDeleteLists(257,2);
1232 glDeleteLists(260,BALLS);
1233 glDeleteLists(290,BALLS);
1234 glDeleteLists(280,2);
1235 atexit(SDL_Quit);
1236 }
1237
plot_statistics(double time,int grx)1238 void plot_statistics( double time, int grx )
1239 {
1240 int a=30;
1241 char out[256];
1242 if( SCREENRESX < 640) return;
1243 glDisable(GL_LIGHTING);
1244
1245 glColor4d(0.1,0.1,0.1,0.7);
1246 glEnable(GL_BLEND);
1247 glBegin(GL_POLYGON);
1248 glVertex3d( -2.0, -2.0, 2.1*RADIUS );
1249 glVertex3d( 2.0, -2.0, 2.1*RADIUS );
1250 glVertex3d( 2.0, 2.0, 2.1*RADIUS );
1251 glVertex3d( -2.0, 2.0, 2.1*RADIUS );
1252 glEnd();
1253
1254 glPrintCentered(768-(a+=90), "STATISTICS",0,1.0,1.0,1.0,1.0,5.0);
1255 glPrint(20,768-(a+=90)," Player",0,1.0,1.0,1.0,1.0,3.0);
1256 glPrint(605,768-a,"1",0,1.0,1.0,1.0,1.0,3.0);
1257 glPrint(725,768-a,"2",0,1.0,1.0,1.0,1.0,3.0);
1258 glPrint(20,768-(a+=70), "standings",0,1.0,1.0,1.0,1.0,sqrt(2.0));
1259 sprintf(out,"%5d", stats[0].wins+stats[1].losses);
1260 glPrint(545,768-a, out,0,1.0,1.0,1.0,1.0,sqrt(2.0));
1261 sprintf(out,"%5d", stats[1].wins+stats[0].losses);
1262 glPrint(665,768-a, out,0,1.0,1.0,1.0,1.0,sqrt(2.0));
1263
1264 sprintf(out,"-games won (correct play on black) %5d %5d",
1265 stats[0].wins, stats[1].wins);
1266 glPrint(20,768-(a+=50), out,0,1.0,1.0,1.0,1.0,1.0);
1267 sprintf(out,"-games lost ('direct' foul on black) %5d %5d",
1268 stats[0].losses, stats[1].losses );
1269 glPrint(20,768-(a+=30), out,0,1.0,1.0,1.0,1.0,1.0);
1270 sprintf(out,"number of pocketed balls %5d %5d",
1271 stats[0].pots, stats[1].pots );
1272 glPrint(20,768-(a+=70), out,0,1.0,1.0,1.0,1.0,1.0);
1273 sprintf(out,"no. of attempts without success %5d %5d",
1274 stats[0].nopots, stats[1].nopots );
1275 glPrint(20,768-(a+=30), out,0,1.0,1.0,1.0,1.0,1.0);
1276 sprintf(out,"fouls: wrong color touched %5d %5d",
1277 stats[0].fouls.wrongct, stats[1].fouls.wrongct );
1278 glPrint(20,768-(a+=30), out,0,1.0,1.0,1.0,1.0,1.0);
1279 sprintf(out,"fouls: wrong color pocketed %5d %5d",
1280 stats[0].fouls.wrongcp, stats[1].fouls.wrongcp );
1281 glPrint(20,768-(a+=30), out,0,1.0,1.0,1.0,1.0,1.0);
1282 sprintf(out,"fouls: white ball disappeared %5d %5d",
1283 stats[0].fouls.whited, stats[1].fouls.whited );
1284 glPrint(20,768-(a+=30), out,0,1.0,1.0,1.0,1.0,1.0);
1285 sprintf(out,"fouls: no ball or rail touched %5d %5d",
1286 stats[0].fouls.notouch, stats[1].fouls.notouch );
1287 glPrint(20,768-(a+=30), out,0,1.0,1.0,1.0,1.0,1.0);
1288 msg2("press an key or mouse button");
1289 SDL_GL_SwapBuffers();
1290 wait_for_click();
1291 PAINT_ALL;
1292 }
1293
help(void)1294 void help( void )
1295 {
1296 int a=30;
1297 if( SCREENRESX < 640) return;
1298 glDisable(GL_LIGHTING);
1299
1300 glColor4d(0.1,0.1,0.1,0.7);
1301 glEnable(GL_BLEND);
1302 glBegin(GL_POLYGON);
1303 glVertex3d( -2.0, -2.0, 2.1*RADIUS );
1304 glVertex3d( 2.0, -2.0, 2.1*RADIUS );
1305 glVertex3d( 2.0, 2.0, 2.1*RADIUS );
1306 glVertex3d( -2.0, 2.0, 2.1*RADIUS );
1307 glEnd();
1308
1309 glPrint(20,768-(a+=45), "HELP-Screen", 0, 1.0, 1.0, 1.0, 1.0,2.0);
1310 glPrint(20,768-(a+=40), "KEYS:", 0, 1.0, 1.0, 1.0, 1.0,sqrt(2.0));
1311 glPrint(20,768-(a+=35), " 'e': change spin, same as middle button", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1312 glPrint(20,768-(a+=35), " 'c': activate/deactivate computer opponent", 0, 1.0, 1.0, 1.0, 1.0,sqrt(2.0));
1313 glPrint(20,768-(a+=35), " 'x': let computer play next shot", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1314 glPrint(20,768-(a+=35), " 'n': new game, current game is lost", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1315 glPrint(20,768-(a+=35), " 'd': demo-mode on; any key to stop demo", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1316 glPrint(20,768-(a+=35), " 'u': undo last shot (no redo implemented)", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1317 glPrint(20,768-(a+=35), "SPACE: toggle free look mode on and off", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1318 glPrint(20,768-(a+=35), " 'c': center view on white ball", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1319 glPrint(20,768-(a+=35), " 'z': calculate end position immediately", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1320 glPrint(20,768-(a+=35), " 'w': toggle special target mode", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1321 glPrint(20,768-(a+=35), " 'h': simulation mode (test)", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1322 glPrint(20,768-(a+=35), " 'F4': switch texture display (on/off)", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1323 glPrint(20,768-(a+=35), " 'F5': switch geometric detail level (hi/lo)", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1324 glPrint(20,768-(a+=35), " 'F1': this screen", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1325 glPrint(20,768-(a+=35), " 'F2': credits", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1326 glPrint(20,768-(a+=35), "'F12': statistics", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1327 glPrint(20,768-(a+=30)," ESC: menu: quit game, computer player: stop", 0, 1.0, 1.0, 1.0, 1.0 ,sqrt(2.0));
1328 msg2("press an key or mouse button");
1329 SDL_GL_SwapBuffers();
1330 wait_for_click();
1331 PAINT_ALL;
1332 }
1333
credits(void)1334 void credits( void )
1335 {
1336 int a=30;
1337 char out[256];
1338 if( SCREENRESX < 640) return;
1339 glDisable(GL_LIGHTING);
1340
1341 glColor4d(0.1,0.1,0.1,0.7);
1342 glEnable(GL_BLEND);
1343 glBegin(GL_POLYGON);
1344 glVertex3d( -2.0, -2.0, 2.1*RADIUS );
1345 glVertex3d( 2.0, -2.0, 2.1*RADIUS );
1346 glVertex3d( 2.0, 2.0, 2.1*RADIUS );
1347 glVertex3d( -2.0, 2.0, 2.1*RADIUS );
1348 glEnd();
1349
1350 sprintf(out,"Another Pool GL");
1351 glPrint(20, 768-(a+=50), out, 0,1.0,1.0,1.0,1.0 ,3.0);
1352 sprintf(out," V %s, %s",VERSION, DATE);
1353 glPrint(20, 768-(a+=30), out, 0,1.0,1.0,1.0,1.0,sqrt(2.0));
1354 glPrint(20, 768-(a+=30), "copyright (c) 1995-2005 by Gerrit Jahn", 0,1.0,1.0,1.0,1.0 ,1.0);
1355 glPrint(20, 768-(a+=30), "http://www.planetjahn.de",0,1.0,1.0,1.0,1.0 ,1.0);
1356 glPrint(10, 768-(a+=80), "CREDITS", 0,1.0,1.0,1.0,1.0 ,sqrt(2.0));
1357 glPrint(10, 768-(a+=30), "------------------------------------------------------------------",0,1.0,1.0,1.0,1.0 ,1.0);
1358 glPrint(10, 768-(a+=30), "'ANOTHER POOL (GL)' is free software; you can redistribute it",0,1.0,1.0,1.0,1.0 ,1.0);
1359 glPrint(10, 768-(a+=30), "and/or modify it under the terms of the GNU General Public License",0,1.0,1.0,1.0,1.0 ,1.0);
1360 glPrint(10, 768-(a+=30), "as published by the Free Software Foundation; either version 2 of",0,1.0,1.0,1.0,1.0 ,1.0);
1361 glPrint(10, 768-(a+=30), "the License, or (at your option) any later version.",0,1.0,1.0,1.0,1.0 ,1.0);
1362 glPrint(10, 768-(a+=30), "Another Pool GL is distributed in the hope that it will be useful,",0,1.0,1.0,1.0,1.0 ,1.0);
1363 glPrint(10, 768-(a+=30), "but WITHOUT ANY WARRANTY; without even the implied warranty of",0,1.0,1.0,1.0,1.0 ,1.0);
1364 glPrint(10, 768-(a+=30), "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",0,1.0,1.0,1.0,1.0 ,1.0);
1365 glPrint(10, 768-(a+=30), "GNU General Public License (see file 'copying') for more details.",0,1.0,1.0,1.0,1.0 ,1.0);
1366 glPrint(10, 768-(a+=30), "------------------------------------------------------------------",0,1.0,1.0,1.0,1.0 ,1.0);
1367 glPrint(10, 768-(a+=30), "If you have any problems, questions or suggestions, look at the",0,1.0,1.0,1.0,1.0 ,1.0);
1368 glPrint(10, 768-(a+=30), "the homepage.",0,1.0,1.0,1.0,1.0 ,1.0);
1369 glPrint(10, 768-(a+=30), " have fun!",0,1.0,1.0,1.0,1.0 ,1.0);
1370 glPrint(10, 768-(a+=30), " ;-) Gerrit Jahn",0,1.0,1.0,1.0,1.0 ,1.0);
1371 msg2("press an key or mouse button");
1372 SDL_GL_SwapBuffers();
1373 wait_for_click();
1374 PAINT_ALL;
1375 }
1376
1377