1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
26 /* values for key_status */
27 #define KEY_NOT_PRESSED FALSE
28 #define KEY_RELEASED FALSE
29 #define KEY_PRESSED TRUE
35 if (XPending(display)) /* got event from X server */
39 XNextEvent(display, &event);
45 HandleButtonEvent((XButtonEvent *) &event);
49 HandleMotionEvent((XMotionEvent *) &event);
54 HandleKeyEvent((XKeyEvent *) &event);
58 HandleOtherEvents(&event);
65 /* don't use all CPU time when idle; the main loop while playing
66 has its own synchronization and is CPU friendly, too */
68 if (game_status != PLAYING)
70 XSync(display, FALSE);
74 /* refresh window contents from drawing buffer, if needed */
77 if (game_status == EXITGAME)
82 void HandleOtherEvents(XEvent *event)
87 HandleExposeEvent((XExposeEvent *) event);
96 HandleFocusEvent((XFocusChangeEvent *) event);
100 HandleClientMessageEvent((XClientMessageEvent *) event);
108 void ClearEventQueue()
110 while(XPending(display))
114 XNextEvent(display, &event);
119 button_status = MB_RELEASED;
123 key_joystick_mapping = 0;
127 HandleOtherEvents(&event);
133 void SleepWhileUnmapped()
135 boolean window_unmapped = TRUE;
137 XAutoRepeatOn(display);
139 while(window_unmapped)
143 XNextEvent(display, &event);
148 button_status = MB_RELEASED;
152 key_joystick_mapping = 0;
156 window_unmapped = FALSE;
160 /* this is only to surely prevent the 'should not happen' case
161 * of recursively looping between 'SleepWhileUnmapped()' and
162 * 'HandleOtherEvents()' which usually calls this funtion.
167 HandleOtherEvents(&event);
172 if (game_status == PLAYING)
173 XAutoRepeatOff(display);
176 void HandleExposeEvent(XExposeEvent *event)
178 int x = event->x, y = event->y;
179 int width = event->width, height = event->height;
181 if (setup.direct_draw && game_status==PLAYING)
184 int x1 = (x-SX)/TILEX, y1 = (y-SY)/TILEY;
185 int x2 = (x-SX+width)/TILEX, y2 = (y-SY+height)/TILEY;
187 SetDrawtoField(DRAW_BACKBUFFER);
189 for(xx=0; xx<SCR_FIELDX; xx++)
190 for(yy=0; yy<SCR_FIELDY; yy++)
191 if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
192 DrawScreenField(xx,yy);
195 SetDrawtoField(DRAW_DIRECT);
198 if (setup.soft_scrolling && game_status == PLAYING)
200 int fx = FX, fy = FY;
202 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
203 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
205 XCopyArea(display,fieldbuffer,backbuffer,gc,
206 fx,fy, SXSIZE,SYSIZE,
210 XCopyArea(display,drawto,window,gc, x,y, width,height, x,y);
215 void HandleButtonEvent(XButtonEvent *event)
217 motion_status = FALSE;
219 if (event->type == ButtonPress)
220 button_status = event->button;
222 button_status = MB_RELEASED;
224 HandleButton(event->x, event->y, button_status);
227 void HandleMotionEvent(XMotionEvent *event)
234 if (!XQueryPointer(display, window, &root, &child, &root_x, &root_y,
235 &win_x, &win_y, &mask))
238 if (!button_status && game_status != LEVELED)
241 motion_status = TRUE;
243 HandleButton(win_x, win_y, button_status);
246 void HandleKeyEvent(XKeyEvent *event)
248 int key_status = (event->type == KeyPress ? KEY_PRESSED : KEY_RELEASED);
251 if (game_status == PLAYING)
253 /* use '0' instead of 'event->state' to get the key without modifiers */
254 key = XLookupKeysym(event, 0);
258 /* get the key with all modifiers */
260 int buffer_size = 10;
261 XComposeStatus compose;
264 char_count = XLookupString(event, buffer, buffer_size, &key, &compose);
265 buffer[char_count] = '\0';
268 HandleKey(key, key_status);
271 void HandleFocusEvent(XFocusChangeEvent *event)
273 static int old_joystick_status = -1;
275 if (event->type == FocusOut)
279 XAutoRepeatOn(display);
280 old_joystick_status = joystick_status;
281 joystick_status = JOYSTICK_OFF;
283 /* simulate key release events for still pressed keys */
284 key_joystick_mapping = 0;
285 for (i=0; i<MAX_PLAYERS; i++)
286 stored_player[i].action = 0;
288 else if (event->type == FocusIn)
290 /* When there are two Rocks'n'Diamonds windows which overlap and
291 the player moves the pointer from one game window to the other,
292 a 'FocusOut' event is generated for the window the pointer is
293 leaving and a 'FocusIn' event is generated for the window the
294 pointer is entering. In some cases, it can happen that the
295 'FocusIn' event is handled by the one game process before the
296 'FocusOut' event by the other game process. In this case the
297 X11 environment would end up with activated keyboard auto repeat,
298 because unfortunately this is a global setting and not (which
299 would be far better) set for each X11 window individually.
300 The effect would be keyboard auto repeat while playing the game
301 (game_status == PLAYING), which is not desired.
302 To avoid this special case, we just wait 1/50 second before
303 processing the 'FocusIn' event.
307 if (game_status == PLAYING)
308 XAutoRepeatOff(display);
309 if (old_joystick_status != -1)
310 joystick_status = old_joystick_status;
314 void HandleClientMessageEvent(XClientMessageEvent *event)
317 if ((event->window == window) &&
318 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
323 void HandleButton(int mx, int my, int button)
325 static int old_mx = 0, old_my = 0;
339 HandleGadgets(mx, my, button);
344 HandleMainMenu(mx,my, 0,0, button);
348 HandleTypeName(0, XK_Return);
352 HandleChooseLevel(mx,my, 0,0, button);
356 HandleHallOfFame(button);
363 HandleHelpScreen(button);
367 HandleSetupScreen(mx,my, 0,0, button);
371 HandleSetupInputScreen(mx,my, 0,0, button);
376 if (button == MB_RELEASED)
378 int sx = (mx - SX) / TILEX;
379 int sy = (my - SY) / TILEY;
381 if (IN_VIS_FIELD(sx,sy))
386 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
388 if (!IN_LEV_FIELD(x, y))
391 printf(" Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
392 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
393 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
394 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
395 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
396 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
397 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
409 void HandleKey(KeySym key, int key_status)
412 static struct SetupKeyboardInfo custom_key;
415 KeySym *keysym_custom;
416 KeySym keysym_default;
420 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
421 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
422 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
423 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
424 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
425 { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
428 if (game_status == PLAYING)
432 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
437 if (setup.input[pnr].use_joystick)
440 custom_key = setup.input[pnr].key;
443 if (key == *key_info[i].keysym_custom)
444 key_action |= key_info[i].action;
446 if (key_status == KEY_PRESSED)
447 stored_player[pnr].action |= key_action;
449 stored_player[pnr].action &= ~key_action;
457 if (key == key_info[i].keysym_default)
458 joy |= key_info[i].action;
463 if (key_status == KEY_PRESSED)
464 key_joystick_mapping |= joy;
466 key_joystick_mapping &= ~joy;
471 if (game_status != PLAYING)
472 key_joystick_mapping = 0;
474 if (key_status == KEY_RELEASED)
477 if (key == XK_Return && game_status == PLAYING && AllPlayersGone)
479 CloseDoor(DOOR_CLOSE_1);
480 game_status = MAINMENU;
485 /* allow quick escape to the main menu with the Escape key */
486 if (key == XK_Escape && game_status != MAINMENU)
488 if (game_status == LEVELED)
490 /* draw smaller door */
491 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
495 redraw_mask |= REDRAW_ALL;
498 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
499 game_status = MAINMENU;
508 if (game_status == PLAYING && (tape.playing || tape.pausing))
515 HandleGadgetsKeyInput(key);
520 HandleTypeName(0, key);
530 if (game_status == MAINMENU)
531 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
532 else if (game_status == CHOOSELEVEL)
533 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
534 else if (game_status == SETUP)
535 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
536 else if (game_status == SETUPINPUT)
537 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
546 HandleHelpScreen(MB_RELEASED);
553 game_status = MAINMENU;
564 HandleLevelEditorKeyInput(key);
585 if (GameFrameDelay == 500)
586 GameFrameDelay = GAME_FRAME_DELAY;
588 GameFrameDelay = 500;
591 GameFrameDelay = (key - XK_0) * 10;
592 printf("Game speed == %d%% (%d ms delay between two frames)\n",
593 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
599 if (ScrollStepSize == TILEX/8)
600 ScrollStepSize = TILEX/4;
602 ScrollStepSize = TILEX/8;
603 printf("ScrollStepSize == %d\n", ScrollStepSize);
612 ScrollStepSize = TILEX/4;
617 ScrollStepSize = TILEX/8;
619 printf("MoveSpeed == %d\n", MoveSpeed);
624 ScrollStepSize = TILEX/8;
625 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
629 ScrollStepSize = TILEX/4;
630 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
634 ScrollStepSize = TILEX/2;
635 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
639 ScrollStepSize = TILEX;
640 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
647 local_player->dynamite = 1000;
658 for(i=0; i<MAX_PLAYERS; i++)
660 printf("Player %d:\n", i);
661 printf(" jx == %d, jy == %d\n",
662 stored_player[i].jx, stored_player[i].jy);
663 printf(" last_jx == %d, last_jy == %d\n",
664 stored_player[i].last_jx, stored_player[i].last_jy);
683 void HandleNoXEvent()
685 if (button_status && game_status != PLAYING)
687 HandleButton(0, 0, -button_status);
698 if (game_status == PLAYING)
702 static int HandleJoystickForAllPlayers()
707 for (i=0; i<MAX_PLAYERS; i++)
712 if (!setup.input[i].use_joystick)
716 joy_action = Joystick(i);
717 result |= joy_action;
720 if (!setup.input[i].use_joystick)
724 stored_player[i].action = joy_action;
730 void HandleJoystick()
732 int joystick = HandleJoystickForAllPlayers();
733 int keyboard = key_joystick_mapping;
734 int joy = (joystick | keyboard);
735 int left = joy & JOY_LEFT;
736 int right = joy & JOY_RIGHT;
737 int up = joy & JOY_UP;
738 int down = joy & JOY_DOWN;
739 int button = joy & JOY_BUTTON;
740 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
741 int dx = (left ? -1 : right ? 1 : 0);
742 int dy = (up ? -1 : down ? 1 : 0);
751 static unsigned long joystickmove_delay = 0;
753 if (joystick && !button &&
754 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
755 newbutton = dx = dy = 0;
757 if (game_status==MAINMENU)
758 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
759 else if (game_status==CHOOSELEVEL)
760 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
761 else if (game_status==SETUP)
762 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
763 else if (game_status==SETUPINPUT)
764 HandleSetupInputScreen(0,0,dx,dy,
765 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
770 HandleHallOfFame(!newbutton);
774 HandleHelpScreen(!newbutton);
778 if (tape.playing || keyboard)
779 newbutton = ((joy & JOY_BUTTON) != 0);
781 if (AllPlayersGone && newbutton)
783 CloseDoor(DOOR_CLOSE_1);
784 game_status = MAINMENU;