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 long 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 int FilterMouseMotionEvents(const Event *event)
43 /* non-motion events are directly passed to event handler functions */
44 if (event->type != EVENT_MOTIONNOTIFY)
47 motion = (MotionEvent *)event;
48 cursor_inside_playfield = (motion->x >= SX && motion->x < SX + SXSIZE &&
49 motion->y >= SY && motion->y < SY + SYSIZE);
51 if (game_status == GAME_MODE_PLAYING && playfield_cursor_set)
53 SetMouseCursor(CURSOR_DEFAULT);
54 playfield_cursor_set = FALSE;
55 DelayReached(&playfield_cursor_delay, 0);
58 /* skip mouse motion events without pressed button outside level editor */
59 if (button_status == MB_RELEASED &&
60 game_status != GAME_MODE_EDITOR && game_status != GAME_MODE_PLAYING)
66 /* to prevent delay problems, skip mouse motion events if the very next
67 event is also a mouse motion event (and therefore effectively only
68 handling the last of a row of mouse motion events in the event queue) */
70 boolean SkipPressedMouseMotionEvent(const Event *event)
72 /* nothing to do if the current event is not a mouse motion event */
73 if (event->type != EVENT_MOTIONNOTIFY)
76 /* only skip motion events with pressed button outside level editor */
77 if (button_status == MB_RELEASED ||
78 game_status == GAME_MODE_EDITOR || game_status == GAME_MODE_PLAYING)
85 PeekEvent(&next_event);
87 /* if next event is also a mouse motion event, skip the current one */
88 if (next_event.type == EVENT_MOTIONNOTIFY)
95 /* this is only really needed for non-SDL targets to filter unwanted events;
96 when using SDL with properly installed event filter, this function can be
97 replaced with a simple "NextEvent()" call, but it doesn't hurt either */
99 static boolean NextValidEvent(Event *event)
101 while (PendingEvent())
103 boolean handle_this_event = FALSE;
107 if (FilterMouseMotionEvents(event))
108 handle_this_event = TRUE;
110 if (SkipPressedMouseMotionEvent(event))
111 handle_this_event = FALSE;
113 if (handle_this_event)
124 if (PendingEvent()) /* got event */
128 while (NextValidEvent(&event))
132 case EVENT_BUTTONPRESS:
133 case EVENT_BUTTONRELEASE:
134 HandleButtonEvent((ButtonEvent *) &event);
137 case EVENT_MOTIONNOTIFY:
138 HandleMotionEvent((MotionEvent *) &event);
142 case EVENT_KEYRELEASE:
143 HandleKeyEvent((KeyEvent *) &event);
147 HandleOtherEvents(&event);
154 /* when playing, display a special mouse pointer inside the playfield */
155 if (game_status == GAME_MODE_PLAYING && !tape.pausing)
157 if (!playfield_cursor_set && cursor_inside_playfield &&
158 DelayReached(&playfield_cursor_delay, 1000))
160 SetMouseCursor(CURSOR_PLAYFIELD);
161 playfield_cursor_set = TRUE;
164 else if (playfield_cursor_set)
166 SetMouseCursor(CURSOR_DEFAULT);
167 playfield_cursor_set = FALSE;
173 /* don't use all CPU time when idle; the main loop while playing
174 has its own synchronization and is CPU friendly, too */
176 if (game_status == GAME_MODE_PLAYING)
183 if (!PendingEvent()) /* delay only if no pending events */
187 /* refresh window contents from drawing buffer, if needed */
190 if (game_status == GAME_MODE_QUIT)
195 void HandleOtherEvents(Event *event)
200 HandleExposeEvent((ExposeEvent *) event);
203 case EVENT_UNMAPNOTIFY:
205 /* This causes the game to stop not only when iconified, but also
206 when on another virtual desktop, which might be not desired. */
207 SleepWhileUnmapped();
213 HandleFocusEvent((FocusChangeEvent *) event);
216 case EVENT_CLIENTMESSAGE:
217 HandleClientMessageEvent((ClientMessageEvent *) event);
220 #if defined(TARGET_SDL)
221 case SDL_JOYAXISMOTION:
222 case SDL_JOYBUTTONDOWN:
223 case SDL_JOYBUTTONUP:
224 HandleJoystickEvent(event);
233 void ClearEventQueue()
235 while (PendingEvent())
243 case EVENT_BUTTONRELEASE:
244 button_status = MB_RELEASED;
247 case EVENT_KEYRELEASE:
251 key_joystick_mapping = 0;
256 HandleOtherEvents(&event);
262 void ClearPlayerAction()
266 /* simulate key release events for still pressed keys */
267 key_joystick_mapping = 0;
268 for (i = 0; i < MAX_PLAYERS; i++)
269 stored_player[i].action = 0;
272 void SleepWhileUnmapped()
274 boolean window_unmapped = TRUE;
276 KeyboardAutoRepeatOn();
278 while (window_unmapped)
286 case EVENT_BUTTONRELEASE:
287 button_status = MB_RELEASED;
290 case EVENT_KEYRELEASE:
291 key_joystick_mapping = 0;
294 case EVENT_MAPNOTIFY:
295 window_unmapped = FALSE;
298 case EVENT_UNMAPNOTIFY:
299 /* this is only to surely prevent the 'should not happen' case
300 * of recursively looping between 'SleepWhileUnmapped()' and
301 * 'HandleOtherEvents()' which usually calls this funtion.
306 HandleOtherEvents(&event);
311 if (game_status == GAME_MODE_PLAYING)
312 KeyboardAutoRepeatOffUnlessAutoplay();
315 void HandleExposeEvent(ExposeEvent *event)
318 RedrawPlayfield(FALSE, event->x, event->y, event->width, event->height);
323 void HandleButtonEvent(ButtonEvent *event)
326 printf("::: BUTTON EVENT: button %d %s\n", event->button,
327 event->type == EVENT_BUTTONPRESS ? "pressed" : "released");
330 motion_status = FALSE;
332 if (event->type == EVENT_BUTTONPRESS)
333 button_status = event->button;
335 button_status = MB_RELEASED;
337 HandleButton(event->x, event->y, button_status, event->button);
340 void HandleMotionEvent(MotionEvent *event)
342 if (!PointerInWindow(window))
343 return; /* window and pointer are on different screens */
345 if (button_status == MB_RELEASED && game_status != GAME_MODE_EDITOR)
348 motion_status = TRUE;
350 HandleButton(event->x, event->y, button_status, button_status);
353 void HandleKeyEvent(KeyEvent *event)
355 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
356 boolean with_modifiers = (game_status == GAME_MODE_PLAYING ? FALSE : TRUE);
357 Key key = GetEventKey(event, with_modifiers);
358 Key keymod = (with_modifiers ? GetEventKey(event, FALSE) : key);
361 printf("::: KEY EVENT: %d %s\n", GetEventKey(event, TRUE),
362 event->type == EVENT_KEYPRESS ? "pressed" : "released");
365 HandleKeyModState(keymod, key_status);
366 HandleKey(key, key_status);
369 void HandleFocusEvent(FocusChangeEvent *event)
371 static int old_joystick_status = -1;
373 if (event->type == EVENT_FOCUSOUT)
375 KeyboardAutoRepeatOn();
376 old_joystick_status = joystick.status;
377 joystick.status = JOYSTICK_NOT_AVAILABLE;
381 else if (event->type == EVENT_FOCUSIN)
383 /* When there are two Rocks'n'Diamonds windows which overlap and
384 the player moves the pointer from one game window to the other,
385 a 'FocusOut' event is generated for the window the pointer is
386 leaving and a 'FocusIn' event is generated for the window the
387 pointer is entering. In some cases, it can happen that the
388 'FocusIn' event is handled by the one game process before the
389 'FocusOut' event by the other game process. In this case the
390 X11 environment would end up with activated keyboard auto repeat,
391 because unfortunately this is a global setting and not (which
392 would be far better) set for each X11 window individually.
393 The effect would be keyboard auto repeat while playing the game
394 (game_status == GAME_MODE_PLAYING), which is not desired.
395 To avoid this special case, we just wait 1/10 second before
396 processing the 'FocusIn' event.
399 if (game_status == GAME_MODE_PLAYING)
402 KeyboardAutoRepeatOffUnlessAutoplay();
405 if (old_joystick_status != -1)
406 joystick.status = old_joystick_status;
410 void HandleClientMessageEvent(ClientMessageEvent *event)
412 if (CheckCloseWindowEvent(event))
416 void HandleButton(int mx, int my, int button, int button_nr)
418 static int old_mx = 0, old_my = 0;
432 if (HandleGadgets(mx, my, button))
434 /* do not handle this button event anymore */
435 mx = my = -32; /* force mouse event to be outside screen tiles */
438 /* do not use scroll wheel button events for anything other than gadgets */
439 if (IS_WHEEL_BUTTON(button_nr))
444 case GAME_MODE_TITLE:
445 HandleTitleScreen(mx, my, 0, 0, button);
449 HandleMainMenu(mx, my, 0, 0, button);
452 case GAME_MODE_PSEUDO_TYPENAME:
453 HandleTypeName(0, KSYM_Return);
456 case GAME_MODE_LEVELS:
457 HandleChooseLevel(mx, my, 0, 0, button);
460 case GAME_MODE_SCORES:
461 HandleHallOfFame(0, 0, 0, 0, button);
464 case GAME_MODE_EDITOR:
465 HandleLevelEditorIdle();
469 HandleInfoScreen(mx, my, 0, 0, button);
472 case GAME_MODE_SETUP:
473 HandleSetupScreen(mx, my, 0, 0, button);
476 case GAME_MODE_PLAYING:
478 if (button == MB_PRESSED && !motion_status && IN_GFX_SCREEN(mx, my))
479 DumpTile(LEVELX((mx - SX) / TILEX), LEVELY((my - SY) / TILEY));
488 static boolean is_string_suffix(char *string, char *suffix)
490 int string_len = strlen(string);
491 int suffix_len = strlen(suffix);
493 if (suffix_len > string_len)
496 return (strEqual(&string[string_len - suffix_len], suffix));
499 #define MAX_CHEAT_INPUT_LEN 32
501 static void HandleKeysSpecial(Key key)
503 static char cheat_input[2 * MAX_CHEAT_INPUT_LEN + 1] = "";
504 char letter = getCharFromKey(key);
505 int cheat_input_len = strlen(cheat_input);
511 if (cheat_input_len >= 2 * MAX_CHEAT_INPUT_LEN)
513 for (i = 0; i < MAX_CHEAT_INPUT_LEN + 1; i++)
514 cheat_input[i] = cheat_input[MAX_CHEAT_INPUT_LEN + i];
516 cheat_input_len = MAX_CHEAT_INPUT_LEN;
519 cheat_input[cheat_input_len++] = letter;
520 cheat_input[cheat_input_len] = '\0';
523 printf("::: '%s' [%d]\n", cheat_input, cheat_input_len);
526 if (game_status == GAME_MODE_MAIN)
528 if (is_string_suffix(cheat_input, ":insert-solution-tape") ||
529 is_string_suffix(cheat_input, ":ist"))
531 InsertSolutionTape();
533 else if (is_string_suffix(cheat_input, ":reload-graphics") ||
534 is_string_suffix(cheat_input, ":rg"))
536 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS);
539 else if (is_string_suffix(cheat_input, ":reload-sounds") ||
540 is_string_suffix(cheat_input, ":rs"))
542 ReloadCustomArtwork(1 << ARTWORK_TYPE_SOUNDS);
545 else if (is_string_suffix(cheat_input, ":reload-music") ||
546 is_string_suffix(cheat_input, ":rm"))
548 ReloadCustomArtwork(1 << ARTWORK_TYPE_MUSIC);
551 else if (is_string_suffix(cheat_input, ":reload-artwork") ||
552 is_string_suffix(cheat_input, ":ra"))
554 ReloadCustomArtwork(1 << ARTWORK_TYPE_GRAPHICS |
555 1 << ARTWORK_TYPE_SOUNDS |
556 1 << ARTWORK_TYPE_MUSIC);
559 else if (is_string_suffix(cheat_input, ":dump-level") ||
560 is_string_suffix(cheat_input, ":dl"))
564 else if (is_string_suffix(cheat_input, ":dump-tape") ||
565 is_string_suffix(cheat_input, ":dt"))
570 else if (game_status == GAME_MODE_PLAYING)
573 if (is_string_suffix(cheat_input, ".q"))
574 DEBUG_SetMaximumDynamite();
577 else if (game_status == GAME_MODE_EDITOR)
579 if (is_string_suffix(cheat_input, ":dump-brush") ||
580 is_string_suffix(cheat_input, ":DB"))
584 else if (is_string_suffix(cheat_input, ":DDB"))
591 void HandleKey(Key key, int key_status)
593 boolean anyTextGadgetActiveOrJustFinished = anyTextGadgetActive();
594 static struct SetupKeyboardInfo custom_key;
602 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
603 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
604 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
605 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
606 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
607 { &custom_key.drop, DEFAULT_KEY_DROP, JOY_BUTTON_2 }
612 if (game_status == GAME_MODE_PLAYING)
614 /* only needed for single-step tape recording mode */
615 static boolean clear_button_2[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
616 static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
619 for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
623 if (setup.input[pnr].use_joystick)
626 custom_key = setup.input[pnr].key;
628 for (i = 0; i < 6; i++)
629 if (key == *key_info[i].key_custom)
630 key_action |= key_info[i].action;
632 if (tape.single_step && clear_button_2[pnr])
634 stored_player[pnr].action &= ~KEY_BUTTON_2;
635 clear_button_2[pnr] = FALSE;
638 if (key_status == KEY_PRESSED)
639 stored_player[pnr].action |= key_action;
641 stored_player[pnr].action &= ~key_action;
643 if (tape.single_step && tape.recording && tape.pausing)
645 if (key_status == KEY_PRESSED &&
646 (key_action & (KEY_MOTION | KEY_BUTTON_1)))
648 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
650 if (key_action & KEY_MOTION)
652 if (stored_player[pnr].action & KEY_BUTTON_2)
653 element_dropped[pnr] = TRUE;
656 else if (key_status == KEY_RELEASED &&
657 (key_action & KEY_BUTTON_2))
659 if (!element_dropped[pnr])
661 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
663 stored_player[pnr].action |= KEY_BUTTON_2;
664 clear_button_2[pnr] = TRUE;
667 element_dropped[pnr] = FALSE;
671 else if (tape.recording && tape.pausing)
673 /* prevent key release events from un-pausing a paused game */
674 if (key_status == KEY_PRESSED &&
675 (key_action & KEY_ACTION))
676 TapeTogglePause(TAPE_TOGGLE_MANUAL);
679 else if (tape.recording && tape.pausing && (key_action & KEY_ACTION))
680 TapeTogglePause(TAPE_TOGGLE_MANUAL);
686 for (i = 0; i < 6; i++)
687 if (key == key_info[i].key_default)
688 joy |= key_info[i].action;
693 if (key_status == KEY_PRESSED)
694 key_joystick_mapping |= joy;
696 key_joystick_mapping &= ~joy;
701 if (game_status != GAME_MODE_PLAYING)
702 key_joystick_mapping = 0;
704 if (key_status == KEY_RELEASED)
707 if ((key == KSYM_Return || key == KSYM_KP_Enter) &&
708 (GetKeyModState() & KMOD_Alt) && video.fullscreen_available)
710 setup.fullscreen = !setup.fullscreen;
712 ToggleFullscreenIfNeeded();
714 if (game_status == GAME_MODE_SETUP)
715 RedrawSetupScreenAfterFullscreenToggle();
721 if (game_status == GAME_MODE_PLAYING &&
722 local_player->LevelSolved_GameEnd &&
723 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
725 if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
726 (key == KSYM_Return || key == setup.shortcut.toggle_pause))
734 if (game_status == GAME_MODE_MAIN &&
735 (key == setup.shortcut.toggle_pause || key == KSYM_space))
737 StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE);
742 if (game_status == GAME_MODE_MAIN || game_status == GAME_MODE_PLAYING)
744 if (key == setup.shortcut.save_game)
746 else if (key == setup.shortcut.load_game)
748 else if (key == setup.shortcut.toggle_pause)
749 TapeTogglePause(TAPE_TOGGLE_MANUAL);
752 if (game_status == GAME_MODE_PLAYING && !network_playing)
754 int centered_player_nr_next = -999;
756 if (key == setup.shortcut.focus_player_all)
757 centered_player_nr_next = -1;
759 for (i = 0; i < MAX_PLAYERS; i++)
760 if (key == setup.shortcut.focus_player[i])
761 centered_player_nr_next = i;
763 if (centered_player_nr_next != -999)
765 game.centered_player_nr_next = centered_player_nr_next;
766 game.set_centered_player = TRUE;
770 tape.centered_player_nr_next = game.centered_player_nr_next;
771 tape.set_centered_player = TRUE;
776 HandleKeysSpecial(key);
778 if (HandleGadgetsKeyInput(key))
780 if (key != KSYM_Escape) /* always allow ESC key to be handled */
781 key = KSYM_UNDEFINED;
786 case GAME_MODE_PSEUDO_TYPENAME:
787 HandleTypeName(0, key);
790 case GAME_MODE_TITLE:
792 case GAME_MODE_LEVELS:
793 case GAME_MODE_SETUP:
795 case GAME_MODE_SCORES:
800 if (game_status == GAME_MODE_TITLE)
801 HandleTitleScreen(0, 0, 0, 0, MB_MENU_CHOICE);
802 else if (game_status == GAME_MODE_MAIN)
803 HandleMainMenu(0, 0, 0, 0, MB_MENU_CHOICE);
804 else if (game_status == GAME_MODE_LEVELS)
805 HandleChooseLevel(0, 0, 0, 0, MB_MENU_CHOICE);
806 else if (game_status == GAME_MODE_SETUP)
807 HandleSetupScreen(0, 0, 0, 0, MB_MENU_CHOICE);
808 else if (game_status == GAME_MODE_INFO)
809 HandleInfoScreen(0, 0, 0, 0, MB_MENU_CHOICE);
810 else if (game_status == GAME_MODE_SCORES)
811 HandleHallOfFame(0, 0, 0, 0, MB_MENU_CHOICE);
815 if (game_status == GAME_MODE_TITLE)
816 HandleTitleScreen(0, 0, 0, 0, MB_MENU_LEAVE);
817 else if (game_status == GAME_MODE_LEVELS)
818 HandleChooseLevel(0, 0, 0, 0, MB_MENU_LEAVE);
819 else if (game_status == GAME_MODE_SETUP)
820 HandleSetupScreen(0, 0, 0, 0, MB_MENU_LEAVE);
821 else if (game_status == GAME_MODE_INFO)
822 HandleInfoScreen(0, 0, 0, 0, MB_MENU_LEAVE);
823 else if (game_status == GAME_MODE_SCORES)
824 HandleHallOfFame(0, 0, 0, 0, MB_MENU_LEAVE);
828 if (game_status == GAME_MODE_LEVELS)
829 HandleChooseLevel(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
830 else if (game_status == GAME_MODE_SETUP)
831 HandleSetupScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
832 else if (game_status == GAME_MODE_INFO)
833 HandleInfoScreen(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
834 else if (game_status == GAME_MODE_SCORES)
835 HandleHallOfFame(0, 0, 0, -1 * SCROLL_PAGE, MB_MENU_MARK);
839 if (game_status == GAME_MODE_LEVELS)
840 HandleChooseLevel(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
841 else if (game_status == GAME_MODE_SETUP)
842 HandleSetupScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
843 else if (game_status == GAME_MODE_INFO)
844 HandleInfoScreen(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
845 else if (game_status == GAME_MODE_SCORES)
846 HandleHallOfFame(0, 0, 0, +1 * SCROLL_PAGE, MB_MENU_MARK);
851 GameFrameDelay = (GameFrameDelay == 500 ? GAME_FRAME_DELAY : 500);
860 case GAME_MODE_EDITOR:
861 if (!anyTextGadgetActiveOrJustFinished || key == KSYM_Escape)
862 HandleLevelEditorKeyInput(key);
865 case GAME_MODE_PLAYING:
870 RequestQuitGame(setup.ask_on_escape);
888 if (GameFrameDelay == 500)
889 GameFrameDelay = GAME_FRAME_DELAY;
891 GameFrameDelay = 500;
894 GameFrameDelay = (key - KSYM_0) * 10;
895 printf("Game speed == %d%% (%d ms delay between two frames)\n",
896 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
902 options.debug = FALSE;
903 printf("debug mode disabled\n");
907 options.debug = TRUE;
908 printf("debug mode enabled\n");
913 if (!global.fps_slowdown)
915 global.fps_slowdown = TRUE;
916 global.fps_slowdown_factor = 2;
917 printf("fps slowdown enabled -- display only every 2nd frame\n");
919 else if (global.fps_slowdown_factor == 2)
921 global.fps_slowdown_factor = 4;
922 printf("fps slowdown enabled -- display only every 4th frame\n");
926 global.fps_slowdown = FALSE;
927 global.fps_slowdown_factor = 1;
928 printf("fps slowdown disabled\n");
933 ScrollStepSize = TILEX/8;
934 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
938 ScrollStepSize = TILEX/4;
939 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
943 ScrollStepSize = TILEX/2;
944 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
948 ScrollStepSize = TILEX;
949 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
953 printf("::: currently using game engine version %d\n",
954 game.engine_version);
965 if (key == KSYM_Escape)
967 game_status = GAME_MODE_MAIN;
977 if (button_status && game_status != GAME_MODE_PLAYING)
979 HandleButton(0, 0, -button_status, button_status);
984 #if defined(NETWORK_AVALIABLE)
992 static int HandleJoystickForAllPlayers()
997 for (i = 0; i < MAX_PLAYERS; i++)
1002 if (!setup.input[i].use_joystick)
1006 joy_action = Joystick(i);
1007 result |= joy_action;
1009 if (!setup.input[i].use_joystick)
1012 stored_player[i].action = joy_action;
1018 void HandleJoystick()
1020 int joystick = HandleJoystickForAllPlayers();
1021 int keyboard = key_joystick_mapping;
1022 int joy = (joystick | keyboard);
1023 int left = joy & JOY_LEFT;
1024 int right = joy & JOY_RIGHT;
1025 int up = joy & JOY_UP;
1026 int down = joy & JOY_DOWN;
1027 int button = joy & JOY_BUTTON;
1028 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
1029 int dx = (left ? -1 : right ? 1 : 0);
1030 int dy = (up ? -1 : down ? 1 : 0);
1032 switch (game_status)
1034 case GAME_MODE_TITLE:
1035 case GAME_MODE_MAIN:
1036 case GAME_MODE_LEVELS:
1037 case GAME_MODE_SETUP:
1038 case GAME_MODE_INFO:
1040 static unsigned long joystickmove_delay = 0;
1042 if (joystick && !button &&
1043 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
1044 newbutton = dx = dy = 0;
1046 if (game_status == GAME_MODE_TITLE)
1047 HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1048 else if (game_status == GAME_MODE_MAIN)
1049 HandleMainMenu(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1050 else if (game_status == GAME_MODE_LEVELS)
1051 HandleChooseLevel(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1052 else if (game_status == GAME_MODE_SETUP)
1053 HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1054 else if (game_status == GAME_MODE_INFO)
1055 HandleInfoScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
1059 case GAME_MODE_SCORES:
1060 HandleHallOfFame(0, 0, dx, dy, !newbutton);
1063 case GAME_MODE_EDITOR:
1064 HandleLevelEditorIdle();
1067 case GAME_MODE_PLAYING:
1068 if (tape.playing || keyboard)
1069 newbutton = ((joy & JOY_BUTTON) != 0);
1072 if (local_player->LevelSolved_GameEnd && newbutton)
1074 if (AllPlayersGone && newbutton)