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 (PendingEvent()) /* got event */
43 case EVENT_BUTTONPRESS:
44 case EVENT_BUTTONRELEASE:
45 HandleButtonEvent((ButtonEvent *) &event);
48 case EVENT_MOTIONNOTIFY:
49 HandleMotionEvent((MotionEvent *) &event);
53 case EVENT_KEYRELEASE:
54 HandleKeyEvent((KeyEvent *) &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)
71 if (!PendingEvent()) /* delay only if no pending events */
75 /* refresh window contents from drawing buffer, if needed */
78 if (game_status == EXITGAME)
83 void HandleOtherEvents(Event *event)
88 HandleExposeEvent((ExposeEvent *) event);
91 case EVENT_UNMAPNOTIFY:
97 HandleFocusEvent((FocusChangeEvent *) event);
100 case EVENT_CLIENTMESSAGE:
101 HandleClientMessageEvent((ClientMessageEvent *) event);
109 void ClearEventQueue()
111 while (PendingEvent())
119 case EVENT_BUTTONRELEASE:
120 button_status = MB_RELEASED;
123 case EVENT_KEYRELEASE:
124 key_joystick_mapping = 0;
128 HandleOtherEvents(&event);
134 void SleepWhileUnmapped()
136 boolean window_unmapped = TRUE;
138 KeyboardAutoRepeatOn();
140 while(window_unmapped)
148 case EVENT_BUTTONRELEASE:
149 button_status = MB_RELEASED;
152 case EVENT_KEYRELEASE:
153 key_joystick_mapping = 0;
156 case EVENT_MAPNOTIFY:
157 window_unmapped = FALSE;
160 case EVENT_UNMAPNOTIFY:
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 KeyboardAutoRepeatOff();
177 void HandleExposeEvent(ExposeEvent *event)
179 #ifndef USE_SDL_LIBRARY
180 int x = event->x, y = event->y;
181 int width = event->width, height = event->height;
183 if (setup.direct_draw && game_status==PLAYING)
186 int x1 = (x-SX)/TILEX, y1 = (y-SY)/TILEY;
187 int x2 = (x-SX+width)/TILEX, y2 = (y-SY+height)/TILEY;
189 SetDrawtoField(DRAW_BACKBUFFER);
191 for(xx=0; xx<SCR_FIELDX; xx++)
192 for(yy=0; yy<SCR_FIELDY; yy++)
193 if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
194 DrawScreenField(xx,yy);
197 SetDrawtoField(DRAW_DIRECT);
200 if (setup.soft_scrolling && game_status == PLAYING)
202 int fx = FX, fy = FY;
204 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
205 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
207 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
210 BlitBitmap(drawto, window, x,y, width,height, x,y);
216 void HandleButtonEvent(ButtonEvent *event)
218 motion_status = FALSE;
220 if (event->type == EVENT_BUTTONPRESS)
221 button_status = event->button;
223 button_status = MB_RELEASED;
225 HandleButton(event->x, event->y, button_status);
228 void HandleMotionEvent(MotionEvent *event)
232 if (!QueryPointer(window, &win_x, &win_y))
233 return; /* window and pointer are on different screens */
235 if (!button_status && game_status != LEVELED)
238 motion_status = TRUE;
240 HandleButton(win_x, win_y, button_status);
243 void HandleKeyEvent(KeyEvent *event)
245 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
246 boolean with_modifiers = (game_status == PLAYING ? FALSE : TRUE);
247 Key key = GetEventKey(event, with_modifiers);
249 HandleKey(key, key_status);
252 void HandleFocusEvent(FocusChangeEvent *event)
254 static int old_joystick_status = -1;
256 if (event->type == EVENT_FOCUSOUT)
260 KeyboardAutoRepeatOn();
261 old_joystick_status = joystick_status;
262 joystick_status = JOYSTICK_OFF;
264 /* simulate key release events for still pressed keys */
265 key_joystick_mapping = 0;
266 for (i=0; i<MAX_PLAYERS; i++)
267 stored_player[i].action = 0;
269 else if (event->type == EVENT_FOCUSIN)
271 /* When there are two Rocks'n'Diamonds windows which overlap and
272 the player moves the pointer from one game window to the other,
273 a 'FocusOut' event is generated for the window the pointer is
274 leaving and a 'FocusIn' event is generated for the window the
275 pointer is entering. In some cases, it can happen that the
276 'FocusIn' event is handled by the one game process before the
277 'FocusOut' event by the other game process. In this case the
278 X11 environment would end up with activated keyboard auto repeat,
279 because unfortunately this is a global setting and not (which
280 would be far better) set for each X11 window individually.
281 The effect would be keyboard auto repeat while playing the game
282 (game_status == PLAYING), which is not desired.
283 To avoid this special case, we just wait 1/10 second before
284 processing the 'FocusIn' event.
287 if (game_status == PLAYING)
290 KeyboardAutoRepeatOff();
292 if (old_joystick_status != -1)
293 joystick_status = old_joystick_status;
297 void HandleClientMessageEvent(ClientMessageEvent *event)
299 #ifdef USE_SDL_LIBRARY
300 CloseAllAndExit(0); /* the only possible message here is SDL_QUIT */
303 if ((event->window == window) &&
304 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
310 void HandleButton(int mx, int my, int button)
312 static int old_mx = 0, old_my = 0;
326 HandleGadgets(mx, my, button);
331 HandleMainMenu(mx,my, 0,0, button);
335 HandleTypeName(0, KEY_Return);
339 HandleChooseLevel(mx,my, 0,0, button);
343 HandleHallOfFame(0,0, 0,0, button);
350 HandleHelpScreen(button);
354 HandleSetupScreen(mx,my, 0,0, button);
358 HandleSetupInputScreen(mx,my, 0,0, button);
363 if (button == MB_RELEASED)
365 int sx = (mx - SX) / TILEX;
366 int sy = (my - SY) / TILEY;
368 if (IN_VIS_FIELD(sx,sy))
373 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
375 if (!IN_LEV_FIELD(x, y))
378 printf(" Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
379 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
380 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
381 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
382 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
383 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
384 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
396 void HandleKey(Key key, int key_status)
399 static struct SetupKeyboardInfo custom_key;
407 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
408 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
409 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
410 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
411 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
412 { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
415 if (game_status == PLAYING)
419 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
424 if (setup.input[pnr].use_joystick)
427 custom_key = setup.input[pnr].key;
430 if (key == *key_info[i].key_custom)
431 key_action |= key_info[i].action;
433 if (key_status == KEY_PRESSED)
434 stored_player[pnr].action |= key_action;
436 stored_player[pnr].action &= ~key_action;
444 if (key == key_info[i].key_default)
445 joy |= key_info[i].action;
450 if (key_status == KEY_PRESSED)
451 key_joystick_mapping |= joy;
453 key_joystick_mapping &= ~joy;
458 if (game_status != PLAYING)
459 key_joystick_mapping = 0;
461 if (key_status == KEY_RELEASED)
464 if ((key == KEY_Return || key == KEY_space) &&
465 game_status == PLAYING && AllPlayersGone)
467 CloseDoor(DOOR_CLOSE_1);
468 game_status = MAINMENU;
473 /* allow quick escape to the main menu with the Escape key */
474 if (key == KEY_Escape && game_status != MAINMENU)
476 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
477 game_status = MAINMENU;
486 if (game_status == PLAYING && (tape.playing || tape.pausing))
493 HandleGadgetsKeyInput(key);
498 HandleTypeName(0, key);
509 if (game_status == MAINMENU)
510 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
511 else if (game_status == CHOOSELEVEL)
512 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
513 else if (game_status == SETUP)
514 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
515 else if (game_status == SETUPINPUT)
516 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
520 if (game_status == CHOOSELEVEL)
521 HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
525 if (game_status == CHOOSELEVEL)
526 HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
535 HandleHelpScreen(MB_RELEASED);
543 game_status = MAINMENU;
549 HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
553 HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
562 HandleLevelEditorKeyInput(key);
583 if (GameFrameDelay == 500)
584 GameFrameDelay = GAME_FRAME_DELAY;
586 GameFrameDelay = 500;
589 GameFrameDelay = (key - KEY_0) * 10;
590 printf("Game speed == %d%% (%d ms delay between two frames)\n",
591 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
597 if (ScrollStepSize == TILEX/8)
598 ScrollStepSize = TILEX/4;
600 ScrollStepSize = TILEX/8;
601 printf("ScrollStepSize == %d\n", ScrollStepSize);
610 ScrollStepSize = TILEX/4;
615 ScrollStepSize = TILEX/8;
617 printf("MoveSpeed == %d\n", MoveSpeed);
622 ScrollStepSize = TILEX/8;
623 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
627 ScrollStepSize = TILEX/4;
628 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
632 ScrollStepSize = TILEX/2;
633 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
637 ScrollStepSize = TILEX;
638 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
645 local_player->dynamite = 1000;
656 for(i=0; i<MAX_PLAYERS; i++)
658 printf("Player %d:\n", i);
659 printf(" jx == %d, jy == %d\n",
660 stored_player[i].jx, stored_player[i].jy);
661 printf(" last_jx == %d, last_jy == %d\n",
662 stored_player[i].last_jx, stored_player[i].last_jy);
681 void HandleNoXEvent()
683 if (button_status && game_status != PLAYING)
685 HandleButton(0, 0, -button_status);
696 if (game_status == PLAYING)
700 static int HandleJoystickForAllPlayers()
705 for (i=0; i<MAX_PLAYERS; i++)
710 if (!setup.input[i].use_joystick)
714 joy_action = Joystick(i);
715 result |= joy_action;
718 if (!setup.input[i].use_joystick)
722 stored_player[i].action = joy_action;
728 void HandleJoystick()
730 int joystick = HandleJoystickForAllPlayers();
731 int keyboard = key_joystick_mapping;
732 int joy = (joystick | keyboard);
733 int left = joy & JOY_LEFT;
734 int right = joy & JOY_RIGHT;
735 int up = joy & JOY_UP;
736 int down = joy & JOY_DOWN;
737 int button = joy & JOY_BUTTON;
738 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
739 int dx = (left ? -1 : right ? 1 : 0);
740 int dy = (up ? -1 : down ? 1 : 0);
749 static unsigned long joystickmove_delay = 0;
751 if (joystick && !button &&
752 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
753 newbutton = dx = dy = 0;
755 if (game_status==MAINMENU)
756 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
757 else if (game_status==CHOOSELEVEL)
758 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
759 else if (game_status==SETUP)
760 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
761 else if (game_status==SETUPINPUT)
762 HandleSetupInputScreen(0,0,dx,dy,
763 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
768 HandleHallOfFame(0,0, dx,dy, !newbutton);
772 HandleHelpScreen(!newbutton);
776 if (tape.playing || keyboard)
777 newbutton = ((joy & JOY_BUTTON) != 0);
779 if (AllPlayersGone && newbutton)
781 CloseDoor(DOOR_CLOSE_1);
782 game_status = MAINMENU;