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 dest_x, int dest_y, int width, int height)
367 if (DrawingOnBackground(dest_x, dest_y) && game_status != PLAYING)
368 BlitBitmap(gfx.background_bitmap, backbuffer, dest_x, dest_y,
369 width, height, dest_x, dest_y);
371 ClearRectangle(backbuffer, dest_x, dest_y, width, height);
373 redraw_mask |= REDRAW_FIELD;
378 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
380 if (setup.soft_scrolling && game_status == PLAYING)
382 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
383 SetDrawtoField(DRAW_BUFFERED);
386 SetDrawtoField(DRAW_BACKBUFFER);
388 if (setup.direct_draw && game_status == PLAYING)
390 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
391 SetDrawtoField(DRAW_DIRECT);
395 static int getGraphicAnimationPhase(int frames, int delay, int mode)
399 if (mode & ANIM_PINGPONG)
401 int max_anim_frames = 2 * frames - 2;
403 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
404 phase = (phase < frames ? phase : max_anim_frames - phase);
407 phase = (FrameCounter % (delay * frames)) / delay;
409 if (mode & ANIM_REVERSE)
415 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
417 /* animation synchronized with global frame counter, not move position */
418 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
419 sync_frame = FrameCounter;
421 return getAnimationFrame(new_graphic_info[graphic].anim_frames,
422 new_graphic_info[graphic].anim_delay,
423 new_graphic_info[graphic].anim_mode,
424 new_graphic_info[graphic].anim_start_frame,
428 void MarkTileDirty(int x, int y)
430 int xx = redraw_x1 + x;
431 int yy = redraw_y1 + y;
436 redraw[xx][yy] = TRUE;
437 redraw_mask |= REDRAW_TILES;
440 void SetBorderElement()
444 BorderElement = EL_EMPTY;
446 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
448 for(x=0; x<lev_fieldx; x++)
450 if (!IS_MASSIVE(Feld[x][y]))
451 BorderElement = EL_STEELWALL;
453 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
459 void DrawAllPlayers()
463 for(i=0; i<MAX_PLAYERS; i++)
464 if (stored_player[i].active)
465 DrawPlayer(&stored_player[i]);
468 void DrawPlayerField(int x, int y)
470 if (!IS_PLAYER(x, y))
473 DrawPlayer(PLAYERINFO(x, y));
476 void DrawPlayer(struct PlayerInfo *player)
478 int jx = player->jx, jy = player->jy;
479 int last_jx = player->last_jx, last_jy = player->last_jy;
480 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
481 int sx = SCREENX(jx), sy = SCREENY(jy);
482 int sxx = 0, syy = 0;
483 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
486 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
488 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
492 if (!IN_LEV_FIELD(jx,jy))
494 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
495 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
496 printf("DrawPlayerField(): This should never happen!\n");
501 if (element == EL_EXPLOSION)
504 /* draw things in the field the player is leaving, if needed */
506 if (player_is_moving)
508 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
510 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
512 if (last_element == EL_DYNAMITE_ACTIVE)
513 DrawDynamite(last_jx, last_jy);
515 DrawLevelFieldThruMask(last_jx, last_jy);
517 else if (last_element == EL_DYNAMITE_ACTIVE)
518 DrawDynamite(last_jx, last_jy);
520 DrawLevelField(last_jx, last_jy);
522 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
526 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
527 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
529 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
532 DrawLevelField(next_jx, next_jy);
536 if (!IN_SCR_FIELD(sx, sy))
539 if (setup.direct_draw)
540 SetDrawtoField(DRAW_BUFFERED);
542 /* draw things behind the player, if needed */
545 DrawLevelElement(jx, jy, Store[jx][jy]);
546 else if (!IS_ACTIVE_BOMB(element))
547 DrawLevelField(jx, jy);
549 DrawLevelElement(jx, jy, EL_EMPTY);
551 /* draw player himself */
553 if (game.emulation == EMU_SUPAPLEX)
555 static int last_dir = MV_LEFT;
556 int action = (player->programmed_action ? player->programmed_action :
558 boolean action_moving =
560 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
561 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
563 graphic = IMG_SP_MURPHY;
567 if (player->MovDir == MV_LEFT)
568 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
569 else if (player->MovDir == MV_RIGHT)
570 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
571 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
572 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
573 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
574 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
576 else if (player->snapped)
578 if (player->MovDir == MV_LEFT)
579 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
580 else if (player->MovDir == MV_RIGHT)
581 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
582 else if (player->MovDir == MV_UP)
583 graphic = IMG_SP_MURPHY_UP_SNAPPING;
584 else if (player->MovDir == MV_DOWN)
585 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
587 else if (action_moving)
589 if (player->MovDir == MV_LEFT)
590 graphic = IMG_SP_MURPHY_LEFT_MOVING;
591 else if (player->MovDir == MV_RIGHT)
592 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
593 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
594 graphic = IMG_SP_MURPHY_LEFT_MOVING;
595 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
596 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
598 graphic = IMG_SP_MURPHY_LEFT_MOVING;
600 frame = getGraphicAnimationFrame(graphic, -1);
603 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
604 last_dir = player->MovDir;
608 if (player->MovDir == MV_LEFT)
609 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
610 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
612 else if (player->MovDir == MV_RIGHT)
613 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
614 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
616 else if (player->MovDir == MV_UP)
617 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
618 player->is_moving ? IMG_PLAYER1_UP_MOVING :
620 else /* MV_DOWN || MV_NO_MOVING */
621 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
622 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
625 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
628 frame = player->Frame;
630 frame = getGraphicAnimationFrame(graphic, player->Frame);
636 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
637 sxx = player->GfxPos;
639 syy = player->GfxPos;
642 if (!setup.soft_scrolling && ScreenMovPos)
647 printf("-> %d\n", player->Frame);
650 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
652 if (SHIELD_ON(player))
654 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
655 IMG_SHIELD_NORMAL_ACTIVE);
656 int frame = getGraphicAnimationFrame(graphic, -1);
658 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
662 if (player->Pushing && player->GfxPos)
664 if (player->Pushing && player_is_moving)
667 int px = SCREENX(next_jx), py = SCREENY(next_jy);
669 if (element == EL_SOKOBAN_FIELD_EMPTY ||
670 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
671 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
675 int element = Feld[next_jx][next_jy];
676 int graphic = el2img(element);
681 if (sxx && IS_PUSHABLE(element))
683 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
685 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
687 frame = getGraphicAnimationFrame(graphic, player->Frame);
691 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
696 if (player->MovDir == MV_LEFT)
701 frame = (player->GfxPos / (TILEX / 4));
703 if (player->MovDir == MV_RIGHT)
704 frame = (frame + 4) % 4;
708 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
709 NO_CUTTING, NO_MASKING);
713 /* draw things in front of player (active dynamite or dynabombs) */
715 if (IS_ACTIVE_BOMB(element))
717 graphic = el2img(element);
720 if (element == EL_DYNAMITE_ACTIVE)
722 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
727 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
731 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
734 if (game.emulation == EMU_SUPAPLEX)
735 DrawGraphic(sx, sy, GFX_SP_DISK_RED, 0);
737 DrawGraphicThruMask(sx, sy, graphic, frame);
740 if (player_is_moving && last_element == EL_EXPLOSION)
742 int stored = Store[last_jx][last_jy];
743 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
744 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
746 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
747 int phase = Frame[last_jx][last_jy] - 1;
748 int frame = getGraphicAnimationFrame(graphic, phase - delay);
751 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
754 /* draw elements that stay over the player */
755 /* handle the field the player is leaving ... */
756 if (player_is_moving && IS_OVER_PLAYER(last_element))
757 DrawLevelField(last_jx, last_jy);
759 /* ... and the field the player is entering */
760 if (IS_OVER_PLAYER(element))
761 DrawLevelField(jx, jy);
763 if (setup.direct_draw)
765 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
766 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
767 int x_size = TILEX * (1 + ABS(jx - last_jx));
768 int y_size = TILEY * (1 + ABS(jy - last_jy));
770 BlitBitmap(drawto_field, window,
771 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
772 SetDrawtoField(DRAW_DIRECT);
775 MarkTileDirty(sx,sy);
778 void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
779 int graphic, int mask_mode)
781 int frame = getGraphicAnimationFrame(graphic, -1);
783 if (mask_mode == USE_MASKING)
784 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
786 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
789 void DrawGraphicAnimation(int x, int y, int graphic)
791 if (!IN_SCR_FIELD(x, y) ||
792 (FrameCounter % new_graphic_info[graphic].anim_delay) != 0)
795 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
796 graphic, NO_MASKING);
801 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
803 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
805 *bitmap = graphic_info[graphic].bitmap;
806 *x = graphic_info[graphic].src_x;
807 *y = graphic_info[graphic].src_y;
809 else if (graphic >= GFX_START_ROCKSELEMENTS &&
810 graphic <= GFX_END_ROCKSELEMENTS)
812 graphic -= GFX_START_ROCKSELEMENTS;
813 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
814 *x = (graphic % GFX_PER_LINE) * TILEX;
815 *y = (graphic / GFX_PER_LINE) * TILEY;
817 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
819 graphic -= GFX_START_ROCKSHEROES;
820 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
821 *x = (graphic % HEROES_PER_LINE) * TILEX;
822 *y = (graphic / HEROES_PER_LINE) * TILEY;
824 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
826 graphic -= GFX_START_ROCKSSP;
827 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
828 *x = (graphic % SP_PER_LINE) * TILEX;
829 *y = (graphic / SP_PER_LINE) * TILEY;
831 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
833 graphic -= GFX_START_ROCKSDC;
834 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
835 *x = (graphic % DC_PER_LINE) * TILEX;
836 *y = (graphic / DC_PER_LINE) * TILEY;
838 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
840 graphic -= GFX_START_ROCKSMORE;
841 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
842 *x = (graphic % MORE_PER_LINE) * TILEX;
843 *y = (graphic / MORE_PER_LINE) * TILEY;
845 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
847 graphic -= GFX_START_ROCKSFONT;
848 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
849 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
850 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
854 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
861 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
863 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
864 int offset_x = new_graphic_info[graphic].offset_x;
865 int offset_y = new_graphic_info[graphic].offset_y;
866 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
867 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
869 *bitmap = src_bitmap;
874 void DrawGraphic(int x, int y, int graphic, int frame)
877 if (!IN_SCR_FIELD(x, y))
879 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
880 printf("DrawGraphic(): This should never happen!\n");
885 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
890 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
895 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
896 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
900 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
907 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
909 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
910 int src_x = new_graphic_info[graphic].src_x;
911 int src_y = new_graphic_info[graphic].src_y;
912 int offset_x = new_graphic_info[graphic].offset_x;
913 int offset_y = new_graphic_info[graphic].offset_y;
915 src_x += frame * offset_x;
916 src_y += frame * offset_y;
919 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
922 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
925 if (!IN_SCR_FIELD(x, y))
927 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
928 printf("DrawGraphicThruMask(): This should never happen!\n");
933 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
938 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
946 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
947 drawing_gc = src_bitmap->stored_clip_gc;
949 GC drawing_gc = src_bitmap->stored_clip_gc;
950 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
951 int src_x = new_graphic_info[graphic].src_x;
952 int src_y = new_graphic_info[graphic].src_y;
953 int offset_x = new_graphic_info[graphic].offset_x;
954 int offset_y = new_graphic_info[graphic].offset_y;
956 src_x += frame * offset_x;
957 src_y += frame * offset_y;
961 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
962 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
965 void DrawMiniGraphic(int x, int y, int graphic)
967 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
968 MarkTileDirty(x / 2, y / 2);
971 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
973 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
975 int mini_starty = src_bitmap->height * 2 / 3;
976 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
977 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
979 if (src_x + MINI_TILEX > src_bitmap->width ||
980 src_y + MINI_TILEY > src_bitmap->height)
982 /* graphic of desired size seems not to be contained in this image;
983 dirty workaround: get it from the middle of the normal sized image */
985 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
986 src_x += (TILEX / 2 - MINI_TILEX / 2);
987 src_y += (TILEY / 2 - MINI_TILEY / 2);
990 *bitmap = src_bitmap;
995 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1000 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1001 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1004 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1005 int cut_mode, int mask_mode)
1014 int width = TILEX, height = TILEY;
1020 DrawGraphic(x, y, graphic, frame);
1024 if (dx || dy) /* shifted graphic */
1026 if (x < BX1) /* object enters playfield from the left */
1033 else if (x > BX2) /* object enters playfield from the right */
1039 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1045 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1047 else if (dx) /* general horizontal movement */
1048 MarkTileDirty(x + SIGN(dx), y);
1050 if (y < BY1) /* object enters playfield from the top */
1052 if (cut_mode==CUT_BELOW) /* object completely above top border */
1060 else if (y > BY2) /* object enters playfield from the bottom */
1066 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1072 else if (dy > 0 && cut_mode == CUT_ABOVE)
1074 if (y == BY2) /* object completely above bottom border */
1080 MarkTileDirty(x, y + 1);
1081 } /* object leaves playfield to the bottom */
1082 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1084 else if (dy) /* general vertical movement */
1085 MarkTileDirty(x, y + SIGN(dy));
1088 src_bitmap = new_graphic_info[graphic].bitmap;
1089 src_x = new_graphic_info[graphic].src_x;
1090 src_y = new_graphic_info[graphic].src_y;
1091 offset_x = new_graphic_info[graphic].offset_x;
1092 offset_y = new_graphic_info[graphic].offset_y;
1094 drawing_gc = src_bitmap->stored_clip_gc;
1096 src_x += frame * offset_x;
1097 src_y += frame * offset_y;
1102 dest_x = FX + x * TILEX + dx;
1103 dest_y = FY + y * TILEY + dy;
1106 if (!IN_SCR_FIELD(x,y))
1108 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1109 printf("DrawGraphicShifted(): This should never happen!\n");
1114 if (mask_mode == USE_MASKING)
1116 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1117 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1121 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1127 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1128 int frame, int cut_mode)
1130 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1134 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1135 int cut_mode, int mask_mode)
1137 int ux = LEVELX(x), uy = LEVELY(y);
1138 int graphic = el2gfx(element);
1139 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1140 int phase4 = phase8 / 2;
1141 int phase2 = phase8 / 4;
1142 int dir = MovDir[ux][uy];
1144 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1146 graphic += 1 * !phase2;
1150 else if (dir == MV_LEFT)
1152 else if (dir == MV_DOWN)
1155 else if (element == EL_SP_SNIKSNAK)
1158 graphic = GFX_SP_SNIKSNAK_LEFT;
1159 else if (dir == MV_RIGHT)
1160 graphic = GFX_SP_SNIKSNAK_RIGHT;
1161 else if (dir == MV_UP)
1162 graphic = GFX_SP_SNIKSNAK_UP;
1164 graphic = GFX_SP_SNIKSNAK_DOWN;
1166 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1168 else if (element == EL_SP_ELECTRON)
1170 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1172 else if (element == EL_MOLE || element == EL_PENGUIN ||
1173 element == EL_PIG || element == EL_DRAGON)
1176 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1177 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1178 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1179 else if (dir == MV_RIGHT)
1180 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1181 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1182 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1183 else if (dir == MV_UP)
1184 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1185 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1186 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1188 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1189 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1190 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1194 else if (element == EL_SATELLITE)
1196 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1198 else if (element == EL_ACID)
1200 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1202 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1206 else if (element == EL_BALLOON)
1210 else if ((element == EL_ROCK ||
1211 element == EL_SP_ZONK ||
1212 element == EL_BD_ROCK ||
1213 element == EL_SP_INFOTRON ||
1217 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1219 if (element == EL_ROCK ||
1220 element == EL_SP_ZONK ||
1221 element == EL_BD_ROCK)
1224 graphic += (4 - phase4) % 4;
1225 else if (dir == MV_RIGHT)
1228 graphic += phase2 * 2;
1230 else if (element != EL_SP_INFOTRON)
1234 else if (element == EL_MAGIC_WALL_ACTIVE ||
1235 element == EL_MAGIC_WALL_EMPTYING ||
1236 element == EL_BD_MAGIC_WALL_ACTIVE ||
1237 element == EL_BD_MAGIC_WALL_EMPTYING ||
1238 element == EL_MAGIC_WALL_FULL ||
1239 element == EL_BD_MAGIC_WALL_FULL)
1241 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1243 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1245 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1246 graphic += (x + 2 * y + 4) % 4;
1248 else if (element == EL_WALL_GROWING)
1250 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1252 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1253 links_massiv = TRUE;
1254 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1255 rechts_massiv = TRUE;
1257 if (links_massiv && rechts_massiv)
1258 graphic = GFX_MAUERWERK;
1259 else if (links_massiv)
1260 graphic = GFX_MAUER_R;
1261 else if (rechts_massiv)
1262 graphic = GFX_MAUER_L;
1265 else if ((element == EL_INVISIBLE_STEELWALL ||
1266 element == EL_INVISIBLE_WALL ||
1267 element == EL_INVISIBLE_SAND) && game.light_time_left)
1269 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1270 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1271 GFX_SAND_INVISIBLE_ON);
1276 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1277 else if (mask_mode == USE_MASKING)
1278 DrawGraphicThruMask(x, y, graphic);
1280 DrawGraphic(x, y, graphic);
1284 inline static int getFramePosition(int x, int y)
1286 int frame_pos = -1; /* default: global synchronization */
1288 int element = Feld[x][y];
1290 if (element == EL_QUICKSAND_FULL ||
1291 element == EL_MAGIC_WALL_FULL ||
1292 element == EL_BD_MAGIC_WALL_FULL)
1294 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1295 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1297 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1303 inline static int getGfxAction(int x, int y)
1305 int gfx_action = GFX_ACTION_DEFAULT;
1308 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1309 gfx_action = GfxAction[x][y];
1310 else if (IS_MOVING(x, y))
1311 gfx_action = GFX_ACTION_MOVING;
1313 gfx_action = GfxAction[x][y];
1318 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1325 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1326 int cut_mode, int mask_mode)
1328 int ux = LEVELX(x), uy = LEVELY(y);
1332 if (IN_LEV_FIELD(ux, uy))
1334 int move_dir = MovDir[ux][uy];
1335 int move_pos = getFramePosition(ux, uy);
1336 int gfx_action = getGfxAction(ux, uy);
1338 graphic = el_dir_act2img(element, move_dir, gfx_action);
1339 frame = getGraphicAnimationFrame(graphic, move_pos);
1343 graphic = el2img(element);
1344 frame = getGraphicAnimationFrame(graphic, 0);
1347 if (element == EL_WALL_GROWING)
1349 boolean left_stopped = FALSE, right_stopped = FALSE;
1351 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1352 left_stopped = TRUE;
1353 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1354 right_stopped = TRUE;
1356 if (left_stopped && right_stopped)
1358 else if (left_stopped)
1360 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1361 frame = new_graphic_info[graphic].anim_frames - 1;
1363 else if (right_stopped)
1365 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1366 frame = new_graphic_info[graphic].anim_frames - 1;
1369 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1371 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1372 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1373 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1374 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1375 IMG_AMOEBA_DEAD_PART1);
1377 graphic += (x + 2 * y + 4) % 4;
1381 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1382 else if (mask_mode == USE_MASKING)
1383 DrawGraphicThruMask(x, y, graphic, frame);
1385 DrawGraphic(x, y, graphic, frame);
1388 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1389 int cut_mode, int mask_mode)
1391 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1392 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1393 cut_mode, mask_mode);
1396 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1399 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1402 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1405 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1409 void DrawOldScreenElementThruMask(int x, int y, int element)
1411 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1414 void DrawScreenElementThruMask(int x, int y, int element)
1416 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1420 void DrawLevelElementThruMask(int x, int y, int element)
1422 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1425 void DrawLevelFieldThruMask(int x, int y)
1427 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1430 void DrawCrumbledSand(int x, int y)
1434 int i, width, height, cx,cy;
1435 int ux = LEVELX(x), uy = LEVELY(y);
1436 int element, graphic;
1438 static int xy[4][2] =
1446 if (!IN_LEV_FIELD(ux, uy))
1449 element = Feld[ux][uy];
1451 if (element == EL_SAND ||
1452 element == EL_LANDMINE ||
1453 element == EL_TRAP ||
1454 element == EL_TRAP_ACTIVE)
1456 if (!IN_SCR_FIELD(x, y))
1459 graphic = IMG_SAND_CRUMBLED;
1461 src_bitmap = new_graphic_info[graphic].bitmap;
1462 src_x = new_graphic_info[graphic].src_x;
1463 src_y = new_graphic_info[graphic].src_y;
1469 uxx = ux + xy[i][0];
1470 uyy = uy + xy[i][1];
1471 if (!IN_LEV_FIELD(uxx, uyy))
1472 element = EL_STEELWALL;
1474 element = Feld[uxx][uyy];
1476 if (element == EL_SAND ||
1477 element == EL_LANDMINE ||
1478 element == EL_TRAP ||
1479 element == EL_TRAP_ACTIVE)
1482 if (i == 1 || i == 2)
1486 cx = (i == 2 ? TILEX - snip : 0);
1494 cy = (i == 3 ? TILEY - snip : 0);
1497 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1498 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1501 MarkTileDirty(x, y);
1505 graphic = IMG_SAND_CRUMBLED;
1507 src_bitmap = new_graphic_info[graphic].bitmap;
1508 src_x = new_graphic_info[graphic].src_x;
1509 src_y = new_graphic_info[graphic].src_y;
1513 int xx, yy, uxx, uyy;
1517 uxx = ux + xy[i][0];
1518 uyy = uy + xy[i][1];
1520 if (!IN_LEV_FIELD(uxx, uyy) ||
1521 (Feld[uxx][uyy] != EL_SAND &&
1522 Feld[uxx][uyy] != EL_LANDMINE &&
1523 Feld[uxx][uyy] != EL_TRAP &&
1524 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1525 !IN_SCR_FIELD(xx, yy))
1528 if (i == 1 || i == 2)
1532 cx = (i == 1 ? TILEX - snip : 0);
1540 cy = (i==0 ? TILEY-snip : 0);
1543 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1544 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1546 MarkTileDirty(xx, yy);
1551 void DrawScreenElement(int x, int y, int element)
1553 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1554 DrawCrumbledSand(x, y);
1557 void DrawLevelElement(int x, int y, int element)
1559 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1560 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1563 void DrawScreenField(int x, int y)
1565 int ux = LEVELX(x), uy = LEVELY(y);
1566 int element, content;
1568 if (!IN_LEV_FIELD(ux, uy))
1570 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1573 element = BorderElement;
1575 DrawScreenElement(x, y, element);
1579 element = Feld[ux][uy];
1580 content = Store[ux][uy];
1582 if (IS_MOVING(ux, uy))
1584 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1585 boolean cut_mode = NO_CUTTING;
1587 if (element == EL_QUICKSAND_EMPTYING ||
1588 element == EL_MAGIC_WALL_EMPTYING ||
1589 element == EL_BD_MAGIC_WALL_EMPTYING ||
1590 element == EL_AMOEBA_DRIPPING)
1591 cut_mode = CUT_ABOVE;
1592 else if (element == EL_QUICKSAND_FILLING ||
1593 element == EL_MAGIC_WALL_FILLING ||
1594 element == EL_BD_MAGIC_WALL_FILLING)
1595 cut_mode = CUT_BELOW;
1597 if (cut_mode == CUT_ABOVE)
1598 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1600 DrawScreenElement(x, y, EL_EMPTY);
1603 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1604 else if (cut_mode == NO_CUTTING)
1605 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1607 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1609 if (content == EL_ACID)
1610 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1612 else if (IS_BLOCKED(ux, uy))
1617 boolean cut_mode = NO_CUTTING;
1618 int element_old, content_old;
1620 Blocked2Moving(ux, uy, &oldx, &oldy);
1623 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1624 MovDir[oldx][oldy] == MV_RIGHT);
1626 element_old = Feld[oldx][oldy];
1627 content_old = Store[oldx][oldy];
1629 if (element_old == EL_QUICKSAND_EMPTYING ||
1630 element_old == EL_MAGIC_WALL_EMPTYING ||
1631 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1632 element_old == EL_AMOEBA_DRIPPING)
1633 cut_mode = CUT_ABOVE;
1635 DrawScreenElement(x, y, EL_EMPTY);
1638 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1640 else if (cut_mode == NO_CUTTING)
1641 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1644 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1647 else if (IS_DRAWABLE(element))
1648 DrawScreenElement(x, y, element);
1650 DrawScreenElement(x, y, EL_EMPTY);
1653 void DrawLevelField(int x, int y)
1655 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1656 DrawScreenField(SCREENX(x), SCREENY(y));
1657 else if (IS_MOVING(x, y))
1661 Moving2Blocked(x, y, &newx, &newy);
1662 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1663 DrawScreenField(SCREENX(newx), SCREENY(newy));
1665 else if (IS_BLOCKED(x, y))
1669 Blocked2Moving(x, y, &oldx, &oldy);
1670 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1671 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1675 void DrawMiniElement(int x, int y, int element)
1679 graphic = el2img(element);
1680 DrawMiniGraphic(x, y, graphic);
1683 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1685 int x = sx + scroll_x, y = sy + scroll_y;
1687 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1688 DrawMiniElement(sx, sy, EL_EMPTY);
1689 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1690 DrawMiniElement(sx, sy, Feld[x][y]);
1693 int steel_type, steel_position;
1696 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1697 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1698 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1699 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1700 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1701 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1704 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1705 steel_position = (x == -1 && y == -1 ? 0 :
1706 x == lev_fieldx && y == -1 ? 1 :
1707 x == -1 && y == lev_fieldy ? 2 :
1708 x == lev_fieldx && y == lev_fieldy ? 3 :
1709 x == -1 || x == lev_fieldx ? 4 :
1710 y == -1 || y == lev_fieldy ? 5 : -1);
1712 if (steel_position != -1)
1713 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1717 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1719 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1720 int mini_startx = src_bitmap->width * 3 / 4;
1721 int mini_starty = src_bitmap->height * 2 / 3;
1722 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1723 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1725 if (src_x + MICRO_TILEX > src_bitmap->width ||
1726 src_y + MICRO_TILEY > src_bitmap->height)
1728 /* graphic of desired size seems not to be contained in this image;
1729 dirty workaround: get it from the middle of the normal sized image */
1731 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1732 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1733 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1736 *bitmap = src_bitmap;
1741 void DrawMicroElement(int xpos, int ypos, int element)
1745 int graphic = el2img(element);
1747 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1748 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1758 for(x=BX1; x<=BX2; x++)
1759 for(y=BY1; y<=BY2; y++)
1760 DrawScreenField(x, y);
1762 redraw_mask |= REDRAW_FIELD;
1765 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1769 for(x=0; x<size_x; x++)
1770 for(y=0; y<size_y; y++)
1771 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1773 redraw_mask |= REDRAW_FIELD;
1776 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1780 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1782 if (lev_fieldx < STD_LEV_FIELDX)
1783 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1784 if (lev_fieldy < STD_LEV_FIELDY)
1785 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1787 xpos += MICRO_TILEX;
1788 ypos += MICRO_TILEY;
1790 for(x=-1; x<=STD_LEV_FIELDX; x++)
1792 for(y=-1; y<=STD_LEV_FIELDY; y++)
1794 int lx = from_x + x, ly = from_y + y;
1796 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1797 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1799 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1800 && BorderElement != EL_EMPTY)
1801 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1806 redraw_mask |= REDRAW_MICROLEVEL;
1809 #define MICROLABEL_EMPTY 0
1810 #define MICROLABEL_LEVEL_NAME 1
1811 #define MICROLABEL_CREATED_BY 2
1812 #define MICROLABEL_LEVEL_AUTHOR 3
1813 #define MICROLABEL_IMPORTED_FROM 4
1814 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1816 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1818 static void DrawMicroLevelLabelExt(int mode)
1820 char label_text[MAX_MICROLABEL_SIZE + 1];
1822 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1824 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1825 mode == MICROLABEL_CREATED_BY ? "created by" :
1826 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1827 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1828 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1829 leveldir_current->imported_from : ""),
1830 MAX_MICROLABEL_SIZE);
1831 label_text[MAX_MICROLABEL_SIZE] = '\0';
1833 if (strlen(label_text) > 0)
1835 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1836 int lypos = MICROLABEL_YPOS;
1838 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1841 redraw_mask |= REDRAW_MICROLEVEL;
1844 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1846 static unsigned long scroll_delay = 0;
1847 static unsigned long label_delay = 0;
1848 static int from_x, from_y, scroll_direction;
1849 static int label_state, label_counter;
1853 from_x = from_y = 0;
1854 scroll_direction = MV_RIGHT;
1858 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1859 DrawMicroLevelLabelExt(label_state);
1861 /* initialize delay counters */
1862 DelayReached(&scroll_delay, 0);
1863 DelayReached(&label_delay, 0);
1868 /* scroll micro level, if needed */
1869 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1870 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1872 switch (scroll_direction)
1878 scroll_direction = MV_UP;
1882 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1885 scroll_direction = MV_DOWN;
1892 scroll_direction = MV_RIGHT;
1896 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1899 scroll_direction = MV_LEFT;
1906 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1909 /* redraw micro level label, if needed */
1910 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1911 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1912 strcmp(level.author, leveldir_current->name) != 0 &&
1913 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1915 int max_label_counter = 23;
1917 if (leveldir_current->imported_from != NULL)
1918 max_label_counter += 14;
1920 label_counter = (label_counter + 1) % max_label_counter;
1921 label_state = (label_counter >= 0 && label_counter <= 7 ?
1922 MICROLABEL_LEVEL_NAME :
1923 label_counter >= 9 && label_counter <= 12 ?
1924 MICROLABEL_CREATED_BY :
1925 label_counter >= 14 && label_counter <= 21 ?
1926 MICROLABEL_LEVEL_AUTHOR :
1927 label_counter >= 23 && label_counter <= 26 ?
1928 MICROLABEL_IMPORTED_FROM :
1929 label_counter >= 28 && label_counter <= 35 ?
1930 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1931 DrawMicroLevelLabelExt(label_state);
1935 int REQ_in_range(int x, int y)
1937 if (y > DY+249 && y < DY+278)
1939 if (x > DX+1 && x < DX+48)
1941 else if (x > DX+51 && x < DX+98)
1947 #define MAX_REQUEST_LINES 13
1948 #define MAX_REQUEST_LINE_LEN 7
1950 boolean Request(char *text, unsigned int req_state)
1952 int mx, my, ty, result = -1;
1953 unsigned int old_door_state;
1955 #if defined(PLATFORM_UNIX)
1956 /* pause network game while waiting for request to answer */
1957 if (options.network &&
1958 game_status == PLAYING &&
1959 req_state & REQUEST_WAIT_FOR)
1960 SendToServer_PausePlaying();
1963 old_door_state = GetDoorState();
1967 CloseDoor(DOOR_CLOSE_1);
1969 /* save old door content */
1970 BlitBitmap(bitmap_db_door, bitmap_db_door,
1971 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1972 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1974 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1976 /* clear door drawing field */
1977 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1979 /* write text for request */
1980 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1982 char text_line[MAX_REQUEST_LINE_LEN + 1];
1988 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1991 if (!tc || tc == ' ')
2002 strncpy(text_line, text, tl);
2005 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2006 text_line, FS_SMALL, FC_YELLOW);
2008 text += tl + (tc == ' ' ? 1 : 0);
2011 if (req_state & REQ_ASK)
2013 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2014 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2016 else if (req_state & REQ_CONFIRM)
2018 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2020 else if (req_state & REQ_PLAYER)
2022 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2023 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2024 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2025 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2028 /* copy request gadgets to door backbuffer */
2029 BlitBitmap(drawto, bitmap_db_door,
2030 DX, DY, DXSIZE, DYSIZE,
2031 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2033 OpenDoor(DOOR_OPEN_1);
2039 if (!(req_state & REQUEST_WAIT_FOR))
2041 SetDrawBackgroundMask(REDRAW_FIELD);
2046 if (game_status != MAINMENU)
2049 button_status = MB_RELEASED;
2051 request_gadget_id = -1;
2053 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2065 case EVENT_BUTTONPRESS:
2066 case EVENT_BUTTONRELEASE:
2067 case EVENT_MOTIONNOTIFY:
2069 if (event.type == EVENT_MOTIONNOTIFY)
2071 if (!PointerInWindow(window))
2072 continue; /* window and pointer are on different screens */
2077 motion_status = TRUE;
2078 mx = ((MotionEvent *) &event)->x;
2079 my = ((MotionEvent *) &event)->y;
2083 motion_status = FALSE;
2084 mx = ((ButtonEvent *) &event)->x;
2085 my = ((ButtonEvent *) &event)->y;
2086 if (event.type == EVENT_BUTTONPRESS)
2087 button_status = ((ButtonEvent *) &event)->button;
2089 button_status = MB_RELEASED;
2092 /* this sets 'request_gadget_id' */
2093 HandleGadgets(mx, my, button_status);
2095 switch(request_gadget_id)
2097 case TOOL_CTRL_ID_YES:
2100 case TOOL_CTRL_ID_NO:
2103 case TOOL_CTRL_ID_CONFIRM:
2104 result = TRUE | FALSE;
2107 case TOOL_CTRL_ID_PLAYER_1:
2110 case TOOL_CTRL_ID_PLAYER_2:
2113 case TOOL_CTRL_ID_PLAYER_3:
2116 case TOOL_CTRL_ID_PLAYER_4:
2127 case EVENT_KEYPRESS:
2128 switch(GetEventKey((KeyEvent *)&event, TRUE))
2141 if (req_state & REQ_PLAYER)
2145 case EVENT_KEYRELEASE:
2146 ClearPlayerAction();
2150 HandleOtherEvents(&event);
2154 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2156 int joy = AnyJoystick();
2158 if (joy & JOY_BUTTON_1)
2160 else if (joy & JOY_BUTTON_2)
2166 /* don't eat all CPU time */
2170 if (game_status != MAINMENU)
2175 if (!(req_state & REQ_STAY_OPEN))
2177 CloseDoor(DOOR_CLOSE_1);
2179 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2181 BlitBitmap(bitmap_db_door, bitmap_db_door,
2182 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2183 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2184 OpenDoor(DOOR_OPEN_1);
2190 SetDrawBackgroundMask(REDRAW_FIELD);
2192 #if defined(PLATFORM_UNIX)
2193 /* continue network game after request */
2194 if (options.network &&
2195 game_status == PLAYING &&
2196 req_state & REQUEST_WAIT_FOR)
2197 SendToServer_ContinuePlaying();
2203 unsigned int OpenDoor(unsigned int door_state)
2205 unsigned int new_door_state;
2207 if (door_state & DOOR_COPY_BACK)
2209 BlitBitmap(bitmap_db_door, bitmap_db_door,
2210 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2211 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2212 door_state &= ~DOOR_COPY_BACK;
2215 new_door_state = MoveDoor(door_state);
2217 return(new_door_state);
2220 unsigned int CloseDoor(unsigned int door_state)
2222 unsigned int new_door_state;
2224 BlitBitmap(backbuffer, bitmap_db_door,
2225 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2226 BlitBitmap(backbuffer, bitmap_db_door,
2227 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2229 new_door_state = MoveDoor(door_state);
2231 return(new_door_state);
2234 unsigned int GetDoorState()
2236 return MoveDoor(DOOR_GET_STATE);
2239 unsigned int SetDoorState(unsigned int door_state)
2241 return MoveDoor(door_state | DOOR_SET_STATE);
2244 unsigned int MoveDoor(unsigned int door_state)
2246 static int door1 = DOOR_OPEN_1;
2247 static int door2 = DOOR_CLOSE_2;
2248 static unsigned long door_delay = 0;
2249 int x, start, stepsize = 2;
2250 unsigned long door_delay_value = stepsize * 5;
2252 if (door_state == DOOR_GET_STATE)
2253 return(door1 | door2);
2255 if (door_state & DOOR_SET_STATE)
2257 if (door_state & DOOR_ACTION_1)
2258 door1 = door_state & DOOR_ACTION_1;
2259 if (door_state & DOOR_ACTION_2)
2260 door2 = door_state & DOOR_ACTION_2;
2262 return(door1 | door2);
2265 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2266 door_state &= ~DOOR_OPEN_1;
2267 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2268 door_state &= ~DOOR_CLOSE_1;
2269 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2270 door_state &= ~DOOR_OPEN_2;
2271 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2272 door_state &= ~DOOR_CLOSE_2;
2274 if (setup.quick_doors)
2277 door_delay_value = 0;
2279 StopSound(SND_MENU_DOOR_OPENING);
2280 StopSound(SND_MENU_DOOR_CLOSING);
2283 if (global.autoplay_leveldir)
2285 door_state |= DOOR_NO_DELAY;
2286 door_state &= ~DOOR_CLOSE_ALL;
2289 if (door_state & DOOR_ACTION)
2291 if (!(door_state & DOOR_NO_DELAY))
2293 /* opening door sound has priority over simultaneously closing door */
2294 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2295 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2296 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2297 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2300 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2302 for(x=start; x<=DXSIZE; x+=stepsize)
2304 Bitmap *bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2305 GC gc = bitmap->stored_clip_gc;
2307 if (!(door_state & DOOR_NO_DELAY))
2308 WaitUntilDelayReached(&door_delay, door_delay_value);
2310 if (door_state & DOOR_ACTION_1)
2312 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2313 int j = (DXSIZE - i) / 3;
2315 BlitBitmap(bitmap_db_door, drawto,
2316 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2317 DXSIZE,DYSIZE - i/2, DX, DY);
2319 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2321 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2322 BlitBitmapMasked(bitmap, drawto,
2323 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2324 DX + DXSIZE - i, DY + j);
2325 BlitBitmapMasked(bitmap, drawto,
2326 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2327 DX + DXSIZE - i, DY + 140 + j);
2328 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2329 BlitBitmapMasked(bitmap, drawto,
2330 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2332 BlitBitmapMasked(bitmap, drawto,
2333 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2336 BlitBitmapMasked(bitmap, drawto,
2337 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2339 BlitBitmapMasked(bitmap, drawto,
2340 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2342 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2343 BlitBitmapMasked(bitmap, drawto,
2344 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2345 DX + DXSIZE - i, DY + 77 + j);
2346 BlitBitmapMasked(bitmap, drawto,
2347 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2348 DX + DXSIZE - i, DY + 203 + j);
2350 redraw_mask |= REDRAW_DOOR_1;
2353 if (door_state & DOOR_ACTION_2)
2355 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2356 int j = (VXSIZE - i) / 3;
2358 BlitBitmap(bitmap_db_door, drawto,
2359 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2360 VXSIZE, VYSIZE - i/2, VX, VY);
2362 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2364 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2365 BlitBitmapMasked(bitmap, drawto,
2366 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2367 VX + VXSIZE-i, VY+j);
2368 SetClipOrigin(bitmap, gc,
2369 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2370 BlitBitmapMasked(bitmap, drawto,
2371 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2374 BlitBitmapMasked(bitmap, drawto,
2375 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2376 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2377 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2378 BlitBitmapMasked(bitmap, drawto,
2379 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2381 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2383 redraw_mask |= REDRAW_DOOR_2;
2388 if (game_status == MAINMENU)
2393 if (setup.quick_doors)
2395 StopSound(SND_MENU_DOOR_OPENING);
2396 StopSound(SND_MENU_DOOR_CLOSING);
2399 if (door_state & DOOR_ACTION_1)
2400 door1 = door_state & DOOR_ACTION_1;
2401 if (door_state & DOOR_ACTION_2)
2402 door2 = door_state & DOOR_ACTION_2;
2404 return (door1 | door2);
2407 void DrawSpecialEditorDoor()
2409 /* draw bigger toolbox window */
2410 BlitBitmap(new_graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2411 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2413 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2414 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2417 redraw_mask |= REDRAW_ALL;
2420 void UndrawSpecialEditorDoor()
2422 /* draw normal tape recorder window */
2423 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2424 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2427 redraw_mask |= REDRAW_ALL;
2431 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2433 XImage *pixel_image;
2434 unsigned long pixel_value;
2436 pixel_image = XGetImage(display, bitmap->drawable,
2437 x, y, 1, 1, AllPlanes, ZPixmap);
2438 pixel_value = XGetPixel(pixel_image, 0, 0);
2440 XDestroyImage(pixel_image);
2446 /* ---------- new tool button stuff ---------------------------------------- */
2448 /* graphic position values for tool buttons */
2449 #define TOOL_BUTTON_YES_XPOS 2
2450 #define TOOL_BUTTON_YES_YPOS 250
2451 #define TOOL_BUTTON_YES_GFX_YPOS 0
2452 #define TOOL_BUTTON_YES_XSIZE 46
2453 #define TOOL_BUTTON_YES_YSIZE 28
2454 #define TOOL_BUTTON_NO_XPOS 52
2455 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2456 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2457 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2458 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2459 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2460 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2461 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2462 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2463 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2464 #define TOOL_BUTTON_PLAYER_XSIZE 30
2465 #define TOOL_BUTTON_PLAYER_YSIZE 30
2466 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2467 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2468 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2469 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2470 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2471 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2472 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2473 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2474 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2475 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2476 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2477 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2478 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2479 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2480 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2481 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2482 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2483 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2484 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2485 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2494 } toolbutton_info[NUM_TOOL_BUTTONS] =
2497 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2498 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2499 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2504 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2505 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2506 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2511 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2512 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2513 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2514 TOOL_CTRL_ID_CONFIRM,
2518 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2519 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2520 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2521 TOOL_CTRL_ID_PLAYER_1,
2525 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2526 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2527 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2528 TOOL_CTRL_ID_PLAYER_2,
2532 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2533 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2534 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2535 TOOL_CTRL_ID_PLAYER_3,
2539 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2540 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2541 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2542 TOOL_CTRL_ID_PLAYER_4,
2547 void CreateToolButtons()
2551 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2553 Bitmap *gd_bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2554 Bitmap *deco_bitmap = None;
2555 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2556 struct GadgetInfo *gi;
2557 unsigned long event_mask;
2558 int gd_xoffset, gd_yoffset;
2559 int gd_x1, gd_x2, gd_y;
2562 event_mask = GD_EVENT_RELEASED;
2564 gd_xoffset = toolbutton_info[i].xpos;
2565 gd_yoffset = toolbutton_info[i].ypos;
2566 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2567 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2568 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2570 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2572 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2574 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2575 &deco_bitmap, &deco_x, &deco_y);
2576 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2577 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2580 gi = CreateGadget(GDI_CUSTOM_ID, id,
2581 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2582 GDI_X, DX + toolbutton_info[i].x,
2583 GDI_Y, DY + toolbutton_info[i].y,
2584 GDI_WIDTH, toolbutton_info[i].width,
2585 GDI_HEIGHT, toolbutton_info[i].height,
2586 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2587 GDI_STATE, GD_BUTTON_UNPRESSED,
2588 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2589 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2590 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2591 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2592 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2593 GDI_DECORATION_SHIFTING, 1, 1,
2594 GDI_EVENT_MASK, event_mask,
2595 GDI_CALLBACK_ACTION, HandleToolButtons,
2599 Error(ERR_EXIT, "cannot create gadget");
2601 tool_gadget[id] = gi;
2605 void FreeToolButtons()
2609 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2610 FreeGadget(tool_gadget[i]);
2613 static void UnmapToolButtons()
2617 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2618 UnmapGadget(tool_gadget[i]);
2621 static void HandleToolButtons(struct GadgetInfo *gi)
2623 request_gadget_id = gi->custom_id;
2626 int get_next_element(int element)
2630 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2631 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2632 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2633 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2634 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2635 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2636 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2638 default: return element;
2642 int el2gfx_OLD(int element)
2646 case EL_EMPTY: return -1;
2647 case EL_SAND: return GFX_ERDREICH;
2648 case EL_WALL: return GFX_MAUERWERK;
2649 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2650 case EL_ROCK: return GFX_FELSBROCKEN;
2651 case EL_EMERALD: return GFX_EDELSTEIN;
2652 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2653 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2654 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2655 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2656 case EL_PLAYER1: return GFX_SPIELER1;
2657 case EL_PLAYER2: return GFX_SPIELER2;
2658 case EL_PLAYER3: return GFX_SPIELER3;
2659 case EL_PLAYER4: return GFX_SPIELER4;
2660 case EL_BUG: return GFX_KAEFER;
2661 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2662 case EL_BUG_UP: return GFX_KAEFER_UP;
2663 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2664 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2665 case EL_SPACESHIP: return GFX_FLIEGER;
2666 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2667 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2668 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2669 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2670 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2671 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2672 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2673 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2674 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2675 case EL_BD_FIREFLY: return GFX_FIREFLY;
2676 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2677 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2678 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2679 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2680 case EL_YAMYAM: return GFX_MAMPFER;
2681 case EL_ROBOT: return GFX_ROBOT;
2682 case EL_STEELWALL: return GFX_BETON;
2683 case EL_DIAMOND: return GFX_DIAMANT;
2684 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2685 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2686 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2687 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2688 case EL_BOMB: return GFX_BOMBE;
2689 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2690 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2691 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2692 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2693 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2694 case EL_ACID: return GFX_SALZSAEURE;
2695 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2696 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2697 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2698 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2699 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2700 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2701 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2702 case EL_NUT: return GFX_KOKOSNUSS;
2703 case EL_GAMEOFLIFE: return GFX_LIFE;
2704 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2705 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2706 case EL_STONEBLOCK: return GFX_BADEWANNE;
2707 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2708 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2709 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2710 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2711 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2712 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2713 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2714 case EL_KEY1: return GFX_SCHLUESSEL1;
2715 case EL_KEY2: return GFX_SCHLUESSEL2;
2716 case EL_KEY3: return GFX_SCHLUESSEL3;
2717 case EL_KEY4: return GFX_SCHLUESSEL4;
2718 case EL_GATE1: return GFX_PFORTE1;
2719 case EL_GATE2: return GFX_PFORTE2;
2720 case EL_GATE3: return GFX_PFORTE3;
2721 case EL_GATE4: return GFX_PFORTE4;
2722 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2723 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2724 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2725 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2726 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2727 case EL_PACMAN: return GFX_PACMAN;
2728 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2729 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2730 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2731 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2732 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2733 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2734 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2735 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2736 case EL_LAMP: return GFX_BIRNE_AUS;
2737 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2738 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2739 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2740 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2741 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2742 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2743 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2744 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2745 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2746 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2747 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2748 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2749 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2750 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2751 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2752 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2753 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2754 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2755 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2756 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2757 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2758 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2759 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2760 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2761 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2762 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2763 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2764 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2765 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2766 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2767 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2768 case EL_MOLE: return GFX_MOLE;
2769 case EL_PENGUIN: return GFX_PINGUIN;
2770 case EL_PIG: return GFX_SCHWEIN;
2771 case EL_DRAGON: return GFX_DRACHE;
2772 case EL_SATELLITE: return GFX_SONDE;
2773 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2774 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2775 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2776 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2777 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2778 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2779 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2780 case EL_SP_ZONK: return GFX_SP_ZONK;
2781 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2782 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2783 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2784 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2785 case EL_EM_GATE1: return GFX_EM_GATE_1;
2786 case EL_EM_GATE2: return GFX_EM_GATE_2;
2787 case EL_EM_GATE3: return GFX_EM_GATE_3;
2788 case EL_EM_GATE4: return GFX_EM_GATE_4;
2789 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2790 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2791 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2792 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2793 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2794 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2795 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2796 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2797 case EL_EM_KEY1: return GFX_EM_KEY_1;
2798 case EL_EM_KEY2: return GFX_EM_KEY_2;
2799 case EL_EM_KEY3: return GFX_EM_KEY_3;
2800 case EL_EM_KEY4: return GFX_EM_KEY_4;
2801 case EL_PEARL: return GFX_PEARL;
2802 case EL_CRYSTAL: return GFX_CRYSTAL;
2803 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2804 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2805 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2806 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2807 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2808 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2809 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2810 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2811 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2812 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2813 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2814 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2815 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2816 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2817 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2818 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2819 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2820 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2821 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2822 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2823 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2824 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2825 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2826 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2827 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2828 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2829 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2830 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2831 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2832 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2833 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2834 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2835 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2836 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2837 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2838 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2839 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2840 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2841 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2842 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2843 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2844 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2845 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2846 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2847 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2848 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2849 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2850 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2851 case EL_LANDMINE: return GFX_LANDMINE;
2852 case EL_ENVELOPE: return GFX_ENVELOPE;
2853 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2854 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2855 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2856 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2857 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2858 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2859 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2860 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2861 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2862 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2863 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2864 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2865 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2866 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2867 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2868 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2869 case EL_MOLE_UP: return GFX_MOLE_UP;
2870 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2871 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2872 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2873 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2874 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2875 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2876 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2877 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2878 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2879 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2880 case EL_BALLOON: return GFX_BALLOON;
2881 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2882 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2883 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2884 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2885 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2886 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2887 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2888 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2889 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2890 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2891 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2892 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2893 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2894 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2895 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2896 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2897 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2898 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2899 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2900 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2901 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2902 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2903 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2904 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2905 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2906 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2907 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2908 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2909 case EL_SPRING: return GFX_SPRING;
2910 case EL_TRAP: return GFX_TRAP_INACTIVE;
2911 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2912 case EL_BD_WALL: return GFX_BD_WALL;
2913 case EL_BD_ROCK: return GFX_BD_ROCK;
2914 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2915 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2919 if (IS_CHAR(element))
2920 return GFX_CHAR_START + (element - EL_CHAR_START);
2921 else if (element >= EL_SP_START && element <= EL_SP_END)
2923 int nr_element = element - EL_SP_START;
2924 int gfx_per_line = 8;
2926 (nr_element / gfx_per_line) * SP_PER_LINE +
2927 (nr_element % gfx_per_line);
2929 return GFX_START_ROCKSSP + nr_graphic;
2937 int el2gfx(int element)
2940 int graphic_OLD = el2gfx_OLD(element);
2945 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2948 int graphic_OLD = el2gfx_OLD(element);
2950 if (element >= MAX_ELEMENTS)
2952 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2955 if (graphic_NEW != graphic_OLD)
2957 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2958 graphic_NEW, graphic_OLD);
2966 int el2img(int element)
2968 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2972 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2979 int el_dir2img(int element, int direction)
2981 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2984 int el_dir_act2img(int element, int direction, int action)
2989 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
2997 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
3004 action = graphics_action_mapping[action];
3005 direction = MV_DIR_BIT(direction);
3007 return element_info[element].direction_graphic[action][direction];