1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static int getGraphicAnimationPhase(int, int, int);
36 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
38 static void UnmapToolButtons();
39 static void HandleToolButtons(struct GadgetInfo *);
41 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
42 static int request_gadget_id = -1;
44 void SetDrawtoField(int mode)
46 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
57 drawto_field = fieldbuffer;
59 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
70 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
74 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
76 if (game_status == PLAYING)
82 width = gfx.sxsize + 2 * TILEX;
83 height = gfx.sysize + 2 * TILEY;
86 if (force_redraw || setup.direct_draw)
89 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
90 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
92 if (setup.direct_draw)
93 SetDrawtoField(DRAW_BACKBUFFER);
95 for(xx=BX1; xx<=BX2; xx++)
96 for(yy=BY1; yy<=BY2; yy++)
97 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
98 DrawNewScreenField(xx, yy);
101 if (setup.direct_draw)
102 SetDrawtoField(DRAW_DIRECT);
105 if (setup.soft_scrolling)
107 int fx = FX, fy = FY;
109 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
110 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
112 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
116 BlitBitmap(drawto, window, x, y, width, height, x, y);
122 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
124 if (setup.direct_draw && game_status == PLAYING)
125 redraw_mask &= ~REDRAW_MAIN;
127 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
128 redraw_mask |= REDRAW_FIELD;
130 if (redraw_mask & REDRAW_FIELD)
131 redraw_mask &= ~REDRAW_TILES;
133 if (redraw_mask == REDRAW_NONE)
136 if (global.fps_slowdown && game_status == PLAYING)
138 static boolean last_frame_skipped = FALSE;
139 boolean skip_even_when_not_scrolling = TRUE;
140 boolean just_scrolling = (ScreenMovDir != 0);
141 boolean verbose = FALSE;
143 if (global.fps_slowdown_factor > 1 &&
144 (FrameCounter % global.fps_slowdown_factor) &&
145 (just_scrolling || skip_even_when_not_scrolling))
147 redraw_mask &= ~REDRAW_MAIN;
149 last_frame_skipped = TRUE;
152 printf("FRAME SKIPPED\n");
156 if (last_frame_skipped)
157 redraw_mask |= REDRAW_FIELD;
159 last_frame_skipped = FALSE;
162 printf("frame not skipped\n");
166 /* synchronize X11 graphics at this point; if we would synchronize the
167 display immediately after the buffer switching (after the XFlush),
168 this could mean that we have to wait for the graphics to complete,
169 although we could go on doing calculations for the next frame */
173 if (redraw_mask & REDRAW_ALL)
175 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
179 if (redraw_mask & REDRAW_FIELD)
181 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
183 BlitBitmap(backbuffer, window,
184 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
188 int fx = FX, fy = FY;
190 if (setup.soft_scrolling)
192 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
193 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
196 if (setup.soft_scrolling ||
197 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
198 ABS(ScreenMovPos) == ScrollStepSize ||
199 redraw_tiles > REDRAWTILES_THRESHOLD)
201 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
205 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
207 (setup.soft_scrolling ?
208 "setup.soft_scrolling" :
209 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
210 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
211 ABS(ScreenGfxPos) == ScrollStepSize ?
212 "ABS(ScreenGfxPos) == ScrollStepSize" :
213 "redraw_tiles > REDRAWTILES_THRESHOLD"));
219 redraw_mask &= ~REDRAW_MAIN;
222 if (redraw_mask & REDRAW_DOORS)
224 if (redraw_mask & REDRAW_DOOR_1)
225 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
226 if (redraw_mask & REDRAW_DOOR_2)
228 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
229 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
232 if (redraw_mask & REDRAW_VIDEO_1)
233 BlitBitmap(backbuffer, window,
234 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
235 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
236 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
237 if (redraw_mask & REDRAW_VIDEO_2)
238 BlitBitmap(backbuffer, window,
239 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
240 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
241 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
242 if (redraw_mask & REDRAW_VIDEO_3)
243 BlitBitmap(backbuffer, window,
244 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
245 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
246 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
249 if (redraw_mask & REDRAW_DOOR_3)
250 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
251 redraw_mask &= ~REDRAW_DOORS;
254 if (redraw_mask & REDRAW_MICROLEVEL)
256 BlitBitmap(backbuffer, window,
257 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
258 MICROLEV_XPOS, MICROLEV_YPOS);
259 BlitBitmap(backbuffer, window,
260 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
261 SX, MICROLABEL_YPOS);
262 redraw_mask &= ~REDRAW_MICROLEVEL;
265 if (redraw_mask & REDRAW_TILES)
267 for(x=0; x<SCR_FIELDX; x++)
268 for(y=0; y<SCR_FIELDY; y++)
269 if (redraw[redraw_x1 + x][redraw_y1 + y])
270 BlitBitmap(buffer, window,
271 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
272 SX + x * TILEX, SY + y * TILEY);
275 if (redraw_mask & REDRAW_FPS) /* display frames per second */
280 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
281 if (!global.fps_slowdown)
284 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
285 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
290 for(x=0; x<MAX_BUF_XSIZE; x++)
291 for(y=0; y<MAX_BUF_YSIZE; y++)
294 redraw_mask = REDRAW_NONE;
300 long fading_delay = 300;
302 if (setup.fading && (redraw_mask & REDRAW_FIELD))
309 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
312 for(i=0;i<2*FULL_SYSIZE;i++)
314 for(y=0;y<FULL_SYSIZE;y++)
316 BlitBitmap(backbuffer, window,
317 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
325 for(i=1;i<FULL_SYSIZE;i+=2)
326 BlitBitmap(backbuffer, window,
327 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
333 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
334 BlitBitmapMasked(backbuffer, window,
335 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
340 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
341 BlitBitmapMasked(backbuffer, window,
342 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
347 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
348 BlitBitmapMasked(backbuffer, window,
349 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
354 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
355 BlitBitmapMasked(backbuffer, window,
356 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
361 redraw_mask &= ~REDRAW_MAIN;
370 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
372 if (setup.soft_scrolling && game_status == PLAYING)
374 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
375 SetDrawtoField(DRAW_BUFFERED);
378 SetDrawtoField(DRAW_BACKBUFFER);
380 if (setup.direct_draw && game_status == PLAYING)
382 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
383 SetDrawtoField(DRAW_DIRECT);
386 redraw_mask |= REDRAW_FIELD;
389 void MarkTileDirty(int x, int y)
391 int xx = redraw_x1 + x;
392 int yy = redraw_y1 + y;
397 redraw[xx][yy] = TRUE;
398 redraw_mask |= REDRAW_TILES;
401 void SetBorderElement()
405 BorderElement = EL_EMPTY;
407 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
409 for(x=0; x<lev_fieldx; x++)
411 if (!IS_MASSIVE(Feld[x][y]))
412 BorderElement = EL_STEELWALL;
414 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
420 void DrawAllPlayers()
424 for(i=0; i<MAX_PLAYERS; i++)
425 if (stored_player[i].active)
426 DrawPlayer(&stored_player[i]);
429 void DrawPlayerField(int x, int y)
431 if (!IS_PLAYER(x, y))
434 DrawPlayer(PLAYERINFO(x, y));
438 void DrawPlayer(struct PlayerInfo *player)
440 int jx = player->jx, jy = player->jy;
441 int last_jx = player->last_jx, last_jy = player->last_jy;
442 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
443 int sx = SCREENX(jx), sy = SCREENY(jy);
444 int sxx = 0, syy = 0;
445 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
447 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
449 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
453 if (!IN_LEV_FIELD(jx,jy))
455 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
456 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
457 printf("DrawPlayerField(): This should never happen!\n");
462 if (element == EL_EXPLOSION)
465 /* draw things in the field the player is leaving, if needed */
467 if (player_is_moving)
469 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
471 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
472 if (last_element == EL_DYNAMITE_ACTIVE)
473 DrawDynamite(last_jx, last_jy);
475 DrawLevelFieldThruMask(last_jx, last_jy);
477 else if (last_element == EL_DYNAMITE_ACTIVE)
478 DrawDynamite(last_jx, last_jy);
480 DrawLevelField(last_jx, last_jy);
482 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
486 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
487 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
489 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
492 DrawLevelField(next_jx, next_jy);
496 if (!IN_SCR_FIELD(sx, sy))
499 if (setup.direct_draw)
500 SetDrawtoField(DRAW_BUFFERED);
502 /* draw things behind the player, if needed */
505 DrawLevelElement(jx, jy, Store[jx][jy]);
506 else if (!IS_ACTIVE_BOMB(element))
507 DrawLevelField(jx, jy);
509 DrawLevelElement(jx, jy, EL_EMPTY);
511 /* draw player himself */
513 if (game.emulation == EMU_SUPAPLEX)
515 static int last_dir = MV_LEFT;
516 int action = (player->programmed_action ? player->programmed_action :
518 boolean action_moving =
520 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
521 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
523 graphic = GFX_SP_MURPHY;
527 if (player->MovDir == MV_LEFT)
528 graphic = GFX_MURPHY_PUSH_LEFT;
529 else if (player->MovDir == MV_RIGHT)
530 graphic = GFX_MURPHY_PUSH_RIGHT;
531 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
532 graphic = GFX_MURPHY_PUSH_LEFT;
533 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
534 graphic = GFX_MURPHY_PUSH_RIGHT;
536 else if (player->snapped)
538 if (player->MovDir == MV_LEFT)
539 graphic = GFX_MURPHY_SNAP_LEFT;
540 else if (player->MovDir == MV_RIGHT)
541 graphic = GFX_MURPHY_SNAP_RIGHT;
542 else if (player->MovDir == MV_UP)
543 graphic = GFX_MURPHY_SNAP_UP;
544 else if (player->MovDir == MV_DOWN)
545 graphic = GFX_MURPHY_SNAP_DOWN;
547 else if (action_moving)
549 if (player->MovDir == MV_LEFT)
550 graphic = GFX_MURPHY_GO_LEFT;
551 else if (player->MovDir == MV_RIGHT)
552 graphic = GFX_MURPHY_GO_RIGHT;
553 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
554 graphic = GFX_MURPHY_GO_LEFT;
555 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
556 graphic = GFX_MURPHY_GO_RIGHT;
558 graphic = GFX_MURPHY_GO_LEFT;
560 graphic += getGraphicAnimationPhase(3, 2, ANIM_PINGPONG);
563 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
564 last_dir = player->MovDir;
568 if (player->MovDir == MV_LEFT)
570 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
571 else if (player->MovDir == MV_RIGHT)
573 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
574 else if (player->MovDir == MV_UP)
575 graphic = GFX_SPIELER1_UP;
576 else /* MV_DOWN || MV_NO_MOVING */
577 graphic = GFX_SPIELER1_DOWN;
579 graphic += player->index_nr * 3 * HEROES_PER_LINE;
580 graphic += player->Frame;
585 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
586 sxx = player->GfxPos;
588 syy = player->GfxPos;
591 if (!setup.soft_scrolling && ScreenMovPos)
594 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
596 if (SHIELD_ON(player))
598 int graphic = (player->shield_deadly_time_left ? GFX2_SHIELD_ACTIVE :
599 GFX2_SHIELD_PASSIVE);
601 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
602 3, 8, ANIM_PINGPONG);
605 if (player->Pushing && player->GfxPos)
607 int px = SCREENX(next_jx), py = SCREENY(next_jy);
609 if (element == EL_SOKOBAN_FIELD_EMPTY ||
610 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
611 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
615 int element = Feld[next_jx][next_jy];
616 int graphic = el2gfx(element);
618 if ((element == EL_ROCK ||
619 element == EL_SP_ZONK ||
620 element == EL_BD_ROCK) && sxx)
622 int phase = (player->GfxPos / (TILEX / 4));
624 if (player->MovDir == MV_LEFT)
627 graphic += (phase + 4) % 4;
630 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
634 /* draw things in front of player (active dynamite or dynabombs) */
636 if (IS_ACTIVE_BOMB(element))
638 graphic = el2gfx(element);
640 if (element == EL_DYNAMITE_ACTIVE)
642 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
647 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
651 if (game.emulation == EMU_SUPAPLEX)
652 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
654 DrawGraphicThruMask(sx, sy, graphic + phase);
657 if (player_is_moving && last_element == EL_EXPLOSION)
659 int phase = Frame[last_jx][last_jy];
663 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
664 GFX_EXPLOSION + ((phase - 1) / delay - 1));
667 /* draw elements that stay over the player */
668 /* handle the field the player is leaving ... */
669 if (player_is_moving && IS_OVER_PLAYER(last_element))
670 DrawLevelField(last_jx, last_jy);
671 /* ... and the field the player is entering */
672 if (IS_OVER_PLAYER(element))
673 DrawLevelField(jx, jy);
675 if (setup.direct_draw)
677 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
678 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
679 int x_size = TILEX * (1 + ABS(jx - last_jx));
680 int y_size = TILEY * (1 + ABS(jy - last_jy));
682 BlitBitmap(drawto_field, window,
683 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
684 SetDrawtoField(DRAW_DIRECT);
687 MarkTileDirty(sx,sy);
692 void DrawPlayer(struct PlayerInfo *player)
694 int jx = player->jx, jy = player->jy;
695 int last_jx = player->last_jx, last_jy = player->last_jy;
696 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
697 int sx = SCREENX(jx), sy = SCREENY(jy);
698 int sxx = 0, syy = 0;
699 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
702 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
704 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
708 if (!IN_LEV_FIELD(jx,jy))
710 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
711 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
712 printf("DrawPlayerField(): This should never happen!\n");
717 if (element == EL_EXPLOSION)
720 /* draw things in the field the player is leaving, if needed */
722 if (player_is_moving)
724 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
726 DrawNewLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
728 if (last_element == EL_DYNAMITE_ACTIVE)
729 DrawDynamite(last_jx, last_jy);
731 DrawNewLevelFieldThruMask(last_jx, last_jy);
733 else if (last_element == EL_DYNAMITE_ACTIVE)
734 DrawDynamite(last_jx, last_jy);
736 DrawNewLevelField(last_jx, last_jy);
738 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
742 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
743 DrawNewLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
745 DrawNewLevelElement(next_jx, next_jy, EL_EMPTY);
748 DrawNewLevelField(next_jx, next_jy);
752 if (!IN_SCR_FIELD(sx, sy))
755 if (setup.direct_draw)
756 SetDrawtoField(DRAW_BUFFERED);
758 /* draw things behind the player, if needed */
761 DrawNewLevelElement(jx, jy, Store[jx][jy]);
762 else if (!IS_ACTIVE_BOMB(element))
763 DrawNewLevelField(jx, jy);
765 DrawNewLevelElement(jx, jy, EL_EMPTY);
767 /* draw player himself */
769 if (game.emulation == EMU_SUPAPLEX)
771 static int last_dir = MV_LEFT;
772 int action = (player->programmed_action ? player->programmed_action :
774 boolean action_moving =
776 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
777 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
779 graphic = IMG_SP_MURPHY;
783 if (player->MovDir == MV_LEFT)
784 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
785 else if (player->MovDir == MV_RIGHT)
786 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
787 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
788 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
789 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
790 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
792 else if (player->snapped)
794 if (player->MovDir == MV_LEFT)
795 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
796 else if (player->MovDir == MV_RIGHT)
797 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
798 else if (player->MovDir == MV_UP)
799 graphic = IMG_SP_MURPHY_UP_SNAPPING;
800 else if (player->MovDir == MV_DOWN)
801 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
803 else if (action_moving)
805 if (player->MovDir == MV_LEFT)
806 graphic = IMG_SP_MURPHY_LEFT_MOVING;
807 else if (player->MovDir == MV_RIGHT)
808 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
809 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
810 graphic = IMG_SP_MURPHY_LEFT_MOVING;
811 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
812 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
814 graphic = IMG_SP_MURPHY_LEFT_MOVING;
816 frame = getNewGraphicAnimationFrame(graphic, -1);
819 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
820 last_dir = player->MovDir;
824 if (player->MovDir == MV_LEFT)
825 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
826 IMG_PLAYER1_LEFT_MOVING);
827 else if (player->MovDir == MV_RIGHT)
828 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
829 IMG_PLAYER1_RIGHT_MOVING);
830 else if (player->MovDir == MV_UP)
831 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
832 IMG_PLAYER1_UP_MOVING);
833 else /* MV_DOWN || MV_NO_MOVING */
834 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
835 IMG_PLAYER1_DOWN_MOVING);
837 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
839 frame = player->Frame;
844 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
845 sxx = player->GfxPos;
847 syy = player->GfxPos;
850 if (!setup.soft_scrolling && ScreenMovPos)
853 DrawNewGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
855 if (SHIELD_ON(player))
857 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
858 IMG_SHIELD_NORMAL_ACTIVE);
859 int frame = getNewGraphicAnimationFrame(graphic, -1);
861 DrawNewGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
864 if (player->Pushing && player->GfxPos)
866 int px = SCREENX(next_jx), py = SCREENY(next_jy);
868 if (element == EL_SOKOBAN_FIELD_EMPTY ||
869 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
870 DrawNewGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
874 int element = Feld[next_jx][next_jy];
875 int graphic = el2img(element);
878 if ((element == EL_ROCK ||
879 element == EL_SP_ZONK ||
880 element == EL_BD_ROCK) && sxx)
882 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_PUSHING);
883 frame = getNewGraphicAnimationFrame(graphic, player->GfxPos);
886 if (player->MovDir == MV_LEFT)
890 frame = (player->GfxPos / (TILEX / 4));
892 if (player->MovDir == MV_RIGHT)
893 frame = (frame + 4) % 4;
897 DrawNewGraphicShifted(px, py, sxx, syy, graphic, frame,
898 NO_CUTTING, NO_MASKING);
902 /* draw things in front of player (active dynamite or dynabombs) */
904 if (IS_ACTIVE_BOMB(element))
906 graphic = el2img(element);
909 if (element == EL_DYNAMITE_ACTIVE)
911 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
916 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
920 frame = getNewGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
923 if (game.emulation == EMU_SUPAPLEX)
924 DrawNewGraphic(sx, sy, GFX_SP_DISK_RED, 0);
926 DrawNewGraphicThruMask(sx, sy, graphic, frame);
929 if (player_is_moving && last_element == EL_EXPLOSION)
931 int frame = Frame[last_jx][last_jy];
935 DrawNewGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
936 GFX_EXPLOSION, ((frame - 1) / delay - 1));
939 /* draw elements that stay over the player */
940 /* handle the field the player is leaving ... */
941 if (player_is_moving && IS_OVER_PLAYER(last_element))
942 DrawNewLevelField(last_jx, last_jy);
943 /* ... and the field the player is entering */
944 if (IS_OVER_PLAYER(element))
945 DrawNewLevelField(jx, jy);
947 if (setup.direct_draw)
949 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
950 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
951 int x_size = TILEX * (1 + ABS(jx - last_jx));
952 int y_size = TILEY * (1 + ABS(jy - last_jy));
954 BlitBitmap(drawto_field, window,
955 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
956 SetDrawtoField(DRAW_DIRECT);
959 MarkTileDirty(sx,sy);
963 static int getGraphicAnimationPhase(int frames, int delay, int mode)
967 if (mode & ANIM_PINGPONG)
969 int max_anim_frames = 2 * frames - 2;
971 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
972 phase = (phase < frames ? phase : max_anim_frames - phase);
975 phase = (FrameCounter % (delay * frames)) / delay;
977 if (mode & ANIM_REVERSE)
983 int getNewGraphicAnimationFrame(int graphic, int sync_frame)
985 int num_frames = new_graphic_info[graphic].anim_frames;
986 int delay = new_graphic_info[graphic].anim_delay;
987 int mode = new_graphic_info[graphic].anim_mode;
990 /* animation synchronized with global frame counter, not move position */
991 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
992 sync_frame = FrameCounter;
994 if (mode & ANIM_LOOP) /* normal, looping animation */
996 frame = (sync_frame % (delay * num_frames)) / delay;
998 else if (mode & ANIM_LINEAR) /* normal, non-looping animation */
1000 frame = sync_frame / delay;
1002 if (frame > num_frames - 1)
1003 frame = num_frames - 1;
1005 else if (mode & ANIM_PINGPONG) /* use border frames once */
1007 int max_anim_frames = 2 * num_frames - 2;
1009 frame = (sync_frame % (delay * max_anim_frames)) / delay;
1010 frame = (frame < num_frames ? frame : max_anim_frames - frame);
1012 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
1014 int max_anim_frames = 2 * num_frames;
1016 frame = (sync_frame % (delay * max_anim_frames)) / delay;
1017 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
1020 if (mode & ANIM_REVERSE) /* use reverse animation direction */
1021 frame = num_frames - frame - 1;
1027 void DrawGraphicAnimationExt(int x, int y, int graphic,
1028 int frames, int delay, int mode, int mask_mode)
1030 int phase = getGraphicAnimationPhase(frames, delay, mode);
1032 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1034 if (mask_mode == USE_MASKING)
1035 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
1037 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
1042 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
1045 int delay = new_graphic_info[graphic].anim_delay;
1047 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1049 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1052 int frame = getNewGraphicAnimationFrame(graphic, -1);
1054 if (mask_mode == USE_MASKING)
1055 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
1057 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
1062 void DrawGraphicAnimation(int x, int y, int graphic,
1063 int frames, int delay, int mode)
1065 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
1069 void DrawNewGraphicAnimation(int x, int y, int graphic)
1071 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
1075 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
1076 int frames, int delay, int mode)
1078 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
1082 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
1085 int frames, int delay,
1088 int phase = getGraphicAnimationPhase(frames, delay, mode);
1090 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
1094 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1096 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
1098 *bitmap = graphic_info[graphic].bitmap;
1099 *x = graphic_info[graphic].src_x;
1100 *y = graphic_info[graphic].src_y;
1102 else if (graphic >= GFX_START_ROCKSELEMENTS &&
1103 graphic <= GFX_END_ROCKSELEMENTS)
1105 graphic -= GFX_START_ROCKSELEMENTS;
1106 *bitmap = pix[PIX_ELEMENTS];
1107 *x = (graphic % GFX_PER_LINE) * TILEX;
1108 *y = (graphic / GFX_PER_LINE) * TILEY;
1110 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1112 graphic -= GFX_START_ROCKSHEROES;
1113 *bitmap = pix[PIX_HEROES];
1114 *x = (graphic % HEROES_PER_LINE) * TILEX;
1115 *y = (graphic / HEROES_PER_LINE) * TILEY;
1117 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1119 graphic -= GFX_START_ROCKSSP;
1120 *bitmap = pix[PIX_SP];
1121 *x = (graphic % SP_PER_LINE) * TILEX;
1122 *y = (graphic / SP_PER_LINE) * TILEY;
1124 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1126 graphic -= GFX_START_ROCKSDC;
1127 *bitmap = pix[PIX_DC];
1128 *x = (graphic % DC_PER_LINE) * TILEX;
1129 *y = (graphic / DC_PER_LINE) * TILEY;
1131 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1133 graphic -= GFX_START_ROCKSMORE;
1134 *bitmap = pix[PIX_MORE];
1135 *x = (graphic % MORE_PER_LINE) * TILEX;
1136 *y = (graphic / MORE_PER_LINE) * TILEY;
1138 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1140 graphic -= GFX_START_ROCKSFONT;
1141 *bitmap = pix[PIX_FONT_EM];
1142 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
1143 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
1147 *bitmap = pix[PIX_SP];
1155 void DrawGraphic(int x, int y, int graphic)
1158 if (!IN_SCR_FIELD(x, y))
1160 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1161 printf("DrawGraphic(): This should never happen!\n");
1166 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
1167 MarkTileDirty(x, y);
1171 void DrawNewGraphic(int x, int y, int graphic, int frame)
1174 if (!IN_SCR_FIELD(x, y))
1176 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1177 printf("DrawNewGraphic(): This should never happen!\n");
1182 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1184 MarkTileDirty(x, y);
1187 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
1192 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1193 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1196 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1199 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1200 int src_x = new_graphic_info[graphic].src_x;
1201 int src_y = new_graphic_info[graphic].src_y;
1202 int offset_x = new_graphic_info[graphic].offset_x;
1203 int offset_y = new_graphic_info[graphic].offset_y;
1205 src_x += frame * offset_x;
1206 src_y += frame * offset_y;
1208 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1211 void DrawGraphicThruMask(int x, int y, int graphic)
1214 if (!IN_SCR_FIELD(x, y))
1216 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1217 printf("DrawGraphicThruMask(): This should never happen!\n");
1222 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
1223 MarkTileDirty(x, y);
1226 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
1229 if (!IN_SCR_FIELD(x, y))
1231 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1232 printf("DrawGraphicThruMask(): This should never happen!\n");
1237 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
1239 MarkTileDirty(x, y);
1242 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
1249 if (graphic == GFX_LEERRAUM)
1252 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1253 drawing_gc = src_bitmap->stored_clip_gc;
1255 if (tile_clipmask[tile] != None)
1257 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1258 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1259 BlitBitmapMasked(src_bitmap, d,
1260 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1266 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
1270 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1271 BlitBitmapMasked(src_bitmap, d,
1272 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1276 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
1277 int graphic, int frame)
1279 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1280 GC drawing_gc = src_bitmap->stored_clip_gc;
1281 int src_x = new_graphic_info[graphic].src_x;
1282 int src_y = new_graphic_info[graphic].src_y;
1283 int offset_x = new_graphic_info[graphic].offset_x;
1284 int offset_y = new_graphic_info[graphic].offset_y;
1286 src_x += frame * offset_x;
1287 src_y += frame * offset_y;
1289 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1290 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1294 void DrawMiniGraphic(int x, int y, int graphic)
1296 DrawMiniGraphicExt(drawto,
1297 SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
1298 MarkTileDirty(x / 2, y / 2);
1302 void DrawNewMiniGraphic(int x, int y, int graphic)
1304 DrawNewMiniGraphicExt(drawto,
1305 SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
1306 MarkTileDirty(x / 2, y / 2);
1310 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1312 if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1314 graphic -= GFX_START_ROCKSELEMENTS;
1315 *bitmap = pix[PIX_ELEMENTS];
1316 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1317 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1319 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1321 graphic -= GFX_START_ROCKSSP;
1322 *bitmap = pix[PIX_SP];
1323 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1324 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1326 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1328 graphic -= GFX_START_ROCKSDC;
1329 *bitmap = pix[PIX_DC];
1330 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1331 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1333 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1335 graphic -= GFX_START_ROCKSMORE;
1336 *bitmap = pix[PIX_MORE];
1337 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1338 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1340 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1342 graphic -= GFX_START_ROCKSFONT;
1343 *bitmap = pix[PIX_FONT_EM];
1344 *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1345 *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1349 *bitmap = pix[PIX_SP];
1350 *x = MINI_SP_STARTX;
1351 *y = MINI_SP_STARTY;
1355 void getNewMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1357 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1358 int mini_startx = 0;
1359 int mini_starty = src_bitmap->height * 2 / 3;
1360 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1361 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1363 *bitmap = src_bitmap;
1370 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1375 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1376 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1380 void DrawNewMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1386 getNewMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1388 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1389 int mini_startx = src_bitmap->width * 2 / 3;
1390 int mini_starty = src_bitmap->height * 2 / 3;
1391 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1392 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1395 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1399 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1400 int cut_mode, int mask_mode)
1402 int width = TILEX, height = TILEY;
1404 int src_x, src_y, dest_x, dest_y;
1411 DrawGraphic(x, y, graphic);
1415 if (dx || dy) /* Verschiebung der Grafik? */
1417 if (x < BX1) /* Element kommt von links ins Bild */
1424 else if (x > BX2) /* Element kommt von rechts ins Bild */
1430 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1436 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1438 else if (dx) /* allg. Bewegung in x-Richtung */
1439 MarkTileDirty(x + SIGN(dx), y);
1441 if (y < BY1) /* Element kommt von oben ins Bild */
1443 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1451 else if (y > BY2) /* Element kommt von unten ins Bild */
1457 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1463 else if (dy > 0 && cut_mode == CUT_ABOVE)
1465 if (y == BY2) /* Element unterhalb des Bildes */
1471 MarkTileDirty(x, y + 1);
1472 } /* Element verläßt unten das Bild */
1473 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1475 else if (dy) /* allg. Bewegung in y-Richtung */
1476 MarkTileDirty(x, y + SIGN(dy));
1479 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1480 drawing_gc = src_bitmap->stored_clip_gc;
1485 dest_x = FX + x * TILEX + dx;
1486 dest_y = FY + y * TILEY + dy;
1489 if (!IN_SCR_FIELD(x,y))
1491 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1492 printf("DrawGraphicShifted(): This should never happen!\n");
1497 if (mask_mode == USE_MASKING)
1499 if (tile_clipmask[tile] != None)
1501 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1502 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1503 BlitBitmapMasked(src_bitmap, drawto_field,
1504 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1510 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1514 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1515 BlitBitmapMasked(src_bitmap, drawto_field,
1516 src_x, src_y, width, height, dest_x, dest_y);
1520 BlitBitmap(src_bitmap, drawto_field,
1521 src_x, src_y, width, height, dest_x, dest_y);
1527 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1528 int cut_mode, int mask_mode)
1537 int width = TILEX, height = TILEY;
1543 DrawNewGraphic(x, y, graphic, frame);
1547 if (dx || dy) /* Verschiebung der Grafik? */
1549 if (x < BX1) /* Element kommt von links ins Bild */
1556 else if (x > BX2) /* Element kommt von rechts ins Bild */
1562 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1568 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1570 else if (dx) /* allg. Bewegung in x-Richtung */
1571 MarkTileDirty(x + SIGN(dx), y);
1573 if (y < BY1) /* Element kommt von oben ins Bild */
1575 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1583 else if (y > BY2) /* Element kommt von unten ins Bild */
1589 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1595 else if (dy > 0 && cut_mode == CUT_ABOVE)
1597 if (y == BY2) /* Element unterhalb des Bildes */
1603 MarkTileDirty(x, y + 1);
1604 } /* Element verläßt unten das Bild */
1605 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1607 else if (dy) /* allg. Bewegung in y-Richtung */
1608 MarkTileDirty(x, y + SIGN(dy));
1611 src_bitmap = new_graphic_info[graphic].bitmap;
1612 src_x = new_graphic_info[graphic].src_x;
1613 src_y = new_graphic_info[graphic].src_y;
1614 offset_x = new_graphic_info[graphic].offset_x;
1615 offset_y = new_graphic_info[graphic].offset_y;
1617 drawing_gc = src_bitmap->stored_clip_gc;
1619 src_x += frame * offset_x;
1620 src_y += frame * offset_y;
1625 dest_x = FX + x * TILEX + dx;
1626 dest_y = FY + y * TILEY + dy;
1629 if (!IN_SCR_FIELD(x,y))
1631 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1632 printf("DrawGraphicShifted(): This should never happen!\n");
1637 if (mask_mode == USE_MASKING)
1639 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1640 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1644 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1651 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1654 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1658 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1659 int frame, int cut_mode)
1661 DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1665 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1666 int cut_mode, int mask_mode)
1668 int ux = LEVELX(x), uy = LEVELY(y);
1669 int graphic = el2gfx(element);
1670 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1671 int phase4 = phase8 / 2;
1672 int phase2 = phase8 / 4;
1673 int dir = MovDir[ux][uy];
1675 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1677 graphic += 1 * !phase2;
1681 else if (dir == MV_LEFT)
1683 else if (dir == MV_DOWN)
1686 else if (element == EL_SP_SNIKSNAK)
1689 graphic = GFX_SP_SNIKSNAK_LEFT;
1690 else if (dir == MV_RIGHT)
1691 graphic = GFX_SP_SNIKSNAK_RIGHT;
1692 else if (dir == MV_UP)
1693 graphic = GFX_SP_SNIKSNAK_UP;
1695 graphic = GFX_SP_SNIKSNAK_DOWN;
1697 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1699 else if (element == EL_SP_ELECTRON)
1701 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1703 else if (element == EL_MOLE || element == EL_PENGUIN ||
1704 element == EL_PIG || element == EL_DRAGON)
1707 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1708 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1709 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1710 else if (dir == MV_RIGHT)
1711 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1712 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1713 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1714 else if (dir == MV_UP)
1715 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1716 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1717 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1719 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1720 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1721 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1725 else if (element == EL_SATELLITE)
1727 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1729 else if (element == EL_ACID)
1731 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1733 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1737 else if (element == EL_BALLOON)
1741 else if ((element == EL_ROCK ||
1742 element == EL_SP_ZONK ||
1743 element == EL_BD_ROCK ||
1744 element == EL_SP_INFOTRON ||
1748 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1750 if (element == EL_ROCK ||
1751 element == EL_SP_ZONK ||
1752 element == EL_BD_ROCK)
1755 graphic += (4 - phase4) % 4;
1756 else if (dir == MV_RIGHT)
1759 graphic += phase2 * 2;
1761 else if (element != EL_SP_INFOTRON)
1765 else if (element == EL_MAGIC_WALL_ACTIVE ||
1766 element == EL_MAGIC_WALL_EMPTYING ||
1767 element == EL_BD_MAGIC_WALL_ACTIVE ||
1768 element == EL_BD_MAGIC_WALL_EMPTYING ||
1769 element == EL_MAGIC_WALL_FULL ||
1770 element == EL_BD_MAGIC_WALL_FULL)
1772 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1774 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1776 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1777 graphic += (x + 2 * y + 4) % 4;
1779 else if (element == EL_WALL_GROWING)
1781 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1783 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1784 links_massiv = TRUE;
1785 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1786 rechts_massiv = TRUE;
1788 if (links_massiv && rechts_massiv)
1789 graphic = GFX_MAUERWERK;
1790 else if (links_massiv)
1791 graphic = GFX_MAUER_R;
1792 else if (rechts_massiv)
1793 graphic = GFX_MAUER_L;
1796 else if ((element == EL_INVISIBLE_STEELWALL ||
1797 element == EL_INVISIBLE_WALL ||
1798 element == EL_INVISIBLE_SAND) && game.light_time_left)
1800 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1801 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1802 GFX_SAND_INVISIBLE_ON);
1807 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1808 else if (mask_mode == USE_MASKING)
1809 DrawGraphicThruMask(x, y, graphic);
1811 DrawGraphic(x, y, graphic);
1815 inline static int getFramePosition(int x, int y)
1817 int element = Feld[x][y];
1820 if (element == EL_QUICKSAND_FULL ||
1821 element == EL_MAGIC_WALL_FULL ||
1822 element == EL_BD_MAGIC_WALL_FULL)
1824 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1825 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1830 inline static int getGfxAction(int x, int y)
1832 int gfx_action = GFX_ACTION_DEFAULT;
1834 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1835 gfx_action = GfxAction[x][y];
1836 else if (IS_MOVING(x, y))
1837 gfx_action = GFX_ACTION_MOVING;
1842 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1843 int cut_mode, int mask_mode)
1845 int ux = LEVELX(x), uy = LEVELY(y);
1846 int move_dir = MovDir[ux][uy];
1847 int move_pos = getFramePosition(ux, uy);
1848 int gfx_action = getGfxAction(ux, uy);
1849 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1850 int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1852 if (element == EL_WALL_GROWING)
1854 boolean left_stopped = FALSE, right_stopped = FALSE;
1856 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1857 left_stopped = TRUE;
1858 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1859 right_stopped = TRUE;
1861 if (left_stopped && right_stopped)
1863 else if (left_stopped)
1865 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1866 frame = new_graphic_info[graphic].anim_frames - 1;
1868 else if (right_stopped)
1870 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1871 frame = new_graphic_info[graphic].anim_frames - 1;
1875 else if ((element == EL_ROCK ||
1876 element == EL_SP_ZONK ||
1877 element == EL_BD_ROCK ||
1878 element == EL_SP_INFOTRON ||
1882 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1884 if (element == EL_ROCK ||
1885 element == EL_SP_ZONK ||
1886 element == EL_BD_ROCK)
1888 if (move_dir == MV_LEFT)
1889 graphic += (4 - phase4) % 4;
1890 else if (move_dir == MV_RIGHT)
1893 graphic += phase2 * 2;
1895 else if (element != EL_SP_INFOTRON)
1900 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1902 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1903 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1904 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1905 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1906 IMG_AMOEBA_DEAD_PART1);
1908 graphic += (x + 2 * y + 4) % 4;
1912 DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1913 else if (mask_mode == USE_MASKING)
1914 DrawNewGraphicThruMask(x, y, graphic, frame);
1916 DrawNewGraphic(x, y, graphic, frame);
1920 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1921 int cut_mode, int mask_mode)
1923 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1924 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1925 cut_mode, mask_mode);
1929 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1930 int cut_mode, int mask_mode)
1932 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1933 DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1934 cut_mode, mask_mode);
1938 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1941 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1945 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1948 DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1952 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1955 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1959 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1962 DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1966 void DrawScreenElementThruMask(int x, int y, int element)
1968 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1971 void DrawNewScreenElementThruMask(int x, int y, int element)
1973 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1978 void DrawLevelElementThruMask(int x, int y, int element)
1980 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1984 void DrawNewLevelElementThruMask(int x, int y, int element)
1986 DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1990 void DrawLevelFieldThruMask(int x, int y)
1992 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1996 void DrawNewLevelFieldThruMask(int x, int y)
1998 DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
2002 void ErdreichAnbroeckeln(int x, int y)
2006 int i, width, height, cx,cy;
2007 int ux = LEVELX(x), uy = LEVELY(y);
2008 int element, graphic;
2010 static int xy[4][2] =
2018 if (!IN_LEV_FIELD(ux, uy))
2021 element = Feld[ux][uy];
2023 if (element == EL_SAND ||
2024 element == EL_LANDMINE ||
2025 element == EL_TRAP ||
2026 element == EL_TRAP_ACTIVE)
2028 if (!IN_SCR_FIELD(x, y))
2031 graphic = GFX_ERDENRAND;
2033 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
2039 uxx = ux + xy[i][0];
2040 uyy = uy + xy[i][1];
2041 if (!IN_LEV_FIELD(uxx, uyy))
2042 element = EL_STEELWALL;
2044 element = Feld[uxx][uyy];
2046 if (element == EL_SAND ||
2047 element == EL_LANDMINE ||
2048 element == EL_TRAP ||
2049 element == EL_TRAP_ACTIVE)
2052 if (i == 1 || i == 2)
2056 cx = (i == 2 ? TILEX - snip : 0);
2064 cy = (i == 3 ? TILEY - snip : 0);
2067 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2068 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
2071 MarkTileDirty(x, y);
2075 graphic = GFX_ERDENRAND;
2077 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
2081 int xx, yy, uxx, uyy;
2085 uxx = ux + xy[i][0];
2086 uyy = uy + xy[i][1];
2088 if (!IN_LEV_FIELD(uxx, uyy) ||
2089 (Feld[uxx][uyy] != EL_SAND &&
2090 Feld[uxx][uyy] != EL_LANDMINE &&
2091 Feld[uxx][uyy] != EL_TRAP &&
2092 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
2093 !IN_SCR_FIELD(xx, yy))
2096 if (i == 1 || i == 2)
2100 cx = (i == 1 ? TILEX - snip : 0);
2108 cy = (i==0 ? TILEY-snip : 0);
2111 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2112 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
2114 MarkTileDirty(xx, yy);
2120 void DrawCrumbledSand(int x, int y)
2124 int i, width, height, cx,cy;
2125 int ux = LEVELX(x), uy = LEVELY(y);
2126 int element, graphic;
2128 static int xy[4][2] =
2136 if (!IN_LEV_FIELD(ux, uy))
2139 element = Feld[ux][uy];
2141 if (element == EL_SAND ||
2142 element == EL_LANDMINE ||
2143 element == EL_TRAP ||
2144 element == EL_TRAP_ACTIVE)
2146 if (!IN_SCR_FIELD(x, y))
2149 graphic = IMG_SAND_CRUMBLED;
2151 src_bitmap = new_graphic_info[graphic].bitmap;
2152 src_x = new_graphic_info[graphic].src_x;
2153 src_y = new_graphic_info[graphic].src_y;
2159 uxx = ux + xy[i][0];
2160 uyy = uy + xy[i][1];
2161 if (!IN_LEV_FIELD(uxx, uyy))
2162 element = EL_STEELWALL;
2164 element = Feld[uxx][uyy];
2166 if (element == EL_SAND ||
2167 element == EL_LANDMINE ||
2168 element == EL_TRAP ||
2169 element == EL_TRAP_ACTIVE)
2172 if (i == 1 || i == 2)
2176 cx = (i == 2 ? TILEX - snip : 0);
2184 cy = (i == 3 ? TILEY - snip : 0);
2187 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2188 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
2191 MarkTileDirty(x, y);
2195 graphic = IMG_SAND_CRUMBLED;
2197 src_bitmap = new_graphic_info[graphic].bitmap;
2198 src_x = new_graphic_info[graphic].src_x;
2199 src_y = new_graphic_info[graphic].src_y;
2203 int xx, yy, uxx, uyy;
2207 uxx = ux + xy[i][0];
2208 uyy = uy + xy[i][1];
2210 if (!IN_LEV_FIELD(uxx, uyy) ||
2211 (Feld[uxx][uyy] != EL_SAND &&
2212 Feld[uxx][uyy] != EL_LANDMINE &&
2213 Feld[uxx][uyy] != EL_TRAP &&
2214 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
2215 !IN_SCR_FIELD(xx, yy))
2218 if (i == 1 || i == 2)
2222 cx = (i == 1 ? TILEX - snip : 0);
2230 cy = (i==0 ? TILEY-snip : 0);
2233 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2234 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
2236 MarkTileDirty(xx, yy);
2242 void DrawScreenElement(int x, int y, int element)
2244 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2245 ErdreichAnbroeckeln(x, y);
2249 void DrawNewScreenElement(int x, int y, int element)
2251 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2252 DrawCrumbledSand(x, y);
2257 void DrawLevelElement(int x, int y, int element)
2259 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2260 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2264 void DrawNewLevelElement(int x, int y, int element)
2266 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2267 DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
2271 void DrawScreenField(int x, int y)
2273 int ux = LEVELX(x), uy = LEVELY(y);
2274 int element, content;
2276 if (!IN_LEV_FIELD(ux, uy))
2278 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
2281 element = BorderElement;
2283 DrawScreenElement(x, y, element);
2287 element = Feld[ux][uy];
2288 content = Store[ux][uy];
2290 if (IS_MOVING(ux, uy))
2292 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
2293 boolean cut_mode = NO_CUTTING;
2295 if (element == EL_QUICKSAND_EMPTYING ||
2296 element == EL_MAGIC_WALL_EMPTYING ||
2297 element == EL_BD_MAGIC_WALL_EMPTYING ||
2298 element == EL_AMOEBA_DRIPPING)
2299 cut_mode = CUT_ABOVE;
2300 else if (element == EL_QUICKSAND_FILLING ||
2301 element == EL_MAGIC_WALL_FILLING ||
2302 element == EL_BD_MAGIC_WALL_FILLING)
2303 cut_mode = CUT_BELOW;
2305 if (cut_mode == CUT_ABOVE)
2306 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2308 DrawScreenElement(x, y, EL_EMPTY);
2311 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
2312 else if (cut_mode == NO_CUTTING)
2313 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
2315 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
2317 if (content == EL_ACID)
2318 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
2320 else if (IS_BLOCKED(ux, uy))
2325 boolean cut_mode = NO_CUTTING;
2326 int element_old, content_old;
2328 Blocked2Moving(ux, uy, &oldx, &oldy);
2331 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2332 MovDir[oldx][oldy] == MV_RIGHT);
2334 element_old = Feld[oldx][oldy];
2335 content_old = Store[oldx][oldy];
2337 if (element_old == EL_QUICKSAND_EMPTYING ||
2338 element_old == EL_MAGIC_WALL_EMPTYING ||
2339 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2340 element_old == EL_AMOEBA_DRIPPING)
2341 cut_mode = CUT_ABOVE;
2343 DrawScreenElement(x, y, EL_EMPTY);
2346 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2348 else if (cut_mode == NO_CUTTING)
2349 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2352 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2355 else if (IS_DRAWABLE(element))
2356 DrawScreenElement(x, y, element);
2358 DrawScreenElement(x, y, EL_EMPTY);
2362 void DrawNewScreenField(int x, int y)
2364 int ux = LEVELX(x), uy = LEVELY(y);
2365 int element, content;
2367 if (!IN_LEV_FIELD(ux, uy))
2369 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
2372 element = BorderElement;
2374 DrawNewScreenElement(x, y, element);
2378 element = Feld[ux][uy];
2379 content = Store[ux][uy];
2381 if (IS_MOVING(ux, uy))
2383 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
2384 boolean cut_mode = NO_CUTTING;
2386 if (element == EL_QUICKSAND_EMPTYING ||
2387 element == EL_MAGIC_WALL_EMPTYING ||
2388 element == EL_BD_MAGIC_WALL_EMPTYING ||
2389 element == EL_AMOEBA_DRIPPING)
2390 cut_mode = CUT_ABOVE;
2391 else if (element == EL_QUICKSAND_FILLING ||
2392 element == EL_MAGIC_WALL_FILLING ||
2393 element == EL_BD_MAGIC_WALL_FILLING)
2394 cut_mode = CUT_BELOW;
2396 if (cut_mode == CUT_ABOVE)
2397 DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2399 DrawNewScreenElement(x, y, EL_EMPTY);
2402 DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
2403 else if (cut_mode == NO_CUTTING)
2404 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
2406 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
2408 if (content == EL_ACID)
2409 DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
2411 else if (IS_BLOCKED(ux, uy))
2416 boolean cut_mode = NO_CUTTING;
2417 int element_old, content_old;
2419 Blocked2Moving(ux, uy, &oldx, &oldy);
2422 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2423 MovDir[oldx][oldy] == MV_RIGHT);
2425 element_old = Feld[oldx][oldy];
2426 content_old = Store[oldx][oldy];
2428 if (element_old == EL_QUICKSAND_EMPTYING ||
2429 element_old == EL_MAGIC_WALL_EMPTYING ||
2430 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2431 element_old == EL_AMOEBA_DRIPPING)
2432 cut_mode = CUT_ABOVE;
2434 DrawNewScreenElement(x, y, EL_EMPTY);
2437 DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2439 else if (cut_mode == NO_CUTTING)
2440 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2443 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2446 else if (IS_DRAWABLE(element))
2447 DrawNewScreenElement(x, y, element);
2449 DrawNewScreenElement(x, y, EL_EMPTY);
2453 void DrawLevelField(int x, int y)
2455 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2456 DrawScreenField(SCREENX(x), SCREENY(y));
2457 else if (IS_MOVING(x, y))
2461 Moving2Blocked(x, y, &newx, &newy);
2462 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2463 DrawScreenField(SCREENX(newx), SCREENY(newy));
2465 else if (IS_BLOCKED(x, y))
2469 Blocked2Moving(x, y, &oldx, &oldy);
2470 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2471 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2476 void DrawNewLevelField(int x, int y)
2478 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2479 DrawNewScreenField(SCREENX(x), SCREENY(y));
2480 else if (IS_MOVING(x, y))
2484 Moving2Blocked(x, y, &newx, &newy);
2485 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2486 DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2488 else if (IS_BLOCKED(x, y))
2492 Blocked2Moving(x, y, &oldx, &oldy);
2493 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2494 DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2499 void DrawMiniElement(int x, int y, int element)
2505 DrawMiniGraphic(x, y, -1);
2509 graphic = el2gfx(element);
2510 DrawMiniGraphic(x, y, graphic);
2514 void DrawNewMiniElement(int x, int y, int element)
2521 DrawNewMiniGraphic(x, y, -1);
2526 graphic = el2img(element);
2527 DrawNewMiniGraphic(x, y, graphic);
2531 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2533 int x = sx + scroll_x, y = sy + scroll_y;
2535 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2536 DrawMiniElement(sx, sy, EL_EMPTY);
2537 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2538 DrawMiniElement(sx, sy, Feld[x][y]);
2541 int steel_type, steel_position;
2544 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
2545 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2546 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
2547 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2548 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
2549 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
2552 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2553 steel_position = (x == -1 && y == -1 ? 0 :
2554 x == lev_fieldx && y == -1 ? 1 :
2555 x == -1 && y == lev_fieldy ? 2 :
2556 x == lev_fieldx && y == lev_fieldy ? 3 :
2557 x == -1 || x == lev_fieldx ? 4 :
2558 y == -1 || y == lev_fieldy ? 5 : -1);
2560 if (steel_position != -1)
2561 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2566 void DrawNewMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2568 int x = sx + scroll_x, y = sy + scroll_y;
2570 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2571 DrawNewMiniElement(sx, sy, EL_EMPTY);
2572 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2573 DrawNewMiniElement(sx, sy, Feld[x][y]);
2576 int steel_type, steel_position;
2579 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
2580 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
2581 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
2582 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2583 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
2584 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
2587 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2588 steel_position = (x == -1 && y == -1 ? 0 :
2589 x == lev_fieldx && y == -1 ? 1 :
2590 x == -1 && y == lev_fieldy ? 2 :
2591 x == lev_fieldx && y == lev_fieldy ? 3 :
2592 x == -1 || x == lev_fieldx ? 4 :
2593 y == -1 || y == lev_fieldy ? 5 : -1);
2595 if (steel_position != -1)
2596 DrawNewMiniGraphic(sx, sy, border[steel_position][steel_type]);
2601 void DrawMicroElement(int xpos, int ypos, int element)
2605 if (element == EL_EMPTY)
2608 graphic = el2gfx(element);
2610 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2612 graphic -= GFX_START_ROCKSSP;
2613 BlitBitmap(pix[PIX_SP], drawto,
2614 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2615 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2616 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2618 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2620 graphic -= GFX_START_ROCKSDC;
2621 BlitBitmap(pix[PIX_DC], drawto,
2622 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2623 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2624 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2626 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2628 graphic -= GFX_START_ROCKSMORE;
2629 BlitBitmap(pix[PIX_MORE], drawto,
2630 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2631 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2632 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2634 else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2636 graphic -= GFX_CHAR_START;
2637 BlitBitmap(pix[PIX_FONT_EM], drawto,
2638 MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2639 MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2640 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2643 BlitBitmap(pix[PIX_ELEMENTS], drawto,
2644 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2645 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2646 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2650 void getNewMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
2652 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
2653 int mini_startx = src_bitmap->width * 3 / 4;
2654 int mini_starty = src_bitmap->height * 2 / 3;
2655 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
2656 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
2658 *bitmap = src_bitmap;
2663 void DrawNewMicroElement(int xpos, int ypos, int element)
2669 if (element == EL_EMPTY)
2672 graphic = el2img(element);
2674 getNewMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
2675 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
2685 for(x=BX1; x<=BX2; x++)
2686 for(y=BY1; y<=BY2; y++)
2687 DrawNewScreenField(x, y);
2689 redraw_mask |= REDRAW_FIELD;
2693 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2697 for(x=0; x<size_x; x++)
2698 for(y=0; y<size_y; y++)
2699 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2701 redraw_mask |= REDRAW_FIELD;
2705 void DrawNewMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2709 for(x=0; x<size_x; x++)
2710 for(y=0; y<size_y; y++)
2711 DrawNewMiniElementOrWall(x, y, scroll_x, scroll_y);
2713 redraw_mask |= REDRAW_FIELD;
2717 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2721 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2723 if (lev_fieldx < STD_LEV_FIELDX)
2724 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2725 if (lev_fieldy < STD_LEV_FIELDY)
2726 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2728 xpos += MICRO_TILEX;
2729 ypos += MICRO_TILEY;
2731 for(x=-1; x<=STD_LEV_FIELDX; x++)
2733 for(y=-1; y<=STD_LEV_FIELDY; y++)
2735 int lx = from_x + x, ly = from_y + y;
2737 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2738 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2740 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2741 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2746 redraw_mask |= REDRAW_MICROLEVEL;
2750 static void DrawNewMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2754 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2756 if (lev_fieldx < STD_LEV_FIELDX)
2757 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2758 if (lev_fieldy < STD_LEV_FIELDY)
2759 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2761 xpos += MICRO_TILEX;
2762 ypos += MICRO_TILEY;
2764 for(x=-1; x<=STD_LEV_FIELDX; x++)
2766 for(y=-1; y<=STD_LEV_FIELDY; y++)
2768 int lx = from_x + x, ly = from_y + y;
2770 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2771 DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2773 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2774 DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2779 redraw_mask |= REDRAW_MICROLEVEL;
2782 #define MICROLABEL_EMPTY 0
2783 #define MICROLABEL_LEVEL_NAME 1
2784 #define MICROLABEL_CREATED_BY 2
2785 #define MICROLABEL_LEVEL_AUTHOR 3
2786 #define MICROLABEL_IMPORTED_FROM 4
2787 #define MICROLABEL_LEVEL_IMPORT_INFO 5
2789 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
2791 static void DrawMicroLevelLabelExt(int mode)
2793 char label_text[MAX_MICROLABEL_SIZE + 1];
2795 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2797 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2798 mode == MICROLABEL_CREATED_BY ? "created by" :
2799 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2800 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2801 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2802 leveldir_current->imported_from : ""),
2803 MAX_MICROLABEL_SIZE);
2804 label_text[MAX_MICROLABEL_SIZE] = '\0';
2806 if (strlen(label_text) > 0)
2808 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2809 int lypos = MICROLABEL_YPOS;
2811 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2814 redraw_mask |= REDRAW_MICROLEVEL;
2817 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2819 static unsigned long scroll_delay = 0;
2820 static unsigned long label_delay = 0;
2821 static int from_x, from_y, scroll_direction;
2822 static int label_state, label_counter;
2826 from_x = from_y = 0;
2827 scroll_direction = MV_RIGHT;
2831 DrawNewMicroLevelExt(xpos, ypos, from_x, from_y);
2832 DrawMicroLevelLabelExt(label_state);
2834 /* initialize delay counters */
2835 DelayReached(&scroll_delay, 0);
2836 DelayReached(&label_delay, 0);
2841 /* scroll micro level, if needed */
2842 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2843 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2845 switch (scroll_direction)
2851 scroll_direction = MV_UP;
2855 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2858 scroll_direction = MV_DOWN;
2865 scroll_direction = MV_RIGHT;
2869 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2872 scroll_direction = MV_LEFT;
2879 DrawNewMicroLevelExt(xpos, ypos, from_x, from_y);
2882 /* redraw micro level label, if needed */
2883 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2884 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2885 strcmp(level.author, leveldir_current->name) != 0 &&
2886 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2888 int max_label_counter = 23;
2890 if (leveldir_current->imported_from != NULL)
2891 max_label_counter += 14;
2893 label_counter = (label_counter + 1) % max_label_counter;
2894 label_state = (label_counter >= 0 && label_counter <= 7 ?
2895 MICROLABEL_LEVEL_NAME :
2896 label_counter >= 9 && label_counter <= 12 ?
2897 MICROLABEL_CREATED_BY :
2898 label_counter >= 14 && label_counter <= 21 ?
2899 MICROLABEL_LEVEL_AUTHOR :
2900 label_counter >= 23 && label_counter <= 26 ?
2901 MICROLABEL_IMPORTED_FROM :
2902 label_counter >= 28 && label_counter <= 35 ?
2903 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2904 DrawMicroLevelLabelExt(label_state);
2908 int REQ_in_range(int x, int y)
2910 if (y > DY+249 && y < DY+278)
2912 if (x > DX+1 && x < DX+48)
2914 else if (x > DX+51 && x < DX+98)
2920 #define MAX_REQUEST_LINES 13
2921 #define MAX_REQUEST_LINE_LEN 7
2923 boolean Request(char *text, unsigned int req_state)
2925 int mx, my, ty, result = -1;
2926 unsigned int old_door_state;
2928 #if defined(PLATFORM_UNIX)
2929 /* pause network game while waiting for request to answer */
2930 if (options.network &&
2931 game_status == PLAYING &&
2932 req_state & REQUEST_WAIT_FOR)
2933 SendToServer_PausePlaying();
2936 old_door_state = GetDoorState();
2940 CloseDoor(DOOR_CLOSE_1);
2942 /* save old door content */
2943 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2944 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2945 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2947 /* clear door drawing field */
2948 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2950 /* write text for request */
2951 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2953 char text_line[MAX_REQUEST_LINE_LEN + 1];
2959 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2962 if (!tc || tc == ' ')
2973 strncpy(text_line, text, tl);
2976 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2977 text_line, FS_SMALL, FC_YELLOW);
2979 text += tl + (tc == ' ' ? 1 : 0);
2982 if (req_state & REQ_ASK)
2984 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2985 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2987 else if (req_state & REQ_CONFIRM)
2989 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2991 else if (req_state & REQ_PLAYER)
2993 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2994 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2995 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2996 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2999 /* copy request gadgets to door backbuffer */
3000 BlitBitmap(drawto, pix[PIX_DB_DOOR],
3001 DX, DY, DXSIZE, DYSIZE,
3002 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3004 OpenDoor(DOOR_OPEN_1);
3010 if (!(req_state & REQUEST_WAIT_FOR))
3013 if (game_status != MAINMENU)
3016 button_status = MB_RELEASED;
3018 request_gadget_id = -1;
3030 case EVENT_BUTTONPRESS:
3031 case EVENT_BUTTONRELEASE:
3032 case EVENT_MOTIONNOTIFY:
3034 if (event.type == EVENT_MOTIONNOTIFY)
3036 if (!PointerInWindow(window))
3037 continue; /* window and pointer are on different screens */
3042 motion_status = TRUE;
3043 mx = ((MotionEvent *) &event)->x;
3044 my = ((MotionEvent *) &event)->y;
3048 motion_status = FALSE;
3049 mx = ((ButtonEvent *) &event)->x;
3050 my = ((ButtonEvent *) &event)->y;
3051 if (event.type == EVENT_BUTTONPRESS)
3052 button_status = ((ButtonEvent *) &event)->button;
3054 button_status = MB_RELEASED;
3057 /* this sets 'request_gadget_id' */
3058 HandleGadgets(mx, my, button_status);
3060 switch(request_gadget_id)
3062 case TOOL_CTRL_ID_YES:
3065 case TOOL_CTRL_ID_NO:
3068 case TOOL_CTRL_ID_CONFIRM:
3069 result = TRUE | FALSE;
3072 case TOOL_CTRL_ID_PLAYER_1:
3075 case TOOL_CTRL_ID_PLAYER_2:
3078 case TOOL_CTRL_ID_PLAYER_3:
3081 case TOOL_CTRL_ID_PLAYER_4:
3092 case EVENT_KEYPRESS:
3093 switch(GetEventKey((KeyEvent *)&event, TRUE))
3106 if (req_state & REQ_PLAYER)
3110 case EVENT_KEYRELEASE:
3111 ClearPlayerAction();
3115 HandleOtherEvents(&event);
3119 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
3121 int joy = AnyJoystick();
3123 if (joy & JOY_BUTTON_1)
3125 else if (joy & JOY_BUTTON_2)
3131 /* don't eat all CPU time */
3135 if (game_status != MAINMENU)
3140 if (!(req_state & REQ_STAY_OPEN))
3142 CloseDoor(DOOR_CLOSE_1);
3144 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
3146 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
3147 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3148 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
3149 OpenDoor(DOOR_OPEN_1);
3155 #if defined(PLATFORM_UNIX)
3156 /* continue network game after request */
3157 if (options.network &&
3158 game_status == PLAYING &&
3159 req_state & REQUEST_WAIT_FOR)
3160 SendToServer_ContinuePlaying();
3166 unsigned int OpenDoor(unsigned int door_state)
3168 unsigned int new_door_state;
3170 if (door_state & DOOR_COPY_BACK)
3172 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
3173 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
3174 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3175 door_state &= ~DOOR_COPY_BACK;
3178 new_door_state = MoveDoor(door_state);
3180 return(new_door_state);
3183 unsigned int CloseDoor(unsigned int door_state)
3185 unsigned int new_door_state;
3187 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
3188 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3189 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
3190 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
3192 new_door_state = MoveDoor(door_state);
3194 return(new_door_state);
3197 unsigned int GetDoorState()
3199 return MoveDoor(DOOR_GET_STATE);
3202 unsigned int SetDoorState(unsigned int door_state)
3204 return MoveDoor(door_state | DOOR_SET_STATE);
3207 unsigned int MoveDoor(unsigned int door_state)
3209 static int door1 = DOOR_OPEN_1;
3210 static int door2 = DOOR_CLOSE_2;
3211 static unsigned long door_delay = 0;
3212 int x, start, stepsize = 2;
3213 unsigned long door_delay_value = stepsize * 5;
3215 if (door_state == DOOR_GET_STATE)
3216 return(door1 | door2);
3218 if (door_state & DOOR_SET_STATE)
3220 if (door_state & DOOR_ACTION_1)
3221 door1 = door_state & DOOR_ACTION_1;
3222 if (door_state & DOOR_ACTION_2)
3223 door2 = door_state & DOOR_ACTION_2;
3225 return(door1 | door2);
3228 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
3229 door_state &= ~DOOR_OPEN_1;
3230 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
3231 door_state &= ~DOOR_CLOSE_1;
3232 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
3233 door_state &= ~DOOR_OPEN_2;
3234 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
3235 door_state &= ~DOOR_CLOSE_2;
3237 if (setup.quick_doors)
3240 door_delay_value = 0;
3241 StopSound(SND_MENU_DOOR_OPENING);
3242 StopSound(SND_MENU_DOOR_CLOSING);
3245 if (door_state & DOOR_ACTION)
3247 if (!(door_state & DOOR_NO_DELAY))
3249 /* opening door sound has priority over simultaneously closing door */
3250 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
3251 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
3252 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
3253 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
3256 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
3258 for(x=start; x<=DXSIZE; x+=stepsize)
3260 Bitmap *bitmap = pix[PIX_DOOR];
3261 GC gc = bitmap->stored_clip_gc;
3263 WaitUntilDelayReached(&door_delay, door_delay_value);
3265 if (door_state & DOOR_ACTION_1)
3267 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
3268 int j = (DXSIZE - i) / 3;
3270 BlitBitmap(pix[PIX_DB_DOOR], drawto,
3271 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
3272 DXSIZE,DYSIZE - i/2, DX, DY);
3274 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
3276 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
3277 BlitBitmapMasked(bitmap, drawto,
3278 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
3279 DX + DXSIZE - i, DY + j);
3280 BlitBitmapMasked(bitmap, drawto,
3281 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
3282 DX + DXSIZE - i, DY + 140 + j);
3283 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
3284 BlitBitmapMasked(bitmap, drawto,
3285 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
3287 BlitBitmapMasked(bitmap, drawto,
3288 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
3291 BlitBitmapMasked(bitmap, drawto,
3292 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
3294 BlitBitmapMasked(bitmap, drawto,
3295 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
3297 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
3298 BlitBitmapMasked(bitmap, drawto,
3299 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
3300 DX + DXSIZE - i, DY + 77 + j);
3301 BlitBitmapMasked(bitmap, drawto,
3302 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
3303 DX + DXSIZE - i, DY + 203 + j);
3305 redraw_mask |= REDRAW_DOOR_1;
3308 if (door_state & DOOR_ACTION_2)
3310 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
3311 int j = (VXSIZE - i) / 3;
3313 BlitBitmap(pix[PIX_DB_DOOR], drawto,
3314 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
3315 VXSIZE, VYSIZE - i/2, VX, VY);
3317 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
3319 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
3320 BlitBitmapMasked(bitmap, drawto,
3321 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
3322 VX + VXSIZE-i, VY+j);
3323 SetClipOrigin(bitmap, gc,
3324 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
3325 BlitBitmapMasked(bitmap, drawto,
3326 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
3329 BlitBitmapMasked(bitmap, drawto,
3330 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
3331 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
3332 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
3333 BlitBitmapMasked(bitmap, drawto,
3334 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
3336 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
3338 redraw_mask |= REDRAW_DOOR_2;
3343 if (game_status == MAINMENU)
3348 if (setup.quick_doors)
3350 StopSound(SND_MENU_DOOR_OPENING);
3351 StopSound(SND_MENU_DOOR_CLOSING);
3354 if (door_state & DOOR_ACTION_1)
3355 door1 = door_state & DOOR_ACTION_1;
3356 if (door_state & DOOR_ACTION_2)
3357 door2 = door_state & DOOR_ACTION_2;
3359 return (door1 | door2);
3362 void DrawSpecialEditorDoor()
3364 /* draw bigger toolbox window */
3365 BlitBitmap(pix[PIX_DOOR], drawto,
3366 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
3368 redraw_mask |= REDRAW_ALL;
3371 void UndrawSpecialEditorDoor()
3373 /* draw normal tape recorder window */
3374 BlitBitmap(pix[PIX_BACK], drawto,
3375 562, 344, 108, 56, EX - 4, EY - 12);
3377 redraw_mask |= REDRAW_ALL;
3381 int ReadPixel(DrawBuffer *bitmap, int x, int y)
3383 XImage *pixel_image;
3384 unsigned long pixel_value;
3386 pixel_image = XGetImage(display, bitmap->drawable,
3387 x, y, 1, 1, AllPlanes, ZPixmap);
3388 pixel_value = XGetPixel(pixel_image, 0, 0);
3390 XDestroyImage(pixel_image);
3396 /* ---------- new tool button stuff ---------------------------------------- */
3398 /* graphic position values for tool buttons */
3399 #define TOOL_BUTTON_YES_XPOS 2
3400 #define TOOL_BUTTON_YES_YPOS 250
3401 #define TOOL_BUTTON_YES_GFX_YPOS 0
3402 #define TOOL_BUTTON_YES_XSIZE 46
3403 #define TOOL_BUTTON_YES_YSIZE 28
3404 #define TOOL_BUTTON_NO_XPOS 52
3405 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
3406 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
3407 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
3408 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
3409 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
3410 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
3411 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
3412 #define TOOL_BUTTON_CONFIRM_XSIZE 96
3413 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
3414 #define TOOL_BUTTON_PLAYER_XSIZE 30
3415 #define TOOL_BUTTON_PLAYER_YSIZE 30
3416 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
3417 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
3418 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
3419 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
3420 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
3421 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
3422 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
3423 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
3424 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
3425 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
3426 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
3427 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
3428 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
3429 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
3430 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
3431 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
3432 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
3433 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
3434 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
3435 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
3444 } toolbutton_info[NUM_TOOL_BUTTONS] =
3447 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
3448 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
3449 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
3454 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
3455 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
3456 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
3461 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
3462 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
3463 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
3464 TOOL_CTRL_ID_CONFIRM,
3468 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3469 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
3470 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3471 TOOL_CTRL_ID_PLAYER_1,
3475 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3476 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
3477 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3478 TOOL_CTRL_ID_PLAYER_2,
3482 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3483 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
3484 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3485 TOOL_CTRL_ID_PLAYER_3,
3489 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3490 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
3491 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3492 TOOL_CTRL_ID_PLAYER_4,
3497 void CreateToolButtons()
3501 for (i=0; i<NUM_TOOL_BUTTONS; i++)
3503 Bitmap *gd_bitmap = pix[PIX_DOOR];
3504 Bitmap *deco_bitmap = None;
3505 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
3506 struct GadgetInfo *gi;
3507 unsigned long event_mask;
3508 int gd_xoffset, gd_yoffset;
3509 int gd_x1, gd_x2, gd_y;
3512 event_mask = GD_EVENT_RELEASED;
3514 gd_xoffset = toolbutton_info[i].xpos;
3515 gd_yoffset = toolbutton_info[i].ypos;
3516 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
3517 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
3518 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
3520 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
3522 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
3523 &deco_bitmap, &deco_x, &deco_y);
3524 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
3525 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
3528 gi = CreateGadget(GDI_CUSTOM_ID, id,
3529 GDI_INFO_TEXT, toolbutton_info[i].infotext,
3530 GDI_X, DX + toolbutton_info[i].x,
3531 GDI_Y, DY + toolbutton_info[i].y,
3532 GDI_WIDTH, toolbutton_info[i].width,
3533 GDI_HEIGHT, toolbutton_info[i].height,
3534 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
3535 GDI_STATE, GD_BUTTON_UNPRESSED,
3536 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
3537 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
3538 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
3539 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
3540 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
3541 GDI_DECORATION_SHIFTING, 1, 1,
3542 GDI_EVENT_MASK, event_mask,
3543 GDI_CALLBACK_ACTION, HandleToolButtons,
3547 Error(ERR_EXIT, "cannot create gadget");
3549 tool_gadget[id] = gi;
3553 static void UnmapToolButtons()
3557 for (i=0; i<NUM_TOOL_BUTTONS; i++)
3558 UnmapGadget(tool_gadget[i]);
3561 static void HandleToolButtons(struct GadgetInfo *gi)
3563 request_gadget_id = gi->custom_id;
3566 int get_next_element(int element)
3570 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
3571 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
3572 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
3573 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
3574 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
3575 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
3576 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
3578 default: return element;
3582 int el2gfx_OLD(int element)
3586 case EL_EMPTY: return -1;
3587 case EL_SAND: return GFX_ERDREICH;
3588 case EL_WALL: return GFX_MAUERWERK;
3589 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
3590 case EL_ROCK: return GFX_FELSBROCKEN;
3591 case EL_EMERALD: return GFX_EDELSTEIN;
3592 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
3593 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
3594 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
3595 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
3596 case EL_PLAYER1: return GFX_SPIELER1;
3597 case EL_PLAYER2: return GFX_SPIELER2;
3598 case EL_PLAYER3: return GFX_SPIELER3;
3599 case EL_PLAYER4: return GFX_SPIELER4;
3600 case EL_BUG: return GFX_KAEFER;
3601 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
3602 case EL_BUG_UP: return GFX_KAEFER_UP;
3603 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
3604 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
3605 case EL_SPACESHIP: return GFX_FLIEGER;
3606 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
3607 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
3608 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
3609 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
3610 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
3611 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
3612 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
3613 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
3614 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
3615 case EL_BD_FIREFLY: return GFX_FIREFLY;
3616 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
3617 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
3618 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
3619 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
3620 case EL_YAMYAM: return GFX_MAMPFER;
3621 case EL_ROBOT: return GFX_ROBOT;
3622 case EL_STEELWALL: return GFX_BETON;
3623 case EL_DIAMOND: return GFX_DIAMANT;
3624 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
3625 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
3626 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
3627 case EL_AMOEBA_DROP: return GFX_TROPFEN;
3628 case EL_BOMB: return GFX_BOMBE;
3629 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
3630 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
3631 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
3632 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
3633 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
3634 case EL_ACID: return GFX_SALZSAEURE;
3635 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
3636 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
3637 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
3638 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
3639 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
3640 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
3641 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
3642 case EL_NUT: return GFX_KOKOSNUSS;
3643 case EL_GAMEOFLIFE: return GFX_LIFE;
3644 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
3645 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
3646 case EL_STONEBLOCK: return GFX_BADEWANNE;
3647 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
3648 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
3649 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
3650 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
3651 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
3652 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
3653 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
3654 case EL_KEY1: return GFX_SCHLUESSEL1;
3655 case EL_KEY2: return GFX_SCHLUESSEL2;
3656 case EL_KEY3: return GFX_SCHLUESSEL3;
3657 case EL_KEY4: return GFX_SCHLUESSEL4;
3658 case EL_GATE1: return GFX_PFORTE1;
3659 case EL_GATE2: return GFX_PFORTE2;
3660 case EL_GATE3: return GFX_PFORTE3;
3661 case EL_GATE4: return GFX_PFORTE4;
3662 case EL_GATE1_GRAY: return GFX_PFORTE1X;
3663 case EL_GATE2_GRAY: return GFX_PFORTE2X;
3664 case EL_GATE3_GRAY: return GFX_PFORTE3X;
3665 case EL_GATE4_GRAY: return GFX_PFORTE4X;
3666 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
3667 case EL_PACMAN: return GFX_PACMAN;
3668 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
3669 case EL_PACMAN_UP: return GFX_PACMAN_UP;
3670 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
3671 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
3672 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
3673 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
3674 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
3675 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
3676 case EL_LAMP: return GFX_BIRNE_AUS;
3677 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
3678 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
3679 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
3680 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
3681 case EL_WALL_GROWING_X: return GFX_MAUER_X;
3682 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
3683 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
3684 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
3685 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
3686 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
3687 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
3688 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
3689 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
3690 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
3691 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
3692 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
3693 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
3694 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
3695 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
3696 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
3697 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
3698 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
3699 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
3700 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
3701 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
3702 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
3703 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
3704 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
3705 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
3706 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
3707 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
3708 case EL_MOLE: return GFX_MOLE;
3709 case EL_PENGUIN: return GFX_PINGUIN;
3710 case EL_PIG: return GFX_SCHWEIN;
3711 case EL_DRAGON: return GFX_DRACHE;
3712 case EL_SATELLITE: return GFX_SONDE;
3713 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
3714 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
3715 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
3716 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
3717 case EL_SPEED_PILL: return GFX_SPEED_PILL;
3718 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
3719 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
3720 case EL_SP_ZONK: return GFX_SP_ZONK;
3721 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3722 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
3723 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3724 case EL_BLACK_ORB: return GFX_BLACK_ORB;
3725 case EL_EM_GATE1: return GFX_EM_GATE_1;
3726 case EL_EM_GATE2: return GFX_EM_GATE_2;
3727 case EL_EM_GATE3: return GFX_EM_GATE_3;
3728 case EL_EM_GATE4: return GFX_EM_GATE_4;
3729 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
3730 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
3731 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
3732 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
3733 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
3734 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
3735 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
3736 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
3737 case EL_EM_KEY1: return GFX_EM_KEY_1;
3738 case EL_EM_KEY2: return GFX_EM_KEY_2;
3739 case EL_EM_KEY3: return GFX_EM_KEY_3;
3740 case EL_EM_KEY4: return GFX_EM_KEY_4;
3741 case EL_PEARL: return GFX_PEARL;
3742 case EL_CRYSTAL: return GFX_CRYSTAL;
3743 case EL_WALL_PEARL: return GFX_WALL_PEARL;
3744 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
3745 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
3746 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
3747 case EL_KEY_WHITE: return GFX_KEY_WHITE;
3748 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
3749 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
3750 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
3751 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
3752 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
3753 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
3754 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
3755 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
3756 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
3757 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
3758 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3759 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3760 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3761 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3762 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3763 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3764 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
3765 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
3766 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
3767 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3768 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3769 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3770 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3771 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3772 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3773 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
3774 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
3775 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
3776 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3777 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3778 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3779 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3780 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3781 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3782 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
3783 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
3784 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
3785 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3786 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3787 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3788 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3789 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3790 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3791 case EL_LANDMINE: return GFX_LANDMINE;
3792 case EL_ENVELOPE: return GFX_ENVELOPE;
3793 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
3794 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
3795 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
3796 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
3797 case EL_SIGN_STOP: return GFX_SIGN_STOP;
3798 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
3799 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
3800 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
3801 case EL_SIGN_HEART: return GFX_SIGN_HEART;
3802 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
3803 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
3804 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
3805 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
3806 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
3807 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
3808 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
3809 case EL_MOLE_UP: return GFX_MOLE_UP;
3810 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
3811 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
3812 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
3813 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
3814 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
3815 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
3816 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
3817 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
3818 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
3819 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
3820 case EL_BALLOON: return GFX_BALLOON;
3821 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
3822 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
3823 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
3824 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
3825 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3826 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
3827 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
3828 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
3829 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
3830 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
3831 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
3832 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
3833 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
3834 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
3835 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
3836 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
3837 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
3838 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
3839 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
3840 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
3841 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
3842 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
3843 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
3844 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
3845 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
3846 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
3847 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
3848 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
3849 case EL_SPRING: return GFX_SPRING;
3850 case EL_SPRING_MOVING: return GFX_SPRING;
3851 case EL_TRAP: return GFX_TRAP_INACTIVE;
3852 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
3853 case EL_BD_WALL: return GFX_BD_WALL;
3854 case EL_BD_ROCK: return GFX_BD_ROCK;
3855 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
3856 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
3860 if (IS_CHAR(element))
3861 return GFX_CHAR_START + (element - EL_CHAR_START);
3862 else if (element >= EL_SP_START && element <= EL_SP_END)
3864 int nr_element = element - EL_SP_START;
3865 int gfx_per_line = 8;
3867 (nr_element / gfx_per_line) * SP_PER_LINE +
3868 (nr_element % gfx_per_line);
3870 return GFX_START_ROCKSSP + nr_graphic;
3878 int el2gfx(int element)
3881 int graphic_OLD = el2gfx_OLD(element);
3886 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3889 int graphic_OLD = el2gfx_OLD(element);
3891 if (element >= MAX_ELEMENTS)
3893 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3896 if (graphic_NEW != graphic_OLD)
3898 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3899 graphic_NEW, graphic_OLD);
3907 int el2img(int element)
3910 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3913 if (graphic_NEW < 0)
3914 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
3915 element, graphic_NEW);
3923 case EL_BD_BUTTERFLY: return IMG_BD_BUTTERFLY;
3924 case EL_BD_FIREFLY: return IMG_BD_FIREFLY;
3925 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
3935 int el_dir2img(int element, int direction)
3937 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3940 int el_dir_act2img(int element, int direction, int action)
3942 action = graphics_action_mapping[action];
3943 direction = MV_DIR_BIT(direction);
3945 return element_info[element].direction_graphic[action][direction];