rnd-20040822-3-src
[rocksndiamonds.git] / src / game_em / input.c
1 /* 2000-08-13T15:29:40Z
2  *
3  * handle input from x11 and keyboard and joystick
4  */
5
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/Xatom.h>
9 #include <X11/keysym.h>
10 #include <sys/time.h>
11 #include <sys/types.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #include "global.h"
19 #include "display.h"
20 #include "level.h"
21
22
23 #if defined(TARGET_X11)
24
25 unsigned long Random;
26
27 struct PLAYER ply1;
28 struct PLAYER ply2;
29 struct LEVEL lev;
30
31 unsigned short **Boom;
32 unsigned short **Cave;
33 unsigned short **Next;
34 unsigned short **Draw;
35
36 static unsigned short *Index[4][HEIGHT];
37 static unsigned short Array[4][HEIGHT][WIDTH];
38
39 static int input_die;
40 static int input_pause;
41 static int input_refresh;
42 static int input_esc;
43
44 static struct timeval tv1;
45 static struct timeval tv2;
46
47 static unsigned char keymatrix[32];
48
49 static int player_mode;
50 static char player_name[32];
51 static int player_level;
52
53 static void drawmenu(int pos)
54 {
55   char buffer[256];
56
57   switch(pos)
58   {
59     case 0:
60       switch(player_mode)
61       {
62         case 0:
63           strcpy(buffer, "quit emerald mine");
64           break;
65
66         case 1:
67           strcpy(buffer, "single player");
68           break;
69
70         case 2:
71           strcpy(buffer, "teamwork");
72           break;
73       }
74
75       title_string(4, 0, 40, buffer);
76       break;
77
78     case 1:
79       sprintf(buffer, "name: %s", player_name);
80       title_string(5, 0, 40, buffer);
81       break;
82
83     case 2:
84       sprintf(buffer, "level: %d", player_level);
85       title_string(6, 0, 40, buffer);
86       break;
87
88     case 3:
89       title_string(7, 0, 40, "highscores");
90       break;
91
92     case 4:
93       title_string(8, 0, 40, "start");
94       break;
95
96     case 5:
97       title_string(10, 3, 13, "played");
98       title_string(10, 14, 26, "score");
99       title_string(10, 27, 37, "won");
100       break;
101
102     case 6:
103       sprintf(buffer, "%d", 0);
104       title_string(11, 3, 13, buffer);
105       sprintf(buffer, "%d", 0);
106       title_string(11, 14, 26, buffer);
107       sprintf(buffer, "%d", 0);
108       title_string(11, 27, 37, buffer);
109       break;
110   }
111 }
112
113 void game_init_vars(void)
114 {
115   int x, y;
116
117   Random = 1684108901;
118
119   for (y = 0; y < HEIGHT; y++)
120     for (x = 0; x < WIDTH; x++)
121       Array[0][y][x] = ZBORDER;
122   for (y = 0; y < HEIGHT; y++)
123     for (x = 0; x < WIDTH; x++)
124       Array[1][y][x] = ZBORDER;
125   for (y = 0; y < HEIGHT; y++)
126     for (x = 0; x < WIDTH; x++)
127       Array[2][y][x] = ZBORDER;
128   for (y = 0; y < HEIGHT; y++)
129     for (x = 0; x < WIDTH; x++)
130       Array[3][y][x] = Xblank;
131
132   for (y = 0; y < HEIGHT; y++)
133     Index[0][y] = Array[0][y];
134   for (y = 0; y < HEIGHT; y++)
135     Index[1][y] = Array[1][y];
136   for (y = 0; y < HEIGHT; y++)
137     Index[2][y] = Array[2][y];
138   for (y = 0; y < HEIGHT; y++)
139     Index[3][y] = Array[3][y];
140
141   Cave = Index[0];
142   Next = Index[1];
143   Draw = Index[2];
144   Boom = Index[3];
145
146   player_mode = 1;                      /* start off as single player */
147   strcpy(player_name, "dave");
148   player_level = 0;
149
150   input_pause = 1    * 0;
151 }
152
153 int game_play_init(int level_nr, char *filename)
154 {
155   if (filename != NULL)
156   {
157     player_level = level_nr;
158
159     if (cave_convert(filename) != 0)
160       return 1;
161   }
162   else  /* !!! SOON OBSOLETE !!! */
163   {
164     char name[MAXNAME+2];
165
166     name[MAXNAME] = 0;
167     snprintf(name, MAXNAME+2, "%s/lev%02d", EM_LVL_DIR, player_level);
168
169     if (name[MAXNAME])
170       snprintf_overflow("read a level in cave/");
171
172     if (cave_convert(name) != 0)
173       return 1;
174   }
175
176   game_initscreen();
177   game_blitscore();
178   game_animscreen();
179
180   return 0;
181 }
182
183 int game_menu_loop(boolean init, byte action)
184 {
185   static int temp = -1;
186   static int pos = -1;
187
188   if (init)
189   {
190     temp = 1;
191     pos = 4;
192
193     return 0;
194   }
195
196   input_eventloop();
197
198   if (input_die)
199     return 1;
200
201   if (input_refresh)
202     blitscreen();
203
204   if (!input_pause)
205   {
206     title_blitants(4 + pos);
207     title_blitscore();
208     title_animscreen();
209
210     ply1.joy_n = ply1.joy_e = ply1.joy_s = ply1.joy_w = 0;
211
212     readjoy(action);
213
214     if (temp == 0)
215     {
216       if (ply1.joy_fire)
217         return 2;
218
219       if (ply1.joy_e && player_level < 99)
220       {
221         player_level++;
222         drawmenu(2);
223       }
224
225       if (ply1.joy_w && player_level > 0)
226       {
227         player_level--;
228         drawmenu(2);
229       }
230
231       if (ply1.joy_n && pos > 0)
232       {
233         drawmenu(pos);
234         pos--;
235         title_blitants(4 + pos);
236       }
237
238       if (ply1.joy_s && pos < 4)
239       {
240         drawmenu(pos);
241         pos++;
242         title_blitants(4 + pos);
243       }
244     }
245
246     temp = (ply1.joy_n || ply1.joy_e || ply1.joy_s || ply1.joy_w ||
247             ply1.joy_fire);
248   }
249
250   return 0;
251 }
252
253 int game_play_loop(byte action)
254 {
255   input_eventloop();
256
257   if (input_die || input_esc)
258     return 1;
259
260   if (input_refresh)
261     blitscreen();
262
263   if (!input_pause)
264   {
265     game_animscreen();
266
267     frame = (frame - 1) & 7;
268
269     readjoy(action);
270
271 #if 1
272     if (input_esc)
273       return 1;
274 #endif
275
276     if (frame == 7)
277     {
278       synchro_1();
279       synchro_2();
280     }
281
282     if (frame == 6)
283     {
284       synchro_3();
285       sound_play();
286       game_blitscore();
287     }
288   }
289
290   return 0;
291 }
292
293 void game_menu_init(void)
294 {
295   int pos = 4;
296   int i;
297
298   title_initscreen();
299
300   for (i = 0; i < 7; i++)
301     drawmenu(i);                        /* display all lines */
302
303   title_blitants(4 + pos);
304   title_blitscore();
305   title_animscreen();
306
307   game_menu_loop(1, 0);
308 }
309
310 int game_loop(byte action)
311 {
312 #if 1
313
314 #if 0
315   printf("::: action == 0x%02x\n", action);
316 #endif
317
318   if (em_game_status == EM_GAME_STATUS_MENU)
319   {
320     int result = game_menu_loop(0, action);
321
322     if (result == 1)
323     {
324       /* exit program */
325
326       return 1;
327     }
328
329     if (result == 2)
330     {
331       /* start playing */
332
333       em_game_status = EM_GAME_STATUS_PLAY;
334       if (game_play_init(player_level, NULL) != 0)
335         em_game_status = EM_GAME_STATUS_MENU;
336     }
337   }
338   else if (em_game_status == EM_GAME_STATUS_PLAY)
339   {
340     if (game_play_loop(action) != 0)
341     {
342       /* stop playing */
343
344       if (skip_menu)
345         return 1;
346
347       em_game_status = EM_GAME_STATUS_MENU;
348       game_menu_init();
349     }
350   }
351
352   return 0;
353
354 #else
355
356   while (1)
357   {
358     int result = game_menu_loop(0);
359
360     if (result == 1)
361       return 1;
362
363     if (result == 2)
364       break;
365   }
366
367   em_game_status = EM_GAME_STATUS_PLAY;
368   if (game_play_init(player_level) != 0)
369     return 0;
370
371   while (1)
372   {
373     if (game_play_loop() != 0)
374       break;
375   }
376
377   em_game_status = EM_GAME_STATUS_MENU;
378   game_menu_init();
379
380   return 0;
381
382 #endif
383 }
384
385 /* read input device for players
386  */
387 void readjoy(byte action)
388 {
389   unsigned int north = 0, east = 0, south = 0, west = 0, fire = 0;
390
391 #if 1
392
393   if (action & JOY_LEFT)
394     west = 1;
395
396   if (action & JOY_RIGHT)
397     east = 1;
398
399   if (action & JOY_UP)
400     north = 1;
401
402   if (action & JOY_DOWN)
403     south = 1;
404
405   if (action & JOY_BUTTON_1)
406     fire = 1;
407
408   if (action & JOY_BUTTON_2)
409     input_esc = 1;
410
411 #else
412
413   unsigned int i;
414
415   for (i = 0; i < 3; i++)
416     if (keymatrix[northKeyCode[i] >> 3] & 1 << (northKeyCode[i] & 7))
417       north = 1;
418
419   for (i = 0; i < 3; i++)
420     if (keymatrix[eastKeyCode[i] >> 3] & 1 << (eastKeyCode[i] & 7))
421       east = 1;
422
423   for (i = 0; i < 3; i++)
424     if (keymatrix[southKeyCode[i] >> 3] & 1 << (southKeyCode[i] & 7))
425       south = 1;
426
427   for (i = 0; i < 3; i++)
428     if (keymatrix[westKeyCode[i] >> 3] & 1 << (westKeyCode[i] & 7))
429       west = 1;
430
431   for (i = 0; i < 3; i++)
432     if (keymatrix[fireKeyCode[i] >> 3] & 1 << (fireKeyCode[i] & 7))
433       fire = 1;
434 #endif
435
436   ply1.joy_fire = fire;
437   if (ply1.joy_stick || (north | east | south | west))
438   {
439     ply1.joy_n = north;
440     ply1.joy_e = east;
441     ply1.joy_s = south;
442     ply1.joy_w = west;
443   }
444 }
445
446 /* handle events from x windows and block until the next frame
447  */
448 void input_eventloop(void)
449 {
450 #if 0
451   XEvent event;
452 #endif
453   unsigned int i;
454   unsigned long count;
455
456   if (input_pause)
457   {
458 #if 0
459     XPeekEvent(display, &event); /* block until an event arrives */
460
461     if (gettimeofday(&tv1, 0) == -1)
462       tv1.tv_usec = 0;
463 #endif
464   }
465   else
466   {
467     XSync(display, False); /* block until all graphics are drawn */
468
469     if (gettimeofday(&tv2, 0) == -1)
470       tv2.tv_usec = 0;
471
472     count = tv2.tv_usec + 1000000 - tv1.tv_usec;
473     if (count >= 1000000)
474       count -= 1000000;
475
476     tv1.tv_usec = tv2.tv_usec;
477     if (count < 25000)
478     {
479       tv2.tv_sec = 0;
480       tv2.tv_usec = 25000 - count;
481 #if 1
482       select(0, 0, 0, 0, &tv2); /* sleep a bit */
483 #else
484       usleep(tv2.tv_usec);
485 #endif
486     }
487   }
488
489   input_die = 0;
490   input_refresh = 0;
491   lastKeySym = NoSymbol;
492
493 #if 0
494   while (XPending(display))
495   {
496     /* drain the event queue */
497     XNextEvent(display, &event);
498
499     switch(event.xany.type)
500     {
501       case KeyPress:
502         XLookupString(&event.xkey, (char *)&count, 1, &lastKeySym, 0);
503         break;
504
505       case Expose:
506         if (event.xexpose.window == xwindow && event.xexpose.count == 0)
507           input_refresh = 1;
508         break;
509
510       case ClientMessage:
511         if (event.xclient.window == xwindow &&
512             (Atom)event.xclient.data.l[0] == deleteAtom)
513           input_die = 1;
514         break;
515
516       case EnterNotify:
517         if (event.xcrossing.window == xwindow)
518           input_pause = 0;
519         break;
520
521       case LeaveNotify:
522         if (event.xcrossing.window == xwindow)
523           input_pause = 1;
524         break;
525     }
526   }
527
528   XQueryKeymap(display, keymatrix); /* read the keyboard */
529 #endif
530
531   input_esc = 0;
532   for (i = 0; i < 1; i++)
533     if (keymatrix[escKeyCode[i] >> 3] & 1 << (escKeyCode[i] & 7))
534       input_esc = 1;
535 }
536
537 #endif