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 void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
38 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
39 static int request_gadget_id = -1;
41 void SetDrawtoField(int mode)
43 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
54 drawto_field = fieldbuffer;
56 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
67 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
71 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
73 if (game_status == PLAYING)
79 width = gfx.sxsize + 2 * TILEX;
80 height = gfx.sysize + 2 * TILEY;
83 if (force_redraw || setup.direct_draw)
86 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
87 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
89 if (setup.direct_draw)
90 SetDrawtoField(DRAW_BACKBUFFER);
92 for(xx=BX1; xx<=BX2; xx++)
93 for(yy=BY1; yy<=BY2; yy++)
94 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
95 DrawScreenField(xx, yy);
98 if (setup.direct_draw)
99 SetDrawtoField(DRAW_DIRECT);
102 if (setup.soft_scrolling)
104 int fx = FX, fy = FY;
106 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
107 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
109 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
113 BlitBitmap(drawto, window, x, y, width, height, x, y);
119 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
121 if (setup.direct_draw && game_status == PLAYING)
122 redraw_mask &= ~REDRAW_MAIN;
124 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
125 redraw_mask |= REDRAW_FIELD;
127 if (redraw_mask & REDRAW_FIELD)
128 redraw_mask &= ~REDRAW_TILES;
130 if (redraw_mask == REDRAW_NONE)
133 if (global.fps_slowdown && game_status == PLAYING)
135 static boolean last_frame_skipped = FALSE;
136 boolean skip_even_when_not_scrolling = TRUE;
137 boolean just_scrolling = (ScreenMovDir != 0);
138 boolean verbose = FALSE;
140 if (global.fps_slowdown_factor > 1 &&
141 (FrameCounter % global.fps_slowdown_factor) &&
142 (just_scrolling || skip_even_when_not_scrolling))
144 redraw_mask &= ~REDRAW_MAIN;
146 last_frame_skipped = TRUE;
149 printf("FRAME SKIPPED\n");
153 if (last_frame_skipped)
154 redraw_mask |= REDRAW_FIELD;
156 last_frame_skipped = FALSE;
159 printf("frame not skipped\n");
163 /* synchronize X11 graphics at this point; if we would synchronize the
164 display immediately after the buffer switching (after the XFlush),
165 this could mean that we have to wait for the graphics to complete,
166 although we could go on doing calculations for the next frame */
170 if (redraw_mask & REDRAW_ALL)
172 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
176 if (redraw_mask & REDRAW_FIELD)
178 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
180 BlitBitmap(backbuffer, window,
181 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
185 int fx = FX, fy = FY;
187 if (setup.soft_scrolling)
189 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
190 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
193 if (setup.soft_scrolling ||
194 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
195 ABS(ScreenMovPos) == ScrollStepSize ||
196 redraw_tiles > REDRAWTILES_THRESHOLD)
198 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
202 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
204 (setup.soft_scrolling ?
205 "setup.soft_scrolling" :
206 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
207 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
208 ABS(ScreenGfxPos) == ScrollStepSize ?
209 "ABS(ScreenGfxPos) == ScrollStepSize" :
210 "redraw_tiles > REDRAWTILES_THRESHOLD"));
216 redraw_mask &= ~REDRAW_MAIN;
219 if (redraw_mask & REDRAW_DOORS)
221 if (redraw_mask & REDRAW_DOOR_1)
222 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
223 if (redraw_mask & REDRAW_DOOR_2)
225 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
226 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
229 if (redraw_mask & REDRAW_VIDEO_1)
230 BlitBitmap(backbuffer, window,
231 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
232 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
233 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
234 if (redraw_mask & REDRAW_VIDEO_2)
235 BlitBitmap(backbuffer, window,
236 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
237 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
238 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
239 if (redraw_mask & REDRAW_VIDEO_3)
240 BlitBitmap(backbuffer, window,
241 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
242 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
243 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
246 if (redraw_mask & REDRAW_DOOR_3)
247 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
248 redraw_mask &= ~REDRAW_DOORS;
251 if (redraw_mask & REDRAW_MICROLEVEL)
253 BlitBitmap(backbuffer, window,
254 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
255 MICROLEV_XPOS, MICROLEV_YPOS);
256 BlitBitmap(backbuffer, window,
257 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
258 SX, MICROLABEL_YPOS);
259 redraw_mask &= ~REDRAW_MICROLEVEL;
262 if (redraw_mask & REDRAW_TILES)
264 for(x=0; x<SCR_FIELDX; x++)
265 for(y=0; y<SCR_FIELDY; y++)
266 if (redraw[redraw_x1 + x][redraw_y1 + y])
267 BlitBitmap(buffer, window,
268 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
269 SX + x * TILEX, SY + y * TILEY);
272 if (redraw_mask & REDRAW_FPS) /* display frames per second */
277 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
278 if (!global.fps_slowdown)
281 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
282 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW, FONT_OPAQUE);
287 for(x=0; x<MAX_BUF_XSIZE; x++)
288 for(y=0; y<MAX_BUF_YSIZE; y++)
291 redraw_mask = REDRAW_NONE;
297 long fading_delay = 300;
299 if (setup.fading && (redraw_mask & REDRAW_FIELD))
306 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
309 for(i=0;i<2*FULL_SYSIZE;i++)
311 for(y=0;y<FULL_SYSIZE;y++)
313 BlitBitmap(backbuffer, window,
314 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
322 for(i=1;i<FULL_SYSIZE;i+=2)
323 BlitBitmap(backbuffer, window,
324 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
330 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
331 BlitBitmapMasked(backbuffer, window,
332 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
337 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
338 BlitBitmapMasked(backbuffer, window,
339 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
344 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
345 BlitBitmapMasked(backbuffer, window,
346 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
351 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
352 BlitBitmapMasked(backbuffer, window,
353 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
358 redraw_mask &= ~REDRAW_MAIN;
365 void DrawBackground(int x, int y, int width, int height)
367 /* some sanity checks */
370 width -= (REAL_SX - x);
376 height -= (REAL_SY - y);
380 if (width > FULL_SXSIZE)
383 if (height > FULL_SYSIZE)
384 height = FULL_SYSIZE;
386 if (DrawingOnBackground(x, y) && game_status != PLAYING)
387 BlitBitmap(gfx.background_bitmap, backbuffer, x - REAL_SX, y - REAL_SY,
388 width, height, x, y);
390 ClearRectangle(backbuffer, x, y, width, height);
392 redraw_mask |= REDRAW_FIELD;
397 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
399 if (setup.soft_scrolling && game_status == PLAYING)
401 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
402 SetDrawtoField(DRAW_BUFFERED);
405 SetDrawtoField(DRAW_BACKBUFFER);
407 if (setup.direct_draw && game_status == PLAYING)
409 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
410 SetDrawtoField(DRAW_DIRECT);
414 static int getGraphicAnimationPhase(int frames, int delay, int mode)
418 if (mode & ANIM_PINGPONG)
420 int max_anim_frames = 2 * frames - 2;
422 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
423 phase = (phase < frames ? phase : max_anim_frames - phase);
426 phase = (FrameCounter % (delay * frames)) / delay;
428 if (mode & ANIM_REVERSE)
434 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
436 /* animation synchronized with global frame counter, not move position */
437 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
438 sync_frame = FrameCounter;
440 return getAnimationFrame(new_graphic_info[graphic].anim_frames,
441 new_graphic_info[graphic].anim_delay,
442 new_graphic_info[graphic].anim_mode,
443 new_graphic_info[graphic].anim_start_frame,
447 void MarkTileDirty(int x, int y)
449 int xx = redraw_x1 + x;
450 int yy = redraw_y1 + y;
455 redraw[xx][yy] = TRUE;
456 redraw_mask |= REDRAW_TILES;
459 void SetBorderElement()
463 BorderElement = EL_EMPTY;
465 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
467 for(x=0; x<lev_fieldx; x++)
469 if (!IS_MASSIVE(Feld[x][y]))
470 BorderElement = EL_STEELWALL;
472 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
478 void DrawAllPlayers()
482 for(i=0; i<MAX_PLAYERS; i++)
483 if (stored_player[i].active)
484 DrawPlayer(&stored_player[i]);
487 void DrawPlayerField(int x, int y)
489 if (!IS_PLAYER(x, y))
492 DrawPlayer(PLAYERINFO(x, y));
495 void DrawPlayer(struct PlayerInfo *player)
497 int jx = player->jx, jy = player->jy;
498 int last_jx = player->last_jx, last_jy = player->last_jy;
499 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
500 int sx = SCREENX(jx), sy = SCREENY(jy);
501 int sxx = 0, syy = 0;
502 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
505 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
507 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
511 if (!IN_LEV_FIELD(jx,jy))
513 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
514 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
515 printf("DrawPlayerField(): This should never happen!\n");
520 if (element == EL_EXPLOSION)
523 /* draw things in the field the player is leaving, if needed */
525 if (player_is_moving)
527 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
529 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
531 if (last_element == EL_DYNAMITE_ACTIVE)
532 DrawDynamite(last_jx, last_jy);
534 DrawLevelFieldThruMask(last_jx, last_jy);
536 else if (last_element == EL_DYNAMITE_ACTIVE)
537 DrawDynamite(last_jx, last_jy);
539 DrawLevelField(last_jx, last_jy);
541 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
545 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
546 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
548 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
551 DrawLevelField(next_jx, next_jy);
555 if (!IN_SCR_FIELD(sx, sy))
558 if (setup.direct_draw)
559 SetDrawtoField(DRAW_BUFFERED);
561 /* draw things behind the player, if needed */
564 DrawLevelElement(jx, jy, Store[jx][jy]);
565 else if (!IS_ACTIVE_BOMB(element))
566 DrawLevelField(jx, jy);
568 DrawLevelElement(jx, jy, EL_EMPTY);
570 /* draw player himself */
572 if (game.emulation == EMU_SUPAPLEX)
574 static int last_dir = MV_LEFT;
575 int action = (player->programmed_action ? player->programmed_action :
577 boolean action_moving =
579 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
580 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
582 graphic = IMG_SP_MURPHY;
586 if (player->MovDir == MV_LEFT)
587 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
588 else if (player->MovDir == MV_RIGHT)
589 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
590 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
591 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
592 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
593 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
595 else if (player->snapped)
597 if (player->MovDir == MV_LEFT)
598 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
599 else if (player->MovDir == MV_RIGHT)
600 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
601 else if (player->MovDir == MV_UP)
602 graphic = IMG_SP_MURPHY_UP_SNAPPING;
603 else if (player->MovDir == MV_DOWN)
604 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
606 else if (action_moving)
608 if (player->MovDir == MV_LEFT)
609 graphic = IMG_SP_MURPHY_LEFT_MOVING;
610 else if (player->MovDir == MV_RIGHT)
611 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
612 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
613 graphic = IMG_SP_MURPHY_LEFT_MOVING;
614 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
615 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
617 graphic = IMG_SP_MURPHY_LEFT_MOVING;
619 frame = getGraphicAnimationFrame(graphic, -1);
622 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
623 last_dir = player->MovDir;
627 if (player->MovDir == MV_LEFT)
628 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
629 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
631 else if (player->MovDir == MV_RIGHT)
632 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
633 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
635 else if (player->MovDir == MV_UP)
636 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
637 player->is_moving ? IMG_PLAYER1_UP_MOVING :
639 else /* MV_DOWN || MV_NO_MOVING */
640 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
641 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
644 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
647 frame = player->Frame;
649 frame = getGraphicAnimationFrame(graphic, player->Frame);
655 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
656 sxx = player->GfxPos;
658 syy = player->GfxPos;
661 if (!setup.soft_scrolling && ScreenMovPos)
666 printf("-> %d\n", player->Frame);
669 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
671 if (SHIELD_ON(player))
673 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
674 IMG_SHIELD_NORMAL_ACTIVE);
675 int frame = getGraphicAnimationFrame(graphic, -1);
677 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
681 if (player->Pushing && player->GfxPos)
683 if (player->Pushing && player_is_moving)
686 int px = SCREENX(next_jx), py = SCREENY(next_jy);
688 if (element == EL_SOKOBAN_FIELD_EMPTY ||
689 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
690 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
694 int element = Feld[next_jx][next_jy];
695 int graphic = el2img(element);
700 if (sxx && IS_PUSHABLE(element))
702 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
704 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
706 frame = getGraphicAnimationFrame(graphic, player->Frame);
710 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
715 if (player->MovDir == MV_LEFT)
720 frame = (player->GfxPos / (TILEX / 4));
722 if (player->MovDir == MV_RIGHT)
723 frame = (frame + 4) % 4;
727 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
728 NO_CUTTING, NO_MASKING);
732 /* draw things in front of player (active dynamite or dynabombs) */
734 if (IS_ACTIVE_BOMB(element))
736 graphic = el2img(element);
739 if (element == EL_DYNAMITE_ACTIVE)
741 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
746 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
750 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
753 if (game.emulation == EMU_SUPAPLEX)
754 DrawGraphic(sx, sy, GFX_SP_DISK_RED, 0);
756 DrawGraphicThruMask(sx, sy, graphic, frame);
759 if (player_is_moving && last_element == EL_EXPLOSION)
761 int stored = Store[last_jx][last_jy];
762 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
763 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
765 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
766 int phase = Frame[last_jx][last_jy] - 1;
767 int frame = getGraphicAnimationFrame(graphic, phase - delay);
770 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
773 /* draw elements that stay over the player */
774 /* handle the field the player is leaving ... */
775 if (player_is_moving && IS_OVER_PLAYER(last_element))
776 DrawLevelField(last_jx, last_jy);
778 /* ... and the field the player is entering */
779 if (IS_OVER_PLAYER(element))
780 DrawLevelField(jx, jy);
782 if (setup.direct_draw)
784 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
785 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
786 int x_size = TILEX * (1 + ABS(jx - last_jx));
787 int y_size = TILEY * (1 + ABS(jy - last_jy));
789 BlitBitmap(drawto_field, window,
790 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
791 SetDrawtoField(DRAW_DIRECT);
794 MarkTileDirty(sx,sy);
797 void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
798 int graphic, int mask_mode)
800 int frame = getGraphicAnimationFrame(graphic, -1);
802 if (mask_mode == USE_MASKING)
803 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
805 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
808 void DrawGraphicAnimation(int x, int y, int graphic)
810 if (!IN_SCR_FIELD(x, y) ||
811 (FrameCounter % new_graphic_info[graphic].anim_delay) != 0)
814 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
815 graphic, NO_MASKING);
820 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
822 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
824 *bitmap = graphic_info[graphic].bitmap;
825 *x = graphic_info[graphic].src_x;
826 *y = graphic_info[graphic].src_y;
828 else if (graphic >= GFX_START_ROCKSELEMENTS &&
829 graphic <= GFX_END_ROCKSELEMENTS)
831 graphic -= GFX_START_ROCKSELEMENTS;
832 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
833 *x = (graphic % GFX_PER_LINE) * TILEX;
834 *y = (graphic / GFX_PER_LINE) * TILEY;
836 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
838 graphic -= GFX_START_ROCKSHEROES;
839 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
840 *x = (graphic % HEROES_PER_LINE) * TILEX;
841 *y = (graphic / HEROES_PER_LINE) * TILEY;
843 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
845 graphic -= GFX_START_ROCKSSP;
846 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
847 *x = (graphic % SP_PER_LINE) * TILEX;
848 *y = (graphic / SP_PER_LINE) * TILEY;
850 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
852 graphic -= GFX_START_ROCKSDC;
853 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
854 *x = (graphic % DC_PER_LINE) * TILEX;
855 *y = (graphic / DC_PER_LINE) * TILEY;
857 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
859 graphic -= GFX_START_ROCKSMORE;
860 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
861 *x = (graphic % MORE_PER_LINE) * TILEX;
862 *y = (graphic / MORE_PER_LINE) * TILEY;
864 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
866 graphic -= GFX_START_ROCKSFONT;
867 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
868 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
869 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
873 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
880 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
882 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
883 int offset_x = new_graphic_info[graphic].offset_x;
884 int offset_y = new_graphic_info[graphic].offset_y;
885 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
886 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
888 *bitmap = src_bitmap;
893 void DrawGraphic(int x, int y, int graphic, int frame)
896 if (!IN_SCR_FIELD(x, y))
898 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
899 printf("DrawGraphic(): This should never happen!\n");
904 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
909 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
914 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
915 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
919 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
926 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
928 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
929 int src_x = new_graphic_info[graphic].src_x;
930 int src_y = new_graphic_info[graphic].src_y;
931 int offset_x = new_graphic_info[graphic].offset_x;
932 int offset_y = new_graphic_info[graphic].offset_y;
934 src_x += frame * offset_x;
935 src_y += frame * offset_y;
938 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
941 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
944 if (!IN_SCR_FIELD(x, y))
946 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
947 printf("DrawGraphicThruMask(): This should never happen!\n");
952 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
957 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
965 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
966 drawing_gc = src_bitmap->stored_clip_gc;
968 GC drawing_gc = src_bitmap->stored_clip_gc;
969 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
970 int src_x = new_graphic_info[graphic].src_x;
971 int src_y = new_graphic_info[graphic].src_y;
972 int offset_x = new_graphic_info[graphic].offset_x;
973 int offset_y = new_graphic_info[graphic].offset_y;
975 src_x += frame * offset_x;
976 src_y += frame * offset_y;
980 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
981 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
984 void DrawMiniGraphic(int x, int y, int graphic)
986 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
987 MarkTileDirty(x / 2, y / 2);
990 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
992 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
994 int mini_starty = src_bitmap->height * 2 / 3;
995 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
996 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
998 if (src_x + MINI_TILEX > src_bitmap->width ||
999 src_y + MINI_TILEY > src_bitmap->height)
1001 /* graphic of desired size seems not to be contained in this image;
1002 dirty workaround: get it from the middle of the normal sized image */
1004 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1005 src_x += (TILEX / 2 - MINI_TILEX / 2);
1006 src_y += (TILEY / 2 - MINI_TILEY / 2);
1009 *bitmap = src_bitmap;
1014 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1019 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1020 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1023 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1024 int cut_mode, int mask_mode)
1033 int width = TILEX, height = TILEY;
1039 DrawGraphic(x, y, graphic, frame);
1043 if (dx || dy) /* shifted graphic */
1045 if (x < BX1) /* object enters playfield from the left */
1052 else if (x > BX2) /* object enters playfield from the right */
1058 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1064 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1066 else if (dx) /* general horizontal movement */
1067 MarkTileDirty(x + SIGN(dx), y);
1069 if (y < BY1) /* object enters playfield from the top */
1071 if (cut_mode==CUT_BELOW) /* object completely above top border */
1079 else if (y > BY2) /* object enters playfield from the bottom */
1085 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1091 else if (dy > 0 && cut_mode == CUT_ABOVE)
1093 if (y == BY2) /* object completely above bottom border */
1099 MarkTileDirty(x, y + 1);
1100 } /* object leaves playfield to the bottom */
1101 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1103 else if (dy) /* general vertical movement */
1104 MarkTileDirty(x, y + SIGN(dy));
1107 src_bitmap = new_graphic_info[graphic].bitmap;
1108 src_x = new_graphic_info[graphic].src_x;
1109 src_y = new_graphic_info[graphic].src_y;
1110 offset_x = new_graphic_info[graphic].offset_x;
1111 offset_y = new_graphic_info[graphic].offset_y;
1113 drawing_gc = src_bitmap->stored_clip_gc;
1115 src_x += frame * offset_x;
1116 src_y += frame * offset_y;
1121 dest_x = FX + x * TILEX + dx;
1122 dest_y = FY + y * TILEY + dy;
1125 if (!IN_SCR_FIELD(x,y))
1127 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1128 printf("DrawGraphicShifted(): This should never happen!\n");
1133 if (mask_mode == USE_MASKING)
1135 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1136 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1140 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1146 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1147 int frame, int cut_mode)
1149 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1153 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1154 int cut_mode, int mask_mode)
1156 int ux = LEVELX(x), uy = LEVELY(y);
1157 int graphic = el2gfx(element);
1158 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1159 int phase4 = phase8 / 2;
1160 int phase2 = phase8 / 4;
1161 int dir = MovDir[ux][uy];
1163 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1165 graphic += 1 * !phase2;
1169 else if (dir == MV_LEFT)
1171 else if (dir == MV_DOWN)
1174 else if (element == EL_SP_SNIKSNAK)
1177 graphic = GFX_SP_SNIKSNAK_LEFT;
1178 else if (dir == MV_RIGHT)
1179 graphic = GFX_SP_SNIKSNAK_RIGHT;
1180 else if (dir == MV_UP)
1181 graphic = GFX_SP_SNIKSNAK_UP;
1183 graphic = GFX_SP_SNIKSNAK_DOWN;
1185 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1187 else if (element == EL_SP_ELECTRON)
1189 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1191 else if (element == EL_MOLE || element == EL_PENGUIN ||
1192 element == EL_PIG || element == EL_DRAGON)
1195 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1196 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1197 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1198 else if (dir == MV_RIGHT)
1199 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1200 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1201 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1202 else if (dir == MV_UP)
1203 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1204 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1205 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1207 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1208 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1209 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1213 else if (element == EL_SATELLITE)
1215 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1217 else if (element == EL_ACID)
1219 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1221 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1225 else if (element == EL_BALLOON)
1229 else if ((element == EL_ROCK ||
1230 element == EL_SP_ZONK ||
1231 element == EL_BD_ROCK ||
1232 element == EL_SP_INFOTRON ||
1236 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1238 if (element == EL_ROCK ||
1239 element == EL_SP_ZONK ||
1240 element == EL_BD_ROCK)
1243 graphic += (4 - phase4) % 4;
1244 else if (dir == MV_RIGHT)
1247 graphic += phase2 * 2;
1249 else if (element != EL_SP_INFOTRON)
1253 else if (element == EL_MAGIC_WALL_ACTIVE ||
1254 element == EL_MAGIC_WALL_EMPTYING ||
1255 element == EL_BD_MAGIC_WALL_ACTIVE ||
1256 element == EL_BD_MAGIC_WALL_EMPTYING ||
1257 element == EL_MAGIC_WALL_FULL ||
1258 element == EL_BD_MAGIC_WALL_FULL)
1260 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1262 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1264 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1265 graphic += (x + 2 * y + 4) % 4;
1267 else if (element == EL_WALL_GROWING)
1269 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1271 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1272 links_massiv = TRUE;
1273 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1274 rechts_massiv = TRUE;
1276 if (links_massiv && rechts_massiv)
1277 graphic = GFX_MAUERWERK;
1278 else if (links_massiv)
1279 graphic = GFX_MAUER_R;
1280 else if (rechts_massiv)
1281 graphic = GFX_MAUER_L;
1284 else if ((element == EL_INVISIBLE_STEELWALL ||
1285 element == EL_INVISIBLE_WALL ||
1286 element == EL_INVISIBLE_SAND) && game.light_time_left)
1288 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1289 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1290 GFX_SAND_INVISIBLE_ON);
1295 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1296 else if (mask_mode == USE_MASKING)
1297 DrawGraphicThruMask(x, y, graphic);
1299 DrawGraphic(x, y, graphic);
1303 inline static int getFramePosition(int x, int y)
1305 int frame_pos = -1; /* default: global synchronization */
1307 int element = Feld[x][y];
1309 if (element == EL_QUICKSAND_FULL ||
1310 element == EL_MAGIC_WALL_FULL ||
1311 element == EL_BD_MAGIC_WALL_FULL)
1313 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1314 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1316 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1322 inline static int getGfxAction(int x, int y)
1324 int gfx_action = GFX_ACTION_DEFAULT;
1327 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1328 gfx_action = GfxAction[x][y];
1329 else if (IS_MOVING(x, y))
1330 gfx_action = GFX_ACTION_MOVING;
1332 gfx_action = GfxAction[x][y];
1337 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1344 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1345 int cut_mode, int mask_mode)
1347 int ux = LEVELX(x), uy = LEVELY(y);
1351 if (IN_LEV_FIELD(ux, uy))
1353 int move_dir = MovDir[ux][uy];
1354 int move_pos = getFramePosition(ux, uy);
1355 int gfx_action = getGfxAction(ux, uy);
1357 graphic = el_dir_act2img(element, move_dir, gfx_action);
1358 frame = getGraphicAnimationFrame(graphic, move_pos);
1362 graphic = el2img(element);
1363 frame = getGraphicAnimationFrame(graphic, 0);
1366 if (element == EL_WALL_GROWING)
1368 boolean left_stopped = FALSE, right_stopped = FALSE;
1370 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1371 left_stopped = TRUE;
1372 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1373 right_stopped = TRUE;
1375 if (left_stopped && right_stopped)
1377 else if (left_stopped)
1379 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1380 frame = new_graphic_info[graphic].anim_frames - 1;
1382 else if (right_stopped)
1384 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1385 frame = new_graphic_info[graphic].anim_frames - 1;
1388 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1390 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1391 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1392 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1393 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1394 IMG_AMOEBA_DEAD_PART1);
1396 graphic += (x + 2 * y + 4) % 4;
1400 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1401 else if (mask_mode == USE_MASKING)
1402 DrawGraphicThruMask(x, y, graphic, frame);
1404 DrawGraphic(x, y, graphic, frame);
1407 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1408 int cut_mode, int mask_mode)
1410 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1411 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1412 cut_mode, mask_mode);
1415 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1418 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1421 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1424 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1428 void DrawOldScreenElementThruMask(int x, int y, int element)
1430 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1433 void DrawScreenElementThruMask(int x, int y, int element)
1435 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1439 void DrawLevelElementThruMask(int x, int y, int element)
1441 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1444 void DrawLevelFieldThruMask(int x, int y)
1446 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1449 void DrawCrumbledSand(int x, int y)
1453 int i, width, height, cx,cy;
1454 int ux = LEVELX(x), uy = LEVELY(y);
1455 int element, graphic;
1457 static int xy[4][2] =
1465 if (!IN_LEV_FIELD(ux, uy))
1468 element = Feld[ux][uy];
1470 if (element == EL_SAND ||
1471 element == EL_LANDMINE ||
1472 element == EL_TRAP ||
1473 element == EL_TRAP_ACTIVE)
1475 if (!IN_SCR_FIELD(x, y))
1478 graphic = IMG_SAND_CRUMBLED;
1480 src_bitmap = new_graphic_info[graphic].bitmap;
1481 src_x = new_graphic_info[graphic].src_x;
1482 src_y = new_graphic_info[graphic].src_y;
1488 uxx = ux + xy[i][0];
1489 uyy = uy + xy[i][1];
1490 if (!IN_LEV_FIELD(uxx, uyy))
1491 element = EL_STEELWALL;
1493 element = Feld[uxx][uyy];
1495 if (element == EL_SAND ||
1496 element == EL_LANDMINE ||
1497 element == EL_TRAP ||
1498 element == EL_TRAP_ACTIVE)
1501 if (i == 1 || i == 2)
1505 cx = (i == 2 ? TILEX - snip : 0);
1513 cy = (i == 3 ? TILEY - snip : 0);
1516 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1517 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1520 MarkTileDirty(x, y);
1524 graphic = IMG_SAND_CRUMBLED;
1526 src_bitmap = new_graphic_info[graphic].bitmap;
1527 src_x = new_graphic_info[graphic].src_x;
1528 src_y = new_graphic_info[graphic].src_y;
1532 int xx, yy, uxx, uyy;
1536 uxx = ux + xy[i][0];
1537 uyy = uy + xy[i][1];
1539 if (!IN_LEV_FIELD(uxx, uyy) ||
1540 (Feld[uxx][uyy] != EL_SAND &&
1541 Feld[uxx][uyy] != EL_LANDMINE &&
1542 Feld[uxx][uyy] != EL_TRAP &&
1543 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1544 !IN_SCR_FIELD(xx, yy))
1547 if (i == 1 || i == 2)
1551 cx = (i == 1 ? TILEX - snip : 0);
1559 cy = (i==0 ? TILEY-snip : 0);
1562 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1563 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1565 MarkTileDirty(xx, yy);
1570 void DrawScreenElement(int x, int y, int element)
1572 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1573 DrawCrumbledSand(x, y);
1576 void DrawLevelElement(int x, int y, int element)
1578 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1579 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1582 void DrawScreenField(int x, int y)
1584 int ux = LEVELX(x), uy = LEVELY(y);
1585 int element, content;
1587 if (!IN_LEV_FIELD(ux, uy))
1589 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1592 element = BorderElement;
1594 DrawScreenElement(x, y, element);
1598 element = Feld[ux][uy];
1599 content = Store[ux][uy];
1601 if (IS_MOVING(ux, uy))
1603 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1604 boolean cut_mode = NO_CUTTING;
1606 if (element == EL_QUICKSAND_EMPTYING ||
1607 element == EL_MAGIC_WALL_EMPTYING ||
1608 element == EL_BD_MAGIC_WALL_EMPTYING ||
1609 element == EL_AMOEBA_DRIPPING)
1610 cut_mode = CUT_ABOVE;
1611 else if (element == EL_QUICKSAND_FILLING ||
1612 element == EL_MAGIC_WALL_FILLING ||
1613 element == EL_BD_MAGIC_WALL_FILLING)
1614 cut_mode = CUT_BELOW;
1616 if (cut_mode == CUT_ABOVE)
1617 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1619 DrawScreenElement(x, y, EL_EMPTY);
1622 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1623 else if (cut_mode == NO_CUTTING)
1624 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1626 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1628 if (content == EL_ACID)
1629 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1631 else if (IS_BLOCKED(ux, uy))
1636 boolean cut_mode = NO_CUTTING;
1637 int element_old, content_old;
1639 Blocked2Moving(ux, uy, &oldx, &oldy);
1642 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1643 MovDir[oldx][oldy] == MV_RIGHT);
1645 element_old = Feld[oldx][oldy];
1646 content_old = Store[oldx][oldy];
1648 if (element_old == EL_QUICKSAND_EMPTYING ||
1649 element_old == EL_MAGIC_WALL_EMPTYING ||
1650 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1651 element_old == EL_AMOEBA_DRIPPING)
1652 cut_mode = CUT_ABOVE;
1654 DrawScreenElement(x, y, EL_EMPTY);
1657 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1659 else if (cut_mode == NO_CUTTING)
1660 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1663 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1666 else if (IS_DRAWABLE(element))
1667 DrawScreenElement(x, y, element);
1669 DrawScreenElement(x, y, EL_EMPTY);
1672 void DrawLevelField(int x, int y)
1674 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1675 DrawScreenField(SCREENX(x), SCREENY(y));
1676 else if (IS_MOVING(x, y))
1680 Moving2Blocked(x, y, &newx, &newy);
1681 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1682 DrawScreenField(SCREENX(newx), SCREENY(newy));
1684 else if (IS_BLOCKED(x, y))
1688 Blocked2Moving(x, y, &oldx, &oldy);
1689 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1690 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1694 void DrawMiniElement(int x, int y, int element)
1698 graphic = el2img(element);
1699 DrawMiniGraphic(x, y, graphic);
1702 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1704 int x = sx + scroll_x, y = sy + scroll_y;
1706 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1707 DrawMiniElement(sx, sy, EL_EMPTY);
1708 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1709 DrawMiniElement(sx, sy, Feld[x][y]);
1712 int steel_type, steel_position;
1715 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1716 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1717 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1718 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1719 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1720 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1723 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1724 steel_position = (x == -1 && y == -1 ? 0 :
1725 x == lev_fieldx && y == -1 ? 1 :
1726 x == -1 && y == lev_fieldy ? 2 :
1727 x == lev_fieldx && y == lev_fieldy ? 3 :
1728 x == -1 || x == lev_fieldx ? 4 :
1729 y == -1 || y == lev_fieldy ? 5 : -1);
1731 if (steel_position != -1)
1732 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1736 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1738 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1739 int mini_startx = src_bitmap->width * 3 / 4;
1740 int mini_starty = src_bitmap->height * 2 / 3;
1741 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1742 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1744 if (src_x + MICRO_TILEX > src_bitmap->width ||
1745 src_y + MICRO_TILEY > src_bitmap->height)
1747 /* graphic of desired size seems not to be contained in this image;
1748 dirty workaround: get it from the middle of the normal sized image */
1750 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1751 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1752 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1755 *bitmap = src_bitmap;
1760 void DrawMicroElement(int xpos, int ypos, int element)
1764 int graphic = el2img(element);
1766 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1767 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1777 for(x=BX1; x<=BX2; x++)
1778 for(y=BY1; y<=BY2; y++)
1779 DrawScreenField(x, y);
1781 redraw_mask |= REDRAW_FIELD;
1784 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1788 for(x=0; x<size_x; x++)
1789 for(y=0; y<size_y; y++)
1790 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1792 redraw_mask |= REDRAW_FIELD;
1795 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1799 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1801 if (lev_fieldx < STD_LEV_FIELDX)
1802 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1803 if (lev_fieldy < STD_LEV_FIELDY)
1804 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1806 xpos += MICRO_TILEX;
1807 ypos += MICRO_TILEY;
1809 for(x=-1; x<=STD_LEV_FIELDX; x++)
1811 for(y=-1; y<=STD_LEV_FIELDY; y++)
1813 int lx = from_x + x, ly = from_y + y;
1815 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1816 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1818 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1819 && BorderElement != EL_EMPTY)
1820 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1825 redraw_mask |= REDRAW_MICROLEVEL;
1828 #define MICROLABEL_EMPTY 0
1829 #define MICROLABEL_LEVEL_NAME 1
1830 #define MICROLABEL_CREATED_BY 2
1831 #define MICROLABEL_LEVEL_AUTHOR 3
1832 #define MICROLABEL_IMPORTED_FROM 4
1833 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1835 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1837 static void DrawMicroLevelLabelExt(int mode)
1839 char label_text[MAX_MICROLABEL_SIZE + 1];
1841 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1843 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1844 mode == MICROLABEL_CREATED_BY ? "created by" :
1845 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1846 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1847 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1848 leveldir_current->imported_from : ""),
1849 MAX_MICROLABEL_SIZE);
1850 label_text[MAX_MICROLABEL_SIZE] = '\0';
1852 if (strlen(label_text) > 0)
1854 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1855 int lypos = MICROLABEL_YPOS;
1857 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1860 redraw_mask |= REDRAW_MICROLEVEL;
1863 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1865 static unsigned long scroll_delay = 0;
1866 static unsigned long label_delay = 0;
1867 static int from_x, from_y, scroll_direction;
1868 static int label_state, label_counter;
1872 from_x = from_y = 0;
1873 scroll_direction = MV_RIGHT;
1877 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1878 DrawMicroLevelLabelExt(label_state);
1880 /* initialize delay counters */
1881 DelayReached(&scroll_delay, 0);
1882 DelayReached(&label_delay, 0);
1887 /* scroll micro level, if needed */
1888 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1889 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1891 switch (scroll_direction)
1897 scroll_direction = MV_UP;
1901 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1904 scroll_direction = MV_DOWN;
1911 scroll_direction = MV_RIGHT;
1915 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1918 scroll_direction = MV_LEFT;
1925 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1928 /* redraw micro level label, if needed */
1929 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1930 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1931 strcmp(level.author, leveldir_current->name) != 0 &&
1932 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1934 int max_label_counter = 23;
1936 if (leveldir_current->imported_from != NULL)
1937 max_label_counter += 14;
1939 label_counter = (label_counter + 1) % max_label_counter;
1940 label_state = (label_counter >= 0 && label_counter <= 7 ?
1941 MICROLABEL_LEVEL_NAME :
1942 label_counter >= 9 && label_counter <= 12 ?
1943 MICROLABEL_CREATED_BY :
1944 label_counter >= 14 && label_counter <= 21 ?
1945 MICROLABEL_LEVEL_AUTHOR :
1946 label_counter >= 23 && label_counter <= 26 ?
1947 MICROLABEL_IMPORTED_FROM :
1948 label_counter >= 28 && label_counter <= 35 ?
1949 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1950 DrawMicroLevelLabelExt(label_state);
1954 int REQ_in_range(int x, int y)
1956 if (y > DY+249 && y < DY+278)
1958 if (x > DX+1 && x < DX+48)
1960 else if (x > DX+51 && x < DX+98)
1966 #define MAX_REQUEST_LINES 13
1967 #define MAX_REQUEST_LINE_LEN 7
1969 boolean Request(char *text, unsigned int req_state)
1971 int mx, my, ty, result = -1;
1972 unsigned int old_door_state;
1974 #if defined(PLATFORM_UNIX)
1975 /* pause network game while waiting for request to answer */
1976 if (options.network &&
1977 game_status == PLAYING &&
1978 req_state & REQUEST_WAIT_FOR)
1979 SendToServer_PausePlaying();
1982 old_door_state = GetDoorState();
1986 CloseDoor(DOOR_CLOSE_1);
1988 /* save old door content */
1989 BlitBitmap(bitmap_db_door, bitmap_db_door,
1990 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1991 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1993 /* clear door drawing field */
1994 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1996 /* write text for request */
1997 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1999 char text_line[MAX_REQUEST_LINE_LEN + 1];
2005 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2008 if (!tc || tc == ' ')
2019 strncpy(text_line, text, tl);
2022 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2023 text_line, FS_SMALL, FC_YELLOW, FONT_OPAQUE);
2025 text += tl + (tc == ' ' ? 1 : 0);
2028 if (req_state & REQ_ASK)
2030 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2031 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2033 else if (req_state & REQ_CONFIRM)
2035 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2037 else if (req_state & REQ_PLAYER)
2039 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2040 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2041 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2042 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2045 /* copy request gadgets to door backbuffer */
2046 BlitBitmap(drawto, bitmap_db_door,
2047 DX, DY, DXSIZE, DYSIZE,
2048 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2050 OpenDoor(DOOR_OPEN_1);
2056 if (!(req_state & REQUEST_WAIT_FOR))
2059 if (game_status != MAINMENU)
2062 button_status = MB_RELEASED;
2064 request_gadget_id = -1;
2076 case EVENT_BUTTONPRESS:
2077 case EVENT_BUTTONRELEASE:
2078 case EVENT_MOTIONNOTIFY:
2080 if (event.type == EVENT_MOTIONNOTIFY)
2082 if (!PointerInWindow(window))
2083 continue; /* window and pointer are on different screens */
2088 motion_status = TRUE;
2089 mx = ((MotionEvent *) &event)->x;
2090 my = ((MotionEvent *) &event)->y;
2094 motion_status = FALSE;
2095 mx = ((ButtonEvent *) &event)->x;
2096 my = ((ButtonEvent *) &event)->y;
2097 if (event.type == EVENT_BUTTONPRESS)
2098 button_status = ((ButtonEvent *) &event)->button;
2100 button_status = MB_RELEASED;
2103 /* this sets 'request_gadget_id' */
2104 HandleGadgets(mx, my, button_status);
2106 switch(request_gadget_id)
2108 case TOOL_CTRL_ID_YES:
2111 case TOOL_CTRL_ID_NO:
2114 case TOOL_CTRL_ID_CONFIRM:
2115 result = TRUE | FALSE;
2118 case TOOL_CTRL_ID_PLAYER_1:
2121 case TOOL_CTRL_ID_PLAYER_2:
2124 case TOOL_CTRL_ID_PLAYER_3:
2127 case TOOL_CTRL_ID_PLAYER_4:
2138 case EVENT_KEYPRESS:
2139 switch(GetEventKey((KeyEvent *)&event, TRUE))
2152 if (req_state & REQ_PLAYER)
2156 case EVENT_KEYRELEASE:
2157 ClearPlayerAction();
2161 HandleOtherEvents(&event);
2165 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2167 int joy = AnyJoystick();
2169 if (joy & JOY_BUTTON_1)
2171 else if (joy & JOY_BUTTON_2)
2177 /* don't eat all CPU time */
2181 if (game_status != MAINMENU)
2186 if (!(req_state & REQ_STAY_OPEN))
2188 CloseDoor(DOOR_CLOSE_1);
2190 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2192 BlitBitmap(bitmap_db_door, bitmap_db_door,
2193 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2194 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2195 OpenDoor(DOOR_OPEN_1);
2201 #if defined(PLATFORM_UNIX)
2202 /* continue network game after request */
2203 if (options.network &&
2204 game_status == PLAYING &&
2205 req_state & REQUEST_WAIT_FOR)
2206 SendToServer_ContinuePlaying();
2212 unsigned int OpenDoor(unsigned int door_state)
2214 unsigned int new_door_state;
2216 if (door_state & DOOR_COPY_BACK)
2218 BlitBitmap(bitmap_db_door, bitmap_db_door,
2219 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2220 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2221 door_state &= ~DOOR_COPY_BACK;
2224 new_door_state = MoveDoor(door_state);
2226 return(new_door_state);
2229 unsigned int CloseDoor(unsigned int door_state)
2231 unsigned int new_door_state;
2233 BlitBitmap(backbuffer, bitmap_db_door,
2234 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2235 BlitBitmap(backbuffer, bitmap_db_door,
2236 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2238 new_door_state = MoveDoor(door_state);
2240 return(new_door_state);
2243 unsigned int GetDoorState()
2245 return MoveDoor(DOOR_GET_STATE);
2248 unsigned int SetDoorState(unsigned int door_state)
2250 return MoveDoor(door_state | DOOR_SET_STATE);
2253 unsigned int MoveDoor(unsigned int door_state)
2255 static int door1 = DOOR_OPEN_1;
2256 static int door2 = DOOR_CLOSE_2;
2257 static unsigned long door_delay = 0;
2258 int x, start, stepsize = 2;
2259 unsigned long door_delay_value = stepsize * 5;
2261 if (door_state == DOOR_GET_STATE)
2262 return(door1 | door2);
2264 if (door_state & DOOR_SET_STATE)
2266 if (door_state & DOOR_ACTION_1)
2267 door1 = door_state & DOOR_ACTION_1;
2268 if (door_state & DOOR_ACTION_2)
2269 door2 = door_state & DOOR_ACTION_2;
2271 return(door1 | door2);
2274 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2275 door_state &= ~DOOR_OPEN_1;
2276 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2277 door_state &= ~DOOR_CLOSE_1;
2278 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2279 door_state &= ~DOOR_OPEN_2;
2280 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2281 door_state &= ~DOOR_CLOSE_2;
2283 if (setup.quick_doors)
2286 door_delay_value = 0;
2288 StopSound(SND_MENU_DOOR_OPENING);
2289 StopSound(SND_MENU_DOOR_CLOSING);
2292 if (global.autoplay_leveldir)
2294 door_state |= DOOR_NO_DELAY;
2295 door_state &= ~DOOR_CLOSE_ALL;
2298 if (door_state & DOOR_ACTION)
2300 if (!(door_state & DOOR_NO_DELAY))
2302 /* opening door sound has priority over simultaneously closing door */
2303 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2304 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2305 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2306 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2309 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2311 for(x=start; x<=DXSIZE; x+=stepsize)
2313 Bitmap *bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2314 GC gc = bitmap->stored_clip_gc;
2316 if (!(door_state & DOOR_NO_DELAY))
2317 WaitUntilDelayReached(&door_delay, door_delay_value);
2319 if (door_state & DOOR_ACTION_1)
2321 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2322 int j = (DXSIZE - i) / 3;
2324 BlitBitmap(bitmap_db_door, drawto,
2325 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2326 DXSIZE,DYSIZE - i/2, DX, DY);
2328 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2330 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2331 BlitBitmapMasked(bitmap, drawto,
2332 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2333 DX + DXSIZE - i, DY + j);
2334 BlitBitmapMasked(bitmap, drawto,
2335 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2336 DX + DXSIZE - i, DY + 140 + j);
2337 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2338 BlitBitmapMasked(bitmap, drawto,
2339 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2341 BlitBitmapMasked(bitmap, drawto,
2342 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2345 BlitBitmapMasked(bitmap, drawto,
2346 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2348 BlitBitmapMasked(bitmap, drawto,
2349 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2351 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2352 BlitBitmapMasked(bitmap, drawto,
2353 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2354 DX + DXSIZE - i, DY + 77 + j);
2355 BlitBitmapMasked(bitmap, drawto,
2356 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2357 DX + DXSIZE - i, DY + 203 + j);
2359 redraw_mask |= REDRAW_DOOR_1;
2362 if (door_state & DOOR_ACTION_2)
2364 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2365 int j = (VXSIZE - i) / 3;
2367 BlitBitmap(bitmap_db_door, drawto,
2368 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2369 VXSIZE, VYSIZE - i/2, VX, VY);
2371 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2373 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2374 BlitBitmapMasked(bitmap, drawto,
2375 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2376 VX + VXSIZE-i, VY+j);
2377 SetClipOrigin(bitmap, gc,
2378 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2379 BlitBitmapMasked(bitmap, drawto,
2380 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2383 BlitBitmapMasked(bitmap, drawto,
2384 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2385 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2386 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2387 BlitBitmapMasked(bitmap, drawto,
2388 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2390 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2392 redraw_mask |= REDRAW_DOOR_2;
2397 if (game_status == MAINMENU)
2402 if (setup.quick_doors)
2404 StopSound(SND_MENU_DOOR_OPENING);
2405 StopSound(SND_MENU_DOOR_CLOSING);
2408 if (door_state & DOOR_ACTION_1)
2409 door1 = door_state & DOOR_ACTION_1;
2410 if (door_state & DOOR_ACTION_2)
2411 door2 = door_state & DOOR_ACTION_2;
2413 return (door1 | door2);
2416 void DrawSpecialEditorDoor()
2418 /* draw bigger toolbox window */
2419 BlitBitmap(new_graphic_info[IMG_MENU_DOOR].bitmap, drawto,
2420 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2422 BlitBitmap(new_graphic_info[IMG_MENU_FRAME].bitmap, drawto,
2423 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2426 redraw_mask |= REDRAW_ALL;
2429 void UndrawSpecialEditorDoor()
2431 /* draw normal tape recorder window */
2432 BlitBitmap(new_graphic_info[IMG_MENU_FRAME].bitmap, drawto,
2433 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2436 redraw_mask |= REDRAW_ALL;
2440 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2442 XImage *pixel_image;
2443 unsigned long pixel_value;
2445 pixel_image = XGetImage(display, bitmap->drawable,
2446 x, y, 1, 1, AllPlanes, ZPixmap);
2447 pixel_value = XGetPixel(pixel_image, 0, 0);
2449 XDestroyImage(pixel_image);
2455 /* ---------- new tool button stuff ---------------------------------------- */
2457 /* graphic position values for tool buttons */
2458 #define TOOL_BUTTON_YES_XPOS 2
2459 #define TOOL_BUTTON_YES_YPOS 250
2460 #define TOOL_BUTTON_YES_GFX_YPOS 0
2461 #define TOOL_BUTTON_YES_XSIZE 46
2462 #define TOOL_BUTTON_YES_YSIZE 28
2463 #define TOOL_BUTTON_NO_XPOS 52
2464 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2465 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2466 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2467 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2468 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2469 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2470 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2471 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2472 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2473 #define TOOL_BUTTON_PLAYER_XSIZE 30
2474 #define TOOL_BUTTON_PLAYER_YSIZE 30
2475 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2476 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2477 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2478 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2479 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2480 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2481 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2482 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2483 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2484 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2485 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2486 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2487 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2488 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2489 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2490 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2491 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2492 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2493 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2494 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2503 } toolbutton_info[NUM_TOOL_BUTTONS] =
2506 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2507 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2508 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2513 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2514 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2515 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2520 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2521 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2522 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2523 TOOL_CTRL_ID_CONFIRM,
2527 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2528 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2529 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2530 TOOL_CTRL_ID_PLAYER_1,
2534 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2535 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2536 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2537 TOOL_CTRL_ID_PLAYER_2,
2541 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2542 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2543 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2544 TOOL_CTRL_ID_PLAYER_3,
2548 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2549 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2550 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2551 TOOL_CTRL_ID_PLAYER_4,
2556 void CreateToolButtons()
2560 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2562 Bitmap *gd_bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2563 Bitmap *deco_bitmap = None;
2564 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2565 struct GadgetInfo *gi;
2566 unsigned long event_mask;
2567 int gd_xoffset, gd_yoffset;
2568 int gd_x1, gd_x2, gd_y;
2571 event_mask = GD_EVENT_RELEASED;
2573 gd_xoffset = toolbutton_info[i].xpos;
2574 gd_yoffset = toolbutton_info[i].ypos;
2575 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2576 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2577 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2579 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2581 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2583 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2584 &deco_bitmap, &deco_x, &deco_y);
2585 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2586 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2589 gi = CreateGadget(GDI_CUSTOM_ID, id,
2590 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2591 GDI_X, DX + toolbutton_info[i].x,
2592 GDI_Y, DY + toolbutton_info[i].y,
2593 GDI_WIDTH, toolbutton_info[i].width,
2594 GDI_HEIGHT, toolbutton_info[i].height,
2595 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2596 GDI_STATE, GD_BUTTON_UNPRESSED,
2597 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2598 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2599 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2600 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2601 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2602 GDI_DECORATION_SHIFTING, 1, 1,
2603 GDI_EVENT_MASK, event_mask,
2604 GDI_CALLBACK_ACTION, HandleToolButtons,
2608 Error(ERR_EXIT, "cannot create gadget");
2610 tool_gadget[id] = gi;
2614 void FreeToolButtons()
2618 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2619 FreeGadget(tool_gadget[i]);
2622 static void UnmapToolButtons()
2626 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2627 UnmapGadget(tool_gadget[i]);
2630 static void HandleToolButtons(struct GadgetInfo *gi)
2632 request_gadget_id = gi->custom_id;
2635 int get_next_element(int element)
2639 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2640 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2641 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2642 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2643 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2644 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2645 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2647 default: return element;
2651 int el2gfx_OLD(int element)
2655 case EL_EMPTY: return -1;
2656 case EL_SAND: return GFX_ERDREICH;
2657 case EL_WALL: return GFX_MAUERWERK;
2658 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2659 case EL_ROCK: return GFX_FELSBROCKEN;
2660 case EL_EMERALD: return GFX_EDELSTEIN;
2661 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2662 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2663 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2664 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2665 case EL_PLAYER1: return GFX_SPIELER1;
2666 case EL_PLAYER2: return GFX_SPIELER2;
2667 case EL_PLAYER3: return GFX_SPIELER3;
2668 case EL_PLAYER4: return GFX_SPIELER4;
2669 case EL_BUG: return GFX_KAEFER;
2670 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2671 case EL_BUG_UP: return GFX_KAEFER_UP;
2672 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2673 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2674 case EL_SPACESHIP: return GFX_FLIEGER;
2675 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2676 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2677 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2678 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2679 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2680 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2681 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2682 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2683 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2684 case EL_BD_FIREFLY: return GFX_FIREFLY;
2685 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2686 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2687 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2688 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2689 case EL_YAMYAM: return GFX_MAMPFER;
2690 case EL_ROBOT: return GFX_ROBOT;
2691 case EL_STEELWALL: return GFX_BETON;
2692 case EL_DIAMOND: return GFX_DIAMANT;
2693 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2694 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2695 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2696 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2697 case EL_BOMB: return GFX_BOMBE;
2698 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2699 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2700 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2701 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2702 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2703 case EL_ACID: return GFX_SALZSAEURE;
2704 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2705 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2706 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2707 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2708 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2709 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2710 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2711 case EL_NUT: return GFX_KOKOSNUSS;
2712 case EL_GAMEOFLIFE: return GFX_LIFE;
2713 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2714 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2715 case EL_STONEBLOCK: return GFX_BADEWANNE;
2716 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2717 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2718 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2719 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2720 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2721 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2722 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2723 case EL_KEY1: return GFX_SCHLUESSEL1;
2724 case EL_KEY2: return GFX_SCHLUESSEL2;
2725 case EL_KEY3: return GFX_SCHLUESSEL3;
2726 case EL_KEY4: return GFX_SCHLUESSEL4;
2727 case EL_GATE1: return GFX_PFORTE1;
2728 case EL_GATE2: return GFX_PFORTE2;
2729 case EL_GATE3: return GFX_PFORTE3;
2730 case EL_GATE4: return GFX_PFORTE4;
2731 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2732 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2733 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2734 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2735 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2736 case EL_PACMAN: return GFX_PACMAN;
2737 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2738 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2739 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2740 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2741 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2742 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2743 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2744 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2745 case EL_LAMP: return GFX_BIRNE_AUS;
2746 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2747 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2748 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2749 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2750 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2751 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2752 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2753 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2754 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2755 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2756 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2757 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2758 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2759 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2760 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2761 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2762 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2763 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2764 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2765 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2766 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2767 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2768 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2769 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2770 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2771 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2772 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2773 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2774 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2775 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2776 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2777 case EL_MOLE: return GFX_MOLE;
2778 case EL_PENGUIN: return GFX_PINGUIN;
2779 case EL_PIG: return GFX_SCHWEIN;
2780 case EL_DRAGON: return GFX_DRACHE;
2781 case EL_SATELLITE: return GFX_SONDE;
2782 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2783 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2784 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2785 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2786 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2787 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2788 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2789 case EL_SP_ZONK: return GFX_SP_ZONK;
2790 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2791 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2792 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2793 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2794 case EL_EM_GATE1: return GFX_EM_GATE_1;
2795 case EL_EM_GATE2: return GFX_EM_GATE_2;
2796 case EL_EM_GATE3: return GFX_EM_GATE_3;
2797 case EL_EM_GATE4: return GFX_EM_GATE_4;
2798 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2799 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2800 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2801 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2802 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2803 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2804 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2805 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2806 case EL_EM_KEY1: return GFX_EM_KEY_1;
2807 case EL_EM_KEY2: return GFX_EM_KEY_2;
2808 case EL_EM_KEY3: return GFX_EM_KEY_3;
2809 case EL_EM_KEY4: return GFX_EM_KEY_4;
2810 case EL_PEARL: return GFX_PEARL;
2811 case EL_CRYSTAL: return GFX_CRYSTAL;
2812 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2813 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2814 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2815 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2816 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2817 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2818 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2819 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2820 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2821 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2822 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2823 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2824 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2825 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2826 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2827 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2828 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2829 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2830 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2831 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2832 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2833 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2834 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2835 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2836 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2837 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2838 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2839 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2840 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2841 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2842 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2843 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2844 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2845 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2846 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2847 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2848 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2849 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2850 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2851 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2852 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2853 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2854 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2855 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2856 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2857 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2858 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2859 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2860 case EL_LANDMINE: return GFX_LANDMINE;
2861 case EL_ENVELOPE: return GFX_ENVELOPE;
2862 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2863 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2864 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2865 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2866 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2867 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2868 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2869 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2870 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2871 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2872 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2873 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2874 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2875 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2876 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2877 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2878 case EL_MOLE_UP: return GFX_MOLE_UP;
2879 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2880 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2881 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2882 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2883 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2884 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2885 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2886 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2887 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2888 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2889 case EL_BALLOON: return GFX_BALLOON;
2890 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2891 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2892 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2893 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2894 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2895 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2896 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2897 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2898 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2899 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2900 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2901 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2902 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2903 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2904 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2905 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2906 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2907 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2908 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2909 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2910 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2911 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2912 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2913 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2914 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2915 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2916 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2917 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2918 case EL_SPRING: return GFX_SPRING;
2919 case EL_TRAP: return GFX_TRAP_INACTIVE;
2920 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2921 case EL_BD_WALL: return GFX_BD_WALL;
2922 case EL_BD_ROCK: return GFX_BD_ROCK;
2923 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2924 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2928 if (IS_CHAR(element))
2929 return GFX_CHAR_START + (element - EL_CHAR_START);
2930 else if (element >= EL_SP_START && element <= EL_SP_END)
2932 int nr_element = element - EL_SP_START;
2933 int gfx_per_line = 8;
2935 (nr_element / gfx_per_line) * SP_PER_LINE +
2936 (nr_element % gfx_per_line);
2938 return GFX_START_ROCKSSP + nr_graphic;
2946 int el2gfx(int element)
2949 int graphic_OLD = el2gfx_OLD(element);
2954 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2957 int graphic_OLD = el2gfx_OLD(element);
2959 if (element >= MAX_ELEMENTS)
2961 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2964 if (graphic_NEW != graphic_OLD)
2966 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2967 graphic_NEW, graphic_OLD);
2975 int el2img(int element)
2977 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2981 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2988 int el_dir2img(int element, int direction)
2990 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2993 int el_dir_act2img(int element, int direction, int action)
2998 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
3006 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
3013 action = graphics_action_mapping[action];
3014 direction = MV_DIR_BIT(direction);
3016 return element_info[element].direction_graphic[action][direction];