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 HandleVideoButtons(mx,my, button);
340 HandleSoundButtons(mx,my, button);
341 HandleGameButtons(mx,my, button);
345 HandleGadgets(mx, my, button);
350 HandleMainMenu(mx,my, 0,0, button);
354 HandleTypeName(0, XK_Return);
358 HandleChooseLevel(mx,my, 0,0, button);
362 HandleHallOfFame(button);
369 HandleHelpScreen(button);
373 HandleSetupScreen(mx,my, 0,0, button);
377 HandleSetupInputScreen(mx,my, 0,0, button);
382 if (button == MB_RELEASED)
384 int sx = (mx - SX) / TILEX;
385 int sy = (my - SY) / TILEY;
387 if (IN_VIS_FIELD(sx,sy))
392 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
394 if (!IN_LEV_FIELD(x, y))
397 printf(" Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
398 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
399 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
400 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
401 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
402 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
403 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
415 void HandleKey(KeySym key, int key_status)
418 static struct SetupKeyboardInfo custom_key;
421 KeySym *keysym_custom;
422 KeySym keysym_default;
426 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
427 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
428 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
429 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
430 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
431 { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
434 if (game_status == PLAYING)
438 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
443 if (setup.input[pnr].use_joystick)
446 custom_key = setup.input[pnr].key;
449 if (key == *key_info[i].keysym_custom)
450 key_action |= key_info[i].action;
452 if (key_status == KEY_PRESSED)
453 stored_player[pnr].action |= key_action;
455 stored_player[pnr].action &= ~key_action;
463 if (key == key_info[i].keysym_default)
464 joy |= key_info[i].action;
469 if (key_status == KEY_PRESSED)
470 key_joystick_mapping |= joy;
472 key_joystick_mapping &= ~joy;
477 if (game_status != PLAYING)
478 key_joystick_mapping = 0;
480 if (key_status == KEY_RELEASED)
483 if (key == XK_Return && game_status == PLAYING && AllPlayersGone)
485 CloseDoor(DOOR_CLOSE_1);
486 game_status = MAINMENU;
491 /* allow quick escape to the main menu with the Escape key */
492 if (key == XK_Escape && game_status != MAINMENU)
494 if (game_status == LEVELED)
496 /* draw smaller door */
497 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
501 redraw_mask |= REDRAW_ALL;
504 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
505 game_status = MAINMENU;
514 if (game_status == PLAYING && (tape.playing || tape.pausing))
521 HandleGadgetsKeyInput(key);
526 HandleTypeName(0, key);
536 if (game_status == MAINMENU)
537 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
538 else if (game_status == CHOOSELEVEL)
539 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
540 else if (game_status == SETUP)
541 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
542 else if (game_status == SETUPINPUT)
543 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
552 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;