rnd-20040820-1-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         switch(pos) {
57         case 0:
58                 switch(player_mode) {
59                 case 0: strcpy(buffer, "quit emerald mine"); break;
60                 case 1: strcpy(buffer, "single player"); break;
61                 case 2: strcpy(buffer, "teamwork"); break;
62                 }
63                 title_string(4, 0, 40, buffer);
64                 break;
65         case 1:
66                 sprintf(buffer, "name: %s", player_name);
67                 title_string(5, 0, 40, buffer);
68                 break;
69         case 2:
70                 sprintf(buffer, "level: %d", player_level);
71                 title_string(6, 0, 40, buffer);
72                 break;
73         case 3:
74                 title_string(7, 0, 40, "highscores");
75                 break;
76         case 4:
77                 title_string(8, 0, 40, "start");
78                 break;
79         case 5:
80                 title_string(10, 1, 13, "played");
81                 title_string(10, 14, 26, "score");
82                 title_string(10, 27, 39, "won");
83                 break;
84         case 6:
85                 sprintf(buffer, "%d", 0);
86                 title_string(11, 1, 13, buffer);
87                 sprintf(buffer, "%d", 0);
88                 title_string(11, 14, 26, buffer);
89                 sprintf(buffer, "%d", 0);
90                 title_string(11, 27, 39, buffer);
91                 break;
92         }
93 }
94
95 /* bring it all together */
96 int game_start(void)
97 {
98         int x,y;
99         char name[MAXNAME+2];
100         int temp;
101         int pos;
102
103         Random = 1684108901;
104
105         for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) Array[0][y][x] = ZBORDER;
106         for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) Array[1][y][x] = ZBORDER;
107         for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) Array[2][y][x] = ZBORDER;
108         for(y = 0; y < HEIGHT; y++) for(x = 0; x < WIDTH; x++) Array[3][y][x] = Xblank;
109
110         for(y = 0; y < HEIGHT; y++) Index[0][y] = Array[0][y];
111         for(y = 0; y < HEIGHT; y++) Index[1][y] = Array[1][y];
112         for(y = 0; y < HEIGHT; y++) Index[2][y] = Array[2][y];
113         for(y = 0; y < HEIGHT; y++) Index[3][y] = Array[3][y];
114
115         Cave = Index[0];
116         Next = Index[1];
117         Draw = Index[2];
118         Boom = Index[3];
119
120         player_mode = 1; /* start off as single player */
121         strcpy(player_name, "dave");
122         player_level = 0;
123
124         input_pause = 1    * 0;
125
126         for(;;) {
127
128                 pos = 4;
129
130                 title_initscreen();
131
132                 for(temp = 0; temp < 7; temp++) drawmenu(temp); /* display all lines */
133                 title_blitants(4 + pos);
134
135                 title_blitscore();
136                 title_animscreen();
137
138 #if 0
139                 printf("--> M1: xwindow == %ld\n", xwindow);
140 #endif
141
142                 temp = 1;
143                 for(;;) {
144                         input_eventloop();
145                         if(input_die) return(0);
146                         if(input_refresh) blitscreen();
147
148 #if 0
149                         printf("--> M2: xwindow == %ld\n", xwindow);
150 #endif
151
152                         if(!input_pause) {
153                                 title_blitants(4 + pos);
154                                 title_blitscore();
155                                 title_animscreen();
156
157 #if 0
158                                 printf("--> M3: xwindow == %ld\n", xwindow);
159 #endif
160
161                                 ply1.joy_n = ply1.joy_e = ply1.joy_s = ply1.joy_w = 0;
162
163                                 readjoy();
164
165                                 if(temp == 0) {
166                                         if(ply1.joy_fire) break;
167
168                                         if(ply1.joy_e && player_level < 99) {
169                                                 player_level++;
170                                                 drawmenu(2);
171                                         }
172                                         if(ply1.joy_w && player_level > 0) {
173                                                 player_level--;
174                                                 drawmenu(2);
175                                         }
176                                         if(ply1.joy_n && pos > 0) {
177                                                 drawmenu(pos);
178                                                 pos--;
179                                                 title_blitants(4 + pos);
180                                         }
181                                         if(ply1.joy_s && pos < 4) {
182                                                 drawmenu(pos);
183                                                 pos++;
184                                                 title_blitants(4 + pos);
185                                         }
186                                 }
187                                 temp = (ply1.joy_n || ply1.joy_e || ply1.joy_s || ply1.joy_w || ply1.joy_fire);
188                         }
189                 }
190
191 #if 0
192                 printf("--> M4: xwindow == %ld\n", xwindow);
193 #endif
194
195                 name[MAXNAME] = 0;
196                 snprintf(name, MAXNAME+2, "%s/lev%02d", EM_LVL_DIR, player_level);
197                 if(name[MAXNAME]) snprintf_overflow("read a level in cave/");
198
199                 if(cave_convert(name)) continue;
200
201 #if 0
202                 printf("--> M5: xwindow == %ld\n", xwindow);
203 #endif
204
205                 game_initscreen();
206 #if 0
207                 printf("--> M6: xwindow == %ld\n", xwindow);
208 #endif
209                 game_blitscore();
210 #if 0
211                 printf("--> M7: xwindow == %ld\n", xwindow);
212 #endif
213                 game_animscreen();
214
215 #if 0
216                 printf("--> M8: xwindow == %ld\n", xwindow);
217 #endif
218
219                 for(;;) {
220                         input_eventloop();
221                         if(input_die || input_esc) break;
222                         if(input_refresh) blitscreen();
223
224                         if(!input_pause) {
225                                 game_animscreen();
226
227                                 frame = (frame - 1) & 7;
228
229                                 readjoy();
230
231                                 if(frame == 7) {
232                                         synchro_1();
233                                         synchro_2();
234                                 }
235                                 if(frame == 6) {
236                                         synchro_3();
237                                         sound_play();
238                                         game_blitscore();
239                                 }
240                         }
241                 }
242         }
243 }
244
245 /* read input device for players
246  */
247 void readjoy(void)
248 {
249         unsigned int i;
250         unsigned int north = 0, east = 0, south = 0, west = 0, fire = 0;
251
252         for(i = 0; i < 3; i++) if(keymatrix[northKeyCode[i] >> 3] & 1 << (northKeyCode[i] & 7)) north = 1;
253         for(i = 0; i < 3; i++) if(keymatrix[eastKeyCode[i] >> 3] & 1 << (eastKeyCode[i] & 7)) east = 1;
254         for(i = 0; i < 3; i++) if(keymatrix[southKeyCode[i] >> 3] & 1 << (southKeyCode[i] & 7)) south = 1;
255         for(i = 0; i < 3; i++) if(keymatrix[westKeyCode[i] >> 3] & 1 << (westKeyCode[i] & 7)) west = 1;
256         for(i = 0; i < 3; i++) if(keymatrix[fireKeyCode[i] >> 3] & 1 << (fireKeyCode[i] & 7)) fire = 1;
257
258         ply1.joy_fire = fire;
259         if(ply1.joy_stick || (north | east | south | west)) {
260                 ply1.joy_n = north;
261                 ply1.joy_e = east;
262                 ply1.joy_s = south;
263                 ply1.joy_w = west;
264         }
265
266 #if 0
267         printf("::: JOY == %d/%d/%d/%d/%d\n",
268                north, east, south, west, fire);
269 #endif
270 }
271
272 /* handle events from x windows and block until the next frame
273  */
274 void input_eventloop(void)
275 {
276         XEvent event;
277         unsigned int i;
278         unsigned long count;
279
280         if(input_pause) {
281                 XPeekEvent(display, &event); /* block until an event arrives */
282
283                 if(gettimeofday(&tv1, 0) == -1) tv1.tv_usec = 0;
284         } else {
285                 XSync(display, False); /* block until all graphics are drawn */
286
287                 if(gettimeofday(&tv2, 0) == -1) tv2.tv_usec = 0;
288                 count = tv2.tv_usec + 1000000 - tv1.tv_usec; if(count >= 1000000) count -= 1000000;
289                 tv1.tv_usec = tv2.tv_usec;
290                 if(count < 25000) {
291                         tv2.tv_sec = 0;
292                         tv2.tv_usec = 25000 - count;
293 #if 1
294                         select(0, 0, 0, 0, &tv2); /* sleep a bit */
295 #else
296                         usleep(tv2.tv_usec);
297 #endif
298                 }
299         }
300
301         input_die = 0;
302         input_refresh = 0;
303         lastKeySym = NoSymbol;
304         while(XPending(display)) { /* drain the event queue */
305                 XNextEvent(display, &event);
306                 switch(event.xany.type) {
307                 case KeyPress:
308                         XLookupString(&event.xkey, (char *)&count, 1, &lastKeySym, 0);
309                         break;
310                 case Expose:
311                         if(event.xexpose.window == xwindow && event.xexpose.count == 0) input_refresh = 1;
312                         break;
313                 case ClientMessage:
314                         if(event.xclient.window == xwindow && (Atom)event.xclient.data.l[0] == deleteAtom) input_die = 1;
315                         break;
316                 case EnterNotify:
317                         if(event.xcrossing.window == xwindow) input_pause = 0;
318                         break;
319                 case LeaveNotify:
320                         if(event.xcrossing.window == xwindow) input_pause = 1;
321                         break;
322                 }
323         }
324         XQueryKeymap(display, keymatrix); /* read the keyboard */
325
326         input_esc = 0;
327         for(i = 0; i < 1; i++) if(keymatrix[escKeyCode[i] >> 3] & 1 << (escKeyCode[i] & 7)) input_esc = 1;
328 }
329
330 #endif