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
32 /* event filter especially needed for SDL event filtering due to
33 delay problems with lots of mouse motion events when mouse
36 int EventFilter(const Event *event)
38 if (event->type != EVENT_MOTIONNOTIFY)
41 /* get mouse motion events without pressed button only in level editor */
42 if (button_status == MB_RELEASED && game_status != LEVELED)
52 if (PendingEvent()) /* got event */
58 if (EventFilter(&event))
62 case EVENT_BUTTONPRESS:
63 case EVENT_BUTTONRELEASE:
64 HandleButtonEvent((ButtonEvent *) &event);
67 case EVENT_MOTIONNOTIFY:
68 HandleMotionEvent((MotionEvent *) &event);
72 case EVENT_KEYRELEASE:
73 HandleKeyEvent((KeyEvent *) &event);
77 HandleOtherEvents(&event);
85 /* don't use all CPU time when idle; the main loop while playing
86 has its own synchronization and is CPU friendly, too */
88 if (game_status != PLAYING)
91 if (!PendingEvent()) /* delay only if no pending events */
95 /* refresh window contents from drawing buffer, if needed */
98 if (game_status == EXITGAME)
103 void HandleOtherEvents(Event *event)
108 HandleExposeEvent((ExposeEvent *) event);
111 case EVENT_UNMAPNOTIFY:
112 SleepWhileUnmapped();
117 HandleFocusEvent((FocusChangeEvent *) event);
120 case EVENT_CLIENTMESSAGE:
121 HandleClientMessageEvent((ClientMessageEvent *) event);
124 #ifdef USE_SDL_LIBRARY
125 case SDL_JOYAXISMOTION:
126 case SDL_JOYBUTTONDOWN:
127 case SDL_JOYBUTTONUP:
128 HandleJoystickEvent(event);
137 void ClearEventQueue()
139 while (PendingEvent())
147 case EVENT_BUTTONRELEASE:
148 button_status = MB_RELEASED;
151 case EVENT_KEYRELEASE:
152 key_joystick_mapping = 0;
156 HandleOtherEvents(&event);
162 void SleepWhileUnmapped()
164 boolean window_unmapped = TRUE;
166 KeyboardAutoRepeatOn();
168 while(window_unmapped)
176 case EVENT_BUTTONRELEASE:
177 button_status = MB_RELEASED;
180 case EVENT_KEYRELEASE:
181 key_joystick_mapping = 0;
184 case EVENT_MAPNOTIFY:
185 window_unmapped = FALSE;
188 case EVENT_UNMAPNOTIFY:
189 /* this is only to surely prevent the 'should not happen' case
190 * of recursively looping between 'SleepWhileUnmapped()' and
191 * 'HandleOtherEvents()' which usually calls this funtion.
196 HandleOtherEvents(&event);
201 if (game_status == PLAYING)
202 KeyboardAutoRepeatOff();
205 void HandleExposeEvent(ExposeEvent *event)
207 #ifndef USE_SDL_LIBRARY
208 int x = event->x, y = event->y;
209 int width = event->width, height = event->height;
211 if (setup.direct_draw && game_status==PLAYING)
214 int x1 = (x-SX)/TILEX, y1 = (y-SY)/TILEY;
215 int x2 = (x-SX+width)/TILEX, y2 = (y-SY+height)/TILEY;
217 SetDrawtoField(DRAW_BACKBUFFER);
219 for(xx=0; xx<SCR_FIELDX; xx++)
220 for(yy=0; yy<SCR_FIELDY; yy++)
221 if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
222 DrawScreenField(xx,yy);
225 SetDrawtoField(DRAW_DIRECT);
228 if (setup.soft_scrolling && game_status == PLAYING)
230 int fx = FX, fy = FY;
232 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
233 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
235 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
238 BlitBitmap(drawto, window, x,y, width,height, x,y);
244 void HandleButtonEvent(ButtonEvent *event)
246 motion_status = FALSE;
248 if (event->type == EVENT_BUTTONPRESS)
249 button_status = event->button;
251 button_status = MB_RELEASED;
253 HandleButton(event->x, event->y, button_status);
256 void HandleMotionEvent(MotionEvent *event)
258 if (!PointerInWindow(window))
259 return; /* window and pointer are on different screens */
262 if (button_status == MB_RELEASED && game_status != LEVELED)
266 motion_status = TRUE;
268 HandleButton(event->x, event->y, button_status);
271 void HandleKeyEvent(KeyEvent *event)
273 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
274 boolean with_modifiers = (game_status == PLAYING ? FALSE : TRUE);
275 Key key = GetEventKey(event, with_modifiers);
277 HandleKey(key, key_status);
280 void HandleFocusEvent(FocusChangeEvent *event)
282 static int old_joystick_status = -1;
284 if (event->type == EVENT_FOCUSOUT)
288 KeyboardAutoRepeatOn();
289 old_joystick_status = joystick_status;
290 joystick_status = JOYSTICK_OFF;
292 /* simulate key release events for still pressed keys */
293 key_joystick_mapping = 0;
294 for (i=0; i<MAX_PLAYERS; i++)
295 stored_player[i].action = 0;
297 else if (event->type == EVENT_FOCUSIN)
299 /* When there are two Rocks'n'Diamonds windows which overlap and
300 the player moves the pointer from one game window to the other,
301 a 'FocusOut' event is generated for the window the pointer is
302 leaving and a 'FocusIn' event is generated for the window the
303 pointer is entering. In some cases, it can happen that the
304 'FocusIn' event is handled by the one game process before the
305 'FocusOut' event by the other game process. In this case the
306 X11 environment would end up with activated keyboard auto repeat,
307 because unfortunately this is a global setting and not (which
308 would be far better) set for each X11 window individually.
309 The effect would be keyboard auto repeat while playing the game
310 (game_status == PLAYING), which is not desired.
311 To avoid this special case, we just wait 1/10 second before
312 processing the 'FocusIn' event.
315 if (game_status == PLAYING)
318 KeyboardAutoRepeatOff();
320 if (old_joystick_status != -1)
321 joystick_status = old_joystick_status;
325 void HandleClientMessageEvent(ClientMessageEvent *event)
327 #ifdef USE_SDL_LIBRARY
328 CloseAllAndExit(0); /* the only possible message here is SDL_QUIT */
331 if ((event->window == window) &&
332 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
338 void HandleButton(int mx, int my, int button)
340 static int old_mx = 0, old_my = 0;
354 HandleGadgets(mx, my, button);
359 HandleMainMenu(mx,my, 0,0, button);
363 HandleTypeName(0, KEY_Return);
367 HandleChooseLevel(mx,my, 0,0, button);
371 HandleHallOfFame(0,0, 0,0, button);
378 HandleHelpScreen(button);
382 HandleSetupScreen(mx,my, 0,0, button);
386 HandleSetupInputScreen(mx,my, 0,0, button);
391 if (button == MB_RELEASED)
393 int sx = (mx - SX) / TILEX;
394 int sy = (my - SY) / TILEY;
396 if (IN_VIS_FIELD(sx,sy))
401 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
403 if (!IN_LEV_FIELD(x, y))
406 printf(" Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
407 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
408 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
409 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
410 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
411 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
412 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
424 void HandleKey(Key key, int key_status)
427 static struct SetupKeyboardInfo custom_key;
435 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
436 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
437 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
438 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
439 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
440 { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
443 if (game_status == PLAYING)
447 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
452 if (setup.input[pnr].use_joystick)
455 custom_key = setup.input[pnr].key;
458 if (key == *key_info[i].key_custom)
459 key_action |= key_info[i].action;
461 if (key_status == KEY_PRESSED)
462 stored_player[pnr].action |= key_action;
464 stored_player[pnr].action &= ~key_action;
472 if (key == key_info[i].key_default)
473 joy |= key_info[i].action;
478 if (key_status == KEY_PRESSED)
479 key_joystick_mapping |= joy;
481 key_joystick_mapping &= ~joy;
486 if (game_status != PLAYING)
487 key_joystick_mapping = 0;
489 if (key_status == KEY_RELEASED)
492 if ((key == KEY_Return || key == KEY_space) &&
493 game_status == PLAYING && AllPlayersGone)
495 CloseDoor(DOOR_CLOSE_1);
496 game_status = MAINMENU;
501 /* allow quick escape to the main menu with the Escape key */
502 if (key == KEY_Escape && game_status != MAINMENU)
504 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
505 game_status = MAINMENU;
514 if (game_status == PLAYING && (tape.playing || tape.pausing))
521 HandleGadgetsKeyInput(key);
526 HandleTypeName(0, key);
537 if (game_status == MAINMENU)
538 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
539 else if (game_status == CHOOSELEVEL)
540 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
541 else if (game_status == SETUP)
542 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
543 else if (game_status == SETUPINPUT)
544 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
548 if (game_status == CHOOSELEVEL)
549 HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
553 if (game_status == CHOOSELEVEL)
554 HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
563 HandleHelpScreen(MB_RELEASED);
571 game_status = MAINMENU;
577 HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
581 HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
590 HandleLevelEditorKeyInput(key);
611 if (GameFrameDelay == 500)
612 GameFrameDelay = GAME_FRAME_DELAY;
614 GameFrameDelay = 500;
617 GameFrameDelay = (key - KEY_0) * 10;
618 printf("Game speed == %d%% (%d ms delay between two frames)\n",
619 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
625 options.debug = FALSE;
626 printf("debug mode disabled\n");
630 options.debug = TRUE;
631 printf("debug mode enabled\n");
636 if (!global.fps_slowdown)
638 global.fps_slowdown = TRUE;
639 global.fps_slowdown_factor = 2;
640 printf("fps slowdown enabled -- display only every 2nd frame\n");
642 else if (global.fps_slowdown_factor == 2)
644 global.fps_slowdown_factor = 4;
645 printf("fps slowdown enabled -- display only every 4th frame\n");
649 global.fps_slowdown = FALSE;
650 global.fps_slowdown_factor = 1;
651 printf("fps slowdown disabled\n");
657 if (ScrollStepSize == TILEX/8)
658 ScrollStepSize = TILEX/4;
660 ScrollStepSize = TILEX/8;
661 printf("ScrollStepSize == %d\n", ScrollStepSize);
670 ScrollStepSize = TILEX/4;
675 ScrollStepSize = TILEX/8;
677 printf("MoveSpeed == %d\n", MoveSpeed);
682 ScrollStepSize = TILEX/8;
683 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
687 ScrollStepSize = TILEX/4;
688 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
692 ScrollStepSize = TILEX/2;
693 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
697 ScrollStepSize = TILEX;
698 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
705 local_player->dynamite = 1000;
716 for(i=0; i<MAX_PLAYERS; i++)
718 printf("Player %d:\n", i);
719 printf(" jx == %d, jy == %d\n",
720 stored_player[i].jx, stored_player[i].jy);
721 printf(" last_jx == %d, last_jy == %d\n",
722 stored_player[i].last_jx, stored_player[i].last_jy);
741 void HandleNoXEvent()
743 if (button_status && game_status != PLAYING)
745 HandleButton(0, 0, -button_status);
749 #if !defined(MSDOS) && !defined(WIN32)
756 if (game_status == PLAYING)
760 static int HandleJoystickForAllPlayers()
765 for (i=0; i<MAX_PLAYERS; i++)
770 if (!setup.input[i].use_joystick)
774 joy_action = Joystick(i);
775 result |= joy_action;
778 if (!setup.input[i].use_joystick)
782 stored_player[i].action = joy_action;
788 void HandleJoystick()
790 int joystick = HandleJoystickForAllPlayers();
791 int keyboard = key_joystick_mapping;
792 int joy = (joystick | keyboard);
793 int left = joy & JOY_LEFT;
794 int right = joy & JOY_RIGHT;
795 int up = joy & JOY_UP;
796 int down = joy & JOY_DOWN;
797 int button = joy & JOY_BUTTON;
798 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
799 int dx = (left ? -1 : right ? 1 : 0);
800 int dy = (up ? -1 : down ? 1 : 0);
809 static unsigned long joystickmove_delay = 0;
811 if (joystick && !button &&
812 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
813 newbutton = dx = dy = 0;
815 if (game_status==MAINMENU)
816 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
817 else if (game_status==CHOOSELEVEL)
818 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
819 else if (game_status==SETUP)
820 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
821 else if (game_status==SETUPINPUT)
822 HandleSetupInputScreen(0,0,dx,dy,
823 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
828 HandleHallOfFame(0,0, dx,dy, !newbutton);
832 HandleHelpScreen(!newbutton);
836 if (tape.playing || keyboard)
837 newbutton = ((joy & JOY_BUTTON) != 0);
839 if (AllPlayersGone && newbutton)
841 CloseDoor(DOOR_CLOSE_1);
842 game_status = MAINMENU;