9c1681ffded48cf3e199ddab69ab451bc28c1dda
[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 player_level)
154 {
155   char name[MAXNAME+2];
156
157   name[MAXNAME] = 0;
158   snprintf(name, MAXNAME+2, "%s/lev%02d", EM_LVL_DIR, player_level);
159
160   if (name[MAXNAME])
161     snprintf_overflow("read a level in cave/");
162
163   if (cave_convert(name) != 0)
164     return 1;
165
166   game_initscreen();
167   game_blitscore();
168   game_animscreen();
169
170   return 0;
171 }
172
173 int game_menu_loop(boolean init, byte action)
174 {
175   static int temp = -1;
176   static int pos = -1;
177
178   if (init)
179   {
180     temp = 1;
181     pos = 4;
182
183     return 0;
184   }
185
186   input_eventloop();
187
188   if (input_die)
189     return 1;
190
191   if (input_refresh)
192     blitscreen();
193
194   if (!input_pause)
195   {
196     title_blitants(4 + pos);
197     title_blitscore();
198     title_animscreen();
199
200     ply1.joy_n = ply1.joy_e = ply1.joy_s = ply1.joy_w = 0;
201
202     readjoy(action);
203
204     if (temp == 0)
205     {
206       if (ply1.joy_fire)
207         return 2;
208
209       if (ply1.joy_e && player_level < 99)
210       {
211         player_level++;
212         drawmenu(2);
213       }
214
215       if (ply1.joy_w && player_level > 0)
216       {
217         player_level--;
218         drawmenu(2);
219       }
220
221       if (ply1.joy_n && pos > 0)
222       {
223         drawmenu(pos);
224         pos--;
225         title_blitants(4 + pos);
226       }
227
228       if (ply1.joy_s && pos < 4)
229       {
230         drawmenu(pos);
231         pos++;
232         title_blitants(4 + pos);
233       }
234     }
235
236     temp = (ply1.joy_n || ply1.joy_e || ply1.joy_s || ply1.joy_w ||
237             ply1.joy_fire);
238   }
239
240   return 0;
241 }
242
243 int game_play_loop(byte action)
244 {
245   input_eventloop();
246
247   if (input_die || input_esc)
248     return 1;
249
250   if (input_refresh)
251     blitscreen();
252
253   if (!input_pause)
254   {
255     game_animscreen();
256
257     frame = (frame - 1) & 7;
258
259     readjoy(action);
260
261 #if 1
262     if (input_esc)
263       return 1;
264 #endif
265
266     if (frame == 7)
267     {
268       synchro_1();
269       synchro_2();
270     }
271
272     if (frame == 6)
273     {
274       synchro_3();
275       sound_play();
276       game_blitscore();
277     }
278   }
279
280   return 0;
281 }
282
283 void game_menu_init(void)
284 {
285   int pos = 4;
286   int i;
287
288   title_initscreen();
289
290   for (i = 0; i < 7; i++)
291     drawmenu(i);                        /* display all lines */
292
293   title_blitants(4 + pos);
294   title_blitscore();
295   title_animscreen();
296
297   game_menu_loop(1, 0);
298 }
299
300 int game_loop(byte action)
301 {
302 #if 1
303
304 #if 0
305   printf("::: action == 0x%02x\n", action);
306 #endif
307
308   if (em_game_status == EM_GAME_STATUS_MENU)
309   {
310     int result = game_menu_loop(0, action);
311
312     if (result == 1)
313     {
314       /* exit program */
315
316       return 1;
317     }
318
319     if (result == 2)
320     {
321       /* start playing */
322
323       em_game_status = EM_GAME_STATUS_PLAY;
324       if (game_play_init(player_level) != 0)
325         em_game_status = EM_GAME_STATUS_MENU;
326     }
327   }
328   else if (em_game_status == EM_GAME_STATUS_PLAY)
329   {
330     if (game_play_loop(action) != 0)
331     {
332       /* stop playing */
333
334       if (skip_menu)
335         return 1;
336
337       em_game_status = EM_GAME_STATUS_MENU;
338       game_menu_init();
339     }
340   }
341
342   return 0;
343
344 #else
345
346   while (1)
347   {
348     int result = game_menu_loop(0);
349
350     if (result == 1)
351       return 1;
352
353     if (result == 2)
354       break;
355   }
356
357   em_game_status = EM_GAME_STATUS_PLAY;
358   if (game_play_init(player_level) != 0)
359     return 0;
360
361   while (1)
362   {
363     if (game_play_loop() != 0)
364       break;
365   }
366
367   em_game_status = EM_GAME_STATUS_MENU;
368   game_menu_init();
369
370   return 0;
371
372 #endif
373 }
374
375 /* read input device for players
376  */
377 void readjoy(byte action)
378 {
379   unsigned int north = 0, east = 0, south = 0, west = 0, fire = 0;
380
381 #if 1
382
383   if (action & JOY_LEFT)
384     west = 1;
385
386   if (action & JOY_RIGHT)
387     east = 1;
388
389   if (action & JOY_UP)
390     north = 1;
391
392   if (action & JOY_DOWN)
393     south = 1;
394
395   if (action & JOY_BUTTON_1)
396     fire = 1;
397
398   if (action & JOY_BUTTON_2)
399     input_esc = 1;
400
401 #else
402
403   unsigned int i;
404
405   for (i = 0; i < 3; i++)
406     if (keymatrix[northKeyCode[i] >> 3] & 1 << (northKeyCode[i] & 7))
407       north = 1;
408
409   for (i = 0; i < 3; i++)
410     if (keymatrix[eastKeyCode[i] >> 3] & 1 << (eastKeyCode[i] & 7))
411       east = 1;
412
413   for (i = 0; i < 3; i++)
414     if (keymatrix[southKeyCode[i] >> 3] & 1 << (southKeyCode[i] & 7))
415       south = 1;
416
417   for (i = 0; i < 3; i++)
418     if (keymatrix[westKeyCode[i] >> 3] & 1 << (westKeyCode[i] & 7))
419       west = 1;
420
421   for (i = 0; i < 3; i++)
422     if (keymatrix[fireKeyCode[i] >> 3] & 1 << (fireKeyCode[i] & 7))
423       fire = 1;
424 #endif
425
426   ply1.joy_fire = fire;
427   if (ply1.joy_stick || (north | east | south | west))
428   {
429     ply1.joy_n = north;
430     ply1.joy_e = east;
431     ply1.joy_s = south;
432     ply1.joy_w = west;
433   }
434 }
435
436 /* handle events from x windows and block until the next frame
437  */
438 void input_eventloop(void)
439 {
440 #if 0
441   XEvent event;
442 #endif
443   unsigned int i;
444   unsigned long count;
445
446   if (input_pause)
447   {
448 #if 0
449     XPeekEvent(display, &event); /* block until an event arrives */
450
451     if (gettimeofday(&tv1, 0) == -1)
452       tv1.tv_usec = 0;
453 #endif
454   }
455   else
456   {
457     XSync(display, False); /* block until all graphics are drawn */
458
459     if (gettimeofday(&tv2, 0) == -1)
460       tv2.tv_usec = 0;
461
462     count = tv2.tv_usec + 1000000 - tv1.tv_usec;
463     if (count >= 1000000)
464       count -= 1000000;
465
466     tv1.tv_usec = tv2.tv_usec;
467     if (count < 25000)
468     {
469       tv2.tv_sec = 0;
470       tv2.tv_usec = 25000 - count;
471 #if 1
472       select(0, 0, 0, 0, &tv2); /* sleep a bit */
473 #else
474       usleep(tv2.tv_usec);
475 #endif
476     }
477   }
478
479   input_die = 0;
480   input_refresh = 0;
481   lastKeySym = NoSymbol;
482
483 #if 0
484   while (XPending(display))
485   {
486     /* drain the event queue */
487     XNextEvent(display, &event);
488
489     switch(event.xany.type)
490     {
491       case KeyPress:
492         XLookupString(&event.xkey, (char *)&count, 1, &lastKeySym, 0);
493         break;
494
495       case Expose:
496         if (event.xexpose.window == xwindow && event.xexpose.count == 0)
497           input_refresh = 1;
498         break;
499
500       case ClientMessage:
501         if (event.xclient.window == xwindow &&
502             (Atom)event.xclient.data.l[0] == deleteAtom)
503           input_die = 1;
504         break;
505
506       case EnterNotify:
507         if (event.xcrossing.window == xwindow)
508           input_pause = 0;
509         break;
510
511       case LeaveNotify:
512         if (event.xcrossing.window == xwindow)
513           input_pause = 1;
514         break;
515     }
516   }
517
518   XQueryKeymap(display, keymatrix); /* read the keyboard */
519 #endif
520
521   input_esc = 0;
522   for (i = 0; i < 1; i++)
523     if (keymatrix[escKeyCode[i] >> 3] & 1 << (escKeyCode[i] & 7))
524       input_esc = 1;
525 }
526
527 #endif