rnd-20040821-2-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, 1, 13, "played");
98       title_string(10, 14, 26, "score");
99       title_string(10, 27, 39, "won");
100       break;
101
102     case 6:
103       sprintf(buffer, "%d", 0);
104       title_string(11, 1, 13, buffer);
105       sprintf(buffer, "%d", 0);
106       title_string(11, 14, 26, buffer);
107       sprintf(buffer, "%d", 0);
108       title_string(11, 27, 39, buffer);
109       break;
110   }
111 }
112
113 /* bring it all together */
114 int game_start(void)
115 {
116   int x,y;
117   char name[MAXNAME+2];
118   int temp;
119   int pos;
120
121   Random = 1684108901;
122
123   for (y = 0; y < HEIGHT; y++)
124     for (x = 0; x < WIDTH; x++)
125       Array[0][y][x] = ZBORDER;
126   for (y = 0; y < HEIGHT; y++)
127     for (x = 0; x < WIDTH; x++)
128       Array[1][y][x] = ZBORDER;
129   for (y = 0; y < HEIGHT; y++)
130     for (x = 0; x < WIDTH; x++)
131       Array[2][y][x] = ZBORDER;
132   for (y = 0; y < HEIGHT; y++)
133     for (x = 0; x < WIDTH; x++)
134       Array[3][y][x] = Xblank;
135
136   for (y = 0; y < HEIGHT; y++)
137     Index[0][y] = Array[0][y];
138   for (y = 0; y < HEIGHT; y++)
139     Index[1][y] = Array[1][y];
140   for (y = 0; y < HEIGHT; y++)
141     Index[2][y] = Array[2][y];
142   for (y = 0; y < HEIGHT; y++)
143     Index[3][y] = Array[3][y];
144
145   Cave = Index[0];
146   Next = Index[1];
147   Draw = Index[2];
148   Boom = Index[3];
149
150   player_mode = 1;                      /* start off as single player */
151   strcpy(player_name, "dave");
152   player_level = 0;
153
154   input_pause = 1    * 0;
155
156   while (1)
157   {
158     pos = 4;
159
160     title_initscreen();
161
162     for (temp = 0; temp < 7; temp++)
163       drawmenu(temp);                   /* display all lines */
164
165     title_blitants(4 + pos);
166
167     title_blitscore();
168     title_animscreen();
169
170     temp = 1;
171     while (1)
172     {
173       input_eventloop();
174       if (input_die) return(0);
175       if (input_refresh) blitscreen();
176
177       if (!input_pause)
178       {
179         title_blitants(4 + pos);
180         title_blitscore();
181         title_animscreen();
182
183         ply1.joy_n = ply1.joy_e = ply1.joy_s = ply1.joy_w = 0;
184
185         readjoy();
186
187         if (temp == 0)
188         {
189           if (ply1.joy_fire)
190             break;
191
192           if (ply1.joy_e && player_level < 99)
193           {
194             player_level++;
195             drawmenu(2);
196           }
197
198           if (ply1.joy_w && player_level > 0)
199           {
200             player_level--;
201             drawmenu(2);
202           }
203
204           if (ply1.joy_n && pos > 0)
205           {
206             drawmenu(pos);
207             pos--;
208             title_blitants(4 + pos);
209           }
210
211           if (ply1.joy_s && pos < 4)
212           {
213             drawmenu(pos);
214             pos++;
215             title_blitants(4 + pos);
216           }
217         }
218
219         temp = (ply1.joy_n ||
220                 ply1.joy_e ||
221                 ply1.joy_s ||
222                 ply1.joy_w ||
223                 ply1.joy_fire);
224       }
225     }
226
227     name[MAXNAME] = 0;
228     snprintf(name, MAXNAME+2, "%s/lev%02d", EM_LVL_DIR, player_level);
229
230     if (name[MAXNAME])
231       snprintf_overflow("read a level in cave/");
232
233     if (cave_convert(name))
234       continue;
235
236     game_initscreen();
237     game_blitscore();
238     game_animscreen();
239
240     while (1)
241     {
242       input_eventloop();
243
244       if (input_die || input_esc)
245         break;
246
247       if (input_refresh)
248         blitscreen();
249
250       if (!input_pause)
251       {
252         game_animscreen();
253
254         frame = (frame - 1) & 7;
255
256         readjoy();
257
258         if (frame == 7)
259         {
260           synchro_1();
261           synchro_2();
262         }
263
264         if (frame == 6)
265         {
266           synchro_3();
267           sound_play();
268           game_blitscore();
269         }
270       }
271     }
272   }
273 }
274
275 /* read input device for players
276  */
277 void readjoy(void)
278 {
279   unsigned int i;
280   unsigned int north = 0, east = 0, south = 0, west = 0, fire = 0;
281
282   for (i = 0; i < 3; i++)
283     if (keymatrix[northKeyCode[i] >> 3] & 1 << (northKeyCode[i] & 7))
284       north = 1;
285
286   for (i = 0; i < 3; i++)
287     if (keymatrix[eastKeyCode[i] >> 3] & 1 << (eastKeyCode[i] & 7))
288       east = 1;
289
290   for (i = 0; i < 3; i++)
291     if (keymatrix[southKeyCode[i] >> 3] & 1 << (southKeyCode[i] & 7))
292       south = 1;
293
294   for (i = 0; i < 3; i++)
295     if (keymatrix[westKeyCode[i] >> 3] & 1 << (westKeyCode[i] & 7))
296       west = 1;
297
298   for (i = 0; i < 3; i++)
299     if (keymatrix[fireKeyCode[i] >> 3] & 1 << (fireKeyCode[i] & 7))
300       fire = 1;
301
302   ply1.joy_fire = fire;
303   if (ply1.joy_stick || (north | east | south | west))
304   {
305     ply1.joy_n = north;
306     ply1.joy_e = east;
307     ply1.joy_s = south;
308     ply1.joy_w = west;
309   }
310 }
311
312 /* handle events from x windows and block until the next frame
313  */
314 void input_eventloop(void)
315 {
316   XEvent event;
317   unsigned int i;
318   unsigned long count;
319
320   if (input_pause)
321   {
322     XPeekEvent(display, &event); /* block until an event arrives */
323
324     if (gettimeofday(&tv1, 0) == -1)
325       tv1.tv_usec = 0;
326   }
327   else
328   {
329     XSync(display, False); /* block until all graphics are drawn */
330
331     if (gettimeofday(&tv2, 0) == -1)
332       tv2.tv_usec = 0;
333
334     count = tv2.tv_usec + 1000000 - tv1.tv_usec;
335     if (count >= 1000000)
336       count -= 1000000;
337
338     tv1.tv_usec = tv2.tv_usec;
339     if (count < 25000)
340     {
341       tv2.tv_sec = 0;
342       tv2.tv_usec = 25000 - count;
343 #if 1
344       select(0, 0, 0, 0, &tv2); /* sleep a bit */
345 #else
346       usleep(tv2.tv_usec);
347 #endif
348     }
349   }
350
351   input_die = 0;
352   input_refresh = 0;
353   lastKeySym = NoSymbol;
354
355   while (XPending(display))
356   {
357     /* drain the event queue */
358     XNextEvent(display, &event);
359
360     switch(event.xany.type)
361     {
362       case KeyPress:
363         XLookupString(&event.xkey, (char *)&count, 1, &lastKeySym, 0);
364         break;
365
366       case Expose:
367         if (event.xexpose.window == xwindow && event.xexpose.count == 0)
368           input_refresh = 1;
369         break;
370
371       case ClientMessage:
372         if (event.xclient.window == xwindow &&
373             (Atom)event.xclient.data.l[0] == deleteAtom)
374           input_die = 1;
375         break;
376
377       case EnterNotify:
378         if (event.xcrossing.window == xwindow)
379           input_pause = 0;
380         break;
381
382       case LeaveNotify:
383         if (event.xcrossing.window == xwindow)
384           input_pause = 1;
385         break;
386     }
387   }
388
389   XQueryKeymap(display, keymatrix); /* read the keyboard */
390
391   input_esc = 0;
392   for (i = 0; i < 1; i++)
393     if (keymatrix[escKeyCode[i] >> 3] & 1 << (escKeyCode[i] & 7))
394       input_esc = 1;
395 }
396
397 #endif