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 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 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
209 BlitBitmap(drawto, window, x,y, width,height, x,y);
214 void HandleButtonEvent(ButtonEvent *event)
216 motion_status = FALSE;
218 if (event->type == EVENT_BUTTONPRESS)
219 button_status = event->button;
221 button_status = MB_RELEASED;
223 HandleButton(event->x, event->y, button_status);
226 void HandleMotionEvent(MotionEvent *event)
230 if (!QueryPointer(window, &win_x, &win_y))
231 return; /* window and pointer are on different screens */
233 if (!button_status && game_status != LEVELED)
236 motion_status = TRUE;
238 HandleButton(win_x, win_y, button_status);
241 void HandleKeyEvent(KeyEvent *event)
243 int key_status = (event->type==EVENT_KEYPRESS ? KEY_PRESSED : KEY_RELEASED);
244 boolean with_modifiers = (game_status == PLAYING ? FALSE : TRUE);
245 Key key = GetEventKey(event, with_modifiers);
247 HandleKey(key, key_status);
250 void HandleFocusEvent(FocusChangeEvent *event)
252 static int old_joystick_status = -1;
254 if (event->type == EVENT_FOCUSOUT)
258 KeyboardAutoRepeatOn();
259 old_joystick_status = joystick_status;
260 joystick_status = JOYSTICK_OFF;
262 /* simulate key release events for still pressed keys */
263 key_joystick_mapping = 0;
264 for (i=0; i<MAX_PLAYERS; i++)
265 stored_player[i].action = 0;
267 else if (event->type == EVENT_FOCUSIN)
269 /* When there are two Rocks'n'Diamonds windows which overlap and
270 the player moves the pointer from one game window to the other,
271 a 'FocusOut' event is generated for the window the pointer is
272 leaving and a 'FocusIn' event is generated for the window the
273 pointer is entering. In some cases, it can happen that the
274 'FocusIn' event is handled by the one game process before the
275 'FocusOut' event by the other game process. In this case the
276 X11 environment would end up with activated keyboard auto repeat,
277 because unfortunately this is a global setting and not (which
278 would be far better) set for each X11 window individually.
279 The effect would be keyboard auto repeat while playing the game
280 (game_status == PLAYING), which is not desired.
281 To avoid this special case, we just wait 1/10 second before
282 processing the 'FocusIn' event.
285 if (game_status == PLAYING)
288 KeyboardAutoRepeatOff();
290 if (old_joystick_status != -1)
291 joystick_status = old_joystick_status;
295 void HandleClientMessageEvent(ClientMessageEvent *event)
297 #ifdef USE_SDL_LIBRARY
298 CloseAllAndExit(0); /* the only possible message here is SDL_QUIT */
301 if ((event->window == window) &&
302 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
308 void HandleButton(int mx, int my, int button)
310 static int old_mx = 0, old_my = 0;
324 HandleGadgets(mx, my, button);
329 HandleMainMenu(mx,my, 0,0, button);
333 HandleTypeName(0, KEY_Return);
337 HandleChooseLevel(mx,my, 0,0, button);
341 HandleHallOfFame(0,0, 0,0, button);
348 HandleHelpScreen(button);
352 HandleSetupScreen(mx,my, 0,0, button);
356 HandleSetupInputScreen(mx,my, 0,0, button);
361 if (button == MB_RELEASED)
363 int sx = (mx - SX) / TILEX;
364 int sy = (my - SY) / TILEY;
366 if (IN_VIS_FIELD(sx,sy))
371 printf("INFO: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
373 if (!IN_LEV_FIELD(x, y))
376 printf(" Feld[%d][%d] == %d\n", x,y, Feld[x][y]);
377 printf(" Store[%d][%d] == %d\n", x,y, Store[x][y]);
378 printf(" Store2[%d][%d] == %d\n", x,y, Store2[x][y]);
379 printf(" StorePlayer[%d][%d] == %d\n", x,y, StorePlayer[x][y]);
380 printf(" MovPos[%d][%d] == %d\n", x,y, MovPos[x][y]);
381 printf(" MovDir[%d][%d] == %d\n", x,y, MovDir[x][y]);
382 printf(" MovDelay[%d][%d] == %d\n", x,y, MovDelay[x][y]);
394 void HandleKey(Key key, int key_status)
397 static struct SetupKeyboardInfo custom_key;
405 { &custom_key.left, DEFAULT_KEY_LEFT, JOY_LEFT },
406 { &custom_key.right, DEFAULT_KEY_RIGHT, JOY_RIGHT },
407 { &custom_key.up, DEFAULT_KEY_UP, JOY_UP },
408 { &custom_key.down, DEFAULT_KEY_DOWN, JOY_DOWN },
409 { &custom_key.snap, DEFAULT_KEY_SNAP, JOY_BUTTON_1 },
410 { &custom_key.bomb, DEFAULT_KEY_BOMB, JOY_BUTTON_2 }
413 if (game_status == PLAYING)
417 for (pnr=0; pnr<MAX_PLAYERS; pnr++)
422 if (setup.input[pnr].use_joystick)
425 custom_key = setup.input[pnr].key;
428 if (key == *key_info[i].key_custom)
429 key_action |= key_info[i].action;
431 if (key_status == KEY_PRESSED)
432 stored_player[pnr].action |= key_action;
434 stored_player[pnr].action &= ~key_action;
442 if (key == key_info[i].key_default)
443 joy |= key_info[i].action;
448 if (key_status == KEY_PRESSED)
449 key_joystick_mapping |= joy;
451 key_joystick_mapping &= ~joy;
456 if (game_status != PLAYING)
457 key_joystick_mapping = 0;
459 if (key_status == KEY_RELEASED)
462 if ((key == KEY_Return || key == KEY_space) &&
463 game_status == PLAYING && AllPlayersGone)
465 CloseDoor(DOOR_CLOSE_1);
466 game_status = MAINMENU;
471 /* allow quick escape to the main menu with the Escape key */
472 if (key == KEY_Escape && game_status != MAINMENU)
474 CloseDoor(DOOR_CLOSE_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
475 game_status = MAINMENU;
484 if (game_status == PLAYING && (tape.playing || tape.pausing))
491 HandleGadgetsKeyInput(key);
496 HandleTypeName(0, key);
507 if (game_status == MAINMENU)
508 HandleMainMenu(0,0, 0,0, MB_MENU_CHOICE);
509 else if (game_status == CHOOSELEVEL)
510 HandleChooseLevel(0,0, 0,0, MB_MENU_CHOICE);
511 else if (game_status == SETUP)
512 HandleSetupScreen(0,0, 0,0, MB_MENU_CHOICE);
513 else if (game_status == SETUPINPUT)
514 HandleSetupInputScreen(0,0, 0,0, MB_MENU_CHOICE);
518 if (game_status == CHOOSELEVEL)
519 HandleChooseLevel(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
523 if (game_status == CHOOSELEVEL)
524 HandleChooseLevel(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
533 HandleHelpScreen(MB_RELEASED);
541 game_status = MAINMENU;
547 HandleHallOfFame(0,0, 0,-SCR_FIELDY, MB_MENU_MARK);
551 HandleHallOfFame(0,0, 0,SCR_FIELDY, MB_MENU_MARK);
560 HandleLevelEditorKeyInput(key);
581 if (GameFrameDelay == 500)
582 GameFrameDelay = GAME_FRAME_DELAY;
584 GameFrameDelay = 500;
587 GameFrameDelay = (key - KEY_0) * 10;
588 printf("Game speed == %d%% (%d ms delay between two frames)\n",
589 GAME_FRAME_DELAY * 100 / GameFrameDelay, GameFrameDelay);
595 if (ScrollStepSize == TILEX/8)
596 ScrollStepSize = TILEX/4;
598 ScrollStepSize = TILEX/8;
599 printf("ScrollStepSize == %d\n", ScrollStepSize);
608 ScrollStepSize = TILEX/4;
613 ScrollStepSize = TILEX/8;
615 printf("MoveSpeed == %d\n", MoveSpeed);
620 ScrollStepSize = TILEX/8;
621 printf("ScrollStepSize == %d (1/8)\n", ScrollStepSize);
625 ScrollStepSize = TILEX/4;
626 printf("ScrollStepSize == %d (1/4)\n", ScrollStepSize);
630 ScrollStepSize = TILEX/2;
631 printf("ScrollStepSize == %d (1/2)\n", ScrollStepSize);
635 ScrollStepSize = TILEX;
636 printf("ScrollStepSize == %d (1/1)\n", ScrollStepSize);
643 local_player->dynamite = 1000;
654 for(i=0; i<MAX_PLAYERS; i++)
656 printf("Player %d:\n", i);
657 printf(" jx == %d, jy == %d\n",
658 stored_player[i].jx, stored_player[i].jy);
659 printf(" last_jx == %d, last_jy == %d\n",
660 stored_player[i].last_jx, stored_player[i].last_jy);
679 void HandleNoXEvent()
681 if (button_status && game_status != PLAYING)
683 HandleButton(0, 0, -button_status);
694 if (game_status == PLAYING)
698 static int HandleJoystickForAllPlayers()
703 for (i=0; i<MAX_PLAYERS; i++)
708 if (!setup.input[i].use_joystick)
712 joy_action = Joystick(i);
713 result |= joy_action;
716 if (!setup.input[i].use_joystick)
720 stored_player[i].action = joy_action;
726 void HandleJoystick()
728 int joystick = HandleJoystickForAllPlayers();
729 int keyboard = key_joystick_mapping;
730 int joy = (joystick | keyboard);
731 int left = joy & JOY_LEFT;
732 int right = joy & JOY_RIGHT;
733 int up = joy & JOY_UP;
734 int down = joy & JOY_DOWN;
735 int button = joy & JOY_BUTTON;
736 int newbutton = (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED);
737 int dx = (left ? -1 : right ? 1 : 0);
738 int dy = (up ? -1 : down ? 1 : 0);
747 static unsigned long joystickmove_delay = 0;
749 if (joystick && !button &&
750 !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
751 newbutton = dx = dy = 0;
753 if (game_status==MAINMENU)
754 HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
755 else if (game_status==CHOOSELEVEL)
756 HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
757 else if (game_status==SETUP)
758 HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
759 else if (game_status==SETUPINPUT)
760 HandleSetupInputScreen(0,0,dx,dy,
761 newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
766 HandleHallOfFame(0,0, dx,dy, !newbutton);
770 HandleHelpScreen(!newbutton);
774 if (tape.playing || keyboard)
775 newbutton = ((joy & JOY_BUTTON) != 0);
777 if (AllPlayersGone && newbutton)
779 CloseDoor(DOOR_CLOSE_1);
780 game_status = MAINMENU;