rnd-20040917-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 struct LevelInfo_EM native_em_level;
32
33 unsigned short **Boom;
34 unsigned short **Cave;
35 unsigned short **Next;
36 unsigned short **Draw;
37
38 static unsigned short *Index[4][HEIGHT];
39 static unsigned short Array[4][HEIGHT][WIDTH];
40
41 static int input_die;
42 static int input_pause;
43 static int input_refresh;
44 static int input_esc;
45
46 static struct timeval tv1;
47 static struct timeval tv2;
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 0
156   if (filename != NULL)
157   {
158 #endif
159
160     player_level = level_nr;
161
162 #if 1
163     prepare_em_level();
164 #else
165     if (!LoadNativeLevel_EM(filename))
166       return 1;
167 #endif
168
169 #if 0
170   }
171   else  /* !!! SOON OBSOLETE !!! */
172   {
173     char name[MAXNAME+2];
174
175     name[MAXNAME] = 0;
176     snprintf(name, MAXNAME+2, "%s/lev%02d", EM_LVL_DIR, player_level);
177
178     if (name[MAXNAME])
179       snprintf_overflow("read a level in cave/");
180
181     if (cave_convert(name) != 0)
182       return 1;
183   }
184 #endif
185
186   game_initscreen();
187   game_blitscore();
188   game_animscreen();
189
190   return 0;
191 }
192
193 int game_menu_loop(boolean init, byte action)
194 {
195   static int temp = -1;
196   static int pos = -1;
197
198   if (init)
199   {
200     temp = 1;
201     pos = 4;
202
203     return 0;
204   }
205
206   input_eventloop();
207
208   if (input_die)
209     return 1;
210
211   if (input_refresh)
212     blitscreen();
213
214   if (!input_pause)
215   {
216     title_blitscore();
217     title_animscreen();
218
219     ply1.joy_n = ply1.joy_e = ply1.joy_s = ply1.joy_w = 0;
220
221     readjoy(action);
222
223     if (temp == 0)
224     {
225       if (ply1.joy_fire)
226         return 2;
227
228       if (ply1.joy_e && player_level < 99)
229       {
230         player_level++;
231         drawmenu(2);
232       }
233
234       if (ply1.joy_w && player_level > 0)
235       {
236         player_level--;
237         drawmenu(2);
238       }
239
240       if (ply1.joy_n && pos > 0)
241       {
242         drawmenu(pos);
243         pos--;
244       }
245
246       if (ply1.joy_s && pos < 4)
247       {
248         drawmenu(pos);
249         pos++;
250       }
251     }
252
253     temp = (ply1.joy_n || ply1.joy_e || ply1.joy_s || ply1.joy_w ||
254             ply1.joy_fire);
255   }
256
257   return 0;
258 }
259
260 int game_play_loop(byte action)
261 {
262   input_eventloop();
263
264   if (input_die || input_esc)
265     return 1;
266
267   if (input_refresh)
268     blitscreen();
269
270   if (!input_pause)
271   {
272     game_animscreen();
273
274     frame = (frame - 1) & 7;
275
276     readjoy(action);
277
278 #if 1
279     if (input_esc)
280       return 1;
281 #endif
282
283     if (frame == 7)
284     {
285       synchro_1();
286       synchro_2();
287     }
288
289     if (frame == 6)
290     {
291       synchro_3();
292       sound_play();
293       game_blitscore();
294     }
295   }
296
297   return 0;
298 }
299
300 void game_menu_init(void)
301 {
302   int i;
303
304   title_initscreen();
305
306   for (i = 0; i < 7; i++)
307     drawmenu(i);                        /* display all lines */
308
309   title_blitscore();
310   title_animscreen();
311
312   game_menu_loop(1, 0);
313 }
314
315 int game_loop(byte action)
316 {
317 #if 0
318   printf("::: action == 0x%02x\n", action);
319 #endif
320
321   if (em_game_status == EM_GAME_STATUS_MENU)
322   {
323     int result = game_menu_loop(0, action);
324
325     if (result == 1)
326     {
327       /* exit program */
328
329       return 1;
330     }
331
332     if (result == 2)
333     {
334       /* start playing */
335
336       em_game_status = EM_GAME_STATUS_PLAY;
337       if (game_play_init(player_level, NULL) != 0)
338         em_game_status = EM_GAME_STATUS_MENU;
339     }
340   }
341   else if (em_game_status == EM_GAME_STATUS_PLAY)
342   {
343     if (game_play_loop(action) != 0)
344     {
345       /* stop playing */
346
347       if (skip_menu)
348         return 1;
349
350       em_game_status = EM_GAME_STATUS_MENU;
351       game_menu_init();
352     }
353   }
354
355   return 0;
356 }
357
358
359 /* read input device for players */
360
361 void readjoy(byte action)
362 {
363   unsigned int north = 0, east = 0, south = 0, west = 0, fire = 0;
364
365   if (action & JOY_LEFT)
366     west = 1;
367
368   if (action & JOY_RIGHT)
369     east = 1;
370
371   if (action & JOY_UP)
372     north = 1;
373
374   if (action & JOY_DOWN)
375     south = 1;
376
377   if (action & JOY_BUTTON_1)
378     fire = 1;
379
380 #if 0
381   if (action & JOY_BUTTON_2)
382     input_esc = 1;
383 #endif
384
385   ply1.joy_fire = fire;
386   if (ply1.joy_stick || (north | east | south | west))
387   {
388     ply1.joy_n = north;
389     ply1.joy_e = east;
390     ply1.joy_s = south;
391     ply1.joy_w = west;
392   }
393 }
394
395
396 /* handle events from x windows and block until the next frame */
397
398 void input_eventloop(void)
399 {
400   unsigned long count;
401
402   if (!input_pause)
403   {
404     XSync(display, False); /* block until all graphics are drawn */
405
406     if (gettimeofday(&tv2, 0) == -1)
407       tv2.tv_usec = 0;
408
409     count = tv2.tv_usec + 1000000 - tv1.tv_usec;
410     if (count >= 1000000)
411       count -= 1000000;
412
413     tv1.tv_usec = tv2.tv_usec;
414     if (count < 25000)
415     {
416       tv2.tv_sec = 0;
417       tv2.tv_usec = 25000 - count;
418 #if 1
419       select(0, 0, 0, 0, &tv2); /* sleep a bit */
420 #else
421       usleep(tv2.tv_usec);
422 #endif
423     }
424   }
425
426   input_esc = 0;
427   input_die = 0;
428   input_refresh = 0;
429 }
430
431 #endif