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);
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;
367 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
369 if (setup.soft_scrolling && game_status == PLAYING)
371 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
372 SetDrawtoField(DRAW_BUFFERED);
375 SetDrawtoField(DRAW_BACKBUFFER);
377 if (setup.direct_draw && game_status == PLAYING)
379 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
380 SetDrawtoField(DRAW_DIRECT);
384 if (game_status != PLAYING &&
385 new_graphic_info[IMG_MENU_BACK].bitmap != NULL)
386 BlitBitmap(new_graphic_info[IMG_MENU_BACK].bitmap, backbuffer,
387 0, 0, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
390 redraw_mask |= REDRAW_FIELD;
393 static int getGraphicAnimationPhase(int frames, int delay, int mode)
397 if (mode & ANIM_PINGPONG)
399 int max_anim_frames = 2 * frames - 2;
401 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
402 phase = (phase < frames ? phase : max_anim_frames - phase);
405 phase = (FrameCounter % (delay * frames)) / delay;
407 if (mode & ANIM_REVERSE)
413 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
415 /* animation synchronized with global frame counter, not move position */
416 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
417 sync_frame = FrameCounter;
419 return getAnimationFrame(new_graphic_info[graphic].anim_frames,
420 new_graphic_info[graphic].anim_delay,
421 new_graphic_info[graphic].anim_mode,
422 new_graphic_info[graphic].anim_start_frame,
426 void MarkTileDirty(int x, int y)
428 int xx = redraw_x1 + x;
429 int yy = redraw_y1 + y;
434 redraw[xx][yy] = TRUE;
435 redraw_mask |= REDRAW_TILES;
438 void SetBorderElement()
442 BorderElement = EL_EMPTY;
444 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
446 for(x=0; x<lev_fieldx; x++)
448 if (!IS_MASSIVE(Feld[x][y]))
449 BorderElement = EL_STEELWALL;
451 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
457 void DrawAllPlayers()
461 for(i=0; i<MAX_PLAYERS; i++)
462 if (stored_player[i].active)
463 DrawPlayer(&stored_player[i]);
466 void DrawPlayerField(int x, int y)
468 if (!IS_PLAYER(x, y))
471 DrawPlayer(PLAYERINFO(x, y));
474 void DrawPlayer(struct PlayerInfo *player)
476 int jx = player->jx, jy = player->jy;
477 int last_jx = player->last_jx, last_jy = player->last_jy;
478 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
479 int sx = SCREENX(jx), sy = SCREENY(jy);
480 int sxx = 0, syy = 0;
481 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
484 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
486 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
490 if (!IN_LEV_FIELD(jx,jy))
492 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
493 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
494 printf("DrawPlayerField(): This should never happen!\n");
499 if (element == EL_EXPLOSION)
502 /* draw things in the field the player is leaving, if needed */
504 if (player_is_moving)
506 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
508 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
510 if (last_element == EL_DYNAMITE_ACTIVE)
511 DrawDynamite(last_jx, last_jy);
513 DrawLevelFieldThruMask(last_jx, last_jy);
515 else if (last_element == EL_DYNAMITE_ACTIVE)
516 DrawDynamite(last_jx, last_jy);
518 DrawLevelField(last_jx, last_jy);
520 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
524 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
525 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
527 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
530 DrawLevelField(next_jx, next_jy);
534 if (!IN_SCR_FIELD(sx, sy))
537 if (setup.direct_draw)
538 SetDrawtoField(DRAW_BUFFERED);
540 /* draw things behind the player, if needed */
543 DrawLevelElement(jx, jy, Store[jx][jy]);
544 else if (!IS_ACTIVE_BOMB(element))
545 DrawLevelField(jx, jy);
547 DrawLevelElement(jx, jy, EL_EMPTY);
549 /* draw player himself */
551 if (game.emulation == EMU_SUPAPLEX)
553 static int last_dir = MV_LEFT;
554 int action = (player->programmed_action ? player->programmed_action :
556 boolean action_moving =
558 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
559 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
561 graphic = IMG_SP_MURPHY;
565 if (player->MovDir == MV_LEFT)
566 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
567 else if (player->MovDir == MV_RIGHT)
568 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
569 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
570 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
571 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
572 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
574 else if (player->snapped)
576 if (player->MovDir == MV_LEFT)
577 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
578 else if (player->MovDir == MV_RIGHT)
579 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
580 else if (player->MovDir == MV_UP)
581 graphic = IMG_SP_MURPHY_UP_SNAPPING;
582 else if (player->MovDir == MV_DOWN)
583 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
585 else if (action_moving)
587 if (player->MovDir == MV_LEFT)
588 graphic = IMG_SP_MURPHY_LEFT_MOVING;
589 else if (player->MovDir == MV_RIGHT)
590 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
591 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
592 graphic = IMG_SP_MURPHY_LEFT_MOVING;
593 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
594 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
596 graphic = IMG_SP_MURPHY_LEFT_MOVING;
598 frame = getGraphicAnimationFrame(graphic, -1);
601 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
602 last_dir = player->MovDir;
606 if (player->MovDir == MV_LEFT)
607 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
608 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
610 else if (player->MovDir == MV_RIGHT)
611 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
612 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
614 else if (player->MovDir == MV_UP)
615 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
616 player->is_moving ? IMG_PLAYER1_UP_MOVING :
618 else /* MV_DOWN || MV_NO_MOVING */
619 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
620 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
623 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
626 frame = player->Frame;
628 frame = getGraphicAnimationFrame(graphic, player->Frame);
634 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
635 sxx = player->GfxPos;
637 syy = player->GfxPos;
640 if (!setup.soft_scrolling && ScreenMovPos)
645 printf("-> %d\n", player->Frame);
648 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
650 if (SHIELD_ON(player))
652 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
653 IMG_SHIELD_NORMAL_ACTIVE);
654 int frame = getGraphicAnimationFrame(graphic, -1);
656 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
660 if (player->Pushing && player->GfxPos)
662 if (player->Pushing && player_is_moving)
665 int px = SCREENX(next_jx), py = SCREENY(next_jy);
667 if (element == EL_SOKOBAN_FIELD_EMPTY ||
668 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
669 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
673 int element = Feld[next_jx][next_jy];
674 int graphic = el2img(element);
679 if (sxx && IS_PUSHABLE(element))
681 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
683 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
685 frame = getGraphicAnimationFrame(graphic, player->Frame);
689 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
694 if (player->MovDir == MV_LEFT)
699 frame = (player->GfxPos / (TILEX / 4));
701 if (player->MovDir == MV_RIGHT)
702 frame = (frame + 4) % 4;
706 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
707 NO_CUTTING, NO_MASKING);
711 /* draw things in front of player (active dynamite or dynabombs) */
713 if (IS_ACTIVE_BOMB(element))
715 graphic = el2img(element);
718 if (element == EL_DYNAMITE_ACTIVE)
720 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
725 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
729 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
732 if (game.emulation == EMU_SUPAPLEX)
733 DrawGraphic(sx, sy, GFX_SP_DISK_RED, 0);
735 DrawGraphicThruMask(sx, sy, graphic, frame);
738 if (player_is_moving && last_element == EL_EXPLOSION)
740 int stored = Store[last_jx][last_jy];
741 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
742 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
744 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
745 int phase = Frame[last_jx][last_jy] - 1;
746 int frame = getGraphicAnimationFrame(graphic, phase - delay);
749 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
752 /* draw elements that stay over the player */
753 /* handle the field the player is leaving ... */
754 if (player_is_moving && IS_OVER_PLAYER(last_element))
755 DrawLevelField(last_jx, last_jy);
757 /* ... and the field the player is entering */
758 if (IS_OVER_PLAYER(element))
759 DrawLevelField(jx, jy);
761 if (setup.direct_draw)
763 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
764 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
765 int x_size = TILEX * (1 + ABS(jx - last_jx));
766 int y_size = TILEY * (1 + ABS(jy - last_jy));
768 BlitBitmap(drawto_field, window,
769 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
770 SetDrawtoField(DRAW_DIRECT);
773 MarkTileDirty(sx,sy);
776 void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
777 int graphic, int mask_mode)
779 int frame = getGraphicAnimationFrame(graphic, -1);
781 if (mask_mode == USE_MASKING)
782 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
784 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
787 void DrawGraphicAnimation(int x, int y, int graphic)
789 if (!IN_SCR_FIELD(x, y) ||
790 (FrameCounter % new_graphic_info[graphic].anim_delay) != 0)
793 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
794 graphic, NO_MASKING);
799 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
801 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
803 *bitmap = graphic_info[graphic].bitmap;
804 *x = graphic_info[graphic].src_x;
805 *y = graphic_info[graphic].src_y;
807 else if (graphic >= GFX_START_ROCKSELEMENTS &&
808 graphic <= GFX_END_ROCKSELEMENTS)
810 graphic -= GFX_START_ROCKSELEMENTS;
811 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
812 *x = (graphic % GFX_PER_LINE) * TILEX;
813 *y = (graphic / GFX_PER_LINE) * TILEY;
815 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
817 graphic -= GFX_START_ROCKSHEROES;
818 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
819 *x = (graphic % HEROES_PER_LINE) * TILEX;
820 *y = (graphic / HEROES_PER_LINE) * TILEY;
822 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
824 graphic -= GFX_START_ROCKSSP;
825 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
826 *x = (graphic % SP_PER_LINE) * TILEX;
827 *y = (graphic / SP_PER_LINE) * TILEY;
829 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
831 graphic -= GFX_START_ROCKSDC;
832 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
833 *x = (graphic % DC_PER_LINE) * TILEX;
834 *y = (graphic / DC_PER_LINE) * TILEY;
836 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
838 graphic -= GFX_START_ROCKSMORE;
839 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
840 *x = (graphic % MORE_PER_LINE) * TILEX;
841 *y = (graphic / MORE_PER_LINE) * TILEY;
843 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
845 graphic -= GFX_START_ROCKSFONT;
846 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
847 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
848 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
852 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
859 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
861 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
862 int offset_x = new_graphic_info[graphic].offset_x;
863 int offset_y = new_graphic_info[graphic].offset_y;
864 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
865 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
867 *bitmap = src_bitmap;
872 void DrawGraphic(int x, int y, int graphic, int frame)
875 if (!IN_SCR_FIELD(x, y))
877 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
878 printf("DrawGraphic(): This should never happen!\n");
883 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
888 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
893 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
894 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
898 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
905 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
907 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
908 int src_x = new_graphic_info[graphic].src_x;
909 int src_y = new_graphic_info[graphic].src_y;
910 int offset_x = new_graphic_info[graphic].offset_x;
911 int offset_y = new_graphic_info[graphic].offset_y;
913 src_x += frame * offset_x;
914 src_y += frame * offset_y;
917 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
920 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
923 if (!IN_SCR_FIELD(x, y))
925 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
926 printf("DrawGraphicThruMask(): This should never happen!\n");
931 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
936 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
944 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
945 drawing_gc = src_bitmap->stored_clip_gc;
947 GC drawing_gc = src_bitmap->stored_clip_gc;
948 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
949 int src_x = new_graphic_info[graphic].src_x;
950 int src_y = new_graphic_info[graphic].src_y;
951 int offset_x = new_graphic_info[graphic].offset_x;
952 int offset_y = new_graphic_info[graphic].offset_y;
954 src_x += frame * offset_x;
955 src_y += frame * offset_y;
959 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
960 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
963 void DrawMiniGraphic(int x, int y, int graphic)
965 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
966 MarkTileDirty(x / 2, y / 2);
969 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
971 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
973 int mini_starty = src_bitmap->height * 2 / 3;
974 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
975 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
977 if (src_x + MINI_TILEX > src_bitmap->width ||
978 src_y + MINI_TILEY > src_bitmap->height)
980 /* graphic of desired size seems not to be contained in this image;
981 dirty workaround: get it from the middle of the normal sized image */
983 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
984 src_x += (TILEX / 2 - MINI_TILEX / 2);
985 src_y += (TILEY / 2 - MINI_TILEY / 2);
988 *bitmap = src_bitmap;
993 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
998 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
999 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1002 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1003 int cut_mode, int mask_mode)
1012 int width = TILEX, height = TILEY;
1018 DrawGraphic(x, y, graphic, frame);
1022 if (dx || dy) /* shifted graphic */
1024 if (x < BX1) /* object enters playfield from the left */
1031 else if (x > BX2) /* object enters playfield from the right */
1037 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1043 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1045 else if (dx) /* general horizontal movement */
1046 MarkTileDirty(x + SIGN(dx), y);
1048 if (y < BY1) /* object enters playfield from the top */
1050 if (cut_mode==CUT_BELOW) /* object completely above top border */
1058 else if (y > BY2) /* object enters playfield from the bottom */
1064 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1070 else if (dy > 0 && cut_mode == CUT_ABOVE)
1072 if (y == BY2) /* object completely above bottom border */
1078 MarkTileDirty(x, y + 1);
1079 } /* object leaves playfield to the bottom */
1080 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1082 else if (dy) /* general vertical movement */
1083 MarkTileDirty(x, y + SIGN(dy));
1086 src_bitmap = new_graphic_info[graphic].bitmap;
1087 src_x = new_graphic_info[graphic].src_x;
1088 src_y = new_graphic_info[graphic].src_y;
1089 offset_x = new_graphic_info[graphic].offset_x;
1090 offset_y = new_graphic_info[graphic].offset_y;
1092 drawing_gc = src_bitmap->stored_clip_gc;
1094 src_x += frame * offset_x;
1095 src_y += frame * offset_y;
1100 dest_x = FX + x * TILEX + dx;
1101 dest_y = FY + y * TILEY + dy;
1104 if (!IN_SCR_FIELD(x,y))
1106 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1107 printf("DrawGraphicShifted(): This should never happen!\n");
1112 if (mask_mode == USE_MASKING)
1114 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1115 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1119 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1125 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1126 int frame, int cut_mode)
1128 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1132 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1133 int cut_mode, int mask_mode)
1135 int ux = LEVELX(x), uy = LEVELY(y);
1136 int graphic = el2gfx(element);
1137 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1138 int phase4 = phase8 / 2;
1139 int phase2 = phase8 / 4;
1140 int dir = MovDir[ux][uy];
1142 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1144 graphic += 1 * !phase2;
1148 else if (dir == MV_LEFT)
1150 else if (dir == MV_DOWN)
1153 else if (element == EL_SP_SNIKSNAK)
1156 graphic = GFX_SP_SNIKSNAK_LEFT;
1157 else if (dir == MV_RIGHT)
1158 graphic = GFX_SP_SNIKSNAK_RIGHT;
1159 else if (dir == MV_UP)
1160 graphic = GFX_SP_SNIKSNAK_UP;
1162 graphic = GFX_SP_SNIKSNAK_DOWN;
1164 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1166 else if (element == EL_SP_ELECTRON)
1168 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1170 else if (element == EL_MOLE || element == EL_PENGUIN ||
1171 element == EL_PIG || element == EL_DRAGON)
1174 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1175 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1176 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1177 else if (dir == MV_RIGHT)
1178 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1179 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1180 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1181 else if (dir == MV_UP)
1182 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1183 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1184 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1186 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1187 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1188 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1192 else if (element == EL_SATELLITE)
1194 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1196 else if (element == EL_ACID)
1198 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1200 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1204 else if (element == EL_BALLOON)
1208 else if ((element == EL_ROCK ||
1209 element == EL_SP_ZONK ||
1210 element == EL_BD_ROCK ||
1211 element == EL_SP_INFOTRON ||
1215 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1217 if (element == EL_ROCK ||
1218 element == EL_SP_ZONK ||
1219 element == EL_BD_ROCK)
1222 graphic += (4 - phase4) % 4;
1223 else if (dir == MV_RIGHT)
1226 graphic += phase2 * 2;
1228 else if (element != EL_SP_INFOTRON)
1232 else if (element == EL_MAGIC_WALL_ACTIVE ||
1233 element == EL_MAGIC_WALL_EMPTYING ||
1234 element == EL_BD_MAGIC_WALL_ACTIVE ||
1235 element == EL_BD_MAGIC_WALL_EMPTYING ||
1236 element == EL_MAGIC_WALL_FULL ||
1237 element == EL_BD_MAGIC_WALL_FULL)
1239 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1241 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1243 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1244 graphic += (x + 2 * y + 4) % 4;
1246 else if (element == EL_WALL_GROWING)
1248 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1250 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1251 links_massiv = TRUE;
1252 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1253 rechts_massiv = TRUE;
1255 if (links_massiv && rechts_massiv)
1256 graphic = GFX_MAUERWERK;
1257 else if (links_massiv)
1258 graphic = GFX_MAUER_R;
1259 else if (rechts_massiv)
1260 graphic = GFX_MAUER_L;
1263 else if ((element == EL_INVISIBLE_STEELWALL ||
1264 element == EL_INVISIBLE_WALL ||
1265 element == EL_INVISIBLE_SAND) && game.light_time_left)
1267 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1268 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1269 GFX_SAND_INVISIBLE_ON);
1274 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1275 else if (mask_mode == USE_MASKING)
1276 DrawGraphicThruMask(x, y, graphic);
1278 DrawGraphic(x, y, graphic);
1282 inline static int getFramePosition(int x, int y)
1284 int frame_pos = -1; /* default: global synchronization */
1286 int element = Feld[x][y];
1288 if (element == EL_QUICKSAND_FULL ||
1289 element == EL_MAGIC_WALL_FULL ||
1290 element == EL_BD_MAGIC_WALL_FULL)
1292 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1293 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1295 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1301 inline static int getGfxAction(int x, int y)
1303 int gfx_action = GFX_ACTION_DEFAULT;
1306 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1307 gfx_action = GfxAction[x][y];
1308 else if (IS_MOVING(x, y))
1309 gfx_action = GFX_ACTION_MOVING;
1311 gfx_action = GfxAction[x][y];
1316 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1323 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1324 int cut_mode, int mask_mode)
1326 int ux = LEVELX(x), uy = LEVELY(y);
1330 if (IN_LEV_FIELD(ux, uy))
1332 int move_dir = MovDir[ux][uy];
1333 int move_pos = getFramePosition(ux, uy);
1334 int gfx_action = getGfxAction(ux, uy);
1336 graphic = el_dir_act2img(element, move_dir, gfx_action);
1337 frame = getGraphicAnimationFrame(graphic, move_pos);
1341 graphic = el2img(element);
1342 frame = getGraphicAnimationFrame(graphic, 0);
1345 if (element == EL_WALL_GROWING)
1347 boolean left_stopped = FALSE, right_stopped = FALSE;
1349 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1350 left_stopped = TRUE;
1351 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1352 right_stopped = TRUE;
1354 if (left_stopped && right_stopped)
1356 else if (left_stopped)
1358 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1359 frame = new_graphic_info[graphic].anim_frames - 1;
1361 else if (right_stopped)
1363 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1364 frame = new_graphic_info[graphic].anim_frames - 1;
1367 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1369 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1370 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1371 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1372 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1373 IMG_AMOEBA_DEAD_PART1);
1375 graphic += (x + 2 * y + 4) % 4;
1379 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1380 else if (mask_mode == USE_MASKING)
1381 DrawGraphicThruMask(x, y, graphic, frame);
1383 DrawGraphic(x, y, graphic, frame);
1386 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1387 int cut_mode, int mask_mode)
1389 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1390 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1391 cut_mode, mask_mode);
1394 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1397 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1400 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1403 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1407 void DrawOldScreenElementThruMask(int x, int y, int element)
1409 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1412 void DrawScreenElementThruMask(int x, int y, int element)
1414 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1418 void DrawLevelElementThruMask(int x, int y, int element)
1420 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1423 void DrawLevelFieldThruMask(int x, int y)
1425 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1428 void DrawCrumbledSand(int x, int y)
1432 int i, width, height, cx,cy;
1433 int ux = LEVELX(x), uy = LEVELY(y);
1434 int element, graphic;
1436 static int xy[4][2] =
1444 if (!IN_LEV_FIELD(ux, uy))
1447 element = Feld[ux][uy];
1449 if (element == EL_SAND ||
1450 element == EL_LANDMINE ||
1451 element == EL_TRAP ||
1452 element == EL_TRAP_ACTIVE)
1454 if (!IN_SCR_FIELD(x, y))
1457 graphic = IMG_SAND_CRUMBLED;
1459 src_bitmap = new_graphic_info[graphic].bitmap;
1460 src_x = new_graphic_info[graphic].src_x;
1461 src_y = new_graphic_info[graphic].src_y;
1467 uxx = ux + xy[i][0];
1468 uyy = uy + xy[i][1];
1469 if (!IN_LEV_FIELD(uxx, uyy))
1470 element = EL_STEELWALL;
1472 element = Feld[uxx][uyy];
1474 if (element == EL_SAND ||
1475 element == EL_LANDMINE ||
1476 element == EL_TRAP ||
1477 element == EL_TRAP_ACTIVE)
1480 if (i == 1 || i == 2)
1484 cx = (i == 2 ? TILEX - snip : 0);
1492 cy = (i == 3 ? TILEY - snip : 0);
1495 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1496 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1499 MarkTileDirty(x, y);
1503 graphic = IMG_SAND_CRUMBLED;
1505 src_bitmap = new_graphic_info[graphic].bitmap;
1506 src_x = new_graphic_info[graphic].src_x;
1507 src_y = new_graphic_info[graphic].src_y;
1511 int xx, yy, uxx, uyy;
1515 uxx = ux + xy[i][0];
1516 uyy = uy + xy[i][1];
1518 if (!IN_LEV_FIELD(uxx, uyy) ||
1519 (Feld[uxx][uyy] != EL_SAND &&
1520 Feld[uxx][uyy] != EL_LANDMINE &&
1521 Feld[uxx][uyy] != EL_TRAP &&
1522 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1523 !IN_SCR_FIELD(xx, yy))
1526 if (i == 1 || i == 2)
1530 cx = (i == 1 ? TILEX - snip : 0);
1538 cy = (i==0 ? TILEY-snip : 0);
1541 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1542 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1544 MarkTileDirty(xx, yy);
1549 void DrawScreenElement(int x, int y, int element)
1551 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1552 DrawCrumbledSand(x, y);
1555 void DrawLevelElement(int x, int y, int element)
1557 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1558 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1561 void DrawScreenField(int x, int y)
1563 int ux = LEVELX(x), uy = LEVELY(y);
1564 int element, content;
1566 if (!IN_LEV_FIELD(ux, uy))
1568 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1571 element = BorderElement;
1573 DrawScreenElement(x, y, element);
1577 element = Feld[ux][uy];
1578 content = Store[ux][uy];
1580 if (IS_MOVING(ux, uy))
1582 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1583 boolean cut_mode = NO_CUTTING;
1585 if (element == EL_QUICKSAND_EMPTYING ||
1586 element == EL_MAGIC_WALL_EMPTYING ||
1587 element == EL_BD_MAGIC_WALL_EMPTYING ||
1588 element == EL_AMOEBA_DRIPPING)
1589 cut_mode = CUT_ABOVE;
1590 else if (element == EL_QUICKSAND_FILLING ||
1591 element == EL_MAGIC_WALL_FILLING ||
1592 element == EL_BD_MAGIC_WALL_FILLING)
1593 cut_mode = CUT_BELOW;
1595 if (cut_mode == CUT_ABOVE)
1596 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1598 DrawScreenElement(x, y, EL_EMPTY);
1601 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1602 else if (cut_mode == NO_CUTTING)
1603 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1605 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1607 if (content == EL_ACID)
1608 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1610 else if (IS_BLOCKED(ux, uy))
1615 boolean cut_mode = NO_CUTTING;
1616 int element_old, content_old;
1618 Blocked2Moving(ux, uy, &oldx, &oldy);
1621 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1622 MovDir[oldx][oldy] == MV_RIGHT);
1624 element_old = Feld[oldx][oldy];
1625 content_old = Store[oldx][oldy];
1627 if (element_old == EL_QUICKSAND_EMPTYING ||
1628 element_old == EL_MAGIC_WALL_EMPTYING ||
1629 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1630 element_old == EL_AMOEBA_DRIPPING)
1631 cut_mode = CUT_ABOVE;
1633 DrawScreenElement(x, y, EL_EMPTY);
1636 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1638 else if (cut_mode == NO_CUTTING)
1639 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1642 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1645 else if (IS_DRAWABLE(element))
1646 DrawScreenElement(x, y, element);
1648 DrawScreenElement(x, y, EL_EMPTY);
1651 void DrawLevelField(int x, int y)
1653 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1654 DrawScreenField(SCREENX(x), SCREENY(y));
1655 else if (IS_MOVING(x, y))
1659 Moving2Blocked(x, y, &newx, &newy);
1660 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1661 DrawScreenField(SCREENX(newx), SCREENY(newy));
1663 else if (IS_BLOCKED(x, y))
1667 Blocked2Moving(x, y, &oldx, &oldy);
1668 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1669 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1673 void DrawMiniElement(int x, int y, int element)
1677 graphic = el2img(element);
1678 DrawMiniGraphic(x, y, graphic);
1681 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1683 int x = sx + scroll_x, y = sy + scroll_y;
1685 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1686 DrawMiniElement(sx, sy, EL_EMPTY);
1687 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1688 DrawMiniElement(sx, sy, Feld[x][y]);
1691 int steel_type, steel_position;
1694 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1695 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1696 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1697 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1698 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1699 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1702 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1703 steel_position = (x == -1 && y == -1 ? 0 :
1704 x == lev_fieldx && y == -1 ? 1 :
1705 x == -1 && y == lev_fieldy ? 2 :
1706 x == lev_fieldx && y == lev_fieldy ? 3 :
1707 x == -1 || x == lev_fieldx ? 4 :
1708 y == -1 || y == lev_fieldy ? 5 : -1);
1710 if (steel_position != -1)
1711 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1715 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1717 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1718 int mini_startx = src_bitmap->width * 3 / 4;
1719 int mini_starty = src_bitmap->height * 2 / 3;
1720 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1721 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1723 if (src_x + MICRO_TILEX > src_bitmap->width ||
1724 src_y + MICRO_TILEY > src_bitmap->height)
1726 /* graphic of desired size seems not to be contained in this image;
1727 dirty workaround: get it from the middle of the normal sized image */
1729 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1730 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1731 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1734 *bitmap = src_bitmap;
1739 void DrawMicroElement(int xpos, int ypos, int element)
1745 if (element == EL_EMPTY)
1748 graphic = el2img(element);
1750 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1751 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1761 for(x=BX1; x<=BX2; x++)
1762 for(y=BY1; y<=BY2; y++)
1763 DrawScreenField(x, y);
1765 redraw_mask |= REDRAW_FIELD;
1768 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1772 for(x=0; x<size_x; x++)
1773 for(y=0; y<size_y; y++)
1774 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1776 redraw_mask |= REDRAW_FIELD;
1779 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1783 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1785 if (lev_fieldx < STD_LEV_FIELDX)
1786 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1787 if (lev_fieldy < STD_LEV_FIELDY)
1788 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1790 xpos += MICRO_TILEX;
1791 ypos += MICRO_TILEY;
1793 for(x=-1; x<=STD_LEV_FIELDX; x++)
1795 for(y=-1; y<=STD_LEV_FIELDY; y++)
1797 int lx = from_x + x, ly = from_y + y;
1799 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1800 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1802 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1803 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1808 redraw_mask |= REDRAW_MICROLEVEL;
1811 #define MICROLABEL_EMPTY 0
1812 #define MICROLABEL_LEVEL_NAME 1
1813 #define MICROLABEL_CREATED_BY 2
1814 #define MICROLABEL_LEVEL_AUTHOR 3
1815 #define MICROLABEL_IMPORTED_FROM 4
1816 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1818 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1820 static void DrawMicroLevelLabelExt(int mode)
1822 char label_text[MAX_MICROLABEL_SIZE + 1];
1824 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1826 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1827 mode == MICROLABEL_CREATED_BY ? "created by" :
1828 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1829 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1830 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1831 leveldir_current->imported_from : ""),
1832 MAX_MICROLABEL_SIZE);
1833 label_text[MAX_MICROLABEL_SIZE] = '\0';
1835 if (strlen(label_text) > 0)
1837 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1838 int lypos = MICROLABEL_YPOS;
1840 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1843 redraw_mask |= REDRAW_MICROLEVEL;
1846 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1848 static unsigned long scroll_delay = 0;
1849 static unsigned long label_delay = 0;
1850 static int from_x, from_y, scroll_direction;
1851 static int label_state, label_counter;
1855 from_x = from_y = 0;
1856 scroll_direction = MV_RIGHT;
1860 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1861 DrawMicroLevelLabelExt(label_state);
1863 /* initialize delay counters */
1864 DelayReached(&scroll_delay, 0);
1865 DelayReached(&label_delay, 0);
1870 /* scroll micro level, if needed */
1871 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1872 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1874 switch (scroll_direction)
1880 scroll_direction = MV_UP;
1884 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1887 scroll_direction = MV_DOWN;
1894 scroll_direction = MV_RIGHT;
1898 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1901 scroll_direction = MV_LEFT;
1908 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1911 /* redraw micro level label, if needed */
1912 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1913 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1914 strcmp(level.author, leveldir_current->name) != 0 &&
1915 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1917 int max_label_counter = 23;
1919 if (leveldir_current->imported_from != NULL)
1920 max_label_counter += 14;
1922 label_counter = (label_counter + 1) % max_label_counter;
1923 label_state = (label_counter >= 0 && label_counter <= 7 ?
1924 MICROLABEL_LEVEL_NAME :
1925 label_counter >= 9 && label_counter <= 12 ?
1926 MICROLABEL_CREATED_BY :
1927 label_counter >= 14 && label_counter <= 21 ?
1928 MICROLABEL_LEVEL_AUTHOR :
1929 label_counter >= 23 && label_counter <= 26 ?
1930 MICROLABEL_IMPORTED_FROM :
1931 label_counter >= 28 && label_counter <= 35 ?
1932 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1933 DrawMicroLevelLabelExt(label_state);
1937 int REQ_in_range(int x, int y)
1939 if (y > DY+249 && y < DY+278)
1941 if (x > DX+1 && x < DX+48)
1943 else if (x > DX+51 && x < DX+98)
1949 #define MAX_REQUEST_LINES 13
1950 #define MAX_REQUEST_LINE_LEN 7
1952 boolean Request(char *text, unsigned int req_state)
1954 int mx, my, ty, result = -1;
1955 unsigned int old_door_state;
1957 #if defined(PLATFORM_UNIX)
1958 /* pause network game while waiting for request to answer */
1959 if (options.network &&
1960 game_status == PLAYING &&
1961 req_state & REQUEST_WAIT_FOR)
1962 SendToServer_PausePlaying();
1965 old_door_state = GetDoorState();
1969 CloseDoor(DOOR_CLOSE_1);
1971 /* save old door content */
1972 BlitBitmap(bitmap_db_door, bitmap_db_door,
1973 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1974 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1976 /* clear door drawing field */
1977 ClearRectangle(drawto, 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 DrawTextExt(drawto, 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))
2042 if (game_status != MAINMENU)
2045 button_status = MB_RELEASED;
2047 request_gadget_id = -1;
2059 case EVENT_BUTTONPRESS:
2060 case EVENT_BUTTONRELEASE:
2061 case EVENT_MOTIONNOTIFY:
2063 if (event.type == EVENT_MOTIONNOTIFY)
2065 if (!PointerInWindow(window))
2066 continue; /* window and pointer are on different screens */
2071 motion_status = TRUE;
2072 mx = ((MotionEvent *) &event)->x;
2073 my = ((MotionEvent *) &event)->y;
2077 motion_status = FALSE;
2078 mx = ((ButtonEvent *) &event)->x;
2079 my = ((ButtonEvent *) &event)->y;
2080 if (event.type == EVENT_BUTTONPRESS)
2081 button_status = ((ButtonEvent *) &event)->button;
2083 button_status = MB_RELEASED;
2086 /* this sets 'request_gadget_id' */
2087 HandleGadgets(mx, my, button_status);
2089 switch(request_gadget_id)
2091 case TOOL_CTRL_ID_YES:
2094 case TOOL_CTRL_ID_NO:
2097 case TOOL_CTRL_ID_CONFIRM:
2098 result = TRUE | FALSE;
2101 case TOOL_CTRL_ID_PLAYER_1:
2104 case TOOL_CTRL_ID_PLAYER_2:
2107 case TOOL_CTRL_ID_PLAYER_3:
2110 case TOOL_CTRL_ID_PLAYER_4:
2121 case EVENT_KEYPRESS:
2122 switch(GetEventKey((KeyEvent *)&event, TRUE))
2135 if (req_state & REQ_PLAYER)
2139 case EVENT_KEYRELEASE:
2140 ClearPlayerAction();
2144 HandleOtherEvents(&event);
2148 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2150 int joy = AnyJoystick();
2152 if (joy & JOY_BUTTON_1)
2154 else if (joy & JOY_BUTTON_2)
2160 /* don't eat all CPU time */
2164 if (game_status != MAINMENU)
2169 if (!(req_state & REQ_STAY_OPEN))
2171 CloseDoor(DOOR_CLOSE_1);
2173 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2175 BlitBitmap(bitmap_db_door, bitmap_db_door,
2176 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2177 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2178 OpenDoor(DOOR_OPEN_1);
2184 #if defined(PLATFORM_UNIX)
2185 /* continue network game after request */
2186 if (options.network &&
2187 game_status == PLAYING &&
2188 req_state & REQUEST_WAIT_FOR)
2189 SendToServer_ContinuePlaying();
2195 unsigned int OpenDoor(unsigned int door_state)
2197 unsigned int new_door_state;
2199 if (door_state & DOOR_COPY_BACK)
2201 BlitBitmap(bitmap_db_door, bitmap_db_door,
2202 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2203 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2204 door_state &= ~DOOR_COPY_BACK;
2207 new_door_state = MoveDoor(door_state);
2209 return(new_door_state);
2212 unsigned int CloseDoor(unsigned int door_state)
2214 unsigned int new_door_state;
2216 BlitBitmap(backbuffer, bitmap_db_door,
2217 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2218 BlitBitmap(backbuffer, bitmap_db_door,
2219 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2221 new_door_state = MoveDoor(door_state);
2223 return(new_door_state);
2226 unsigned int GetDoorState()
2228 return MoveDoor(DOOR_GET_STATE);
2231 unsigned int SetDoorState(unsigned int door_state)
2233 return MoveDoor(door_state | DOOR_SET_STATE);
2236 unsigned int MoveDoor(unsigned int door_state)
2238 static int door1 = DOOR_OPEN_1;
2239 static int door2 = DOOR_CLOSE_2;
2240 static unsigned long door_delay = 0;
2241 int x, start, stepsize = 2;
2242 unsigned long door_delay_value = stepsize * 5;
2244 if (door_state == DOOR_GET_STATE)
2245 return(door1 | door2);
2247 if (door_state & DOOR_SET_STATE)
2249 if (door_state & DOOR_ACTION_1)
2250 door1 = door_state & DOOR_ACTION_1;
2251 if (door_state & DOOR_ACTION_2)
2252 door2 = door_state & DOOR_ACTION_2;
2254 return(door1 | door2);
2257 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2258 door_state &= ~DOOR_OPEN_1;
2259 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2260 door_state &= ~DOOR_CLOSE_1;
2261 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2262 door_state &= ~DOOR_OPEN_2;
2263 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2264 door_state &= ~DOOR_CLOSE_2;
2266 if (setup.quick_doors)
2269 door_delay_value = 0;
2271 StopSound(SND_MENU_DOOR_OPENING);
2272 StopSound(SND_MENU_DOOR_CLOSING);
2275 if (global.autoplay_leveldir)
2277 door_state |= DOOR_NO_DELAY;
2278 door_state &= ~DOOR_CLOSE_ALL;
2281 if (door_state & DOOR_ACTION)
2283 if (!(door_state & DOOR_NO_DELAY))
2285 /* opening door sound has priority over simultaneously closing door */
2286 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2287 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2288 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2289 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2292 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2294 for(x=start; x<=DXSIZE; x+=stepsize)
2296 Bitmap *bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2297 GC gc = bitmap->stored_clip_gc;
2299 if (!(door_state & DOOR_NO_DELAY))
2300 WaitUntilDelayReached(&door_delay, door_delay_value);
2302 if (door_state & DOOR_ACTION_1)
2304 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2305 int j = (DXSIZE - i) / 3;
2307 BlitBitmap(bitmap_db_door, drawto,
2308 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2309 DXSIZE,DYSIZE - i/2, DX, DY);
2311 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2313 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2314 BlitBitmapMasked(bitmap, drawto,
2315 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2316 DX + DXSIZE - i, DY + j);
2317 BlitBitmapMasked(bitmap, drawto,
2318 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2319 DX + DXSIZE - i, DY + 140 + j);
2320 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2321 BlitBitmapMasked(bitmap, drawto,
2322 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2324 BlitBitmapMasked(bitmap, drawto,
2325 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2328 BlitBitmapMasked(bitmap, drawto,
2329 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2331 BlitBitmapMasked(bitmap, drawto,
2332 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2334 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2335 BlitBitmapMasked(bitmap, drawto,
2336 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2337 DX + DXSIZE - i, DY + 77 + j);
2338 BlitBitmapMasked(bitmap, drawto,
2339 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2340 DX + DXSIZE - i, DY + 203 + j);
2342 redraw_mask |= REDRAW_DOOR_1;
2345 if (door_state & DOOR_ACTION_2)
2347 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2348 int j = (VXSIZE - i) / 3;
2350 BlitBitmap(bitmap_db_door, drawto,
2351 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2352 VXSIZE, VYSIZE - i/2, VX, VY);
2354 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2356 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2357 BlitBitmapMasked(bitmap, drawto,
2358 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2359 VX + VXSIZE-i, VY+j);
2360 SetClipOrigin(bitmap, gc,
2361 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2362 BlitBitmapMasked(bitmap, drawto,
2363 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2366 BlitBitmapMasked(bitmap, drawto,
2367 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2368 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2369 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2370 BlitBitmapMasked(bitmap, drawto,
2371 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2373 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2375 redraw_mask |= REDRAW_DOOR_2;
2380 if (game_status == MAINMENU)
2385 if (setup.quick_doors)
2387 StopSound(SND_MENU_DOOR_OPENING);
2388 StopSound(SND_MENU_DOOR_CLOSING);
2391 if (door_state & DOOR_ACTION_1)
2392 door1 = door_state & DOOR_ACTION_1;
2393 if (door_state & DOOR_ACTION_2)
2394 door2 = door_state & DOOR_ACTION_2;
2396 return (door1 | door2);
2399 void DrawSpecialEditorDoor()
2401 /* draw bigger toolbox window */
2402 BlitBitmap(new_graphic_info[IMG_MENU_DOOR].bitmap, drawto,
2403 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2405 BlitBitmap(new_graphic_info[IMG_MENU_FRAME].bitmap, drawto,
2406 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2409 redraw_mask |= REDRAW_ALL;
2412 void UndrawSpecialEditorDoor()
2414 /* draw normal tape recorder window */
2415 BlitBitmap(new_graphic_info[IMG_MENU_FRAME].bitmap, drawto,
2416 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2419 redraw_mask |= REDRAW_ALL;
2423 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2425 XImage *pixel_image;
2426 unsigned long pixel_value;
2428 pixel_image = XGetImage(display, bitmap->drawable,
2429 x, y, 1, 1, AllPlanes, ZPixmap);
2430 pixel_value = XGetPixel(pixel_image, 0, 0);
2432 XDestroyImage(pixel_image);
2438 /* ---------- new tool button stuff ---------------------------------------- */
2440 /* graphic position values for tool buttons */
2441 #define TOOL_BUTTON_YES_XPOS 2
2442 #define TOOL_BUTTON_YES_YPOS 250
2443 #define TOOL_BUTTON_YES_GFX_YPOS 0
2444 #define TOOL_BUTTON_YES_XSIZE 46
2445 #define TOOL_BUTTON_YES_YSIZE 28
2446 #define TOOL_BUTTON_NO_XPOS 52
2447 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2448 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2449 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2450 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2451 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2452 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2453 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2454 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2455 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2456 #define TOOL_BUTTON_PLAYER_XSIZE 30
2457 #define TOOL_BUTTON_PLAYER_YSIZE 30
2458 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2459 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2460 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2461 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2462 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2463 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2464 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2465 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2466 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2467 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2468 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2469 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2470 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2471 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2472 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2473 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2474 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2475 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2476 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2477 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2486 } toolbutton_info[NUM_TOOL_BUTTONS] =
2489 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2490 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2491 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2496 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2497 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2498 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2503 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2504 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2505 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2506 TOOL_CTRL_ID_CONFIRM,
2510 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2511 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2512 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2513 TOOL_CTRL_ID_PLAYER_1,
2517 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2518 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2519 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2520 TOOL_CTRL_ID_PLAYER_2,
2524 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2525 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2526 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2527 TOOL_CTRL_ID_PLAYER_3,
2531 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2532 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2533 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2534 TOOL_CTRL_ID_PLAYER_4,
2539 void CreateToolButtons()
2543 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2545 Bitmap *gd_bitmap = new_graphic_info[IMG_MENU_DOOR].bitmap;
2546 Bitmap *deco_bitmap = None;
2547 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2548 struct GadgetInfo *gi;
2549 unsigned long event_mask;
2550 int gd_xoffset, gd_yoffset;
2551 int gd_x1, gd_x2, gd_y;
2554 event_mask = GD_EVENT_RELEASED;
2556 gd_xoffset = toolbutton_info[i].xpos;
2557 gd_yoffset = toolbutton_info[i].ypos;
2558 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2559 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2560 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2562 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2564 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2566 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2567 &deco_bitmap, &deco_x, &deco_y);
2568 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2569 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2572 gi = CreateGadget(GDI_CUSTOM_ID, id,
2573 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2574 GDI_X, DX + toolbutton_info[i].x,
2575 GDI_Y, DY + toolbutton_info[i].y,
2576 GDI_WIDTH, toolbutton_info[i].width,
2577 GDI_HEIGHT, toolbutton_info[i].height,
2578 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2579 GDI_STATE, GD_BUTTON_UNPRESSED,
2580 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2581 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2582 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2583 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2584 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2585 GDI_DECORATION_SHIFTING, 1, 1,
2586 GDI_EVENT_MASK, event_mask,
2587 GDI_CALLBACK_ACTION, HandleToolButtons,
2591 Error(ERR_EXIT, "cannot create gadget");
2593 tool_gadget[id] = gi;
2597 void FreeToolButtons()
2601 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2602 FreeGadget(tool_gadget[i]);
2605 static void UnmapToolButtons()
2609 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2610 UnmapGadget(tool_gadget[i]);
2613 static void HandleToolButtons(struct GadgetInfo *gi)
2615 request_gadget_id = gi->custom_id;
2618 int get_next_element(int element)
2622 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2623 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2624 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2625 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2626 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2627 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2628 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2630 default: return element;
2634 int el2gfx_OLD(int element)
2638 case EL_EMPTY: return -1;
2639 case EL_SAND: return GFX_ERDREICH;
2640 case EL_WALL: return GFX_MAUERWERK;
2641 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2642 case EL_ROCK: return GFX_FELSBROCKEN;
2643 case EL_EMERALD: return GFX_EDELSTEIN;
2644 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2645 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2646 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2647 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2648 case EL_PLAYER1: return GFX_SPIELER1;
2649 case EL_PLAYER2: return GFX_SPIELER2;
2650 case EL_PLAYER3: return GFX_SPIELER3;
2651 case EL_PLAYER4: return GFX_SPIELER4;
2652 case EL_BUG: return GFX_KAEFER;
2653 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2654 case EL_BUG_UP: return GFX_KAEFER_UP;
2655 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2656 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2657 case EL_SPACESHIP: return GFX_FLIEGER;
2658 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2659 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2660 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2661 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2662 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2663 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2664 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2665 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2666 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2667 case EL_BD_FIREFLY: return GFX_FIREFLY;
2668 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2669 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2670 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2671 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2672 case EL_YAMYAM: return GFX_MAMPFER;
2673 case EL_ROBOT: return GFX_ROBOT;
2674 case EL_STEELWALL: return GFX_BETON;
2675 case EL_DIAMOND: return GFX_DIAMANT;
2676 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2677 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2678 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2679 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2680 case EL_BOMB: return GFX_BOMBE;
2681 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2682 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2683 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2684 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2685 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2686 case EL_ACID: return GFX_SALZSAEURE;
2687 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2688 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2689 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2690 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2691 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2692 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2693 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2694 case EL_NUT: return GFX_KOKOSNUSS;
2695 case EL_GAMEOFLIFE: return GFX_LIFE;
2696 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2697 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2698 case EL_STONEBLOCK: return GFX_BADEWANNE;
2699 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2700 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2701 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2702 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2703 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2704 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2705 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2706 case EL_KEY1: return GFX_SCHLUESSEL1;
2707 case EL_KEY2: return GFX_SCHLUESSEL2;
2708 case EL_KEY3: return GFX_SCHLUESSEL3;
2709 case EL_KEY4: return GFX_SCHLUESSEL4;
2710 case EL_GATE1: return GFX_PFORTE1;
2711 case EL_GATE2: return GFX_PFORTE2;
2712 case EL_GATE3: return GFX_PFORTE3;
2713 case EL_GATE4: return GFX_PFORTE4;
2714 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2715 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2716 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2717 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2718 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2719 case EL_PACMAN: return GFX_PACMAN;
2720 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2721 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2722 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2723 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2724 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2725 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2726 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2727 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2728 case EL_LAMP: return GFX_BIRNE_AUS;
2729 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2730 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2731 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2732 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2733 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2734 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2735 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2736 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2737 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2738 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2739 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2740 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2741 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2742 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2743 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2744 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2745 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2746 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2747 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2748 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2749 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2750 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2751 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2752 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2753 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2754 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2755 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2756 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2757 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2758 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2759 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2760 case EL_MOLE: return GFX_MOLE;
2761 case EL_PENGUIN: return GFX_PINGUIN;
2762 case EL_PIG: return GFX_SCHWEIN;
2763 case EL_DRAGON: return GFX_DRACHE;
2764 case EL_SATELLITE: return GFX_SONDE;
2765 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2766 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2767 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2768 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2769 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2770 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2771 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2772 case EL_SP_ZONK: return GFX_SP_ZONK;
2773 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2774 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2775 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2776 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2777 case EL_EM_GATE1: return GFX_EM_GATE_1;
2778 case EL_EM_GATE2: return GFX_EM_GATE_2;
2779 case EL_EM_GATE3: return GFX_EM_GATE_3;
2780 case EL_EM_GATE4: return GFX_EM_GATE_4;
2781 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2782 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2783 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2784 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2785 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2786 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2787 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2788 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2789 case EL_EM_KEY1: return GFX_EM_KEY_1;
2790 case EL_EM_KEY2: return GFX_EM_KEY_2;
2791 case EL_EM_KEY3: return GFX_EM_KEY_3;
2792 case EL_EM_KEY4: return GFX_EM_KEY_4;
2793 case EL_PEARL: return GFX_PEARL;
2794 case EL_CRYSTAL: return GFX_CRYSTAL;
2795 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2796 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2797 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2798 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2799 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2800 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2801 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2802 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2803 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2804 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2805 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2806 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2807 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2808 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2809 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2810 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2811 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2812 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2813 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2814 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2815 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2816 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2817 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2818 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2819 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2820 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2821 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2822 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2823 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2824 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2825 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2826 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2827 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2828 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2829 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2830 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2831 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2832 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2833 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2834 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2835 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2836 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2837 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2838 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2839 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2840 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2841 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2842 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2843 case EL_LANDMINE: return GFX_LANDMINE;
2844 case EL_ENVELOPE: return GFX_ENVELOPE;
2845 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2846 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2847 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2848 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2849 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2850 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2851 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2852 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2853 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2854 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2855 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2856 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2857 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2858 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2859 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2860 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2861 case EL_MOLE_UP: return GFX_MOLE_UP;
2862 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2863 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2864 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2865 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2866 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2867 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2868 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2869 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2870 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2871 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2872 case EL_BALLOON: return GFX_BALLOON;
2873 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2874 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2875 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2876 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2877 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2878 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2879 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2880 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2881 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2882 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2883 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2884 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2885 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2886 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2887 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2888 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2889 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2890 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2891 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2892 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2893 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2894 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2895 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2896 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2897 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2898 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2899 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2900 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2901 case EL_SPRING: return GFX_SPRING;
2902 case EL_TRAP: return GFX_TRAP_INACTIVE;
2903 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2904 case EL_BD_WALL: return GFX_BD_WALL;
2905 case EL_BD_ROCK: return GFX_BD_ROCK;
2906 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2907 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2911 if (IS_CHAR(element))
2912 return GFX_CHAR_START + (element - EL_CHAR_START);
2913 else if (element >= EL_SP_START && element <= EL_SP_END)
2915 int nr_element = element - EL_SP_START;
2916 int gfx_per_line = 8;
2918 (nr_element / gfx_per_line) * SP_PER_LINE +
2919 (nr_element % gfx_per_line);
2921 return GFX_START_ROCKSSP + nr_graphic;
2929 int el2gfx(int element)
2932 int graphic_OLD = el2gfx_OLD(element);
2937 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2940 int graphic_OLD = el2gfx_OLD(element);
2942 if (element >= MAX_ELEMENTS)
2944 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2947 if (graphic_NEW != graphic_OLD)
2949 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2950 graphic_NEW, graphic_OLD);
2958 int el2img(int element)
2960 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2964 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2971 int el_dir2img(int element, int direction)
2973 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2976 int el_dir_act2img(int element, int direction, int action)
2981 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
2989 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
2996 action = graphics_action_mapping[action];
2997 direction = MV_DIR_BIT(direction);
2999 return element_info[element].direction_graphic[action][direction];