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);
71 if (!XPending(display)) /* delay only if no pending events */
75 /* refresh window contents from drawing buffer, if needed */
78 if (game_status == EXITGAME)
83 void HandleOtherEvents(XEvent *event)
88 HandleExposeEvent((XExposeEvent *) event);
97 HandleFocusEvent((XFocusChangeEvent *) event);
101 HandleClientMessageEvent((XClientMessageEvent *) event);
109 void ClearEventQueue()
111 while(XPending(display))
115 XNextEvent(display, &event);
120 button_status = MB_RELEASED;
124 key_joystick_mapping = 0;
128 HandleOtherEvents(&event);
134 void SleepWhileUnmapped()
136 boolean window_unmapped = TRUE;
138 XAutoRepeatOn(display);
140 while(window_unmapped)
144 XNextEvent(display, &event);
149 button_status = MB_RELEASED;
153 key_joystick_mapping = 0;
157 window_unmapped = FALSE;
161 /* this is only to surely prevent the 'should not happen' case
162 * of recursively looping between 'SleepWhileUnmapped()' and
163 * 'HandleOtherEvents()' which usually calls this funtion.
168 HandleOtherEvents(&event);
173 if (game_status == PLAYING)
174 XAutoRepeatOff(display);
177 void HandleExposeEvent(XExposeEvent *event)
179 int x = event->x, y = event->y;
180 int width = event->width, height = event->height;
182 if (setup.direct_draw && game_status==PLAYING)
185 int x1 = (x-SX)/TILEX, y1 = (y-SY)/TILEY;
186 int x2 = (x-SX+width)/TILEX, y2 = (y-SY+height)/TILEY;
188 SetDrawtoField(DRAW_BACKBUFFER);
190 for(xx=0; xx<SCR_FIELDX; xx++)
191 for(yy=0; yy<SCR_FIELDY; yy++)
192 if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
193 DrawScreenField(xx,yy);
196 SetDrawtoField(DRAW_DIRECT);
199 if (setup.soft_scrolling && game_status == PLAYING)
201 int fx = FX, fy = FY;
203 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
204 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
206 XCopyArea(display,fieldbuffer,backbuffer,gc,
207 fx,fy, SXSIZE,SYSIZE,
211 XCopyArea(display,drawto,window,gc, x,y, width,height, x,y);
216 void HandleButtonEvent(XButtonEvent *event)
218 motion_status = FALSE;
220 if (event->type == ButtonPress)
221 button_status = event->button;
223 button_status = MB_RELEASED;
225 HandleButton(event->x, event->y, button_status);
228 void HandleMotionEvent(XMotionEvent *event)
235 if (!XQueryPointer(display, window, &root, &child, &root_x, &root_y,
236 &win_x, &win_y, &mask))
239 if (!button_status && game_status != LEVELED)
242 motion_status = TRUE;
244 HandleButton(win_x, win_y, button_status);
247 void HandleKeyEvent(XKeyEvent *event)
249 int key_status = (event->type == KeyPress ? KEY_PRESSED : KEY_RELEASED);
252 if (game_status == PLAYING)
254 /* use '0' instead of 'event->state' to get the key without modifiers */
255 key = XLookupKeysym(event, 0);
259 /* get the key with all modifiers */
261 int buffer_size = 10;
262 XComposeStatus compose;
265 char_count = XLookupString(event, buffer, buffer_size, &key, &compose);
266 buffer[char_count] = '\0';
269 HandleKey(key, key_status);
272 void HandleFocusEvent(XFocusChangeEvent *event)
274 static int old_joystick_status = -1;
276 if (event->type == FocusOut)
280 XAutoRepeatOn(display);
281 old_joystick_status = joystick_status;
282 joystick_status = JOYSTICK_OFF;
284 /* simulate key release events for still pressed keys */
285 key_joystick_mapping = 0;
286 for (i=0; i<MAX_PLAYERS; i++)
287 stored_player[i].action = 0;
289 else if (event->type == FocusIn)
291 /* When there are two Rocks'n'Diamonds windows which overlap and
292 the player moves the pointer from one game window to the other,
293 a 'FocusOut' event is generated for the window the pointer is
294 leaving and a 'FocusIn' event is generated for the window the
295 pointer is entering. In some cases, it can happen that the
296 'FocusIn' event is handled by the one game process before the
297 'FocusOut' event by the other game process. In this case the
298 X11 environment would end up with activated keyboard auto repeat,
299 because unfortunately this is a global setting and not (which
300 would be far better) set for each X11 window individually.
301 The effect would be keyboard auto repeat while playing the game
302 (game_status == PLAYING), which is not desired.
303 To avoid this special case, we just wait 1/10 second before
304 processing the 'FocusIn' event.
307 if (game_status == PLAYING)
310 XAutoRepeatOff(display);
312 if (old_joystick_status != -1)
313 joystick_status = old_joystick_status;
317 void HandleClientMessageEvent(XClientMessageEvent *event)
320 if ((event->window == window) &&
321 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
326 void HandleButton(int mx, int my, int button)
328 static int old_mx = 0, old_my = 0;
342 HandleGadgets(mx, my, button);
347 HandleMainMenu(mx,my, 0,0, button);
351 HandleTypeName(0, XK_Return);
355 HandleChooseLevel(mx,my, 0,0, button);
359 HandleHallOfFame(button);
366 HandleHelpScreen(button);
370 HandleSetupScreen(mx,my, 0,0, button);
374 HandleSetupInputScreen(mx,my, 0,0, button);
379 if (button == MB_RELEASED)
381 int sx = (mx - SX) / TILEX;
382 int sy = (my - SY) / TILEY;
384 if (IN_VIS_FIELD(sx,sy))
389 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
391 if (!IN_LEV_FIELD(x, y))
394 printf(" Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
395 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
396 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
397 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
398 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
399 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
400 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
412 void HandleKey(KeySym key, int key_status)
415 static struct SetupKeyboardInfo custom_key;
418 KeySym *keysym_custom;
419 KeySym keysym_default;
423 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
424 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
425 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
426 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
427 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
428 { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
431 if (game_status == PLAYING)
435 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
440 if (setup.input[pnr].use_joystick)
443 custom_key = setup.input[pnr].key;
446 if (key == *key_info[i].keysym_custom)
447 key_action |= key_info[i].action;
449 if (key_status == KEY_PRESSED)
450 stored_player[pnr].action |= key_action;
452 stored_player[pnr].action &= ~key_action;
460 if (key == key_info[i].keysym_default)
461 joy |= key_info[i].action;
466 if (key_status == KEY_PRESSED)
467 key_joystick_mapping |= joy;
469 key_joystick_mapping &= ~joy;
474 if (game_status != PLAYING)
475 key_joystick_mapping = 0;
477 if (key_status == KEY_RELEASED)
480 if ((key == XK_Return || key == XK_space) &&
481 game_status == PLAYING && AllPlayersGone)
483 CloseDoor(DOOR_CLOSE_1);
484 game_status = MAINMENU;
489 /* allow quick escape to the main menu with the Escape key */
490 if (key == XK_Escape && game_status != MAINMENU)
492 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
493 game_status = MAINMENU;
502 if (game_status == PLAYING && (tape.playing || tape.pausing))
509 HandleGadgetsKeyInput(key);
514 HandleTypeName(0, key);
525 if (game_status == MAINMENU)
526 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
527 else if (game_status == CHOOSELEVEL)
528 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
529 else if (game_status == SETUP)
530 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
531 else if (game_status == SETUPINPUT)
532 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
536 if (game_status == CHOOSELEVEL)
537 HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
541 if (game_status == CHOOSELEVEL)
542 HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
551 HandleHelpScreen(MB_RELEASED);
559 game_status = MAINMENU;
570 HandleLevelEditorKeyInput(key);
591 if (GameFrameDelay == 500)
592 GameFrameDelay = GAME_FRAME_DELAY;
594 GameFrameDelay = 500;
597 GameFrameDelay = (key - XK_0) * 10;
598 printf("Game speed == %d%% (%d ms delay between two frames)\n",
599 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
605 if (ScrollStepSize == TILEX/8)
606 ScrollStepSize = TILEX/4;
608 ScrollStepSize = TILEX/8;
609 printf("ScrollStepSize == %d\n", ScrollStepSize);
618 ScrollStepSize = TILEX/4;
623 ScrollStepSize = TILEX/8;
625 printf("MoveSpeed == %d\n", MoveSpeed);
630 ScrollStepSize = TILEX/8;
631 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
635 ScrollStepSize = TILEX/4;
636 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
640 ScrollStepSize = TILEX/2;
641 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
645 ScrollStepSize = TILEX;
646 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
653 local_player->dynamite = 1000;
664 for(i=0; i<MAX_PLAYERS; i++)
666 printf("Player %d:\n", i);
667 printf(" jx == %d, jy == %d\n",
668 stored_player[i].jx, stored_player[i].jy);
669 printf(" last_jx == %d, last_jy == %d\n",
670 stored_player[i].last_jx, stored_player[i].last_jy);
689 void HandleNoXEvent()
691 if (button_status && game_status != PLAYING)
693 HandleButton(0, 0, -button_status);
704 if (game_status == PLAYING)
708 static int HandleJoystickForAllPlayers()
713 for (i=0; i<MAX_PLAYERS; i++)
718 if (!setup.input[i].use_joystick)
722 joy_action = Joystick(i);
723 result |= joy_action;
726 if (!setup.input[i].use_joystick)
730 stored_player[i].action = joy_action;
736 void HandleJoystick()
738 int joystick = HandleJoystickForAllPlayers();
739 int keyboard = key_joystick_mapping;
740 int joy = (joystick | keyboard);
741 int left = joy & JOY_LEFT;
742 int right = joy & JOY_RIGHT;
743 int up = joy & JOY_UP;
744 int down = joy & JOY_DOWN;
745 int button = joy & JOY_BUTTON;
746 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
747 int dx = (left ? -1 : right ? 1 : 0);
748 int dy = (up ? -1 : down ? 1 : 0);
757 static unsigned long joystickmove_delay = 0;
759 if (joystick && !button &&
760 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
761 newbutton = dx = dy = 0;
763 if (game_status==MAINMENU)
764 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
765 else if (game_status==CHOOSELEVEL)
766 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
767 else if (game_status==SETUP)
768 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
769 else if (game_status==SETUPINPUT)
770 HandleSetupInputScreen(0,0,dx,dy,
771 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
776 HandleHallOfFame(!newbutton);
780 HandleHelpScreen(!newbutton);
784 if (tape.playing || keyboard)
785 newbutton = ((joy & JOY_BUTTON) != 0);
787 if (AllPlayersGone && newbutton)
789 CloseDoor(DOOR_CLOSE_1);
790 game_status = MAINMENU;