1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
27 #define DEBUG_EVENTS 0
30 static boolean cursor_inside_playfield = FALSE;
31 static boolean playfield_cursor_set = FALSE;
32 static unsigned int playfield_cursor_delay = 0;
35 /* event filter especially needed for SDL event filtering due to
36 delay problems with lots of mouse motion events when mouse button
37 not pressed (X11 can handle this with 'PointerMotionHintMask') */
39 /* event filter addition for SDL2: as SDL2 does not have a function to enable
40 or disable keyboard auto-repeat, filter repeated keyboard events instead */
42 static int FilterEventsExt(const Event *event)
46 #if defined(TARGET_SDL2)
47 /* skip repeated key press events if keyboard auto-repeat is disabled */
48 if (event->type == EVENT_KEYPRESS &&
54 /* non-motion events are directly passed to event handler functions */
55 if (event->type != EVENT_MOTIONNOTIFY)
58 motion = (MotionEvent *)event;
59 cursor_inside_playfield = (motion->x >= SX && motion->x < SX + SXSIZE &&
60 motion->y >= SY && motion->y < SY + SYSIZE);
62 if (game_status == GAME_MODE_PLAYING && playfield_cursor_set)
64 SetMouseCursor(CURSOR_DEFAULT);
65 playfield_cursor_set = FALSE;
66 DelayReached(&playfield_cursor_delay, 0);
69 /* skip mouse motion events without pressed button outside level editor */
70 if (button_status == MB_RELEASED &&
71 game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
77 #if defined(TARGET_SDL2)
78 int FilterEvents(void *userdata, Event *event)
80 return FilterEventsExt(event);
83 int FilterEvents(const Event *event)
85 return FilterEventsExt(event);
89 /* to prevent delay problems, skip mouse motion events if the very next
90 event is also a mouse motion event (and therefore effectively only
91 handling the last of a row of mouse motion events in the event queue) */
93 boolean SkipPressedMouseMotionEvent(const Event *event)
95 /* nothing to do if the current event is not a mouse motion event */
96 if (event->type != EVENT_MOTIONNOTIFY)
99 /* only skip motion events with pressed button outside level editor */
100 if (button_status == MB_RELEASED ||
101 game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
108 PeekEvent(&next_event);
110 /* if next event is also a mouse motion event, skip the current one */
111 if (next_event.type == EVENT_MOTIONNOTIFY)
118 /* this is only really needed for non-SDL targets to filter unwanted events;
119 when using SDL with properly installed event filter, this function can be
120 replaced with a simple "NextEvent()" call, but it doesn't hurt either */
122 static boolean NextValidEvent(Event *event)
124 while (PendingEvent())
126 boolean handle_this_event = FALSE;
130 if (FilterEventsExt(event))
131 handle_this_event = TRUE;
133 if (SkipPressedMouseMotionEvent(event))
134 handle_this_event = FALSE;
136 if (handle_this_event)
147 if (PendingEvent()) /* got event */
151 while (NextValidEvent(&event))
155 case EVENT_BUTTONPRESS:
156 case EVENT_BUTTONRELEASE:
157 HandleButtonEvent((ButtonEvent *) &event);
160 case EVENT_MOTIONNOTIFY:
161 HandleMotionEvent((MotionEvent *) &event);
164 #if defined(TARGET_SDL2)
165 case EVENT_FINGERPRESS:
166 case EVENT_FINGERRELEASE:
167 case EVENT_FINGERMOTION:
168 HandleFingerEvent((FingerEvent *) &event);
173 case EVENT_KEYRELEASE:
174 HandleKeyEvent((KeyEvent *) &event);
178 HandleOtherEvents(&event);
185 /* when playing, display a special mouse pointer inside the playfield */
186 if (game_status == GAME_MODE_PLAYING && !tape.pausing)
188 if (!playfield_cursor_set && cursor_inside_playfield &&
189 DelayReached(&playfield_cursor_delay, 1000))
191 SetMouseCursor(CURSOR_PLAYFIELD);
192 playfield_cursor_set = TRUE;
195 else if (playfield_cursor_set)
197 SetMouseCursor(CURSOR_DEFAULT);
198 playfield_cursor_set = FALSE;
204 /* don't use all CPU time when idle; the main loop while playing
205 has its own synchronization and is CPU friendly, too */
207 if (game_status == GAME_MODE_PLAYING)
214 if (!PendingEvent()) /* delay only if no pending events */
218 /* refresh window contents from drawing buffer, if needed */
221 if (game_status == GAME_MODE_QUIT)
226 void HandleOtherEvents(Event *event)
231 HandleExposeEvent((ExposeEvent *) event);
234 case EVENT_UNMAPNOTIFY:
236 /* This causes the game to stop not only when iconified, but also
237 when on another virtual desktop, which might be not desired. */
238 SleepWhileUnmapped();
244 HandleFocusEvent((FocusChangeEvent *) event);
247 case EVENT_CLIENTMESSAGE:
248 HandleClientMessageEvent((ClientMessageEvent *) event);
251 #if defined(TARGET_SDL)
252 case SDL_JOYAXISMOTION:
253 case SDL_JOYBUTTONDOWN:
254 case SDL_JOYBUTTONUP:
255 HandleJoystickEvent(event);
259 HandleWindowManagerEvent(event);
268 void ClearEventQueue()
270 while (PendingEvent())
278 case EVENT_BUTTONRELEASE:
279 button_status = MB_RELEASED;
282 case EVENT_KEYRELEASE:
286 key_joystick_mapping = 0;
291 HandleOtherEvents(&event);
297 void ClearPlayerAction()
301 /* simulate key release events for still pressed keys */
302 key_joystick_mapping = 0;
303 for (i = 0; i < MAX_PLAYERS; i++)
304 stored_player[i].action = 0;
307 void SleepWhileUnmapped()
309 boolean window_unmapped = TRUE;
311 KeyboardAutoRepeatOn();
313 while (window_unmapped)
321 case EVENT_BUTTONRELEASE:
322 button_status = MB_RELEASED;
325 case EVENT_KEYRELEASE:
326 key_joystick_mapping = 0;
329 case EVENT_MAPNOTIFY:
330 window_unmapped = FALSE;
333 case EVENT_UNMAPNOTIFY:
334 /* this is only to surely prevent the 'should not happen' case
335 * of recursively looping between 'SleepWhileUnmapped()' and
336 * 'HandleOtherEvents()' which usually calls this funtion.
341 HandleOtherEvents(&event);
346 if (game_status == GAME_MODE_PLAYING)
347 KeyboardAutoRepeatOffUnlessAutoplay();
350 void HandleExposeEvent(ExposeEvent *event)
352 #if !defined(TARGET_SDL)
353 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
358 void HandleButtonEvent(ButtonEvent *event)
361 printf("::: BUTTON EVENT: button %d %s\n", event->button,
362 event->type == EVENT_BUTTONPRESS ? "pressed" : "released");
365 motion_status = FALSE;
367 if (event->type == EVENT_BUTTONPRESS)
368 button_status = event->button;
370 button_status = MB_RELEASED;
372 HandleButton(event->x, event->y, button_status, event->button);
375 void HandleMotionEvent(MotionEvent *event)
377 if (!PointerInWindow(window))
378 return; /* window and pointer are on different screens */
380 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
383 motion_status = TRUE;
385 HandleButton(event->x, event->y, button_status, button_status);
388 #if defined(TARGET_SDL2)
389 void HandleFingerEvent(FingerEvent *event)
391 static int num_events = 0;
395 Error(ERR_DEBUG, "FINGER EVENT: finger was %s, touch ID %lld, finger ID %lld, x/y %f/%f, dx/dy %f/%f, pressure %f",
396 (event->type == EVENT_FINGERPRESS ? "pressed" :
397 event->type == EVENT_FINGERRELEASE ? "released" : "moved"),
401 event->dx, event->dy,
405 int x = (int)(event->x * video.width);
406 int y = (int)(event->y * video.height);
407 int button = MB_LEFTBUTTON;
409 Error(ERR_DEBUG, "=> screen x/y %d/%d", x, y);
412 if (++num_events >= max_events)
417 if (event->type == EVENT_FINGERPRESS)
418 button_status = button;
420 button_status = MB_RELEASED;
422 int max_x = SX + SXSIZE;
423 int max_y = SY + SYSIZE;
425 if (game_status == GAME_MODE_PLAYING &&
428 int key_status = (event->type == EVENT_FINGERRELEASE ? KEY_RELEASED :
430 Key key = (y < max_y / 3 ? setup.input[0].key.up :
431 y > 2 * max_y / 3 ? setup.input[0].key.down :
432 x < max_x / 3 ? setup.input[0].key.left :
433 x > 2 * max_x / 3 ? setup.input[0].key.right :
434 setup.input[0].key.drop);
436 Error(ERR_DEBUG, "=> key == %d, key_status == %d", key, key_status);
438 HandleKey(key, key_status);
442 HandleButton(x, y, button_status, button);
448 void HandleKeyEvent(KeyEvent *event)
450 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
451 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
452 Key key = GetEventKey(event, with_modifiers);
453 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
456 printf("::: KEY EVENT: %d %s\n", GetEventKey(event, TRUE),
457 event->type == EVENT_KEYPRESS ? "pressed" : "released");
460 HandleKeyModState(keymod, key_status);
461 HandleKey(key, key_status);
464 void HandleFocusEvent(FocusChangeEvent *event)
466 static int old_joystick_status = -1;
468 if (event->type == EVENT_FOCUSOUT)
470 KeyboardAutoRepeatOn();
471 old_joystick_status = joystick.status;
472 joystick.status = JOYSTICK_NOT_AVAILABLE;
476 else if (event->type == EVENT_FOCUSIN)
478 /* When there are two Rocks'n'Diamonds windows which overlap and
479 the player moves the pointer from one game window to the other,
480 a 'FocusOut' event is generated for the window the pointer is
481 leaving and a 'FocusIn' event is generated for the window the
482 pointer is entering. In some cases, it can happen that the
483 'FocusIn' event is handled by the one game process before the
484 'FocusOut' event by the other game process. In this case the
485 X11 environment would end up with activated keyboard auto repeat,
486 because unfortunately this is a global setting and not (which
487 would be far better) set for each X11 window individually.
488 The effect would be keyboard auto repeat while playing the game
489 (game_status == GAME_MODE_PLAYING), which is not desired.
490 To avoid this special case, we just wait 1/10 second before
491 processing the 'FocusIn' event.
494 if (game_status == GAME_MODE_PLAYING)
497 KeyboardAutoRepeatOffUnlessAutoplay();
500 if (old_joystick_status != -1)
501 joystick.status = old_joystick_status;
505 void HandleClientMessageEvent(ClientMessageEvent *event)
507 if (CheckCloseWindowEvent(event))
511 void HandleWindowManagerEvent(Event *event)
513 #if defined(TARGET_SDL)
514 SDLHandleWindowManagerEvent(event);
518 void HandleButton(int mx, int my, int button, int button_nr)
520 static int old_mx = 0, old_my = 0;
534 if (HandleGadgets(mx, my, button))
536 /* do not handle this button event anymore */
537 mx = my = -32; /* force mouse event to be outside screen tiles */
540 /* do not use scroll wheel button events for anything other than gadgets */
541 if (IS_WHEEL_BUTTON(button_nr))
546 case GAME_MODE_TITLE:
547 HandleTitleScreen(mx, my, 0, 0, button);
551 HandleMainMenu(mx, my, 0, 0, button);
554 case GAME_MODE_PSEUDO_TYPENAME:
555 HandleTypeName(0, KSYM_Return);
558 case GAME_MODE_LEVELS:
559 HandleChooseLevelSet(mx, my, 0, 0, button);
562 case GAME_MODE_LEVELNR:
563 HandleChooseLevelNr(mx, my, 0, 0, button);
566 case GAME_MODE_SCORES:
567 HandleHallOfFame(0, 0, 0, 0, button);
570 case GAME_MODE_EDITOR:
571 HandleLevelEditorIdle();
575 HandleInfoScreen(mx, my, 0, 0, button);
578 case GAME_MODE_SETUP:
579 HandleSetupScreen(mx, my, 0, 0, button);
582 case GAME_MODE_PLAYING:
584 if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
585 DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
594 static boolean is_string_suffix(char *string, char *suffix)
596 int string_len = strlen(string);
597 int suffix_len = strlen(suffix);
599 if (suffix_len > string_len)
602 return (strEqual(&string[string_len - suffix_len], suffix));
605 #define MAX_CHEAT_INPUT_LEN 32
607 static void HandleKeysSpecial(Key key)
609 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
610 char letter = getCharFromKey(key);
611 int cheat_input_len = strlen(cheat_input);
617 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
619 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
620 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
622 cheat_input_len = MAX_CHEAT_INPUT_LEN;
625 cheat_input[cheat_input_len++] = letter;
626 cheat_input[cheat_input_len] = '\0';
629 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
632 if (game_status == GAME_MODE_MAIN)
634 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
635 is_string_suffix(cheat_input, ":ist"))
637 InsertSolutionTape();
639 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
640 is_string_suffix(cheat_input, ":rg"))
642 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
645 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
646 is_string_suffix(cheat_input, ":rs"))
648 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
651 else if (is_string_suffix(cheat_input, ":reload-music") ||
652 is_string_suffix(cheat_input, ":rm"))
654 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
657 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
658 is_string_suffix(cheat_input, ":ra"))
660 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
661 1 << ARTWORK_TYPE_SOUNDS |
662 1 << ARTWORK_TYPE_MUSIC);
665 else if (is_string_suffix(cheat_input, ":dump-level") ||
666 is_string_suffix(cheat_input, ":dl"))
670 else if (is_string_suffix(cheat_input, ":dump-tape") ||
671 is_string_suffix(cheat_input, ":dt"))
675 else if (is_string_suffix(cheat_input, ":save-native-level") ||
676 is_string_suffix(cheat_input, ":snl"))
678 SaveNativeLevel(&level);
681 else if (game_status == GAME_MODE_PLAYING)
684 if (is_string_suffix(cheat_input, ".q"))
685 DEBUG_SetMaximumDynamite();
688 else if (game_status == GAME_MODE_EDITOR)
690 if (is_string_suffix(cheat_input, ":dump-brush") ||
691 is_string_suffix(cheat_input, ":DB"))
695 else if (is_string_suffix(cheat_input, ":DDB"))
702 void HandleKey(Key key, int key_status)
704 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
705 static struct SetupKeyboardInfo ski;
706 static struct SetupShortcutInfo ssi;
715 { &ski.left, &ssi.snap_left, DEFAULT_KEY_LEFT, JOY_LEFT },
716 { &ski.right, &ssi.snap_right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
717 { &ski.up, &ssi.snap_up, DEFAULT_KEY_UP, JOY_UP },
718 { &ski.down, &ssi.snap_down, DEFAULT_KEY_DOWN, JOY_DOWN },
719 { &ski.snap, NULL, DEFAULT_KEY_SNAP, JOY_BUTTON_SNAP },
720 { &ski.drop, NULL, DEFAULT_KEY_DROP, JOY_BUTTON_DROP }
725 if (game_status == GAME_MODE_PLAYING)
727 /* only needed for single-step tape recording mode */
728 static boolean clear_snap_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
729 static boolean clear_drop_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
730 static boolean element_snapped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
731 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
734 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
738 if (setup.input[pnr].use_joystick)
741 ski = setup.input[pnr].key;
743 for (i = 0; i < NUM_PLAYER_ACTIONS; i++)
744 if (key == *key_info[i].key_custom)
745 key_action |= key_info[i].action;
747 /* use combined snap+direction keys for the first player only */
750 ssi = setup.shortcut;
752 for (i = 0; i < NUM_DIRECTIONS; i++)
753 if (key == *key_info[i].key_snap)
754 key_action |= key_info[i].action | JOY_BUTTON_SNAP;
757 /* clear delayed snap and drop actions in single step mode (see below) */
758 if (tape.single_step)
760 if (clear_snap_button[pnr])
762 stored_player[pnr].action &= ~KEY_BUTTON_SNAP;
763 clear_snap_button[pnr] = FALSE;
766 if (clear_drop_button[pnr])
768 stored_player[pnr].action &= ~KEY_BUTTON_DROP;
769 clear_drop_button[pnr] = FALSE;
773 if (key_status == KEY_PRESSED)
774 stored_player[pnr].action |= key_action;
776 stored_player[pnr].action &= ~key_action;
778 if (tape.single_step && tape.recording && tape.pausing)
780 if (key_status == KEY_PRESSED && key_action & KEY_MOTION)
782 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
784 /* if snap key already pressed, don't snap when releasing (below) */
785 if (stored_player[pnr].action & KEY_BUTTON_SNAP)
786 element_snapped[pnr] = TRUE;
788 /* if drop key already pressed, don't drop when releasing (below) */
789 if (stored_player[pnr].action & KEY_BUTTON_DROP)
790 element_dropped[pnr] = TRUE;
793 else if (key_status == KEY_PRESSED && key_action & KEY_BUTTON_DROP)
795 if (level.game_engine_type == GAME_ENGINE_TYPE_EM ||
796 level.game_engine_type == GAME_ENGINE_TYPE_SP)
799 printf("::: drop key pressed\n");
802 if (level.game_engine_type == GAME_ENGINE_TYPE_SP &&
803 getRedDiskReleaseFlag_SP() == 0)
804 stored_player[pnr].action &= ~KEY_BUTTON_DROP;
806 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
810 else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON)
812 if (key_action & KEY_BUTTON_SNAP)
814 /* if snap key was released without moving (see above), snap now */
815 if (!element_snapped[pnr])
817 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
819 stored_player[pnr].action |= KEY_BUTTON_SNAP;
821 /* clear delayed snap button on next event */
822 clear_snap_button[pnr] = TRUE;
825 element_snapped[pnr] = FALSE;
829 if (key_action & KEY_BUTTON_DROP &&
830 level.game_engine_type == GAME_ENGINE_TYPE_RND)
832 /* if drop key was released without moving (see above), drop now */
833 if (!element_dropped[pnr])
835 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
837 if (level.game_engine_type != GAME_ENGINE_TYPE_SP ||
838 getRedDiskReleaseFlag_SP() != 0)
839 stored_player[pnr].action |= KEY_BUTTON_DROP;
841 /* clear delayed drop button on next event */
842 clear_drop_button[pnr] = TRUE;
845 element_dropped[pnr] = FALSE;
850 else if (tape.recording && tape.pausing)
852 /* prevent key release events from un-pausing a paused game */
853 if (key_status == KEY_PRESSED && key_action & KEY_ACTION)
854 TapeTogglePause(TAPE_TOGGLE_MANUAL);
860 for (i = 0; i < NUM_PLAYER_ACTIONS; i++)
861 if (key == key_info[i].key_default)
862 joy |= key_info[i].action;
867 if (key_status == KEY_PRESSED)
868 key_joystick_mapping |= joy;
870 key_joystick_mapping &= ~joy;
875 if (game_status != GAME_MODE_PLAYING)
876 key_joystick_mapping = 0;
878 if (key_status == KEY_RELEASED)
881 if ((key == KSYM_Return || key == KSYM_KP_Enter) &&
882 (GetKeyModState() & KMOD_Alt) && video.fullscreen_available)
884 setup.fullscreen = !setup.fullscreen;
886 ToggleFullscreenIfNeeded();
888 if (game_status == GAME_MODE_SETUP)
889 RedrawSetupScreenAfterFullscreenToggle();
895 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd &&
896 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
898 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
899 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
907 if (game_status == GAME_MODE_MAIN &&
908 (key == setup.shortcut.toggle_pause || key == KSYM_space))
910 StartGameActions(options.network, setup.autorecord, level.random_seed);
915 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
917 if (key == setup.shortcut.save_game)
919 else if (key == setup.shortcut.load_game)
921 else if (key == setup.shortcut.toggle_pause)
922 TapeTogglePause(TAPE_TOGGLE_MANUAL);
924 HandleTapeButtonKeys(key);
925 HandleSoundButtonKeys(key);
928 if (game_status == GAME_MODE_PLAYING && !network_playing)
930 int centered_player_nr_next = -999;
932 if (key == setup.shortcut.focus_player_all)
933 centered_player_nr_next = -1;
935 for (i = 0; i < MAX_PLAYERS; i++)
936 if (key == setup.shortcut.focus_player[i])
937 centered_player_nr_next = i;
939 if (centered_player_nr_next != -999)
941 game.centered_player_nr_next = centered_player_nr_next;
942 game.set_centered_player = TRUE;
946 tape.centered_player_nr_next = game.centered_player_nr_next;
947 tape.set_centered_player = TRUE;
952 HandleKeysSpecial(key);
954 if (HandleGadgetsKeyInput(key))
956 if (key != KSYM_Escape) /* always allow ESC key to be handled */
957 key = KSYM_UNDEFINED;
962 case GAME_MODE_PSEUDO_TYPENAME:
963 HandleTypeName(0, key);
966 case GAME_MODE_TITLE:
968 case GAME_MODE_LEVELS:
969 case GAME_MODE_LEVELNR:
970 case GAME_MODE_SETUP:
972 case GAME_MODE_SCORES:
977 if (game_status == GAME_MODE_TITLE)
978 HandleTitleScreen(0, 0, 0, 0, MB_MENU_CHOICE);
979 else if (game_status == GAME_MODE_MAIN)
980 HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE);
981 else if (game_status == GAME_MODE_LEVELS)
982 HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_CHOICE);
983 else if (game_status == GAME_MODE_LEVELNR)
984 HandleChooseLevelNr(0, 0, 0, 0, MB_MENU_CHOICE);
985 else if (game_status == GAME_MODE_SETUP)
986 HandleSetupScreen(0, 0, 0, 0, MB_MENU_CHOICE);
987 else if (game_status == GAME_MODE_INFO)
988 HandleInfoScreen(0, 0, 0, 0, MB_MENU_CHOICE);
989 else if (game_status == GAME_MODE_SCORES)
990 HandleHallOfFame(0, 0, 0, 0, MB_MENU_CHOICE);
994 if (game_status != GAME_MODE_MAIN)
995 FadeSkipNextFadeIn();
997 if (game_status == GAME_MODE_TITLE)
998 HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE);
999 else if (game_status == GAME_MODE_LEVELS)
1000 HandleChooseLevelSet(0, 0, 0, 0, MB_MENU_LEAVE);
1001 else if (game_status == GAME_MODE_LEVELNR)
1002 HandleChooseLevelNr(0, 0, 0, 0, MB_MENU_LEAVE);
1003 else if (game_status == GAME_MODE_SETUP)
1004 HandleSetupScreen(0, 0, 0, 0, MB_MENU_LEAVE);
1005 else if (game_status == GAME_MODE_INFO)
1006 HandleInfoScreen(0, 0, 0, 0, MB_MENU_LEAVE);
1007 else if (game_status == GAME_MODE_SCORES)
1008 HandleHallOfFame(0, 0, 0, 0, MB_MENU_LEAVE);
1012 if (game_status == GAME_MODE_LEVELS)
1013 HandleChooseLevelSet(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
1014 else if (game_status == GAME_MODE_LEVELNR)
1015 HandleChooseLevelNr(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
1016 else if (game_status == GAME_MODE_SETUP)
1017 HandleSetupScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
1018 else if (game_status == GAME_MODE_INFO)
1019 HandleInfoScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
1020 else if (game_status == GAME_MODE_SCORES)
1021 HandleHallOfFame(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
1024 case KSYM_Page_Down:
1025 if (game_status == GAME_MODE_LEVELS)
1026 HandleChooseLevelSet(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
1027 else if (game_status == GAME_MODE_LEVELNR)
1028 HandleChooseLevelNr(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
1029 else if (game_status == GAME_MODE_SETUP)
1030 HandleSetupScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
1031 else if (game_status == GAME_MODE_INFO)
1032 HandleInfoScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
1033 else if (game_status == GAME_MODE_SCORES)
1034 HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
1039 GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500);
1043 setup.sp_show_border_elements = !setup.sp_show_border_elements;
1044 printf("Supaplex border elements %s\n",
1045 setup.sp_show_border_elements ? "enabled" : "disabled");
1054 case GAME_MODE_EDITOR:
1055 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
1056 HandleLevelEditorKeyInput(key);
1059 case GAME_MODE_PLAYING:
1064 RequestQuitGame(setup.ask_on_escape);
1082 if (GameFrameDelay == 500)
1083 GameFrameDelay = GAME_FRAME_DELAY;
1085 GameFrameDelay = 500;
1088 GameFrameDelay = (key - KSYM_0) * 10;
1089 printf("Game speed == %d%% (%d ms delay between two frames)\n",
1090 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
1096 options.debug = FALSE;
1097 printf("debug mode disabled\n");
1101 options.debug = TRUE;
1102 printf("debug mode enabled\n");
1107 if (!global.fps_slowdown)
1109 global.fps_slowdown = TRUE;
1110 global.fps_slowdown_factor = 2;
1111 printf("fps slowdown enabled -- display only every 2nd frame\n");
1113 else if (global.fps_slowdown_factor == 2)
1115 global.fps_slowdown_factor = 4;
1116 printf("fps slowdown enabled -- display only every 4th frame\n");
1120 global.fps_slowdown = FALSE;
1121 global.fps_slowdown_factor = 1;
1122 printf("fps slowdown disabled\n");
1127 ScrollStepSize = TILEX / 8;
1128 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
1132 ScrollStepSize = TILEX / 4;
1133 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
1137 ScrollStepSize = TILEX / 2;
1138 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
1142 ScrollStepSize = TILEX;
1143 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
1147 printf("::: currently using game engine version %d\n",
1148 game.engine_version);
1159 if (key == KSYM_Escape)
1161 game_status = GAME_MODE_MAIN;
1169 void HandleNoEvent()
1171 if (button_status && game_status != GAME_MODE_PLAYING)
1173 HandleButton(0, 0, -button_status, button_status);
1178 #if defined(NETWORK_AVALIABLE)
1179 if (options.network)
1186 static int HandleJoystickForAllPlayers()
1191 for (i = 0; i < MAX_PLAYERS; i++)
1193 byte joy_action = 0;
1196 if (!setup.input[i].use_joystick)
1200 joy_action = Joystick(i);
1201 result |= joy_action;
1203 if (!setup.input[i].use_joystick)
1206 stored_player[i].action = joy_action;
1212 void HandleJoystick()
1214 int joystick = HandleJoystickForAllPlayers();
1215 int keyboard = key_joystick_mapping;
1216 int joy = (joystick | keyboard);
1217 int left = joy & JOY_LEFT;
1218 int right = joy & JOY_RIGHT;
1219 int up = joy & JOY_UP;
1220 int down = joy & JOY_DOWN;
1221 int button = joy & JOY_BUTTON;
1222 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1223 int dx = (left ? -1 : right ? 1 : 0);
1224 int dy = (up ? -1 : down ? 1 : 0);
1226 switch (game_status)
1228 case GAME_MODE_TITLE:
1229 case GAME_MODE_MAIN:
1230 case GAME_MODE_LEVELS:
1231 case GAME_MODE_LEVELNR:
1232 case GAME_MODE_SETUP:
1233 case GAME_MODE_INFO:
1235 static unsigned int joystickmove_delay = 0;
1237 if (joystick && !button &&
1238 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1239 newbutton = dx = dy = 0;
1241 if (game_status == GAME_MODE_TITLE)
1242 HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1243 else if (game_status == GAME_MODE_MAIN)
1244 HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1245 else if (game_status == GAME_MODE_LEVELS)
1246 HandleChooseLevelSet(0,0,dx,dy,newbutton?MB_MENU_CHOICE : MB_MENU_MARK);
1247 else if (game_status == GAME_MODE_LEVELNR)
1248 HandleChooseLevelNr(0,0,dx,dy,newbutton? MB_MENU_CHOICE : MB_MENU_MARK);
1249 else if (game_status == GAME_MODE_SETUP)
1250 HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1251 else if (game_status == GAME_MODE_INFO)
1252 HandleInfoScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1256 case GAME_MODE_SCORES:
1257 HandleHallOfFame(0, 0, dx, dy, !newbutton);
1260 case GAME_MODE_EDITOR:
1261 HandleLevelEditorIdle();
1264 case GAME_MODE_PLAYING:
1265 if (tape.playing || keyboard)
1266 newbutton = ((joy & JOY_BUTTON) != 0);
1269 if (local_player->LevelSolved_GameEnd && newbutton)
1271 if (AllPlayersGone && newbutton)