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/10 second before
303 processing the 'FocusIn' event.
306 if (game_status == PLAYING)
309 XAutoRepeatOff(display);
311 if (old_joystick_status != -1)
312 joystick_status = old_joystick_status;
316 void HandleClientMessageEvent(XClientMessageEvent *event)
319 if ((event->window == window) &&
320 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
325 void HandleButton(int mx, int my, int button)
327 static int old_mx = 0, old_my = 0;
341 HandleGadgets(mx, my, button);
346 HandleMainMenu(mx,my, 0,0, button);
350 HandleTypeName(0, XK_Return);
354 HandleChooseLevel(mx,my, 0,0, button);
358 HandleHallOfFame(button);
365 HandleHelpScreen(button);
369 HandleSetupScreen(mx,my, 0,0, button);
373 HandleSetupInputScreen(mx,my, 0,0, button);
378 if (button == MB_RELEASED)
380 int sx = (mx - SX) / TILEX;
381 int sy = (my - SY) / TILEY;
383 if (IN_VIS_FIELD(sx,sy))
388 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
390 if (!IN_LEV_FIELD(x, y))
393 printf(" Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
394 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
395 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
396 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
397 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
398 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
399 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
411 void HandleKey(KeySym key, int key_status)
414 static struct SetupKeyboardInfo custom_key;
417 KeySym *keysym_custom;
418 KeySym keysym_default;
422 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
423 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
424 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
425 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
426 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
427 { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
430 if (game_status == PLAYING)
434 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
439 if (setup.input[pnr].use_joystick)
442 custom_key = setup.input[pnr].key;
445 if (key == *key_info[i].keysym_custom)
446 key_action |= key_info[i].action;
448 if (key_status == KEY_PRESSED)
449 stored_player[pnr].action |= key_action;
451 stored_player[pnr].action &= ~key_action;
459 if (key == key_info[i].keysym_default)
460 joy |= key_info[i].action;
465 if (key_status == KEY_PRESSED)
466 key_joystick_mapping |= joy;
468 key_joystick_mapping &= ~joy;
473 if (game_status != PLAYING)
474 key_joystick_mapping = 0;
476 if (key_status == KEY_RELEASED)
479 if (key == XK_Return && game_status == PLAYING && AllPlayersGone)
481 CloseDoor(DOOR_CLOSE_1);
482 game_status = MAINMENU;
487 /* allow quick escape to the main menu with the Escape key */
488 if (key == XK_Escape && game_status != MAINMENU)
490 if (game_status == LEVELED)
492 /* draw smaller door */
493 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
497 redraw_mask |= REDRAW_ALL;
500 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
501 game_status = MAINMENU;
510 if (game_status == PLAYING && (tape.playing || tape.pausing))
517 HandleGadgetsKeyInput(key);
522 HandleTypeName(0, key);
532 if (game_status == MAINMENU)
533 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
534 else if (game_status == CHOOSELEVEL)
535 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
536 else if (game_status == SETUP)
537 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
538 else if (game_status == SETUPINPUT)
539 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
548 HandleHelpScreen(MB_RELEASED);
555 game_status = MAINMENU;
566 HandleLevelEditorKeyInput(key);
587 if (GameFrameDelay == 500)
588 GameFrameDelay = GAME_FRAME_DELAY;
590 GameFrameDelay = 500;
593 GameFrameDelay = (key - XK_0) * 10;
594 printf("Game speed == %d%% (%d ms delay between two frames)\n",
595 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
601 if (ScrollStepSize == TILEX/8)
602 ScrollStepSize = TILEX/4;
604 ScrollStepSize = TILEX/8;
605 printf("ScrollStepSize == %d\n", ScrollStepSize);
614 ScrollStepSize = TILEX/4;
619 ScrollStepSize = TILEX/8;
621 printf("MoveSpeed == %d\n", MoveSpeed);
626 ScrollStepSize = TILEX/8;
627 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
631 ScrollStepSize = TILEX/4;
632 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
636 ScrollStepSize = TILEX/2;
637 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
641 ScrollStepSize = TILEX;
642 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
649 local_player->dynamite = 1000;
660 for(i=0; i<MAX_PLAYERS; i++)
662 printf("Player %d:\n", i);
663 printf(" jx == %d, jy == %d\n",
664 stored_player[i].jx, stored_player[i].jy);
665 printf(" last_jx == %d, last_jy == %d\n",
666 stored_player[i].last_jx, stored_player[i].last_jy);
685 void HandleNoXEvent()
687 if (button_status && game_status != PLAYING)
689 HandleButton(0, 0, -button_status);
700 if (game_status == PLAYING)
704 static int HandleJoystickForAllPlayers()
709 for (i=0; i<MAX_PLAYERS; i++)
714 if (!setup.input[i].use_joystick)
718 joy_action = Joystick(i);
719 result |= joy_action;
722 if (!setup.input[i].use_joystick)
726 stored_player[i].action = joy_action;
732 void HandleJoystick()
734 int joystick = HandleJoystickForAllPlayers();
735 int keyboard = key_joystick_mapping;
736 int joy = (joystick | keyboard);
737 int left = joy & JOY_LEFT;
738 int right = joy & JOY_RIGHT;
739 int up = joy & JOY_UP;
740 int down = joy & JOY_DOWN;
741 int button = joy & JOY_BUTTON;
742 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
743 int dx = (left ? -1 : right ? 1 : 0);
744 int dy = (up ? -1 : down ? 1 : 0);
753 static unsigned long joystickmove_delay = 0;
755 if (joystick && !button &&
756 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
757 newbutton = dx = dy = 0;
759 if (game_status==MAINMENU)
760 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
761 else if (game_status==CHOOSELEVEL)
762 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
763 else if (game_status==SETUP)
764 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
765 else if (game_status==SETUPINPUT)
766 HandleSetupInputScreen(0,0,dx,dy,
767 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
772 HandleHallOfFame(!newbutton);
776 HandleHelpScreen(!newbutton);
780 if (tape.playing || keyboard)
781 newbutton = ((joy & JOY_BUTTON) != 0);
783 if (AllPlayersGone && newbutton)
785 CloseDoor(DOOR_CLOSE_1);
786 game_status = MAINMENU;