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(0,0, 0,0, 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;
565 HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
569 HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
578 HandleLevelEditorKeyInput(key);
599 if (GameFrameDelay == 500)
600 GameFrameDelay = GAME_FRAME_DELAY;
602 GameFrameDelay = 500;
605 GameFrameDelay = (key - XK_0) * 10;
606 printf("Game speed == %d%% (%d ms delay between two frames)\n",
607 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
613 if (ScrollStepSize == TILEX/8)
614 ScrollStepSize = TILEX/4;
616 ScrollStepSize = TILEX/8;
617 printf("ScrollStepSize == %d\n", ScrollStepSize);
626 ScrollStepSize = TILEX/4;
631 ScrollStepSize = TILEX/8;
633 printf("MoveSpeed == %d\n", MoveSpeed);
638 ScrollStepSize = TILEX/8;
639 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
643 ScrollStepSize = TILEX/4;
644 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
648 ScrollStepSize = TILEX/2;
649 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
653 ScrollStepSize = TILEX;
654 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
661 local_player->dynamite = 1000;
672 for(i=0; i<MAX_PLAYERS; i++)
674 printf("Player %d:\n", i);
675 printf(" jx == %d, jy == %d\n",
676 stored_player[i].jx, stored_player[i].jy);
677 printf(" last_jx == %d, last_jy == %d\n",
678 stored_player[i].last_jx, stored_player[i].last_jy);
697 void HandleNoXEvent()
699 if (button_status && game_status != PLAYING)
701 HandleButton(0, 0, -button_status);
712 if (game_status == PLAYING)
716 static int HandleJoystickForAllPlayers()
721 for (i=0; i<MAX_PLAYERS; i++)
726 if (!setup.input[i].use_joystick)
730 joy_action = Joystick(i);
731 result |= joy_action;
734 if (!setup.input[i].use_joystick)
738 stored_player[i].action = joy_action;
744 void HandleJoystick()
746 int joystick = HandleJoystickForAllPlayers();
747 int keyboard = key_joystick_mapping;
748 int joy = (joystick | keyboard);
749 int left = joy & JOY_LEFT;
750 int right = joy & JOY_RIGHT;
751 int up = joy & JOY_UP;
752 int down = joy & JOY_DOWN;
753 int button = joy & JOY_BUTTON;
754 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
755 int dx = (left ? -1 : right ? 1 : 0);
756 int dy = (up ? -1 : down ? 1 : 0);
765 static unsigned long joystickmove_delay = 0;
767 if (joystick && !button &&
768 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
769 newbutton = dx = dy = 0;
771 if (game_status==MAINMENU)
772 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
773 else if (game_status==CHOOSELEVEL)
774 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
775 else if (game_status==SETUP)
776 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
777 else if (game_status==SETUPINPUT)
778 HandleSetupInputScreen(0,0,dx,dy,
779 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
784 HandleHallOfFame(0,0, dx,dy, !newbutton);
788 HandleHelpScreen(!newbutton);
792 if (tape.playing || keyboard)
793 newbutton = ((joy & JOY_BUTTON) != 0);
795 if (AllPlayersGone && newbutton)
797 CloseDoor(DOOR_CLOSE_1);
798 game_status = MAINMENU;