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 && game_status == PLAYING && AllPlayersGone)
482 CloseDoor(DOOR_CLOSE_1);
483 game_status = MAINMENU;
488 /* allow quick escape to the main menu with the Escape key */
489 if (key == XK_Escape && game_status != MAINMENU)
491 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
492 game_status = MAINMENU;
501 if (game_status == PLAYING && (tape.playing || tape.pausing))
508 HandleGadgetsKeyInput(key);
513 HandleTypeName(0, key);
523 if (game_status == MAINMENU)
524 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
525 else if (game_status == CHOOSELEVEL)
526 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
527 else if (game_status == SETUP)
528 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
529 else if (game_status == SETUPINPUT)
530 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
534 if (game_status == CHOOSELEVEL)
535 HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
539 if (game_status == CHOOSELEVEL)
540 HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
549 HandleHelpScreen(MB_RELEASED);
556 game_status = MAINMENU;
567 HandleLevelEditorKeyInput(key);
588 if (GameFrameDelay == 500)
589 GameFrameDelay = GAME_FRAME_DELAY;
591 GameFrameDelay = 500;
594 GameFrameDelay = (key - XK_0) * 10;
595 printf("Game speed == %d%% (%d ms delay between two frames)\n",
596 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
602 if (ScrollStepSize == TILEX/8)
603 ScrollStepSize = TILEX/4;
605 ScrollStepSize = TILEX/8;
606 printf("ScrollStepSize == %d\n", ScrollStepSize);
615 ScrollStepSize = TILEX/4;
620 ScrollStepSize = TILEX/8;
622 printf("MoveSpeed == %d\n", MoveSpeed);
627 ScrollStepSize = TILEX/8;
628 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
632 ScrollStepSize = TILEX/4;
633 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
637 ScrollStepSize = TILEX/2;
638 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
642 ScrollStepSize = TILEX;
643 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
650 local_player->dynamite = 1000;
661 for(i=0; i<MAX_PLAYERS; i++)
663 printf("Player %d:\n", i);
664 printf(" jx == %d, jy == %d\n",
665 stored_player[i].jx, stored_player[i].jy);
666 printf(" last_jx == %d, last_jy == %d\n",
667 stored_player[i].last_jx, stored_player[i].last_jy);
686 void HandleNoXEvent()
688 if (button_status && game_status != PLAYING)
690 HandleButton(0, 0, -button_status);
701 if (game_status == PLAYING)
705 static int HandleJoystickForAllPlayers()
710 for (i=0; i<MAX_PLAYERS; i++)
715 if (!setup.input[i].use_joystick)
719 joy_action = Joystick(i);
720 result |= joy_action;
723 if (!setup.input[i].use_joystick)
727 stored_player[i].action = joy_action;
733 void HandleJoystick()
735 int joystick = HandleJoystickForAllPlayers();
736 int keyboard = key_joystick_mapping;
737 int joy = (joystick | keyboard);
738 int left = joy & JOY_LEFT;
739 int right = joy & JOY_RIGHT;
740 int up = joy & JOY_UP;
741 int down = joy & JOY_DOWN;
742 int button = joy & JOY_BUTTON;
743 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
744 int dx = (left ? -1 : right ? 1 : 0);
745 int dy = (up ? -1 : down ? 1 : 0);
754 static unsigned long joystickmove_delay = 0;
756 if (joystick && !button &&
757 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
758 newbutton = dx = dy = 0;
760 if (game_status==MAINMENU)
761 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
762 else if (game_status==CHOOSELEVEL)
763 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
764 else if (game_status==SETUP)
765 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
766 else if (game_status==SETUPINPUT)
767 HandleSetupInputScreen(0,0,dx,dy,
768 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
773 HandleHallOfFame(!newbutton);
777 HandleHelpScreen(!newbutton);
781 if (tape.playing || keyboard)
782 newbutton = ((joy & JOY_BUTTON) != 0);
784 if (AllPlayersGone && newbutton)
786 CloseDoor(DOOR_CLOSE_1);
787 game_status = MAINMENU;