1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static int getGraphicAnimationPhase(int, int, int);
36 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
38 static void UnmapToolButtons();
39 static void HandleToolButtons(struct GadgetInfo *);
41 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
42 static int request_gadget_id = -1;
44 void SetDrawtoField(int mode)
46 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
57 drawto_field = fieldbuffer;
59 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
70 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
74 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
76 if (game_status == PLAYING)
82 width = gfx.sxsize + 2 * TILEX;
83 height = gfx.sysize + 2 * TILEY;
86 if (force_redraw || setup.direct_draw)
89 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
90 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
92 if (setup.direct_draw)
93 SetDrawtoField(DRAW_BACKBUFFER);
95 for(xx=BX1; xx<=BX2; xx++)
96 for(yy=BY1; yy<=BY2; yy++)
97 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
98 DrawScreenField(xx, yy);
101 if (setup.direct_draw)
102 SetDrawtoField(DRAW_DIRECT);
105 if (setup.soft_scrolling)
107 int fx = FX, fy = FY;
109 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
110 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
112 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
116 BlitBitmap(drawto, window, x, y, width, height, x, y);
122 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
124 if (setup.direct_draw && game_status == PLAYING)
125 redraw_mask &= ~REDRAW_MAIN;
127 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
128 redraw_mask |= REDRAW_FIELD;
130 if (redraw_mask & REDRAW_FIELD)
131 redraw_mask &= ~REDRAW_TILES;
133 if (redraw_mask == REDRAW_NONE)
136 if (global.fps_slowdown && game_status == PLAYING)
138 static boolean last_frame_skipped = FALSE;
139 boolean skip_even_when_not_scrolling = TRUE;
140 boolean just_scrolling = (ScreenMovDir != 0);
141 boolean verbose = FALSE;
143 if (global.fps_slowdown_factor > 1 &&
144 (FrameCounter % global.fps_slowdown_factor) &&
145 (just_scrolling || skip_even_when_not_scrolling))
147 redraw_mask &= ~REDRAW_MAIN;
149 last_frame_skipped = TRUE;
152 printf("FRAME SKIPPED\n");
156 if (last_frame_skipped)
157 redraw_mask |= REDRAW_FIELD;
159 last_frame_skipped = FALSE;
162 printf("frame not skipped\n");
166 /* synchronize X11 graphics at this point; if we would synchronize the
167 display immediately after the buffer switching (after the XFlush),
168 this could mean that we have to wait for the graphics to complete,
169 although we could go on doing calculations for the next frame */
173 if (redraw_mask & REDRAW_ALL)
175 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
179 if (redraw_mask & REDRAW_FIELD)
181 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
183 BlitBitmap(backbuffer, window,
184 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
188 int fx = FX, fy = FY;
190 if (setup.soft_scrolling)
192 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
193 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
196 if (setup.soft_scrolling ||
197 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
198 ABS(ScreenMovPos) == ScrollStepSize ||
199 redraw_tiles > REDRAWTILES_THRESHOLD)
201 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
205 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
207 (setup.soft_scrolling ?
208 "setup.soft_scrolling" :
209 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
210 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
211 ABS(ScreenGfxPos) == ScrollStepSize ?
212 "ABS(ScreenGfxPos) == ScrollStepSize" :
213 "redraw_tiles > REDRAWTILES_THRESHOLD"));
219 redraw_mask &= ~REDRAW_MAIN;
222 if (redraw_mask & REDRAW_DOORS)
224 if (redraw_mask & REDRAW_DOOR_1)
225 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
226 if (redraw_mask & REDRAW_DOOR_2)
228 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
229 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
232 if (redraw_mask & REDRAW_VIDEO_1)
233 BlitBitmap(backbuffer, window,
234 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
235 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
236 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
237 if (redraw_mask & REDRAW_VIDEO_2)
238 BlitBitmap(backbuffer, window,
239 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
240 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
241 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
242 if (redraw_mask & REDRAW_VIDEO_3)
243 BlitBitmap(backbuffer, window,
244 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
245 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
246 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
249 if (redraw_mask & REDRAW_DOOR_3)
250 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
251 redraw_mask &= ~REDRAW_DOORS;
254 if (redraw_mask & REDRAW_MICROLEVEL)
256 BlitBitmap(backbuffer, window,
257 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
258 MICROLEV_XPOS, MICROLEV_YPOS);
259 BlitBitmap(backbuffer, window,
260 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
261 SX, MICROLABEL_YPOS);
262 redraw_mask &= ~REDRAW_MICROLEVEL;
265 if (redraw_mask & REDRAW_TILES)
267 for(x=0; x<SCR_FIELDX; x++)
268 for(y=0; y<SCR_FIELDY; y++)
269 if (redraw[redraw_x1 + x][redraw_y1 + y])
270 BlitBitmap(buffer, window,
271 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
272 SX + x * TILEX, SY + y * TILEY);
275 if (redraw_mask & REDRAW_FPS) /* display frames per second */
280 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
281 if (!global.fps_slowdown)
284 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
285 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
290 for(x=0; x<MAX_BUF_XSIZE; x++)
291 for(y=0; y<MAX_BUF_YSIZE; y++)
294 redraw_mask = REDRAW_NONE;
300 long fading_delay = 300;
302 if (setup.fading && (redraw_mask & REDRAW_FIELD))
309 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
312 for(i=0;i<2*FULL_SYSIZE;i++)
314 for(y=0;y<FULL_SYSIZE;y++)
316 BlitBitmap(backbuffer, window,
317 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
325 for(i=1;i<FULL_SYSIZE;i+=2)
326 BlitBitmap(backbuffer, window,
327 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
333 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
334 BlitBitmapMasked(backbuffer, window,
335 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
340 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
341 BlitBitmapMasked(backbuffer, window,
342 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
347 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
348 BlitBitmapMasked(backbuffer, window,
349 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
354 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
355 BlitBitmapMasked(backbuffer, window,
356 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
361 redraw_mask &= ~REDRAW_MAIN;
370 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
372 if (setup.soft_scrolling && game_status == PLAYING)
374 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
375 SetDrawtoField(DRAW_BUFFERED);
378 SetDrawtoField(DRAW_BACKBUFFER);
380 if (setup.direct_draw && game_status == PLAYING)
382 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
383 SetDrawtoField(DRAW_DIRECT);
386 redraw_mask |= REDRAW_FIELD;
389 void MarkTileDirty(int x, int y)
391 int xx = redraw_x1 + x;
392 int yy = redraw_y1 + y;
397 redraw[xx][yy] = TRUE;
398 redraw_mask |= REDRAW_TILES;
401 void SetBorderElement()
405 BorderElement = EL_LEERRAUM;
407 for(y=0; y<lev_fieldy && BorderElement == EL_LEERRAUM; y++)
409 for(x=0; x<lev_fieldx; x++)
411 if (!IS_MASSIVE(Feld[x][y]))
412 BorderElement = EL_BETON;
414 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
420 void DrawAllPlayers()
424 for(i=0; i<MAX_PLAYERS; i++)
425 if (stored_player[i].active)
426 DrawPlayer(&stored_player[i]);
429 void DrawPlayerField(int x, int y)
431 if (!IS_PLAYER(x, y))
434 DrawPlayer(PLAYERINFO(x, y));
437 void DrawPlayer(struct PlayerInfo *player)
439 int jx = player->jx, jy = player->jy;
440 int last_jx = player->last_jx, last_jy = player->last_jy;
441 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
442 int sx = SCREENX(jx), sy = SCREENY(jy);
443 int sxx = 0, syy = 0;
444 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
446 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
448 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
452 if (!IN_LEV_FIELD(jx,jy))
454 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
455 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
456 printf("DrawPlayerField(): This should never happen!\n");
461 if (element == EL_EXPLODING)
464 /* draw things in the field the player is leaving, if needed */
466 if (player_is_moving)
468 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
470 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
471 if (last_element == EL_DYNAMITE_ACTIVE)
472 DrawDynamite(last_jx, last_jy);
474 DrawLevelFieldThruMask(last_jx, last_jy);
476 else if (last_element == EL_DYNAMITE_ACTIVE)
477 DrawDynamite(last_jx, last_jy);
479 DrawLevelField(last_jx, last_jy);
481 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
485 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
486 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
488 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
491 DrawLevelField(next_jx, next_jy);
495 if (!IN_SCR_FIELD(sx, sy))
498 if (setup.direct_draw)
499 SetDrawtoField(DRAW_BUFFERED);
501 /* draw things behind the player, if needed */
504 DrawLevelElement(jx, jy, Store[jx][jy]);
505 else if (!IS_ACTIVE_BOMB(element))
506 DrawLevelField(jx, jy);
508 DrawLevelElement(jx, jy, EL_LEERRAUM);
510 /* draw player himself */
512 if (game.emulation == EMU_SUPAPLEX)
514 static int last_dir = MV_LEFT;
515 int action = (player->programmed_action ? player->programmed_action :
517 boolean action_moving =
519 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
520 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
522 graphic = GFX_SP_MURPHY;
526 if (player->MovDir == MV_LEFT)
527 graphic = GFX_MURPHY_PUSH_LEFT;
528 else if (player->MovDir == MV_RIGHT)
529 graphic = GFX_MURPHY_PUSH_RIGHT;
530 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
531 graphic = GFX_MURPHY_PUSH_LEFT;
532 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
533 graphic = GFX_MURPHY_PUSH_RIGHT;
535 else if (player->snapped)
537 if (player->MovDir == MV_LEFT)
538 graphic = GFX_MURPHY_SNAP_LEFT;
539 else if (player->MovDir == MV_RIGHT)
540 graphic = GFX_MURPHY_SNAP_RIGHT;
541 else if (player->MovDir == MV_UP)
542 graphic = GFX_MURPHY_SNAP_UP;
543 else if (player->MovDir == MV_DOWN)
544 graphic = GFX_MURPHY_SNAP_DOWN;
546 else if (action_moving)
548 if (player->MovDir == MV_LEFT)
549 graphic = GFX_MURPHY_GO_LEFT;
550 else if (player->MovDir == MV_RIGHT)
551 graphic = GFX_MURPHY_GO_RIGHT;
552 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
553 graphic = GFX_MURPHY_GO_LEFT;
554 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
555 graphic = GFX_MURPHY_GO_RIGHT;
557 graphic = GFX_MURPHY_GO_LEFT;
559 graphic += getGraphicAnimationPhase(3, 2, ANIM_PINGPONG);
562 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
563 last_dir = player->MovDir;
567 if (player->MovDir == MV_LEFT)
569 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
570 else if (player->MovDir == MV_RIGHT)
572 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
573 else if (player->MovDir == MV_UP)
574 graphic = GFX_SPIELER1_UP;
575 else /* MV_DOWN || MV_NO_MOVING */
576 graphic = GFX_SPIELER1_DOWN;
578 graphic += player->index_nr * 3 * HEROES_PER_LINE;
579 graphic += player->Frame;
584 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
585 sxx = player->GfxPos;
587 syy = player->GfxPos;
590 if (!setup.soft_scrolling && ScreenMovPos)
593 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
595 if (SHIELD_ON(player))
597 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
598 GFX2_SHIELD_PASSIVE);
600 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
601 3, 8, ANIM_PINGPONG);
604 if (player->Pushing && player->GfxPos)
606 int px = SCREENX(next_jx), py = SCREENY(next_jy);
608 if (element == EL_SOKOBAN_FELD_LEER ||
609 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
610 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
614 int element = Feld[next_jx][next_jy];
615 int graphic = el2gfx(element);
617 if ((element == EL_FELSBROCKEN ||
618 element == EL_SP_ZONK ||
619 element == EL_BD_ROCK) && sxx)
621 int phase = (player->GfxPos / (TILEX / 4));
623 if (player->MovDir == MV_LEFT)
626 graphic += (phase + 4) % 4;
629 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
633 /* draw things in front of player (active dynamite or dynabombs) */
635 if (IS_ACTIVE_BOMB(element))
637 graphic = el2gfx(element);
639 if (element == EL_DYNAMITE_ACTIVE)
641 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
646 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
650 if (game.emulation == EMU_SUPAPLEX)
651 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
653 DrawGraphicThruMask(sx, sy, graphic + phase);
656 if (player_is_moving && last_element == EL_EXPLODING)
658 int phase = Frame[last_jx][last_jy];
662 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
663 GFX_EXPLOSION + ((phase - 1) / delay - 1));
666 /* draw elements that stay over the player */
667 /* handle the field the player is leaving ... */
668 if (player_is_moving && IS_OVER_PLAYER(last_element))
669 DrawLevelField(last_jx, last_jy);
670 /* ... and the field the player is entering */
671 if (IS_OVER_PLAYER(element))
672 DrawLevelField(jx, jy);
674 if (setup.direct_draw)
676 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
677 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
678 int x_size = TILEX * (1 + ABS(jx - last_jx));
679 int y_size = TILEY * (1 + ABS(jy - last_jy));
681 BlitBitmap(drawto_field, window,
682 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
683 SetDrawtoField(DRAW_DIRECT);
686 MarkTileDirty(sx,sy);
689 static int getGraphicAnimationPhase(int frames, int delay, int mode)
693 if (mode == ANIM_PINGPONG)
695 int max_anim_frames = 2 * frames - 2;
697 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698 phase = (phase < frames ? phase : max_anim_frames - phase);
701 phase = (FrameCounter % (delay * frames)) / delay;
703 if (mode == ANIM_REVERSE)
709 static int getNewGraphicAnimationFrame(int graphic)
711 int frames = new_graphic_info[graphic].anim_frames;
712 int delay = new_graphic_info[graphic].anim_delay;
713 int mode = new_graphic_info[graphic].anim_mode;
716 if (mode == ANIM_PINGPONG)
718 int max_anim_frames = 2 * frames - 2;
720 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
721 phase = (phase < frames ? phase : max_anim_frames - phase);
724 phase = (FrameCounter % (delay * frames)) / delay;
726 if (mode == ANIM_REVERSE)
727 phase = (frames - 1) - phase;
732 void DrawGraphicAnimationExt(int x, int y, int graphic,
733 int frames, int delay, int mode, int mask_mode)
735 int phase = getGraphicAnimationPhase(frames, delay, mode);
737 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
739 if (mask_mode == USE_MASKING)
740 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
742 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
746 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
748 int delay = new_graphic_info[graphic].anim_delay;
750 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
752 int frame = getNewGraphicAnimationFrame(graphic);
754 if (mask_mode == USE_MASKING)
755 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
757 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
761 void DrawGraphicAnimation(int x, int y, int graphic,
762 int frames, int delay, int mode)
764 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
767 void DrawNewGraphicAnimation(int x, int y, int graphic)
769 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
772 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
773 int frames, int delay, int mode)
775 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
778 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
781 int frames, int delay,
784 int phase = getGraphicAnimationPhase(frames, delay, mode);
786 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
789 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
791 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
793 *bitmap = graphic_info[graphic].bitmap;
794 *x = graphic_info[graphic].src_x;
795 *y = graphic_info[graphic].src_y;
797 else if (graphic >= GFX_START_ROCKSELEMENTS &&
798 graphic <= GFX_END_ROCKSELEMENTS)
800 graphic -= GFX_START_ROCKSELEMENTS;
801 *bitmap = pix[PIX_ELEMENTS];
802 *x = (graphic % GFX_PER_LINE) * TILEX;
803 *y = (graphic / GFX_PER_LINE) * TILEY;
805 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
807 graphic -= GFX_START_ROCKSHEROES;
808 *bitmap = pix[PIX_HEROES];
809 *x = (graphic % HEROES_PER_LINE) * TILEX;
810 *y = (graphic / HEROES_PER_LINE) * TILEY;
812 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
814 graphic -= GFX_START_ROCKSSP;
815 *bitmap = pix[PIX_SP];
816 *x = (graphic % SP_PER_LINE) * TILEX;
817 *y = (graphic / SP_PER_LINE) * TILEY;
819 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
821 graphic -= GFX_START_ROCKSDC;
822 *bitmap = pix[PIX_DC];
823 *x = (graphic % DC_PER_LINE) * TILEX;
824 *y = (graphic / DC_PER_LINE) * TILEY;
826 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
828 graphic -= GFX_START_ROCKSMORE;
829 *bitmap = pix[PIX_MORE];
830 *x = (graphic % MORE_PER_LINE) * TILEX;
831 *y = (graphic / MORE_PER_LINE) * TILEY;
833 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
835 graphic -= GFX_START_ROCKSFONT;
836 *bitmap = pix[PIX_FONT_EM];
837 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
838 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
842 *bitmap = pix[PIX_SP];
848 void DrawGraphic(int x, int y, int graphic)
851 if (!IN_SCR_FIELD(x, y))
853 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
854 printf("DrawGraphic(): This should never happen!\n");
859 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
863 void DrawNewGraphic(int x, int y, int graphic, int frame)
866 if (!IN_SCR_FIELD(x, y))
868 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
869 printf("DrawNewGraphic(): This should never happen!\n");
874 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
879 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
884 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
885 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
888 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
891 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
892 int src_x = new_graphic_info[graphic].src_x;
893 int src_y = new_graphic_info[graphic].src_y;
895 if (new_graphic_info[graphic].anim_vertical)
896 src_y += frame * TILEY;
898 src_x += frame * TILEX;
900 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
903 void DrawGraphicThruMask(int x, int y, int graphic)
906 if (!IN_SCR_FIELD(x, y))
908 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
909 printf("DrawGraphicThruMask(): This should never happen!\n");
914 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
918 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
921 if (!IN_SCR_FIELD(x, y))
923 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
924 printf("DrawGraphicThruMask(): This should never happen!\n");
929 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
934 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
941 if (graphic == GFX_LEERRAUM)
944 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
945 drawing_gc = src_bitmap->stored_clip_gc;
947 if (tile_clipmask[tile] != None)
949 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
950 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
951 BlitBitmapMasked(src_bitmap, d,
952 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
958 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
962 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
963 BlitBitmapMasked(src_bitmap, d,
964 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
968 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
969 int graphic, int frame)
971 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
972 GC drawing_gc = src_bitmap->stored_clip_gc;
973 int src_x = new_graphic_info[graphic].src_x;
974 int src_y = new_graphic_info[graphic].src_y;
976 if (new_graphic_info[graphic].anim_vertical)
977 src_y += frame * TILEY;
979 src_x += frame * TILEX;
981 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
982 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
985 void DrawMiniGraphic(int x, int y, int graphic)
987 DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
988 MarkTileDirty(x/2, y/2);
991 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
993 if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
995 graphic -= GFX_START_ROCKSELEMENTS;
996 *bitmap = pix[PIX_ELEMENTS];
997 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
998 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1000 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1002 graphic -= GFX_START_ROCKSSP;
1003 *bitmap = pix[PIX_SP];
1004 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1005 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1007 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1009 graphic -= GFX_START_ROCKSDC;
1010 *bitmap = pix[PIX_DC];
1011 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1012 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1014 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1016 graphic -= GFX_START_ROCKSMORE;
1017 *bitmap = pix[PIX_MORE];
1018 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1019 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1021 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1023 graphic -= GFX_START_ROCKSFONT;
1024 *bitmap = pix[PIX_FONT_EM];
1025 *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1026 *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1030 *bitmap = pix[PIX_SP];
1031 *x = MINI_SP_STARTX;
1032 *y = MINI_SP_STARTY;
1036 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1041 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1042 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1045 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1046 int cut_mode, int mask_mode)
1048 int width = TILEX, height = TILEY;
1050 int src_x, src_y, dest_x, dest_y;
1057 DrawGraphic(x, y, graphic);
1061 if (dx || dy) /* Verschiebung der Grafik? */
1063 if (x < BX1) /* Element kommt von links ins Bild */
1070 else if (x > BX2) /* Element kommt von rechts ins Bild */
1076 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1082 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1084 else if (dx) /* allg. Bewegung in x-Richtung */
1085 MarkTileDirty(x + SIGN(dx), y);
1087 if (y < BY1) /* Element kommt von oben ins Bild */
1089 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1097 else if (y > BY2) /* Element kommt von unten ins Bild */
1103 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1109 else if (dy > 0 && cut_mode == CUT_ABOVE)
1111 if (y == BY2) /* Element unterhalb des Bildes */
1117 MarkTileDirty(x, y + 1);
1118 } /* Element verläßt unten das Bild */
1119 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1121 else if (dy) /* allg. Bewegung in y-Richtung */
1122 MarkTileDirty(x, y + SIGN(dy));
1125 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1126 drawing_gc = src_bitmap->stored_clip_gc;
1131 dest_x = FX + x * TILEX + dx;
1132 dest_y = FY + y * TILEY + dy;
1135 if (!IN_SCR_FIELD(x,y))
1137 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1138 printf("DrawGraphicShifted(): This should never happen!\n");
1143 if (mask_mode == USE_MASKING)
1145 if (tile_clipmask[tile] != None)
1147 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1148 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1149 BlitBitmapMasked(src_bitmap, drawto_field,
1150 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1156 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1160 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1161 BlitBitmapMasked(src_bitmap, drawto_field,
1162 src_x, src_y, width, height, dest_x, dest_y);
1166 BlitBitmap(src_bitmap, drawto_field,
1167 src_x, src_y, width, height, dest_x, dest_y);
1172 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1175 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1178 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1179 int cut_mode, int mask_mode)
1181 int ux = LEVELX(x), uy = LEVELY(y);
1182 int graphic = el2gfx(element);
1183 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1184 int phase4 = phase8 / 2;
1185 int phase2 = phase8 / 4;
1186 int dir = MovDir[ux][uy];
1188 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1190 graphic += 1 * !phase2;
1194 else if (dir == MV_LEFT)
1196 else if (dir == MV_DOWN)
1199 else if (element == EL_SP_SNIKSNAK)
1202 graphic = GFX_SP_SNIKSNAK_LEFT;
1203 else if (dir == MV_RIGHT)
1204 graphic = GFX_SP_SNIKSNAK_RIGHT;
1205 else if (dir == MV_UP)
1206 graphic = GFX_SP_SNIKSNAK_UP;
1208 graphic = GFX_SP_SNIKSNAK_DOWN;
1210 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1212 else if (element == EL_SP_ELECTRON)
1214 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1216 else if (element == EL_MOLE || element == EL_PINGUIN ||
1217 element == EL_SCHWEIN || element == EL_DRACHE)
1220 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1221 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1222 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1223 else if (dir == MV_RIGHT)
1224 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1225 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1226 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1227 else if (dir == MV_UP)
1228 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1229 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1230 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1232 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1233 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1234 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1238 else if (element == EL_SONDE)
1240 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1242 else if (element == EL_SALZSAEURE)
1244 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1246 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1250 else if (element == EL_BALLOON)
1254 else if ((element == EL_FELSBROCKEN ||
1255 element == EL_SP_ZONK ||
1256 element == EL_BD_ROCK ||
1257 element == EL_SP_INFOTRON ||
1261 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1263 if (element == EL_FELSBROCKEN ||
1264 element == EL_SP_ZONK ||
1265 element == EL_BD_ROCK)
1268 graphic += (4 - phase4) % 4;
1269 else if (dir == MV_RIGHT)
1272 graphic += phase2 * 2;
1274 else if (element != EL_SP_INFOTRON)
1278 else if (element == EL_MAGIC_WALL_EMPTY ||
1279 element == EL_MAGIC_WALL_EMPTYING ||
1280 element == EL_MAGIC_WALL_BD_EMPTY ||
1281 element == EL_MAGIC_WALL_BD_EMPTYING ||
1282 element == EL_MAGIC_WALL_FULL ||
1283 element == EL_MAGIC_WALL_BD_FULL)
1285 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1287 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1289 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1290 graphic += (x + 2 * y + 4) % 4;
1292 else if (element == EL_MAUER_LEBT)
1294 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1296 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1297 links_massiv = TRUE;
1298 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1299 rechts_massiv = TRUE;
1301 if (links_massiv && rechts_massiv)
1302 graphic = GFX_MAUERWERK;
1303 else if (links_massiv)
1304 graphic = GFX_MAUER_R;
1305 else if (rechts_massiv)
1306 graphic = GFX_MAUER_L;
1308 else if ((element == EL_INVISIBLE_STEEL ||
1309 element == EL_UNSICHTBAR ||
1310 element == EL_SAND_INVISIBLE) && game.light_time_left)
1312 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1313 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1314 GFX_SAND_INVISIBLE_ON);
1318 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1319 else if (mask_mode == USE_MASKING)
1320 DrawGraphicThruMask(x, y, graphic);
1322 DrawGraphic(x, y, graphic);
1325 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1326 int cut_mode, int mask_mode)
1328 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1329 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1330 cut_mode, mask_mode);
1333 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1336 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1339 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1342 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1345 void DrawScreenElementThruMask(int x, int y, int element)
1347 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1350 void DrawLevelElementThruMask(int x, int y, int element)
1352 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1355 void DrawLevelFieldThruMask(int x, int y)
1357 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1360 void ErdreichAnbroeckeln(int x, int y)
1364 int i, width, height, cx,cy;
1365 int ux = LEVELX(x), uy = LEVELY(y);
1366 int element, graphic;
1368 static int xy[4][2] =
1376 if (!IN_LEV_FIELD(ux, uy))
1379 element = Feld[ux][uy];
1381 if (element == EL_ERDREICH ||
1382 element == EL_LANDMINE ||
1383 element == EL_TRAP_INACTIVE ||
1384 element == EL_TRAP_ACTIVE)
1386 if (!IN_SCR_FIELD(x, y))
1389 graphic = GFX_ERDENRAND;
1391 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1397 uxx = ux + xy[i][0];
1398 uyy = uy + xy[i][1];
1399 if (!IN_LEV_FIELD(uxx, uyy))
1402 element = Feld[uxx][uyy];
1404 if (element == EL_ERDREICH ||
1405 element == EL_LANDMINE ||
1406 element == EL_TRAP_INACTIVE ||
1407 element == EL_TRAP_ACTIVE)
1410 if (i == 1 || i == 2)
1414 cx = (i == 2 ? TILEX - snip : 0);
1422 cy = (i == 3 ? TILEY - snip : 0);
1425 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1426 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1429 MarkTileDirty(x, y);
1433 graphic = GFX_ERDENRAND;
1435 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1439 int xx, yy, uxx, uyy;
1443 uxx = ux + xy[i][0];
1444 uyy = uy + xy[i][1];
1446 if (!IN_LEV_FIELD(uxx, uyy) ||
1447 (Feld[uxx][uyy] != EL_ERDREICH &&
1448 Feld[uxx][uyy] != EL_LANDMINE &&
1449 Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1450 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1451 !IN_SCR_FIELD(xx, yy))
1454 if (i == 1 || i == 2)
1458 cx = (i == 1 ? TILEX - snip : 0);
1466 cy = (i==0 ? TILEY-snip : 0);
1469 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1470 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1472 MarkTileDirty(xx, yy);
1477 void DrawScreenElement(int x, int y, int element)
1479 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1480 ErdreichAnbroeckeln(x, y);
1483 void DrawLevelElement(int x, int y, int element)
1485 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1486 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1489 void DrawScreenField(int x, int y)
1491 int ux = LEVELX(x), uy = LEVELY(y);
1492 int element, content;
1494 if (!IN_LEV_FIELD(ux, uy))
1496 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1497 element = EL_LEERRAUM;
1499 element = BorderElement;
1501 DrawScreenElement(x, y, element);
1505 element = Feld[ux][uy];
1506 content = Store[ux][uy];
1508 if (IS_MOVING(ux, uy))
1510 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1511 boolean cut_mode = NO_CUTTING;
1513 if (element == EL_QUICKSAND_EMPTYING ||
1514 element == EL_MAGIC_WALL_EMPTYING ||
1515 element == EL_MAGIC_WALL_BD_EMPTYING ||
1516 element == EL_AMOEBA_DRIPPING)
1517 cut_mode = CUT_ABOVE;
1518 else if (element == EL_QUICKSAND_FILLING ||
1519 element == EL_MAGIC_WALL_FILLING ||
1520 element == EL_MAGIC_WALL_BD_FILLING)
1521 cut_mode = CUT_BELOW;
1523 if (cut_mode == CUT_ABOVE)
1524 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1526 DrawScreenElement(x, y, EL_LEERRAUM);
1529 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1530 else if (cut_mode == NO_CUTTING)
1531 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1533 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1535 if (content == EL_SALZSAEURE)
1536 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1538 else if (IS_BLOCKED(ux, uy))
1543 boolean cut_mode = NO_CUTTING;
1544 int element_old, content_old;
1546 Blocked2Moving(ux, uy, &oldx, &oldy);
1549 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1550 MovDir[oldx][oldy] == MV_RIGHT);
1552 element_old = Feld[oldx][oldy];
1553 content_old = Store[oldx][oldy];
1555 if (element_old == EL_QUICKSAND_EMPTYING ||
1556 element_old == EL_MAGIC_WALL_EMPTYING ||
1557 element_old == EL_MAGIC_WALL_BD_EMPTYING ||
1558 element_old == EL_AMOEBA_DRIPPING)
1559 cut_mode = CUT_ABOVE;
1561 DrawScreenElement(x, y, EL_LEERRAUM);
1564 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1566 else if (cut_mode == NO_CUTTING)
1567 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1570 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1573 else if (IS_DRAWABLE(element))
1574 DrawScreenElement(x, y, element);
1576 DrawScreenElement(x, y, EL_LEERRAUM);
1579 void DrawLevelField(int x, int y)
1581 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1582 DrawScreenField(SCREENX(x), SCREENY(y));
1583 else if (IS_MOVING(x, y))
1587 Moving2Blocked(x, y, &newx, &newy);
1588 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1589 DrawScreenField(SCREENX(newx), SCREENY(newy));
1591 else if (IS_BLOCKED(x, y))
1595 Blocked2Moving(x, y, &oldx, &oldy);
1596 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1597 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1601 void DrawMiniElement(int x, int y, int element)
1607 DrawMiniGraphic(x, y, -1);
1611 graphic = el2gfx(element);
1612 DrawMiniGraphic(x, y, graphic);
1615 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1617 int x = sx + scroll_x, y = sy + scroll_y;
1619 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1620 DrawMiniElement(sx, sy, EL_LEERRAUM);
1621 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1622 DrawMiniElement(sx, sy, Feld[x][y]);
1625 int steel_type, steel_position;
1628 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1629 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1630 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1631 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1632 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1633 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1636 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1637 steel_position = (x == -1 && y == -1 ? 0 :
1638 x == lev_fieldx && y == -1 ? 1 :
1639 x == -1 && y == lev_fieldy ? 2 :
1640 x == lev_fieldx && y == lev_fieldy ? 3 :
1641 x == -1 || x == lev_fieldx ? 4 :
1642 y == -1 || y == lev_fieldy ? 5 : -1);
1644 if (steel_position != -1)
1645 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1649 void DrawMicroElement(int xpos, int ypos, int element)
1653 if (element == EL_LEERRAUM)
1656 graphic = el2gfx(element);
1658 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1660 graphic -= GFX_START_ROCKSSP;
1661 BlitBitmap(pix[PIX_SP], drawto,
1662 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1663 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1664 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1666 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1668 graphic -= GFX_START_ROCKSDC;
1669 BlitBitmap(pix[PIX_DC], drawto,
1670 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1671 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1672 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1674 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1676 graphic -= GFX_START_ROCKSMORE;
1677 BlitBitmap(pix[PIX_MORE], drawto,
1678 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
1679 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
1680 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1682 else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
1684 graphic -= GFX_CHAR_START;
1685 BlitBitmap(pix[PIX_FONT_EM], drawto,
1686 MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
1687 MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
1688 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1691 BlitBitmap(pix[PIX_ELEMENTS], drawto,
1692 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1693 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1694 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1703 for(x=BX1; x<=BX2; x++)
1704 for(y=BY1; y<=BY2; y++)
1705 DrawScreenField(x, y);
1707 redraw_mask |= REDRAW_FIELD;
1710 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1714 for(x=0; x<size_x; x++)
1715 for(y=0; y<size_y; y++)
1716 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1718 redraw_mask |= REDRAW_FIELD;
1721 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1725 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1727 if (lev_fieldx < STD_LEV_FIELDX)
1728 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1729 if (lev_fieldy < STD_LEV_FIELDY)
1730 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1732 xpos += MICRO_TILEX;
1733 ypos += MICRO_TILEY;
1735 for(x=-1; x<=STD_LEV_FIELDX; x++)
1737 for(y=-1; y<=STD_LEV_FIELDY; y++)
1739 int lx = from_x + x, ly = from_y + y;
1741 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1742 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1744 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1745 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1750 redraw_mask |= REDRAW_MICROLEVEL;
1753 #define MICROLABEL_EMPTY 0
1754 #define MICROLABEL_LEVEL_NAME 1
1755 #define MICROLABEL_CREATED_BY 2
1756 #define MICROLABEL_LEVEL_AUTHOR 3
1757 #define MICROLABEL_IMPORTED_FROM 4
1758 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1760 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1762 static void DrawMicroLevelLabelExt(int mode)
1764 char label_text[MAX_MICROLABEL_SIZE + 1];
1766 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1768 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1769 mode == MICROLABEL_CREATED_BY ? "created by" :
1770 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1771 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1772 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1773 leveldir_current->imported_from : ""),
1774 MAX_MICROLABEL_SIZE);
1775 label_text[MAX_MICROLABEL_SIZE] = '\0';
1777 if (strlen(label_text) > 0)
1779 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1780 int lypos = MICROLABEL_YPOS;
1782 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1785 redraw_mask |= REDRAW_MICROLEVEL;
1788 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1790 static unsigned long scroll_delay = 0;
1791 static unsigned long label_delay = 0;
1792 static int from_x, from_y, scroll_direction;
1793 static int label_state, label_counter;
1797 from_x = from_y = 0;
1798 scroll_direction = MV_RIGHT;
1802 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1803 DrawMicroLevelLabelExt(label_state);
1805 /* initialize delay counters */
1806 DelayReached(&scroll_delay, 0);
1807 DelayReached(&label_delay, 0);
1812 /* scroll micro level, if needed */
1813 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1814 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1816 switch (scroll_direction)
1822 scroll_direction = MV_UP;
1826 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1829 scroll_direction = MV_DOWN;
1836 scroll_direction = MV_RIGHT;
1840 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1843 scroll_direction = MV_LEFT;
1850 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1853 /* redraw micro level label, if needed */
1854 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1855 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1856 strcmp(level.author, leveldir_current->name) != 0 &&
1857 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1859 int max_label_counter = 23;
1861 if (leveldir_current->imported_from != NULL)
1862 max_label_counter += 14;
1864 label_counter = (label_counter + 1) % max_label_counter;
1865 label_state = (label_counter >= 0 && label_counter <= 7 ?
1866 MICROLABEL_LEVEL_NAME :
1867 label_counter >= 9 && label_counter <= 12 ?
1868 MICROLABEL_CREATED_BY :
1869 label_counter >= 14 && label_counter <= 21 ?
1870 MICROLABEL_LEVEL_AUTHOR :
1871 label_counter >= 23 && label_counter <= 26 ?
1872 MICROLABEL_IMPORTED_FROM :
1873 label_counter >= 28 && label_counter <= 35 ?
1874 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1875 DrawMicroLevelLabelExt(label_state);
1879 int REQ_in_range(int x, int y)
1881 if (y > DY+249 && y < DY+278)
1883 if (x > DX+1 && x < DX+48)
1885 else if (x > DX+51 && x < DX+98)
1891 #define MAX_REQUEST_LINES 13
1892 #define MAX_REQUEST_LINE_LEN 7
1894 boolean Request(char *text, unsigned int req_state)
1896 int mx, my, ty, result = -1;
1897 unsigned int old_door_state;
1899 #if defined(PLATFORM_UNIX)
1900 /* pause network game while waiting for request to answer */
1901 if (options.network &&
1902 game_status == PLAYING &&
1903 req_state & REQUEST_WAIT_FOR)
1904 SendToServer_PausePlaying();
1907 old_door_state = GetDoorState();
1911 CloseDoor(DOOR_CLOSE_1);
1913 /* save old door content */
1914 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1915 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1916 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1918 /* clear door drawing field */
1919 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1921 /* write text for request */
1922 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1924 char text_line[MAX_REQUEST_LINE_LEN + 1];
1930 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1933 if (!tc || tc == ' ')
1944 strncpy(text_line, text, tl);
1947 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
1948 text_line, FS_SMALL, FC_YELLOW);
1950 text += tl + (tc == ' ' ? 1 : 0);
1953 if (req_state & REQ_ASK)
1955 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1956 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1958 else if (req_state & REQ_CONFIRM)
1960 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1962 else if (req_state & REQ_PLAYER)
1964 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1965 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1966 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1967 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1970 /* copy request gadgets to door backbuffer */
1971 BlitBitmap(drawto, pix[PIX_DB_DOOR],
1972 DX, DY, DXSIZE, DYSIZE,
1973 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1975 OpenDoor(DOOR_OPEN_1);
1981 if (!(req_state & REQUEST_WAIT_FOR))
1984 if (game_status != MAINMENU)
1987 button_status = MB_RELEASED;
1989 request_gadget_id = -1;
2001 case EVENT_BUTTONPRESS:
2002 case EVENT_BUTTONRELEASE:
2003 case EVENT_MOTIONNOTIFY:
2005 if (event.type == EVENT_MOTIONNOTIFY)
2007 if (!PointerInWindow(window))
2008 continue; /* window and pointer are on different screens */
2013 motion_status = TRUE;
2014 mx = ((MotionEvent *) &event)->x;
2015 my = ((MotionEvent *) &event)->y;
2019 motion_status = FALSE;
2020 mx = ((ButtonEvent *) &event)->x;
2021 my = ((ButtonEvent *) &event)->y;
2022 if (event.type == EVENT_BUTTONPRESS)
2023 button_status = ((ButtonEvent *) &event)->button;
2025 button_status = MB_RELEASED;
2028 /* this sets 'request_gadget_id' */
2029 HandleGadgets(mx, my, button_status);
2031 switch(request_gadget_id)
2033 case TOOL_CTRL_ID_YES:
2036 case TOOL_CTRL_ID_NO:
2039 case TOOL_CTRL_ID_CONFIRM:
2040 result = TRUE | FALSE;
2043 case TOOL_CTRL_ID_PLAYER_1:
2046 case TOOL_CTRL_ID_PLAYER_2:
2049 case TOOL_CTRL_ID_PLAYER_3:
2052 case TOOL_CTRL_ID_PLAYER_4:
2063 case EVENT_KEYPRESS:
2064 switch(GetEventKey((KeyEvent *)&event, TRUE))
2077 if (req_state & REQ_PLAYER)
2081 case EVENT_KEYRELEASE:
2082 ClearPlayerAction();
2086 HandleOtherEvents(&event);
2090 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2092 int joy = AnyJoystick();
2094 if (joy & JOY_BUTTON_1)
2096 else if (joy & JOY_BUTTON_2)
2102 /* don't eat all CPU time */
2106 if (game_status != MAINMENU)
2111 if (!(req_state & REQ_STAY_OPEN))
2113 CloseDoor(DOOR_CLOSE_1);
2115 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2117 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2118 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2119 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2120 OpenDoor(DOOR_OPEN_1);
2126 #if defined(PLATFORM_UNIX)
2127 /* continue network game after request */
2128 if (options.network &&
2129 game_status == PLAYING &&
2130 req_state & REQUEST_WAIT_FOR)
2131 SendToServer_ContinuePlaying();
2137 unsigned int OpenDoor(unsigned int door_state)
2139 unsigned int new_door_state;
2141 if (door_state & DOOR_COPY_BACK)
2143 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2144 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2145 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2146 door_state &= ~DOOR_COPY_BACK;
2149 new_door_state = MoveDoor(door_state);
2151 return(new_door_state);
2154 unsigned int CloseDoor(unsigned int door_state)
2156 unsigned int new_door_state;
2158 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2159 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2160 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2161 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2163 new_door_state = MoveDoor(door_state);
2165 return(new_door_state);
2168 unsigned int GetDoorState()
2170 return MoveDoor(DOOR_GET_STATE);
2173 unsigned int SetDoorState(unsigned int door_state)
2175 return MoveDoor(door_state | DOOR_SET_STATE);
2178 unsigned int MoveDoor(unsigned int door_state)
2180 static int door1 = DOOR_OPEN_1;
2181 static int door2 = DOOR_CLOSE_2;
2182 static unsigned long door_delay = 0;
2183 int x, start, stepsize = 2;
2184 unsigned long door_delay_value = stepsize * 5;
2186 if (door_state == DOOR_GET_STATE)
2187 return(door1 | door2);
2189 if (door_state & DOOR_SET_STATE)
2191 if (door_state & DOOR_ACTION_1)
2192 door1 = door_state & DOOR_ACTION_1;
2193 if (door_state & DOOR_ACTION_2)
2194 door2 = door_state & DOOR_ACTION_2;
2196 return(door1 | door2);
2199 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2200 door_state &= ~DOOR_OPEN_1;
2201 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2202 door_state &= ~DOOR_CLOSE_1;
2203 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2204 door_state &= ~DOOR_OPEN_2;
2205 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2206 door_state &= ~DOOR_CLOSE_2;
2208 if (setup.quick_doors)
2211 door_delay_value = 0;
2212 StopSound(SND_MENU_DOOR_OPENING);
2213 StopSound(SND_MENU_DOOR_CLOSING);
2216 if (door_state & DOOR_ACTION)
2218 if (!(door_state & DOOR_NO_DELAY))
2220 /* opening door sound has priority over simultaneously closing door */
2221 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2222 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2223 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2224 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2227 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2229 for(x=start; x<=DXSIZE; x+=stepsize)
2231 Bitmap *bitmap = pix[PIX_DOOR];
2232 GC gc = bitmap->stored_clip_gc;
2234 WaitUntilDelayReached(&door_delay, door_delay_value);
2236 if (door_state & DOOR_ACTION_1)
2238 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2239 int j = (DXSIZE - i) / 3;
2241 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2242 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2243 DXSIZE,DYSIZE - i/2, DX, DY);
2245 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2247 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2248 BlitBitmapMasked(bitmap, drawto,
2249 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2250 DX + DXSIZE - i, DY + j);
2251 BlitBitmapMasked(bitmap, drawto,
2252 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2253 DX + DXSIZE - i, DY + 140 + j);
2254 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2255 BlitBitmapMasked(bitmap, drawto,
2256 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2258 BlitBitmapMasked(bitmap, drawto,
2259 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2262 BlitBitmapMasked(bitmap, drawto,
2263 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2265 BlitBitmapMasked(bitmap, drawto,
2266 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2268 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2269 BlitBitmapMasked(bitmap, drawto,
2270 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2271 DX + DXSIZE - i, DY + 77 + j);
2272 BlitBitmapMasked(bitmap, drawto,
2273 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2274 DX + DXSIZE - i, DY + 203 + j);
2276 redraw_mask |= REDRAW_DOOR_1;
2279 if (door_state & DOOR_ACTION_2)
2281 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2282 int j = (VXSIZE - i) / 3;
2284 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2285 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2286 VXSIZE, VYSIZE - i/2, VX, VY);
2288 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2290 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2291 BlitBitmapMasked(bitmap, drawto,
2292 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2293 VX + VXSIZE-i, VY+j);
2294 SetClipOrigin(bitmap, gc,
2295 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2296 BlitBitmapMasked(bitmap, drawto,
2297 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2300 BlitBitmapMasked(bitmap, drawto,
2301 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2302 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2303 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2304 BlitBitmapMasked(bitmap, drawto,
2305 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2307 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2309 redraw_mask |= REDRAW_DOOR_2;
2314 if (game_status == MAINMENU)
2319 if (setup.quick_doors)
2321 StopSound(SND_MENU_DOOR_OPENING);
2322 StopSound(SND_MENU_DOOR_CLOSING);
2325 if (door_state & DOOR_ACTION_1)
2326 door1 = door_state & DOOR_ACTION_1;
2327 if (door_state & DOOR_ACTION_2)
2328 door2 = door_state & DOOR_ACTION_2;
2330 return (door1 | door2);
2333 void DrawSpecialEditorDoor()
2335 /* draw bigger toolbox window */
2336 BlitBitmap(pix[PIX_DOOR], drawto,
2337 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2339 redraw_mask |= REDRAW_ALL;
2342 void UndrawSpecialEditorDoor()
2344 /* draw normal tape recorder window */
2345 BlitBitmap(pix[PIX_BACK], drawto,
2346 562, 344, 108, 56, EX - 4, EY - 12);
2348 redraw_mask |= REDRAW_ALL;
2352 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2354 XImage *pixel_image;
2355 unsigned long pixel_value;
2357 pixel_image = XGetImage(display, bitmap->drawable,
2358 x, y, 1, 1, AllPlanes, ZPixmap);
2359 pixel_value = XGetPixel(pixel_image, 0, 0);
2361 XDestroyImage(pixel_image);
2367 /* ---------- new tool button stuff ---------------------------------------- */
2369 /* graphic position values for tool buttons */
2370 #define TOOL_BUTTON_YES_XPOS 2
2371 #define TOOL_BUTTON_YES_YPOS 250
2372 #define TOOL_BUTTON_YES_GFX_YPOS 0
2373 #define TOOL_BUTTON_YES_XSIZE 46
2374 #define TOOL_BUTTON_YES_YSIZE 28
2375 #define TOOL_BUTTON_NO_XPOS 52
2376 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2377 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2378 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2379 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2380 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2381 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2382 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2383 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2384 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2385 #define TOOL_BUTTON_PLAYER_XSIZE 30
2386 #define TOOL_BUTTON_PLAYER_YSIZE 30
2387 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2388 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2389 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2390 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2391 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2392 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2393 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2394 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2395 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2396 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2397 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2398 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2399 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2400 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2401 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2402 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2403 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2404 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2405 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2406 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2415 } toolbutton_info[NUM_TOOL_BUTTONS] =
2418 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2419 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2420 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2425 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2426 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2427 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2432 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2433 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2434 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2435 TOOL_CTRL_ID_CONFIRM,
2439 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2440 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2441 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2442 TOOL_CTRL_ID_PLAYER_1,
2446 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2447 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2448 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2449 TOOL_CTRL_ID_PLAYER_2,
2453 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2454 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2455 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2456 TOOL_CTRL_ID_PLAYER_3,
2460 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2461 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2462 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2463 TOOL_CTRL_ID_PLAYER_4,
2468 void CreateToolButtons()
2472 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2474 Bitmap *gd_bitmap = pix[PIX_DOOR];
2475 Bitmap *deco_bitmap = None;
2476 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2477 struct GadgetInfo *gi;
2478 unsigned long event_mask;
2479 int gd_xoffset, gd_yoffset;
2480 int gd_x1, gd_x2, gd_y;
2483 event_mask = GD_EVENT_RELEASED;
2485 gd_xoffset = toolbutton_info[i].xpos;
2486 gd_yoffset = toolbutton_info[i].ypos;
2487 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2488 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2489 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2491 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2493 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2494 &deco_bitmap, &deco_x, &deco_y);
2495 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2496 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2499 gi = CreateGadget(GDI_CUSTOM_ID, id,
2500 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2501 GDI_X, DX + toolbutton_info[i].x,
2502 GDI_Y, DY + toolbutton_info[i].y,
2503 GDI_WIDTH, toolbutton_info[i].width,
2504 GDI_HEIGHT, toolbutton_info[i].height,
2505 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2506 GDI_STATE, GD_BUTTON_UNPRESSED,
2507 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2508 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2509 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2510 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2511 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2512 GDI_DECORATION_SHIFTING, 1, 1,
2513 GDI_EVENT_MASK, event_mask,
2514 GDI_CALLBACK_ACTION, HandleToolButtons,
2518 Error(ERR_EXIT, "cannot create gadget");
2520 tool_gadget[id] = gi;
2524 static void UnmapToolButtons()
2528 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2529 UnmapGadget(tool_gadget[i]);
2532 static void HandleToolButtons(struct GadgetInfo *gi)
2534 request_gadget_id = gi->custom_id;
2537 int get_next_element(int element)
2541 case EL_QUICKSAND_FILLING: return EL_MORAST_VOLL;
2542 case EL_QUICKSAND_EMPTYING: return EL_MORAST_LEER;
2543 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2544 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_EMPTY;
2545 case EL_MAGIC_WALL_BD_FILLING: return EL_MAGIC_WALL_BD_FULL;
2546 case EL_MAGIC_WALL_BD_EMPTYING: return EL_MAGIC_WALL_BD_EMPTY;
2547 case EL_AMOEBA_DRIPPING: return EL_AMOEBE_NASS;
2549 default: return element;
2553 int el2gfx_OLD(int element)
2557 case EL_LEERRAUM: return -1;
2558 case EL_ERDREICH: return GFX_ERDREICH;
2559 case EL_MAUERWERK: return GFX_MAUERWERK;
2560 case EL_FELSBODEN: return GFX_FELSBODEN;
2561 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2562 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2563 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2564 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2565 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2566 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2567 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2568 case EL_SPIELER1: return GFX_SPIELER1;
2569 case EL_SPIELER2: return GFX_SPIELER2;
2570 case EL_SPIELER3: return GFX_SPIELER3;
2571 case EL_SPIELER4: return GFX_SPIELER4;
2572 case EL_KAEFER: return GFX_KAEFER;
2573 case EL_KAEFER_RIGHT: return GFX_KAEFER_RIGHT;
2574 case EL_KAEFER_UP: return GFX_KAEFER_UP;
2575 case EL_KAEFER_LEFT: return GFX_KAEFER_LEFT;
2576 case EL_KAEFER_DOWN: return GFX_KAEFER_DOWN;
2577 case EL_FLIEGER: return GFX_FLIEGER;
2578 case EL_FLIEGER_RIGHT: return GFX_FLIEGER_RIGHT;
2579 case EL_FLIEGER_UP: return GFX_FLIEGER_UP;
2580 case EL_FLIEGER_LEFT: return GFX_FLIEGER_LEFT;
2581 case EL_FLIEGER_DOWN: return GFX_FLIEGER_DOWN;
2582 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2583 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2584 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2585 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2586 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2587 case EL_FIREFLY: return GFX_FIREFLY;
2588 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2589 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
2590 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2591 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2592 case EL_MAMPFER: return GFX_MAMPFER;
2593 case EL_ROBOT: return GFX_ROBOT;
2594 case EL_BETON: return GFX_BETON;
2595 case EL_DIAMANT: return GFX_DIAMANT;
2596 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2597 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2598 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2599 case EL_TROPFEN: return GFX_TROPFEN;
2600 case EL_BOMBE: return GFX_BOMBE;
2601 case EL_MAGIC_WALL_OFF: return GFX_MAGIC_WALL_OFF;
2602 case EL_MAGIC_WALL_EMPTY: return GFX_MAGIC_WALL_EMPTY;
2603 case EL_MAGIC_WALL_EMPTYING:return GFX_MAGIC_WALL_EMPTY;
2604 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2605 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2606 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2607 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2608 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2609 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2610 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2611 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2612 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2613 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2614 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2615 case EL_LIFE: return GFX_LIFE;
2616 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2617 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2618 case EL_BADEWANNE: return GFX_BADEWANNE;
2619 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2620 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2621 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2622 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2623 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2624 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2625 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2626 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2627 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2628 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2629 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2630 case EL_PFORTE1: return GFX_PFORTE1;
2631 case EL_PFORTE2: return GFX_PFORTE2;
2632 case EL_PFORTE3: return GFX_PFORTE3;
2633 case EL_PFORTE4: return GFX_PFORTE4;
2634 case EL_PFORTE1X: return GFX_PFORTE1X;
2635 case EL_PFORTE2X: return GFX_PFORTE2X;
2636 case EL_PFORTE3X: return GFX_PFORTE3X;
2637 case EL_PFORTE4X: return GFX_PFORTE4X;
2638 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2639 case EL_PACMAN: return GFX_PACMAN;
2640 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2641 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2642 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2643 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2644 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2645 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2646 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2647 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2648 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2649 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2650 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2651 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2652 case EL_MAUER_X: return GFX_MAUER_X;
2653 case EL_MAUER_Y: return GFX_MAUER_Y;
2654 case EL_MAUER_XY: return GFX_MAUER_XY;
2655 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2656 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2657 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2658 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2659 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2660 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2661 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2662 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2663 case EL_MAMPFER2: return GFX_MAMPFER2;
2664 case EL_MAGIC_WALL_BD_OFF: return GFX_MAGIC_WALL_BD_OFF;
2665 case EL_MAGIC_WALL_BD_EMPTY:return GFX_MAGIC_WALL_BD_EMPTY;
2666 case EL_MAGIC_WALL_BD_EMPTYING:return GFX_MAGIC_WALL_BD_EMPTY;
2667 case EL_MAGIC_WALL_BD_FULL: return GFX_MAGIC_WALL_BD_FULL;
2668 case EL_MAGIC_WALL_BD_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2669 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2670 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2671 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2672 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2673 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2674 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2675 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2676 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2677 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2678 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2679 case EL_MOLE: return GFX_MOLE;
2680 case EL_PINGUIN: return GFX_PINGUIN;
2681 case EL_SCHWEIN: return GFX_SCHWEIN;
2682 case EL_DRACHE: return GFX_DRACHE;
2683 case EL_SONDE: return GFX_SONDE;
2684 case EL_PFEIL_LEFT: return GFX_PFEIL_LEFT;
2685 case EL_PFEIL_RIGHT: return GFX_PFEIL_RIGHT;
2686 case EL_PFEIL_UP: return GFX_PFEIL_UP;
2687 case EL_PFEIL_DOWN: return GFX_PFEIL_DOWN;
2688 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2689 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2690 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2691 case EL_SP_ZONK: return GFX_SP_ZONK;
2692 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2693 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2694 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2695 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2696 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2697 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2698 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2699 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2700 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2701 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2702 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2703 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2704 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2705 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2706 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2707 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2708 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2709 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2710 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2711 case EL_PEARL: return GFX_PEARL;
2712 case EL_CRYSTAL: return GFX_CRYSTAL;
2713 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2714 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2715 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2716 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2717 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2718 case EL_SHIELD_PASSIVE: return GFX_SHIELD_PASSIVE;
2719 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
2720 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2721 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2722 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2723 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2724 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2725 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2726 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2727 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2728 case EL_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2729 case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2730 case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2731 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2732 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2733 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2734 case EL_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2735 case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2736 case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2737 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2738 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2739 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2740 case EL_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2741 case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2742 case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2743 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2744 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2745 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2746 case EL_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2747 case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2748 case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2749 case EL_LANDMINE: return GFX_LANDMINE;
2750 case EL_ENVELOPE: return GFX_ENVELOPE;
2751 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2752 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2753 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2754 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2755 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2756 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2757 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2758 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2759 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2760 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2761 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2762 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2763 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2764 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2765 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2766 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2767 case EL_MOLE_UP: return GFX_MOLE_UP;
2768 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2769 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2770 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2771 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2772 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2773 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2774 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2775 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2776 case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2777 case EL_BALLOON: return GFX_BALLOON;
2778 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2779 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2780 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2781 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2782 case EL_BALLOON_SEND_ANY: return GFX_BALLOON_SEND_ANY;
2783 case EL_EMC_STEEL_WALL_1: return GFX_EMC_STEEL_WALL_1;
2784 case EL_EMC_STEEL_WALL_2: return GFX_EMC_STEEL_WALL_2;
2785 case EL_EMC_STEEL_WALL_3: return GFX_EMC_STEEL_WALL_3;
2786 case EL_EMC_STEEL_WALL_4: return GFX_EMC_STEEL_WALL_4;
2787 case EL_EMC_WALL_1: return GFX_EMC_WALL_1;
2788 case EL_EMC_WALL_2: return GFX_EMC_WALL_2;
2789 case EL_EMC_WALL_3: return GFX_EMC_WALL_3;
2790 case EL_EMC_WALL_4: return GFX_EMC_WALL_4;
2791 case EL_EMC_WALL_5: return GFX_EMC_WALL_5;
2792 case EL_EMC_WALL_6: return GFX_EMC_WALL_6;
2793 case EL_EMC_WALL_7: return GFX_EMC_WALL_7;
2794 case EL_EMC_WALL_8: return GFX_EMC_WALL_8;
2795 case EL_TUBE_CROSS: return GFX_TUBE_CROSS;
2796 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2797 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2798 case EL_TUBE_VERT_LEFT: return GFX_TUBE_VERT_LEFT;
2799 case EL_TUBE_VERT_RIGHT: return GFX_TUBE_VERT_RIGHT;
2800 case EL_TUBE_HORIZ_UP: return GFX_TUBE_HORIZ_UP;
2801 case EL_TUBE_HORIZ_DOWN: return GFX_TUBE_HORIZ_DOWN;
2802 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2803 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2804 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2805 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2806 case EL_SPRING: return GFX_SPRING;
2807 case EL_SPRING_MOVING: return GFX_SPRING;
2808 case EL_TRAP_INACTIVE: return GFX_TRAP_INACTIVE;
2809 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2810 case EL_BD_WALL: return GFX_BD_WALL;
2811 case EL_BD_ROCK: return GFX_BD_ROCK;
2812 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2813 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2817 if (IS_CHAR(element))
2818 return GFX_CHAR_START + (element - EL_CHAR_START);
2819 else if (element >= EL_SP_START && element <= EL_SP_END)
2821 int nr_element = element - EL_SP_START;
2822 int gfx_per_line = 8;
2824 (nr_element / gfx_per_line) * SP_PER_LINE +
2825 (nr_element % gfx_per_line);
2827 return GFX_START_ROCKSSP + nr_graphic;
2835 int el2gfx(int element)
2837 int graphic_NEW = element_info[element].graphic;
2840 int graphic_OLD = el2gfx_OLD(element);
2842 if (element >= MAX_ELEMENTS)
2844 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2847 if (graphic_NEW != graphic_OLD)
2849 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2850 graphic_NEW, graphic_OLD);