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);
670 (element == EL_SOKOBAN_FIELD_EMPTY ||
671 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
672 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
676 int element = Feld[next_jx][next_jy];
677 int graphic = el2img(element);
682 if ((sxx || syy) && IS_PUSHABLE(element))
684 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
686 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
688 frame = getGraphicAnimationFrame(graphic, player->Frame);
692 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
697 if (player->MovDir == MV_LEFT)
702 frame = (player->GfxPos / (TILEX / 4));
704 if (player->MovDir == MV_RIGHT)
705 frame = (frame + 4) % 4;
709 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
710 NO_CUTTING, NO_MASKING);
714 /* draw things in front of player (active dynamite or dynabombs) */
716 if (IS_ACTIVE_BOMB(element))
718 graphic = el2img(element);
721 if (element == EL_DYNAMITE_ACTIVE)
723 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
728 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
732 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
735 if (game.emulation == EMU_SUPAPLEX)
736 DrawGraphic(sx, sy, IMG_SP_DISK_RED, 0);
738 DrawGraphicThruMask(sx, sy, graphic, frame);
741 if (player_is_moving && last_element == EL_EXPLOSION)
743 int stored = Store[last_jx][last_jy];
744 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
745 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
747 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
748 int phase = Frame[last_jx][last_jy] - 1;
749 int frame = getGraphicAnimationFrame(graphic, phase - delay);
752 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
755 /* draw elements that stay over the player */
756 /* handle the field the player is leaving ... */
757 if (player_is_moving && IS_OVER_PLAYER(last_element))
758 DrawLevelField(last_jx, last_jy);
760 /* ... and the field the player is entering */
761 if (IS_OVER_PLAYER(element))
762 DrawLevelField(jx, jy);
764 if (setup.direct_draw)
766 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
767 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
768 int x_size = TILEX * (1 + ABS(jx - last_jx));
769 int y_size = TILEY * (1 + ABS(jy - last_jy));
771 BlitBitmap(drawto_field, window,
772 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
773 SetDrawtoField(DRAW_DIRECT);
776 MarkTileDirty(sx,sy);
779 void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
780 int graphic, int mask_mode)
782 int frame = getGraphicAnimationFrame(graphic, -1);
784 if (mask_mode == USE_MASKING)
785 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
787 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
790 void DrawGraphicAnimation(int x, int y, int graphic)
792 if (!IN_SCR_FIELD(x, y) ||
793 (FrameCounter % new_graphic_info[graphic].anim_delay) != 0)
796 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
797 graphic, NO_MASKING);
802 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
804 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
806 *bitmap = graphic_info[graphic].bitmap;
807 *x = graphic_info[graphic].src_x;
808 *y = graphic_info[graphic].src_y;
810 else if (graphic >= GFX_START_ROCKSELEMENTS &&
811 graphic <= GFX_END_ROCKSELEMENTS)
813 graphic -= GFX_START_ROCKSELEMENTS;
814 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
815 *x = (graphic % GFX_PER_LINE) * TILEX;
816 *y = (graphic / GFX_PER_LINE) * TILEY;
818 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
820 graphic -= GFX_START_ROCKSHEROES;
821 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
822 *x = (graphic % HEROES_PER_LINE) * TILEX;
823 *y = (graphic / HEROES_PER_LINE) * TILEY;
825 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
827 graphic -= GFX_START_ROCKSSP;
828 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
829 *x = (graphic % SP_PER_LINE) * TILEX;
830 *y = (graphic / SP_PER_LINE) * TILEY;
832 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
834 graphic -= GFX_START_ROCKSDC;
835 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
836 *x = (graphic % DC_PER_LINE) * TILEX;
837 *y = (graphic / DC_PER_LINE) * TILEY;
839 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
841 graphic -= GFX_START_ROCKSMORE;
842 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
843 *x = (graphic % MORE_PER_LINE) * TILEX;
844 *y = (graphic / MORE_PER_LINE) * TILEY;
846 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
848 graphic -= GFX_START_ROCKSFONT;
849 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
850 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
851 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
855 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
862 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
864 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
865 int offset_x = new_graphic_info[graphic].offset_x;
866 int offset_y = new_graphic_info[graphic].offset_y;
867 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
868 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
870 *bitmap = src_bitmap;
875 void DrawGraphic(int x, int y, int graphic, int frame)
878 if (!IN_SCR_FIELD(x, y))
880 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
881 printf("DrawGraphic(): This should never happen!\n");
886 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
891 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
896 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
897 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
901 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
908 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
910 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
911 int src_x = new_graphic_info[graphic].src_x;
912 int src_y = new_graphic_info[graphic].src_y;
913 int offset_x = new_graphic_info[graphic].offset_x;
914 int offset_y = new_graphic_info[graphic].offset_y;
916 src_x += frame * offset_x;
917 src_y += frame * offset_y;
920 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
923 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
926 if (!IN_SCR_FIELD(x, y))
928 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
929 printf("DrawGraphicThruMask(): This should never happen!\n");
934 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
939 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
947 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
948 drawing_gc = src_bitmap->stored_clip_gc;
950 GC drawing_gc = src_bitmap->stored_clip_gc;
951 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
952 int src_x = new_graphic_info[graphic].src_x;
953 int src_y = new_graphic_info[graphic].src_y;
954 int offset_x = new_graphic_info[graphic].offset_x;
955 int offset_y = new_graphic_info[graphic].offset_y;
957 src_x += frame * offset_x;
958 src_y += frame * offset_y;
962 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
963 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
966 void DrawMiniGraphic(int x, int y, int graphic)
968 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
969 MarkTileDirty(x / 2, y / 2);
972 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
974 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
976 int mini_starty = src_bitmap->height * 2 / 3;
977 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
978 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
980 if (src_x + MINI_TILEX > src_bitmap->width ||
981 src_y + MINI_TILEY > src_bitmap->height)
983 /* graphic of desired size seems not to be contained in this image;
984 dirty workaround: get it from the middle of the normal sized image */
986 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
987 src_x += (TILEX / 2 - MINI_TILEX / 2);
988 src_y += (TILEY / 2 - MINI_TILEY / 2);
991 *bitmap = src_bitmap;
996 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1001 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1002 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1005 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1006 int cut_mode, int mask_mode)
1015 int width = TILEX, height = TILEY;
1021 DrawGraphic(x, y, graphic, frame);
1025 if (dx || dy) /* shifted graphic */
1027 if (x < BX1) /* object enters playfield from the left */
1034 else if (x > BX2) /* object enters playfield from the right */
1040 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1046 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1048 else if (dx) /* general horizontal movement */
1049 MarkTileDirty(x + SIGN(dx), y);
1051 if (y < BY1) /* object enters playfield from the top */
1053 if (cut_mode==CUT_BELOW) /* object completely above top border */
1061 else if (y > BY2) /* object enters playfield from the bottom */
1067 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1073 else if (dy > 0 && cut_mode == CUT_ABOVE)
1075 if (y == BY2) /* object completely above bottom border */
1081 MarkTileDirty(x, y + 1);
1082 } /* object leaves playfield to the bottom */
1083 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1085 else if (dy) /* general vertical movement */
1086 MarkTileDirty(x, y + SIGN(dy));
1089 src_bitmap = new_graphic_info[graphic].bitmap;
1090 src_x = new_graphic_info[graphic].src_x;
1091 src_y = new_graphic_info[graphic].src_y;
1092 offset_x = new_graphic_info[graphic].offset_x;
1093 offset_y = new_graphic_info[graphic].offset_y;
1095 drawing_gc = src_bitmap->stored_clip_gc;
1097 src_x += frame * offset_x;
1098 src_y += frame * offset_y;
1103 dest_x = FX + x * TILEX + dx;
1104 dest_y = FY + y * TILEY + dy;
1107 if (!IN_SCR_FIELD(x,y))
1109 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1110 printf("DrawGraphicShifted(): This should never happen!\n");
1115 if (mask_mode == USE_MASKING)
1117 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1118 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1122 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1128 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1129 int frame, int cut_mode)
1131 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1135 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1136 int cut_mode, int mask_mode)
1138 int ux = LEVELX(x), uy = LEVELY(y);
1139 int graphic = el2gfx(element);
1140 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1141 int phase4 = phase8 / 2;
1142 int phase2 = phase8 / 4;
1143 int dir = MovDir[ux][uy];
1145 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1147 graphic += 1 * !phase2;
1151 else if (dir == MV_LEFT)
1153 else if (dir == MV_DOWN)
1156 else if (element == EL_SP_SNIKSNAK)
1159 graphic = GFX_SP_SNIKSNAK_LEFT;
1160 else if (dir == MV_RIGHT)
1161 graphic = GFX_SP_SNIKSNAK_RIGHT;
1162 else if (dir == MV_UP)
1163 graphic = GFX_SP_SNIKSNAK_UP;
1165 graphic = GFX_SP_SNIKSNAK_DOWN;
1167 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1169 else if (element == EL_SP_ELECTRON)
1171 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1173 else if (element == EL_MOLE || element == EL_PENGUIN ||
1174 element == EL_PIG || element == EL_DRAGON)
1177 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1178 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1179 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1180 else if (dir == MV_RIGHT)
1181 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1182 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1183 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1184 else if (dir == MV_UP)
1185 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1186 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1187 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1189 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1190 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1191 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1195 else if (element == EL_SATELLITE)
1197 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1199 else if (element == EL_ACID)
1201 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1203 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1207 else if (element == EL_BALLOON)
1211 else if ((element == EL_ROCK ||
1212 element == EL_SP_ZONK ||
1213 element == EL_BD_ROCK ||
1214 element == EL_SP_INFOTRON ||
1218 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1220 if (element == EL_ROCK ||
1221 element == EL_SP_ZONK ||
1222 element == EL_BD_ROCK)
1225 graphic += (4 - phase4) % 4;
1226 else if (dir == MV_RIGHT)
1229 graphic += phase2 * 2;
1231 else if (element != EL_SP_INFOTRON)
1235 else if (element == EL_MAGIC_WALL_ACTIVE ||
1236 element == EL_MAGIC_WALL_EMPTYING ||
1237 element == EL_BD_MAGIC_WALL_ACTIVE ||
1238 element == EL_BD_MAGIC_WALL_EMPTYING ||
1239 element == EL_MAGIC_WALL_FULL ||
1240 element == EL_BD_MAGIC_WALL_FULL)
1242 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1244 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1246 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1247 graphic += (x + 2 * y + 4) % 4;
1249 else if (element == EL_WALL_GROWING)
1251 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1253 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1254 links_massiv = TRUE;
1255 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1256 rechts_massiv = TRUE;
1258 if (links_massiv && rechts_massiv)
1259 graphic = GFX_MAUERWERK;
1260 else if (links_massiv)
1261 graphic = GFX_MAUER_R;
1262 else if (rechts_massiv)
1263 graphic = GFX_MAUER_L;
1266 else if ((element == EL_INVISIBLE_STEELWALL ||
1267 element == EL_INVISIBLE_WALL ||
1268 element == EL_INVISIBLE_SAND) && game.light_time_left)
1270 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1271 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1272 GFX_SAND_INVISIBLE_ON);
1277 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1278 else if (mask_mode == USE_MASKING)
1279 DrawGraphicThruMask(x, y, graphic);
1281 DrawGraphic(x, y, graphic);
1285 inline static int getFramePosition(int x, int y)
1287 int frame_pos = -1; /* default: global synchronization */
1289 int element = Feld[x][y];
1291 if (element == EL_QUICKSAND_FULL ||
1292 element == EL_MAGIC_WALL_FULL ||
1293 element == EL_BD_MAGIC_WALL_FULL)
1295 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1296 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1298 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1304 inline static int getGfxAction(int x, int y)
1306 int gfx_action = GFX_ACTION_DEFAULT;
1309 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1310 gfx_action = GfxAction[x][y];
1311 else if (IS_MOVING(x, y))
1312 gfx_action = GFX_ACTION_MOVING;
1314 gfx_action = GfxAction[x][y];
1319 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1326 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1327 int cut_mode, int mask_mode)
1329 int ux = LEVELX(x), uy = LEVELY(y);
1333 if (IN_LEV_FIELD(ux, uy))
1335 int move_dir = MovDir[ux][uy];
1336 int move_pos = getFramePosition(ux, uy);
1337 int gfx_action = getGfxAction(ux, uy);
1339 graphic = el_dir_act2img(element, move_dir, gfx_action);
1340 frame = getGraphicAnimationFrame(graphic, move_pos);
1344 graphic = el2img(element);
1345 frame = getGraphicAnimationFrame(graphic, 0);
1348 if (element == EL_WALL_GROWING)
1350 boolean left_stopped = FALSE, right_stopped = FALSE;
1352 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1353 left_stopped = TRUE;
1354 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1355 right_stopped = TRUE;
1357 if (left_stopped && right_stopped)
1359 else if (left_stopped)
1361 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1362 frame = new_graphic_info[graphic].anim_frames - 1;
1364 else if (right_stopped)
1366 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1367 frame = new_graphic_info[graphic].anim_frames - 1;
1370 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1372 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1373 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1374 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1375 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1376 IMG_AMOEBA_DEAD_PART1);
1378 graphic += (x + 2 * y + 4) % 4;
1382 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1383 else if (mask_mode == USE_MASKING)
1384 DrawGraphicThruMask(x, y, graphic, frame);
1386 DrawGraphic(x, y, graphic, frame);
1389 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1390 int cut_mode, int mask_mode)
1392 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1393 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1394 cut_mode, mask_mode);
1397 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1400 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1403 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1406 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1410 void DrawOldScreenElementThruMask(int x, int y, int element)
1412 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1415 void DrawScreenElementThruMask(int x, int y, int element)
1417 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1421 void DrawLevelElementThruMask(int x, int y, int element)
1423 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1426 void DrawLevelFieldThruMask(int x, int y)
1428 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1431 void DrawCrumbledSand(int x, int y)
1435 int i, width, height, cx,cy;
1436 int ux = LEVELX(x), uy = LEVELY(y);
1437 int element, graphic;
1439 static int xy[4][2] =
1447 if (!IN_LEV_FIELD(ux, uy))
1450 element = Feld[ux][uy];
1452 if (element == EL_SAND ||
1453 element == EL_LANDMINE ||
1454 element == EL_TRAP ||
1455 element == EL_TRAP_ACTIVE)
1457 if (!IN_SCR_FIELD(x, y))
1460 graphic = IMG_SAND_CRUMBLED;
1462 src_bitmap = new_graphic_info[graphic].bitmap;
1463 src_x = new_graphic_info[graphic].src_x;
1464 src_y = new_graphic_info[graphic].src_y;
1470 uxx = ux + xy[i][0];
1471 uyy = uy + xy[i][1];
1472 if (!IN_LEV_FIELD(uxx, uyy))
1473 element = EL_STEELWALL;
1475 element = Feld[uxx][uyy];
1477 if (element == EL_SAND ||
1478 element == EL_LANDMINE ||
1479 element == EL_TRAP ||
1480 element == EL_TRAP_ACTIVE)
1483 if (i == 1 || i == 2)
1487 cx = (i == 2 ? TILEX - snip : 0);
1495 cy = (i == 3 ? TILEY - snip : 0);
1498 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1499 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1502 MarkTileDirty(x, y);
1506 graphic = IMG_SAND_CRUMBLED;
1508 src_bitmap = new_graphic_info[graphic].bitmap;
1509 src_x = new_graphic_info[graphic].src_x;
1510 src_y = new_graphic_info[graphic].src_y;
1514 int xx, yy, uxx, uyy;
1518 uxx = ux + xy[i][0];
1519 uyy = uy + xy[i][1];
1521 if (!IN_LEV_FIELD(uxx, uyy) ||
1522 (Feld[uxx][uyy] != EL_SAND &&
1523 Feld[uxx][uyy] != EL_LANDMINE &&
1524 Feld[uxx][uyy] != EL_TRAP &&
1525 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1526 !IN_SCR_FIELD(xx, yy))
1529 if (i == 1 || i == 2)
1533 cx = (i == 1 ? TILEX - snip : 0);
1541 cy = (i==0 ? TILEY-snip : 0);
1544 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1545 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1547 MarkTileDirty(xx, yy);
1552 void DrawScreenElement(int x, int y, int element)
1554 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1555 DrawCrumbledSand(x, y);
1558 void DrawLevelElement(int x, int y, int element)
1560 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1561 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1564 void DrawScreenField(int x, int y)
1566 int ux = LEVELX(x), uy = LEVELY(y);
1567 int element, content;
1569 if (!IN_LEV_FIELD(ux, uy))
1571 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1574 element = BorderElement;
1576 DrawScreenElement(x, y, element);
1580 element = Feld[ux][uy];
1581 content = Store[ux][uy];
1583 if (IS_MOVING(ux, uy))
1585 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1586 boolean cut_mode = NO_CUTTING;
1588 if (element == EL_QUICKSAND_EMPTYING ||
1589 element == EL_MAGIC_WALL_EMPTYING ||
1590 element == EL_BD_MAGIC_WALL_EMPTYING ||
1591 element == EL_AMOEBA_DRIPPING)
1592 cut_mode = CUT_ABOVE;
1593 else if (element == EL_QUICKSAND_FILLING ||
1594 element == EL_MAGIC_WALL_FILLING ||
1595 element == EL_BD_MAGIC_WALL_FILLING)
1596 cut_mode = CUT_BELOW;
1598 if (cut_mode == CUT_ABOVE)
1599 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1601 DrawScreenElement(x, y, EL_EMPTY);
1604 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1605 else if (cut_mode == NO_CUTTING)
1606 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1608 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1610 if (content == EL_ACID)
1611 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1613 else if (IS_BLOCKED(ux, uy))
1618 boolean cut_mode = NO_CUTTING;
1619 int element_old, content_old;
1621 Blocked2Moving(ux, uy, &oldx, &oldy);
1624 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1625 MovDir[oldx][oldy] == MV_RIGHT);
1627 element_old = Feld[oldx][oldy];
1628 content_old = Store[oldx][oldy];
1630 if (element_old == EL_QUICKSAND_EMPTYING ||
1631 element_old == EL_MAGIC_WALL_EMPTYING ||
1632 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1633 element_old == EL_AMOEBA_DRIPPING)
1634 cut_mode = CUT_ABOVE;
1636 DrawScreenElement(x, y, EL_EMPTY);
1639 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1641 else if (cut_mode == NO_CUTTING)
1642 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1645 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1648 else if (IS_DRAWABLE(element))
1649 DrawScreenElement(x, y, element);
1651 DrawScreenElement(x, y, EL_EMPTY);
1654 void DrawLevelField(int x, int y)
1656 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1657 DrawScreenField(SCREENX(x), SCREENY(y));
1658 else if (IS_MOVING(x, y))
1662 Moving2Blocked(x, y, &newx, &newy);
1663 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1664 DrawScreenField(SCREENX(newx), SCREENY(newy));
1666 else if (IS_BLOCKED(x, y))
1670 Blocked2Moving(x, y, &oldx, &oldy);
1671 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1672 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1676 void DrawMiniElement(int x, int y, int element)
1680 graphic = el2img(element);
1681 DrawMiniGraphic(x, y, graphic);
1684 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1686 int x = sx + scroll_x, y = sy + scroll_y;
1688 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1689 DrawMiniElement(sx, sy, EL_EMPTY);
1690 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1691 DrawMiniElement(sx, sy, Feld[x][y]);
1694 int steel_type, steel_position;
1697 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1698 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1699 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1700 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1701 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1702 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1705 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1706 steel_position = (x == -1 && y == -1 ? 0 :
1707 x == lev_fieldx && y == -1 ? 1 :
1708 x == -1 && y == lev_fieldy ? 2 :
1709 x == lev_fieldx && y == lev_fieldy ? 3 :
1710 x == -1 || x == lev_fieldx ? 4 :
1711 y == -1 || y == lev_fieldy ? 5 : -1);
1713 if (steel_position != -1)
1714 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1718 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1720 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1721 int mini_startx = src_bitmap->width * 3 / 4;
1722 int mini_starty = src_bitmap->height * 2 / 3;
1723 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1724 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1726 if (src_x + MICRO_TILEX > src_bitmap->width ||
1727 src_y + MICRO_TILEY > src_bitmap->height)
1729 /* graphic of desired size seems not to be contained in this image;
1730 dirty workaround: get it from the middle of the normal sized image */
1732 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1733 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1734 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1737 *bitmap = src_bitmap;
1742 void DrawMicroElement(int xpos, int ypos, int element)
1746 int graphic = el2img(element);
1748 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1749 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1759 for(x=BX1; x<=BX2; x++)
1760 for(y=BY1; y<=BY2; y++)
1761 DrawScreenField(x, y);
1763 redraw_mask |= REDRAW_FIELD;
1766 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1770 for(x=0; x<size_x; x++)
1771 for(y=0; y<size_y; y++)
1772 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1774 redraw_mask |= REDRAW_FIELD;
1777 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1781 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1783 if (lev_fieldx < STD_LEV_FIELDX)
1784 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1785 if (lev_fieldy < STD_LEV_FIELDY)
1786 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1788 xpos += MICRO_TILEX;
1789 ypos += MICRO_TILEY;
1791 for(x=-1; x<=STD_LEV_FIELDX; x++)
1793 for(y=-1; y<=STD_LEV_FIELDY; y++)
1795 int lx = from_x + x, ly = from_y + y;
1797 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1798 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1800 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1801 && BorderElement != EL_EMPTY)
1802 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1807 redraw_mask |= REDRAW_MICROLEVEL;
1810 #define MICROLABEL_EMPTY 0
1811 #define MICROLABEL_LEVEL_NAME 1
1812 #define MICROLABEL_CREATED_BY 2
1813 #define MICROLABEL_LEVEL_AUTHOR 3
1814 #define MICROLABEL_IMPORTED_FROM 4
1815 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1817 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1819 static void DrawMicroLevelLabelExt(int mode)
1821 char label_text[MAX_MICROLABEL_SIZE + 1];
1823 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1825 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1826 mode == MICROLABEL_CREATED_BY ? "created by" :
1827 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1828 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1829 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1830 leveldir_current->imported_from : ""),
1831 MAX_MICROLABEL_SIZE);
1832 label_text[MAX_MICROLABEL_SIZE] = '\0';
1834 if (strlen(label_text) > 0)
1836 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1837 int lypos = MICROLABEL_YPOS;
1839 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1842 redraw_mask |= REDRAW_MICROLEVEL;
1845 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1847 static unsigned long scroll_delay = 0;
1848 static unsigned long label_delay = 0;
1849 static int from_x, from_y, scroll_direction;
1850 static int label_state, label_counter;
1854 from_x = from_y = 0;
1855 scroll_direction = MV_RIGHT;
1859 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1860 DrawMicroLevelLabelExt(label_state);
1862 /* initialize delay counters */
1863 DelayReached(&scroll_delay, 0);
1864 DelayReached(&label_delay, 0);
1869 /* scroll micro level, if needed */
1870 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1871 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1873 switch (scroll_direction)
1879 scroll_direction = MV_UP;
1883 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1886 scroll_direction = MV_DOWN;
1893 scroll_direction = MV_RIGHT;
1897 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1900 scroll_direction = MV_LEFT;
1907 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1910 /* redraw micro level label, if needed */
1911 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1912 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1913 strcmp(level.author, leveldir_current->name) != 0 &&
1914 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1916 int max_label_counter = 23;
1918 if (leveldir_current->imported_from != NULL)
1919 max_label_counter += 14;
1921 label_counter = (label_counter + 1) % max_label_counter;
1922 label_state = (label_counter >= 0 && label_counter <= 7 ?
1923 MICROLABEL_LEVEL_NAME :
1924 label_counter >= 9 && label_counter <= 12 ?
1925 MICROLABEL_CREATED_BY :
1926 label_counter >= 14 && label_counter <= 21 ?
1927 MICROLABEL_LEVEL_AUTHOR :
1928 label_counter >= 23 && label_counter <= 26 ?
1929 MICROLABEL_IMPORTED_FROM :
1930 label_counter >= 28 && label_counter <= 35 ?
1931 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1932 DrawMicroLevelLabelExt(label_state);
1936 int REQ_in_range(int x, int y)
1938 if (y > DY+249 && y < DY+278)
1940 if (x > DX+1 && x < DX+48)
1942 else if (x > DX+51 && x < DX+98)
1948 #define MAX_REQUEST_LINES 13
1949 #define MAX_REQUEST_LINE_LEN 7
1951 boolean Request(char *text, unsigned int req_state)
1953 int mx, my, ty, result = -1;
1954 unsigned int old_door_state;
1956 #if defined(PLATFORM_UNIX)
1957 /* pause network game while waiting for request to answer */
1958 if (options.network &&
1959 game_status == PLAYING &&
1960 req_state & REQUEST_WAIT_FOR)
1961 SendToServer_PausePlaying();
1964 old_door_state = GetDoorState();
1968 CloseDoor(DOOR_CLOSE_1);
1970 /* save old door content */
1971 BlitBitmap(bitmap_db_door, bitmap_db_door,
1972 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1973 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1975 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1977 /* clear door drawing field */
1978 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1980 /* write text for request */
1981 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1983 char text_line[MAX_REQUEST_LINE_LEN + 1];
1989 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1992 if (!tc || tc == ' ')
2003 strncpy(text_line, text, tl);
2006 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2007 text_line, FS_SMALL, FC_YELLOW);
2009 text += tl + (tc == ' ' ? 1 : 0);
2012 if (req_state & REQ_ASK)
2014 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2015 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2017 else if (req_state & REQ_CONFIRM)
2019 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2021 else if (req_state & REQ_PLAYER)
2023 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2024 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2025 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2026 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2029 /* copy request gadgets to door backbuffer */
2030 BlitBitmap(drawto, bitmap_db_door,
2031 DX, DY, DXSIZE, DYSIZE,
2032 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2034 OpenDoor(DOOR_OPEN_1);
2040 if (!(req_state & REQUEST_WAIT_FOR))
2042 SetDrawBackgroundMask(REDRAW_FIELD);
2047 if (game_status != MAINMENU)
2050 button_status = MB_RELEASED;
2052 request_gadget_id = -1;
2054 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2066 case EVENT_BUTTONPRESS:
2067 case EVENT_BUTTONRELEASE:
2068 case EVENT_MOTIONNOTIFY:
2070 if (event.type == EVENT_MOTIONNOTIFY)
2072 if (!PointerInWindow(window))
2073 continue; /* window and pointer are on different screens */
2078 motion_status = TRUE;
2079 mx = ((MotionEvent *) &event)->x;
2080 my = ((MotionEvent *) &event)->y;
2084 motion_status = FALSE;
2085 mx = ((ButtonEvent *) &event)->x;
2086 my = ((ButtonEvent *) &event)->y;
2087 if (event.type == EVENT_BUTTONPRESS)
2088 button_status = ((ButtonEvent *) &event)->button;
2090 button_status = MB_RELEASED;
2093 /* this sets 'request_gadget_id' */
2094 HandleGadgets(mx, my, button_status);
2096 switch(request_gadget_id)
2098 case TOOL_CTRL_ID_YES:
2101 case TOOL_CTRL_ID_NO:
2104 case TOOL_CTRL_ID_CONFIRM:
2105 result = TRUE | FALSE;
2108 case TOOL_CTRL_ID_PLAYER_1:
2111 case TOOL_CTRL_ID_PLAYER_2:
2114 case TOOL_CTRL_ID_PLAYER_3:
2117 case TOOL_CTRL_ID_PLAYER_4:
2128 case EVENT_KEYPRESS:
2129 switch(GetEventKey((KeyEvent *)&event, TRUE))
2142 if (req_state & REQ_PLAYER)
2146 case EVENT_KEYRELEASE:
2147 ClearPlayerAction();
2151 HandleOtherEvents(&event);
2155 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2157 int joy = AnyJoystick();
2159 if (joy & JOY_BUTTON_1)
2161 else if (joy & JOY_BUTTON_2)
2167 /* don't eat all CPU time */
2171 if (game_status != MAINMENU)
2176 if (!(req_state & REQ_STAY_OPEN))
2178 CloseDoor(DOOR_CLOSE_1);
2180 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2182 BlitBitmap(bitmap_db_door, bitmap_db_door,
2183 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2184 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2185 OpenDoor(DOOR_OPEN_1);
2191 SetDrawBackgroundMask(REDRAW_FIELD);
2193 #if defined(PLATFORM_UNIX)
2194 /* continue network game after request */
2195 if (options.network &&
2196 game_status == PLAYING &&
2197 req_state & REQUEST_WAIT_FOR)
2198 SendToServer_ContinuePlaying();
2204 unsigned int OpenDoor(unsigned int door_state)
2206 unsigned int new_door_state;
2208 if (door_state & DOOR_COPY_BACK)
2210 BlitBitmap(bitmap_db_door, bitmap_db_door,
2211 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2212 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2213 door_state &= ~DOOR_COPY_BACK;
2216 new_door_state = MoveDoor(door_state);
2218 return(new_door_state);
2221 unsigned int CloseDoor(unsigned int door_state)
2223 unsigned int new_door_state;
2225 BlitBitmap(backbuffer, bitmap_db_door,
2226 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2227 BlitBitmap(backbuffer, bitmap_db_door,
2228 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2230 new_door_state = MoveDoor(door_state);
2232 return(new_door_state);
2235 unsigned int GetDoorState()
2237 return MoveDoor(DOOR_GET_STATE);
2240 unsigned int SetDoorState(unsigned int door_state)
2242 return MoveDoor(door_state | DOOR_SET_STATE);
2245 unsigned int MoveDoor(unsigned int door_state)
2247 static int door1 = DOOR_OPEN_1;
2248 static int door2 = DOOR_CLOSE_2;
2249 static unsigned long door_delay = 0;
2250 int x, start, stepsize = 2;
2251 unsigned long door_delay_value = stepsize * 5;
2253 if (door_state == DOOR_GET_STATE)
2254 return(door1 | door2);
2256 if (door_state & DOOR_SET_STATE)
2258 if (door_state & DOOR_ACTION_1)
2259 door1 = door_state & DOOR_ACTION_1;
2260 if (door_state & DOOR_ACTION_2)
2261 door2 = door_state & DOOR_ACTION_2;
2263 return(door1 | door2);
2266 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2267 door_state &= ~DOOR_OPEN_1;
2268 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2269 door_state &= ~DOOR_CLOSE_1;
2270 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2271 door_state &= ~DOOR_OPEN_2;
2272 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2273 door_state &= ~DOOR_CLOSE_2;
2275 if (setup.quick_doors)
2278 door_delay_value = 0;
2280 StopSound(SND_MENU_DOOR_OPENING);
2281 StopSound(SND_MENU_DOOR_CLOSING);
2284 if (global.autoplay_leveldir)
2286 door_state |= DOOR_NO_DELAY;
2287 door_state &= ~DOOR_CLOSE_ALL;
2290 if (door_state & DOOR_ACTION)
2292 if (!(door_state & DOOR_NO_DELAY))
2294 /* opening door sound has priority over simultaneously closing door */
2295 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2296 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2297 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2298 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2301 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2303 for(x=start; x<=DXSIZE; x+=stepsize)
2305 Bitmap *bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2306 GC gc = bitmap->stored_clip_gc;
2308 if (!(door_state & DOOR_NO_DELAY))
2309 WaitUntilDelayReached(&door_delay, door_delay_value);
2311 if (door_state & DOOR_ACTION_1)
2313 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2314 int j = (DXSIZE - i) / 3;
2316 BlitBitmap(bitmap_db_door, drawto,
2317 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2318 DXSIZE,DYSIZE - i/2, DX, DY);
2320 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2322 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2323 BlitBitmapMasked(bitmap, drawto,
2324 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2325 DX + DXSIZE - i, DY + j);
2326 BlitBitmapMasked(bitmap, drawto,
2327 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2328 DX + DXSIZE - i, DY + 140 + j);
2329 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2330 BlitBitmapMasked(bitmap, drawto,
2331 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2333 BlitBitmapMasked(bitmap, drawto,
2334 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2337 BlitBitmapMasked(bitmap, drawto,
2338 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2340 BlitBitmapMasked(bitmap, drawto,
2341 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2343 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2344 BlitBitmapMasked(bitmap, drawto,
2345 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2346 DX + DXSIZE - i, DY + 77 + j);
2347 BlitBitmapMasked(bitmap, drawto,
2348 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2349 DX + DXSIZE - i, DY + 203 + j);
2351 redraw_mask |= REDRAW_DOOR_1;
2354 if (door_state & DOOR_ACTION_2)
2356 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2357 int j = (VXSIZE - i) / 3;
2359 BlitBitmap(bitmap_db_door, drawto,
2360 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2361 VXSIZE, VYSIZE - i/2, VX, VY);
2363 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2365 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2366 BlitBitmapMasked(bitmap, drawto,
2367 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2368 VX + VXSIZE-i, VY+j);
2369 SetClipOrigin(bitmap, gc,
2370 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2371 BlitBitmapMasked(bitmap, drawto,
2372 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2375 BlitBitmapMasked(bitmap, drawto,
2376 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2377 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2378 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2379 BlitBitmapMasked(bitmap, drawto,
2380 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2382 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2384 redraw_mask |= REDRAW_DOOR_2;
2389 if (game_status == MAINMENU)
2394 if (setup.quick_doors)
2396 StopSound(SND_MENU_DOOR_OPENING);
2397 StopSound(SND_MENU_DOOR_CLOSING);
2400 if (door_state & DOOR_ACTION_1)
2401 door1 = door_state & DOOR_ACTION_1;
2402 if (door_state & DOOR_ACTION_2)
2403 door2 = door_state & DOOR_ACTION_2;
2405 return (door1 | door2);
2408 void DrawSpecialEditorDoor()
2410 /* draw bigger toolbox window */
2411 BlitBitmap(new_graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2412 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2414 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2415 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2418 redraw_mask |= REDRAW_ALL;
2421 void UndrawSpecialEditorDoor()
2423 /* draw normal tape recorder window */
2424 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2425 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2428 redraw_mask |= REDRAW_ALL;
2432 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2434 XImage *pixel_image;
2435 unsigned long pixel_value;
2437 pixel_image = XGetImage(display, bitmap->drawable,
2438 x, y, 1, 1, AllPlanes, ZPixmap);
2439 pixel_value = XGetPixel(pixel_image, 0, 0);
2441 XDestroyImage(pixel_image);
2447 /* ---------- new tool button stuff ---------------------------------------- */
2449 /* graphic position values for tool buttons */
2450 #define TOOL_BUTTON_YES_XPOS 2
2451 #define TOOL_BUTTON_YES_YPOS 250
2452 #define TOOL_BUTTON_YES_GFX_YPOS 0
2453 #define TOOL_BUTTON_YES_XSIZE 46
2454 #define TOOL_BUTTON_YES_YSIZE 28
2455 #define TOOL_BUTTON_NO_XPOS 52
2456 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2457 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2458 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2459 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2460 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2461 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2462 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2463 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2464 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2465 #define TOOL_BUTTON_PLAYER_XSIZE 30
2466 #define TOOL_BUTTON_PLAYER_YSIZE 30
2467 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2468 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2469 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2470 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2471 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2472 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2473 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2474 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2475 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2476 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2477 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2478 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2479 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2480 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2481 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2482 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2483 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2484 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2485 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2486 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2495 } toolbutton_info[NUM_TOOL_BUTTONS] =
2498 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2499 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2500 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2505 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2506 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2507 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2512 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2513 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2514 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2515 TOOL_CTRL_ID_CONFIRM,
2519 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2520 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2521 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2522 TOOL_CTRL_ID_PLAYER_1,
2526 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2527 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2528 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2529 TOOL_CTRL_ID_PLAYER_2,
2533 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2534 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2535 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2536 TOOL_CTRL_ID_PLAYER_3,
2540 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2541 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2542 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2543 TOOL_CTRL_ID_PLAYER_4,
2548 void CreateToolButtons()
2552 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2554 Bitmap *gd_bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2555 Bitmap *deco_bitmap = None;
2556 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2557 struct GadgetInfo *gi;
2558 unsigned long event_mask;
2559 int gd_xoffset, gd_yoffset;
2560 int gd_x1, gd_x2, gd_y;
2563 event_mask = GD_EVENT_RELEASED;
2565 gd_xoffset = toolbutton_info[i].xpos;
2566 gd_yoffset = toolbutton_info[i].ypos;
2567 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2568 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2569 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2571 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2573 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2575 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2576 &deco_bitmap, &deco_x, &deco_y);
2577 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2578 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2581 gi = CreateGadget(GDI_CUSTOM_ID, id,
2582 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2583 GDI_X, DX + toolbutton_info[i].x,
2584 GDI_Y, DY + toolbutton_info[i].y,
2585 GDI_WIDTH, toolbutton_info[i].width,
2586 GDI_HEIGHT, toolbutton_info[i].height,
2587 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2588 GDI_STATE, GD_BUTTON_UNPRESSED,
2589 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2590 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2591 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2592 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2593 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2594 GDI_DECORATION_SHIFTING, 1, 1,
2595 GDI_EVENT_MASK, event_mask,
2596 GDI_CALLBACK_ACTION, HandleToolButtons,
2600 Error(ERR_EXIT, "cannot create gadget");
2602 tool_gadget[id] = gi;
2606 void FreeToolButtons()
2610 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2611 FreeGadget(tool_gadget[i]);
2614 static void UnmapToolButtons()
2618 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2619 UnmapGadget(tool_gadget[i]);
2622 static void HandleToolButtons(struct GadgetInfo *gi)
2624 request_gadget_id = gi->custom_id;
2627 int get_next_element(int element)
2631 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2632 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2633 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2634 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2635 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2636 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2637 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2639 default: return element;
2643 int el2gfx_OLD(int element)
2647 case EL_EMPTY: return -1;
2648 case EL_SAND: return GFX_ERDREICH;
2649 case EL_WALL: return GFX_MAUERWERK;
2650 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2651 case EL_ROCK: return GFX_FELSBROCKEN;
2652 case EL_EMERALD: return GFX_EDELSTEIN;
2653 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2654 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2655 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2656 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2657 case EL_PLAYER1: return GFX_SPIELER1;
2658 case EL_PLAYER2: return GFX_SPIELER2;
2659 case EL_PLAYER3: return GFX_SPIELER3;
2660 case EL_PLAYER4: return GFX_SPIELER4;
2661 case EL_BUG: return GFX_KAEFER;
2662 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2663 case EL_BUG_UP: return GFX_KAEFER_UP;
2664 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2665 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2666 case EL_SPACESHIP: return GFX_FLIEGER;
2667 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2668 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2669 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2670 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2671 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2672 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2673 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2674 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2675 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2676 case EL_BD_FIREFLY: return GFX_FIREFLY;
2677 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2678 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2679 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2680 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2681 case EL_YAMYAM: return GFX_MAMPFER;
2682 case EL_ROBOT: return GFX_ROBOT;
2683 case EL_STEELWALL: return GFX_BETON;
2684 case EL_DIAMOND: return GFX_DIAMANT;
2685 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2686 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2687 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2688 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2689 case EL_BOMB: return GFX_BOMBE;
2690 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2691 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2692 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2693 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2694 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2695 case EL_ACID: return GFX_SALZSAEURE;
2696 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2697 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2698 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2699 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2700 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2701 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2702 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2703 case EL_NUT: return GFX_KOKOSNUSS;
2704 case EL_GAMEOFLIFE: return GFX_LIFE;
2705 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2706 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2707 case EL_STONEBLOCK: return GFX_BADEWANNE;
2708 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2709 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2710 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2711 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2712 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2713 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2714 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2715 case EL_KEY1: return GFX_SCHLUESSEL1;
2716 case EL_KEY2: return GFX_SCHLUESSEL2;
2717 case EL_KEY3: return GFX_SCHLUESSEL3;
2718 case EL_KEY4: return GFX_SCHLUESSEL4;
2719 case EL_GATE1: return GFX_PFORTE1;
2720 case EL_GATE2: return GFX_PFORTE2;
2721 case EL_GATE3: return GFX_PFORTE3;
2722 case EL_GATE4: return GFX_PFORTE4;
2723 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2724 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2725 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2726 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2727 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2728 case EL_PACMAN: return GFX_PACMAN;
2729 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2730 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2731 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2732 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2733 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2734 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2735 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2736 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2737 case EL_LAMP: return GFX_BIRNE_AUS;
2738 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2739 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2740 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2741 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2742 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2743 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2744 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2745 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2746 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2747 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2748 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2749 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2750 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2751 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2752 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2753 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2754 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2755 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2756 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2757 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2758 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2759 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2760 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2761 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2762 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2763 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2764 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2765 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2766 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2767 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2768 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2769 case EL_MOLE: return GFX_MOLE;
2770 case EL_PENGUIN: return GFX_PINGUIN;
2771 case EL_PIG: return GFX_SCHWEIN;
2772 case EL_DRAGON: return GFX_DRACHE;
2773 case EL_SATELLITE: return GFX_SONDE;
2774 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2775 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2776 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2777 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2778 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2779 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2780 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2781 case EL_SP_ZONK: return GFX_SP_ZONK;
2782 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2783 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2784 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2785 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2786 case EL_EM_GATE1: return GFX_EM_GATE_1;
2787 case EL_EM_GATE2: return GFX_EM_GATE_2;
2788 case EL_EM_GATE3: return GFX_EM_GATE_3;
2789 case EL_EM_GATE4: return GFX_EM_GATE_4;
2790 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2791 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2792 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2793 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2794 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2795 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2796 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2797 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2798 case EL_EM_KEY1: return GFX_EM_KEY_1;
2799 case EL_EM_KEY2: return GFX_EM_KEY_2;
2800 case EL_EM_KEY3: return GFX_EM_KEY_3;
2801 case EL_EM_KEY4: return GFX_EM_KEY_4;
2802 case EL_PEARL: return GFX_PEARL;
2803 case EL_CRYSTAL: return GFX_CRYSTAL;
2804 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2805 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2806 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2807 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2808 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2809 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2810 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2811 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2812 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2813 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2814 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2815 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2816 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2817 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2818 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2819 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2820 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2821 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2822 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2823 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2824 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2825 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2826 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2827 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2828 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2829 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2830 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2831 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2832 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2833 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2834 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2835 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2836 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2837 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2838 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2839 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2840 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2841 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2842 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2843 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2844 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2845 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2846 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2847 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2848 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2849 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2850 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2851 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2852 case EL_LANDMINE: return GFX_LANDMINE;
2853 case EL_ENVELOPE: return GFX_ENVELOPE;
2854 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2855 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2856 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2857 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2858 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2859 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2860 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2861 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2862 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2863 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2864 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2865 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2866 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2867 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2868 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2869 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2870 case EL_MOLE_UP: return GFX_MOLE_UP;
2871 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2872 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2873 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2874 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2875 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2876 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2877 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2878 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2879 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2880 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2881 case EL_BALLOON: return GFX_BALLOON;
2882 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2883 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2884 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2885 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2886 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2887 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2888 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2889 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2890 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2891 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2892 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2893 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2894 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2895 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2896 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2897 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2898 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2899 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2900 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2901 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2902 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2903 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2904 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2905 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2906 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2907 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2908 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2909 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2910 case EL_SPRING: return GFX_SPRING;
2911 case EL_TRAP: return GFX_TRAP_INACTIVE;
2912 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2913 case EL_BD_WALL: return GFX_BD_WALL;
2914 case EL_BD_ROCK: return GFX_BD_ROCK;
2915 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2916 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2920 if (IS_CHAR(element))
2921 return GFX_CHAR_START + (element - EL_CHAR_START);
2922 else if (element >= EL_SP_START && element <= EL_SP_END)
2924 int nr_element = element - EL_SP_START;
2925 int gfx_per_line = 8;
2927 (nr_element / gfx_per_line) * SP_PER_LINE +
2928 (nr_element % gfx_per_line);
2930 return GFX_START_ROCKSSP + nr_graphic;
2938 int el2gfx(int element)
2941 int graphic_OLD = el2gfx_OLD(element);
2946 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2949 int graphic_OLD = el2gfx_OLD(element);
2951 if (element >= MAX_ELEMENTS)
2953 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2956 if (graphic_NEW != graphic_OLD)
2958 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2959 graphic_NEW, graphic_OLD);
2967 int el2img(int element)
2969 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2973 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2980 int el_dir2img(int element, int direction)
2982 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2985 int el_dir_act2img(int element, int direction, int action)
2990 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
2998 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
3005 action = graphics_action_mapping[action];
3006 direction = MV_DIR_BIT(direction);
3008 return element_info[element].direction_graphic[action][direction];