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_EMPTY;
407 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
409 for(x=0; x<lev_fieldx; x++)
411 if (!IS_MASSIVE(Feld[x][y]))
412 BorderElement = EL_STEELWALL;
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_EMPTY);
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_EMPTY);
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_ROCK ||
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, int sync_frame)
711 int num_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 /* animation synchronized with global frame counter, not move position */
717 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
718 sync_frame = FrameCounter;
720 if (mode & ANIM_PINGPONG) /* use border frames once */
722 int max_anim_frames = 2 * num_frames - 2;
724 frame = (sync_frame % (delay * max_anim_frames)) / delay;
725 frame = (frame < num_frames ? frame : max_anim_frames - frame);
727 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
729 int max_anim_frames = 2 * num_frames;
731 frame = (sync_frame % (delay * max_anim_frames)) / delay;
732 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
734 else /* mode == ANIM_NORMAL || mode == ANIM_REVERSE */
735 frame = (sync_frame % (delay * num_frames)) / delay;
737 if (mode & ANIM_REVERSE) /* use reverse animation direction */
738 frame = num_frames - frame - 1;
743 void DrawGraphicAnimationExt(int x, int y, int graphic,
744 int frames, int delay, int mode, int mask_mode)
746 int phase = getGraphicAnimationPhase(frames, delay, mode);
748 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
750 if (mask_mode == USE_MASKING)
751 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
753 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
757 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
759 int delay = new_graphic_info[graphic].anim_delay;
761 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
763 int frame = getNewGraphicAnimationFrame(graphic, -1);
765 if (mask_mode == USE_MASKING)
766 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
768 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
772 void DrawGraphicAnimation(int x, int y, int graphic,
773 int frames, int delay, int mode)
775 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
778 void DrawNewGraphicAnimation(int x, int y, int graphic)
780 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
783 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
784 int frames, int delay, int mode)
786 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
789 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
792 int frames, int delay,
795 int phase = getGraphicAnimationPhase(frames, delay, mode);
797 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
800 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
802 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
804 *bitmap = graphic_info[graphic].bitmap;
805 *x = graphic_info[graphic].src_x;
806 *y = graphic_info[graphic].src_y;
808 else if (graphic >= GFX_START_ROCKSELEMENTS &&
809 graphic <= GFX_END_ROCKSELEMENTS)
811 graphic -= GFX_START_ROCKSELEMENTS;
812 *bitmap = pix[PIX_ELEMENTS];
813 *x = (graphic % GFX_PER_LINE) * TILEX;
814 *y = (graphic / GFX_PER_LINE) * TILEY;
816 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
818 graphic -= GFX_START_ROCKSHEROES;
819 *bitmap = pix[PIX_HEROES];
820 *x = (graphic % HEROES_PER_LINE) * TILEX;
821 *y = (graphic / HEROES_PER_LINE) * TILEY;
823 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
825 graphic -= GFX_START_ROCKSSP;
826 *bitmap = pix[PIX_SP];
827 *x = (graphic % SP_PER_LINE) * TILEX;
828 *y = (graphic / SP_PER_LINE) * TILEY;
830 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
832 graphic -= GFX_START_ROCKSDC;
833 *bitmap = pix[PIX_DC];
834 *x = (graphic % DC_PER_LINE) * TILEX;
835 *y = (graphic / DC_PER_LINE) * TILEY;
837 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
839 graphic -= GFX_START_ROCKSMORE;
840 *bitmap = pix[PIX_MORE];
841 *x = (graphic % MORE_PER_LINE) * TILEX;
842 *y = (graphic / MORE_PER_LINE) * TILEY;
844 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
846 graphic -= GFX_START_ROCKSFONT;
847 *bitmap = pix[PIX_FONT_EM];
848 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
849 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
853 *bitmap = pix[PIX_SP];
859 void DrawGraphic(int x, int y, int graphic)
862 if (!IN_SCR_FIELD(x, y))
864 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
865 printf("DrawGraphic(): This should never happen!\n");
870 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
874 void DrawNewGraphic(int x, int y, int graphic, int frame)
877 if (!IN_SCR_FIELD(x, y))
879 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
880 printf("DrawNewGraphic(): This should never happen!\n");
885 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
890 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
895 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
896 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
899 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
902 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
903 int src_x = new_graphic_info[graphic].src_x;
904 int src_y = new_graphic_info[graphic].src_y;
906 if (new_graphic_info[graphic].anim_vertical)
907 src_y += frame * TILEY;
909 src_x += frame * TILEX;
911 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
914 void DrawGraphicThruMask(int x, int y, int graphic)
917 if (!IN_SCR_FIELD(x, y))
919 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
920 printf("DrawGraphicThruMask(): This should never happen!\n");
925 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
929 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
932 if (!IN_SCR_FIELD(x, y))
934 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
935 printf("DrawGraphicThruMask(): This should never happen!\n");
940 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
945 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
952 if (graphic == GFX_LEERRAUM)
955 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
956 drawing_gc = src_bitmap->stored_clip_gc;
958 if (tile_clipmask[tile] != None)
960 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
961 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
962 BlitBitmapMasked(src_bitmap, d,
963 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
969 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
973 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
974 BlitBitmapMasked(src_bitmap, d,
975 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
979 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
980 int graphic, int frame)
982 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
983 GC drawing_gc = src_bitmap->stored_clip_gc;
984 int src_x = new_graphic_info[graphic].src_x;
985 int src_y = new_graphic_info[graphic].src_y;
987 if (new_graphic_info[graphic].anim_vertical)
988 src_y += frame * TILEY;
990 src_x += frame * TILEX;
992 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
993 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
996 void DrawMiniGraphic(int x, int y, int graphic)
998 DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
999 MarkTileDirty(x/2, y/2);
1002 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1004 if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1006 graphic -= GFX_START_ROCKSELEMENTS;
1007 *bitmap = pix[PIX_ELEMENTS];
1008 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1009 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1011 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1013 graphic -= GFX_START_ROCKSSP;
1014 *bitmap = pix[PIX_SP];
1015 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1016 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1018 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1020 graphic -= GFX_START_ROCKSDC;
1021 *bitmap = pix[PIX_DC];
1022 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1023 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1025 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1027 graphic -= GFX_START_ROCKSMORE;
1028 *bitmap = pix[PIX_MORE];
1029 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1030 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1032 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1034 graphic -= GFX_START_ROCKSFONT;
1035 *bitmap = pix[PIX_FONT_EM];
1036 *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1037 *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1041 *bitmap = pix[PIX_SP];
1042 *x = MINI_SP_STARTX;
1043 *y = MINI_SP_STARTY;
1047 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1052 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1053 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1056 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1057 int cut_mode, int mask_mode)
1059 int width = TILEX, height = TILEY;
1061 int src_x, src_y, dest_x, dest_y;
1068 DrawGraphic(x, y, graphic);
1072 if (dx || dy) /* Verschiebung der Grafik? */
1074 if (x < BX1) /* Element kommt von links ins Bild */
1081 else if (x > BX2) /* Element kommt von rechts ins Bild */
1087 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1093 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1095 else if (dx) /* allg. Bewegung in x-Richtung */
1096 MarkTileDirty(x + SIGN(dx), y);
1098 if (y < BY1) /* Element kommt von oben ins Bild */
1100 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1108 else if (y > BY2) /* Element kommt von unten ins Bild */
1114 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1120 else if (dy > 0 && cut_mode == CUT_ABOVE)
1122 if (y == BY2) /* Element unterhalb des Bildes */
1128 MarkTileDirty(x, y + 1);
1129 } /* Element verläßt unten das Bild */
1130 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1132 else if (dy) /* allg. Bewegung in y-Richtung */
1133 MarkTileDirty(x, y + SIGN(dy));
1136 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1137 drawing_gc = src_bitmap->stored_clip_gc;
1142 dest_x = FX + x * TILEX + dx;
1143 dest_y = FY + y * TILEY + dy;
1146 if (!IN_SCR_FIELD(x,y))
1148 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1149 printf("DrawGraphicShifted(): This should never happen!\n");
1154 if (mask_mode == USE_MASKING)
1156 if (tile_clipmask[tile] != None)
1158 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1159 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1160 BlitBitmapMasked(src_bitmap, drawto_field,
1161 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1167 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1171 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1172 BlitBitmapMasked(src_bitmap, drawto_field,
1173 src_x, src_y, width, height, dest_x, dest_y);
1177 BlitBitmap(src_bitmap, drawto_field,
1178 src_x, src_y, width, height, dest_x, dest_y);
1183 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1184 int cut_mode, int mask_mode)
1191 int width = TILEX, height = TILEY;
1197 DrawNewGraphic(x, y, graphic, frame);
1201 if (dx || dy) /* Verschiebung der Grafik? */
1203 if (x < BX1) /* Element kommt von links ins Bild */
1210 else if (x > BX2) /* Element kommt von rechts ins Bild */
1216 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1222 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1224 else if (dx) /* allg. Bewegung in x-Richtung */
1225 MarkTileDirty(x + SIGN(dx), y);
1227 if (y < BY1) /* Element kommt von oben ins Bild */
1229 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1237 else if (y > BY2) /* Element kommt von unten ins Bild */
1243 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1249 else if (dy > 0 && cut_mode == CUT_ABOVE)
1251 if (y == BY2) /* Element unterhalb des Bildes */
1257 MarkTileDirty(x, y + 1);
1258 } /* Element verläßt unten das Bild */
1259 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1261 else if (dy) /* allg. Bewegung in y-Richtung */
1262 MarkTileDirty(x, y + SIGN(dy));
1265 src_bitmap = new_graphic_info[graphic].bitmap;
1266 drawing_gc = src_bitmap->stored_clip_gc;
1267 src_x = new_graphic_info[graphic].src_x;
1268 src_y = new_graphic_info[graphic].src_y;
1270 if (new_graphic_info[graphic].anim_vertical)
1271 src_y += frame * TILEY;
1273 src_x += frame * TILEX;
1278 dest_x = FX + x * TILEX + dx;
1279 dest_y = FY + y * TILEY + dy;
1282 if (!IN_SCR_FIELD(x,y))
1284 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1285 printf("DrawGraphicShifted(): This should never happen!\n");
1290 if (mask_mode == USE_MASKING)
1291 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1293 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1299 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1302 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1305 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1306 int frame, int cut_mode)
1308 DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1311 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1312 int cut_mode, int mask_mode)
1314 int ux = LEVELX(x), uy = LEVELY(y);
1315 int graphic = el2gfx(element);
1316 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1317 int phase4 = phase8 / 2;
1318 int phase2 = phase8 / 4;
1319 int dir = MovDir[ux][uy];
1321 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1323 graphic += 1 * !phase2;
1327 else if (dir == MV_LEFT)
1329 else if (dir == MV_DOWN)
1332 else if (element == EL_SP_SNIKSNAK)
1335 graphic = GFX_SP_SNIKSNAK_LEFT;
1336 else if (dir == MV_RIGHT)
1337 graphic = GFX_SP_SNIKSNAK_RIGHT;
1338 else if (dir == MV_UP)
1339 graphic = GFX_SP_SNIKSNAK_UP;
1341 graphic = GFX_SP_SNIKSNAK_DOWN;
1343 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1345 else if (element == EL_SP_ELECTRON)
1347 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1349 else if (element == EL_MOLE || element == EL_PENGUIN ||
1350 element == EL_PIG || element == EL_DRAGON)
1353 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1354 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1355 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1356 else if (dir == MV_RIGHT)
1357 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1358 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1359 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1360 else if (dir == MV_UP)
1361 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1362 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1363 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1365 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1366 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1367 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1371 else if (element == EL_SATELLITE)
1373 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1375 else if (element == EL_ACID)
1377 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1379 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1383 else if (element == EL_BALLOON)
1387 else if ((element == EL_ROCK ||
1388 element == EL_SP_ZONK ||
1389 element == EL_BD_ROCK ||
1390 element == EL_SP_INFOTRON ||
1394 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1396 if (element == EL_ROCK ||
1397 element == EL_SP_ZONK ||
1398 element == EL_BD_ROCK)
1401 graphic += (4 - phase4) % 4;
1402 else if (dir == MV_RIGHT)
1405 graphic += phase2 * 2;
1407 else if (element != EL_SP_INFOTRON)
1411 else if (element == EL_MAGIC_WALL_EMPTY ||
1412 element == EL_MAGIC_WALL_EMPTYING ||
1413 element == EL_MAGIC_WALL_BD_EMPTY ||
1414 element == EL_MAGIC_WALL_BD_EMPTYING ||
1415 element == EL_MAGIC_WALL_FULL ||
1416 element == EL_MAGIC_WALL_BD_FULL)
1418 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1420 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1422 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1423 graphic += (x + 2 * y + 4) % 4;
1425 else if (element == EL_WALL_GROWING)
1427 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1429 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1430 links_massiv = TRUE;
1431 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1432 rechts_massiv = TRUE;
1434 if (links_massiv && rechts_massiv)
1435 graphic = GFX_MAUERWERK;
1436 else if (links_massiv)
1437 graphic = GFX_MAUER_R;
1438 else if (rechts_massiv)
1439 graphic = GFX_MAUER_L;
1441 else if ((element == EL_INVISIBLE_STEELWALL ||
1442 element == EL_INVISIBLE_WALL ||
1443 element == EL_SAND_INVISIBLE) && game.light_time_left)
1445 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1446 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1447 GFX_SAND_INVISIBLE_ON);
1451 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1452 else if (mask_mode == USE_MASKING)
1453 DrawGraphicThruMask(x, y, graphic);
1455 DrawGraphic(x, y, graphic);
1458 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1459 int cut_mode, int mask_mode)
1461 int ux = LEVELX(x), uy = LEVELY(y);
1462 int move_dir = MovDir[ux][uy];
1463 int move_pos = ABS(MovPos[ux][uy]) / (TILEX / 8);
1464 int graphic = el_dir2img(element, move_dir);
1465 int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1466 int phase8 = move_pos;
1467 int phase4 = phase8 / 2;
1468 int phase2 = phase8 / 4;
1470 int dir = move_dir; /* !!! THROW AWAY LATER !!! */
1477 else if (element == EL_PACMAN || element == EL_BUG ||
1478 element == EL_SPACESHIP)
1480 graphic += 1 * !phase2;
1484 else if (dir == MV_LEFT)
1486 else if (dir == MV_DOWN)
1489 else if (element == EL_SP_SNIKSNAK)
1492 graphic = GFX_SP_SNIKSNAK_LEFT;
1493 else if (dir == MV_RIGHT)
1494 graphic = GFX_SP_SNIKSNAK_RIGHT;
1495 else if (dir == MV_UP)
1496 graphic = GFX_SP_SNIKSNAK_UP;
1498 graphic = GFX_SP_SNIKSNAK_DOWN;
1500 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1502 else if (element == EL_SP_ELECTRON)
1504 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1507 else if (element == EL_MOLE || element == EL_PENGUIN ||
1508 element == EL_PIG || element == EL_DRAGON)
1511 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1512 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1513 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1514 else if (dir == MV_RIGHT)
1515 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1516 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1517 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1518 else if (dir == MV_UP)
1519 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1520 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1521 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1523 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1524 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1525 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1529 else if (element == EL_SATELLITE)
1532 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1534 graphic = GFX_SONDE_START + getNewGraphicAnimationFrame(graphic, move_pos);
1537 else if (element == EL_ACID)
1540 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1542 graphic = GFX_GEBLUBBER + getNewGraphicAnimationFrame(graphic, move_pos);
1545 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1549 else if (element == EL_BALLOON)
1553 else if ((element == EL_ROCK ||
1554 element == EL_SP_ZONK ||
1555 element == EL_BD_ROCK ||
1556 element == EL_SP_INFOTRON ||
1560 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1562 if (element == EL_ROCK ||
1563 element == EL_SP_ZONK ||
1564 element == EL_BD_ROCK)
1567 graphic += (4 - phase4) % 4;
1568 else if (dir == MV_RIGHT)
1571 graphic += phase2 * 2;
1573 else if (element != EL_SP_INFOTRON)
1577 else if (element == EL_MAGIC_WALL_EMPTY ||
1578 element == EL_MAGIC_WALL_EMPTYING ||
1579 element == EL_MAGIC_WALL_BD_EMPTY ||
1580 element == EL_MAGIC_WALL_BD_EMPTYING ||
1581 element == EL_MAGIC_WALL_FULL ||
1582 element == EL_MAGIC_WALL_BD_FULL)
1585 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1587 graphic += 3 + getNewGraphicAnimationFrame(graphic, move_pos);
1590 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1592 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1593 graphic += (x + 2 * y + 4) % 4;
1595 else if (element == EL_WALL_GROWING)
1597 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1599 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1600 links_massiv = TRUE;
1601 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1602 rechts_massiv = TRUE;
1604 if (links_massiv && rechts_massiv)
1605 graphic = GFX_MAUERWERK;
1606 else if (links_massiv)
1607 graphic = GFX_MAUER_R;
1608 else if (rechts_massiv)
1609 graphic = GFX_MAUER_L;
1611 else if ((element == EL_INVISIBLE_STEELWALL ||
1612 element == EL_INVISIBLE_WALL ||
1613 element == EL_SAND_INVISIBLE) && game.light_time_left)
1615 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1616 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1617 GFX_SAND_INVISIBLE_ON);
1621 DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1622 else if (mask_mode == USE_MASKING)
1623 DrawNewGraphicThruMask(x, y, graphic, frame);
1625 DrawNewGraphic(x, y, graphic, frame);
1628 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1629 int cut_mode, int mask_mode)
1631 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1632 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1633 cut_mode, mask_mode);
1636 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1637 int cut_mode, int mask_mode)
1639 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1640 DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1641 cut_mode, mask_mode);
1644 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1647 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1650 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1653 DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1656 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1659 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1662 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1665 DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1668 void DrawScreenElementThruMask(int x, int y, int element)
1670 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1673 void DrawNewScreenElementThruMask(int x, int y, int element)
1675 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1678 void DrawLevelElementThruMask(int x, int y, int element)
1680 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1683 void DrawNewLevelElementThruMask(int x, int y, int element)
1685 DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1688 void DrawLevelFieldThruMask(int x, int y)
1690 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1693 void DrawNewLevelFieldThruMask(int x, int y)
1695 DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1698 void ErdreichAnbroeckeln(int x, int y)
1702 int i, width, height, cx,cy;
1703 int ux = LEVELX(x), uy = LEVELY(y);
1704 int element, graphic;
1706 static int xy[4][2] =
1714 if (!IN_LEV_FIELD(ux, uy))
1717 element = Feld[ux][uy];
1719 if (element == EL_SAND ||
1720 element == EL_LANDMINE ||
1721 element == EL_TRAP_INACTIVE ||
1722 element == EL_TRAP_ACTIVE)
1724 if (!IN_SCR_FIELD(x, y))
1727 graphic = GFX_ERDENRAND;
1729 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1735 uxx = ux + xy[i][0];
1736 uyy = uy + xy[i][1];
1737 if (!IN_LEV_FIELD(uxx, uyy))
1738 element = EL_STEELWALL;
1740 element = Feld[uxx][uyy];
1742 if (element == EL_SAND ||
1743 element == EL_LANDMINE ||
1744 element == EL_TRAP_INACTIVE ||
1745 element == EL_TRAP_ACTIVE)
1748 if (i == 1 || i == 2)
1752 cx = (i == 2 ? TILEX - snip : 0);
1760 cy = (i == 3 ? TILEY - snip : 0);
1763 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1764 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1767 MarkTileDirty(x, y);
1771 graphic = GFX_ERDENRAND;
1773 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1777 int xx, yy, uxx, uyy;
1781 uxx = ux + xy[i][0];
1782 uyy = uy + xy[i][1];
1784 if (!IN_LEV_FIELD(uxx, uyy) ||
1785 (Feld[uxx][uyy] != EL_SAND &&
1786 Feld[uxx][uyy] != EL_LANDMINE &&
1787 Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1788 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1789 !IN_SCR_FIELD(xx, yy))
1792 if (i == 1 || i == 2)
1796 cx = (i == 1 ? TILEX - snip : 0);
1804 cy = (i==0 ? TILEY-snip : 0);
1807 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1808 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1810 MarkTileDirty(xx, yy);
1815 void DrawScreenElement(int x, int y, int element)
1817 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1818 ErdreichAnbroeckeln(x, y);
1821 void DrawNewScreenElement(int x, int y, int element)
1823 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1824 ErdreichAnbroeckeln(x, y);
1827 void DrawLevelElement(int x, int y, int element)
1829 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1830 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1833 void DrawNewLevelElement(int x, int y, int element)
1835 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1836 DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1839 void DrawScreenField(int x, int y)
1841 int ux = LEVELX(x), uy = LEVELY(y);
1842 int element, content;
1844 if (!IN_LEV_FIELD(ux, uy))
1846 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1849 element = BorderElement;
1851 DrawScreenElement(x, y, element);
1855 element = Feld[ux][uy];
1856 content = Store[ux][uy];
1858 if (IS_MOVING(ux, uy))
1860 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1861 boolean cut_mode = NO_CUTTING;
1863 if (element == EL_QUICKSAND_EMPTYING ||
1864 element == EL_MAGIC_WALL_EMPTYING ||
1865 element == EL_MAGIC_WALL_BD_EMPTYING ||
1866 element == EL_AMOEBA_DRIPPING)
1867 cut_mode = CUT_ABOVE;
1868 else if (element == EL_QUICKSAND_FILLING ||
1869 element == EL_MAGIC_WALL_FILLING ||
1870 element == EL_MAGIC_WALL_BD_FILLING)
1871 cut_mode = CUT_BELOW;
1873 if (cut_mode == CUT_ABOVE)
1874 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1876 DrawScreenElement(x, y, EL_EMPTY);
1879 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1880 else if (cut_mode == NO_CUTTING)
1881 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1883 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1885 if (content == EL_ACID)
1886 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1888 else if (IS_BLOCKED(ux, uy))
1893 boolean cut_mode = NO_CUTTING;
1894 int element_old, content_old;
1896 Blocked2Moving(ux, uy, &oldx, &oldy);
1899 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1900 MovDir[oldx][oldy] == MV_RIGHT);
1902 element_old = Feld[oldx][oldy];
1903 content_old = Store[oldx][oldy];
1905 if (element_old == EL_QUICKSAND_EMPTYING ||
1906 element_old == EL_MAGIC_WALL_EMPTYING ||
1907 element_old == EL_MAGIC_WALL_BD_EMPTYING ||
1908 element_old == EL_AMOEBA_DRIPPING)
1909 cut_mode = CUT_ABOVE;
1911 DrawScreenElement(x, y, EL_EMPTY);
1914 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1916 else if (cut_mode == NO_CUTTING)
1917 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1920 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1923 else if (IS_DRAWABLE(element))
1924 DrawScreenElement(x, y, element);
1926 DrawScreenElement(x, y, EL_EMPTY);
1929 void DrawNewScreenField(int x, int y)
1931 int ux = LEVELX(x), uy = LEVELY(y);
1932 int element, content;
1934 if (!IN_LEV_FIELD(ux, uy))
1936 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1939 element = BorderElement;
1941 DrawNewScreenElement(x, y, element);
1945 element = Feld[ux][uy];
1946 content = Store[ux][uy];
1948 if (IS_MOVING(ux, uy))
1950 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1951 boolean cut_mode = NO_CUTTING;
1953 if (element == EL_QUICKSAND_EMPTYING ||
1954 element == EL_MAGIC_WALL_EMPTYING ||
1955 element == EL_MAGIC_WALL_BD_EMPTYING ||
1956 element == EL_AMOEBA_DRIPPING)
1957 cut_mode = CUT_ABOVE;
1958 else if (element == EL_QUICKSAND_FILLING ||
1959 element == EL_MAGIC_WALL_FILLING ||
1960 element == EL_MAGIC_WALL_BD_FILLING)
1961 cut_mode = CUT_BELOW;
1963 if (cut_mode == CUT_ABOVE)
1964 DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1966 DrawNewScreenElement(x, y, EL_EMPTY);
1969 DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1970 else if (cut_mode == NO_CUTTING)
1971 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1973 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1975 if (content == EL_ACID)
1976 DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1978 else if (IS_BLOCKED(ux, uy))
1983 boolean cut_mode = NO_CUTTING;
1984 int element_old, content_old;
1986 Blocked2Moving(ux, uy, &oldx, &oldy);
1989 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1990 MovDir[oldx][oldy] == MV_RIGHT);
1992 element_old = Feld[oldx][oldy];
1993 content_old = Store[oldx][oldy];
1995 if (element_old == EL_QUICKSAND_EMPTYING ||
1996 element_old == EL_MAGIC_WALL_EMPTYING ||
1997 element_old == EL_MAGIC_WALL_BD_EMPTYING ||
1998 element_old == EL_AMOEBA_DRIPPING)
1999 cut_mode = CUT_ABOVE;
2001 DrawNewScreenElement(x, y, EL_EMPTY);
2004 DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2006 else if (cut_mode == NO_CUTTING)
2007 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2010 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2013 else if (IS_DRAWABLE(element))
2014 DrawNewScreenElement(x, y, element);
2016 DrawNewScreenElement(x, y, EL_EMPTY);
2019 void DrawLevelField(int x, int y)
2021 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2022 DrawScreenField(SCREENX(x), SCREENY(y));
2023 else if (IS_MOVING(x, y))
2027 Moving2Blocked(x, y, &newx, &newy);
2028 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2029 DrawScreenField(SCREENX(newx), SCREENY(newy));
2031 else if (IS_BLOCKED(x, y))
2035 Blocked2Moving(x, y, &oldx, &oldy);
2036 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2037 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2041 void DrawNewLevelField(int x, int y)
2043 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2044 DrawNewScreenField(SCREENX(x), SCREENY(y));
2045 else if (IS_MOVING(x, y))
2049 Moving2Blocked(x, y, &newx, &newy);
2050 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2051 DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2053 else if (IS_BLOCKED(x, y))
2057 Blocked2Moving(x, y, &oldx, &oldy);
2058 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2059 DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2063 void DrawMiniElement(int x, int y, int element)
2069 DrawMiniGraphic(x, y, -1);
2073 graphic = el2gfx(element);
2074 DrawMiniGraphic(x, y, graphic);
2077 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2079 int x = sx + scroll_x, y = sy + scroll_y;
2081 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2082 DrawMiniElement(sx, sy, EL_EMPTY);
2083 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2084 DrawMiniElement(sx, sy, Feld[x][y]);
2087 int steel_type, steel_position;
2090 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
2091 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2092 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
2093 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2094 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
2095 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
2098 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2099 steel_position = (x == -1 && y == -1 ? 0 :
2100 x == lev_fieldx && y == -1 ? 1 :
2101 x == -1 && y == lev_fieldy ? 2 :
2102 x == lev_fieldx && y == lev_fieldy ? 3 :
2103 x == -1 || x == lev_fieldx ? 4 :
2104 y == -1 || y == lev_fieldy ? 5 : -1);
2106 if (steel_position != -1)
2107 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2111 void DrawMicroElement(int xpos, int ypos, int element)
2115 if (element == EL_EMPTY)
2118 graphic = el2gfx(element);
2120 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2122 graphic -= GFX_START_ROCKSSP;
2123 BlitBitmap(pix[PIX_SP], drawto,
2124 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2125 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2126 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2128 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2130 graphic -= GFX_START_ROCKSDC;
2131 BlitBitmap(pix[PIX_DC], drawto,
2132 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2133 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2134 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2136 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2138 graphic -= GFX_START_ROCKSMORE;
2139 BlitBitmap(pix[PIX_MORE], drawto,
2140 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2141 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2142 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2144 else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2146 graphic -= GFX_CHAR_START;
2147 BlitBitmap(pix[PIX_FONT_EM], drawto,
2148 MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2149 MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2150 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2153 BlitBitmap(pix[PIX_ELEMENTS], drawto,
2154 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2155 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2156 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2165 for(x=BX1; x<=BX2; x++)
2166 for(y=BY1; y<=BY2; y++)
2167 DrawScreenField(x, y);
2169 redraw_mask |= REDRAW_FIELD;
2172 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2176 for(x=0; x<size_x; x++)
2177 for(y=0; y<size_y; y++)
2178 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2180 redraw_mask |= REDRAW_FIELD;
2183 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2187 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2189 if (lev_fieldx < STD_LEV_FIELDX)
2190 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2191 if (lev_fieldy < STD_LEV_FIELDY)
2192 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2194 xpos += MICRO_TILEX;
2195 ypos += MICRO_TILEY;
2197 for(x=-1; x<=STD_LEV_FIELDX; x++)
2199 for(y=-1; y<=STD_LEV_FIELDY; y++)
2201 int lx = from_x + x, ly = from_y + y;
2203 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2204 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2206 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2207 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2212 redraw_mask |= REDRAW_MICROLEVEL;
2215 #define MICROLABEL_EMPTY 0
2216 #define MICROLABEL_LEVEL_NAME 1
2217 #define MICROLABEL_CREATED_BY 2
2218 #define MICROLABEL_LEVEL_AUTHOR 3
2219 #define MICROLABEL_IMPORTED_FROM 4
2220 #define MICROLABEL_LEVEL_IMPORT_INFO 5
2222 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
2224 static void DrawMicroLevelLabelExt(int mode)
2226 char label_text[MAX_MICROLABEL_SIZE + 1];
2228 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2230 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2231 mode == MICROLABEL_CREATED_BY ? "created by" :
2232 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2233 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2234 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2235 leveldir_current->imported_from : ""),
2236 MAX_MICROLABEL_SIZE);
2237 label_text[MAX_MICROLABEL_SIZE] = '\0';
2239 if (strlen(label_text) > 0)
2241 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2242 int lypos = MICROLABEL_YPOS;
2244 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2247 redraw_mask |= REDRAW_MICROLEVEL;
2250 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2252 static unsigned long scroll_delay = 0;
2253 static unsigned long label_delay = 0;
2254 static int from_x, from_y, scroll_direction;
2255 static int label_state, label_counter;
2259 from_x = from_y = 0;
2260 scroll_direction = MV_RIGHT;
2264 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2265 DrawMicroLevelLabelExt(label_state);
2267 /* initialize delay counters */
2268 DelayReached(&scroll_delay, 0);
2269 DelayReached(&label_delay, 0);
2274 /* scroll micro level, if needed */
2275 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2276 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2278 switch (scroll_direction)
2284 scroll_direction = MV_UP;
2288 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2291 scroll_direction = MV_DOWN;
2298 scroll_direction = MV_RIGHT;
2302 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2305 scroll_direction = MV_LEFT;
2312 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2315 /* redraw micro level label, if needed */
2316 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2317 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2318 strcmp(level.author, leveldir_current->name) != 0 &&
2319 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2321 int max_label_counter = 23;
2323 if (leveldir_current->imported_from != NULL)
2324 max_label_counter += 14;
2326 label_counter = (label_counter + 1) % max_label_counter;
2327 label_state = (label_counter >= 0 && label_counter <= 7 ?
2328 MICROLABEL_LEVEL_NAME :
2329 label_counter >= 9 && label_counter <= 12 ?
2330 MICROLABEL_CREATED_BY :
2331 label_counter >= 14 && label_counter <= 21 ?
2332 MICROLABEL_LEVEL_AUTHOR :
2333 label_counter >= 23 && label_counter <= 26 ?
2334 MICROLABEL_IMPORTED_FROM :
2335 label_counter >= 28 && label_counter <= 35 ?
2336 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2337 DrawMicroLevelLabelExt(label_state);
2341 int REQ_in_range(int x, int y)
2343 if (y > DY+249 && y < DY+278)
2345 if (x > DX+1 && x < DX+48)
2347 else if (x > DX+51 && x < DX+98)
2353 #define MAX_REQUEST_LINES 13
2354 #define MAX_REQUEST_LINE_LEN 7
2356 boolean Request(char *text, unsigned int req_state)
2358 int mx, my, ty, result = -1;
2359 unsigned int old_door_state;
2361 #if defined(PLATFORM_UNIX)
2362 /* pause network game while waiting for request to answer */
2363 if (options.network &&
2364 game_status == PLAYING &&
2365 req_state & REQUEST_WAIT_FOR)
2366 SendToServer_PausePlaying();
2369 old_door_state = GetDoorState();
2373 CloseDoor(DOOR_CLOSE_1);
2375 /* save old door content */
2376 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2377 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2378 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2380 /* clear door drawing field */
2381 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2383 /* write text for request */
2384 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2386 char text_line[MAX_REQUEST_LINE_LEN + 1];
2392 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2395 if (!tc || tc == ' ')
2406 strncpy(text_line, text, tl);
2409 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2410 text_line, FS_SMALL, FC_YELLOW);
2412 text += tl + (tc == ' ' ? 1 : 0);
2415 if (req_state & REQ_ASK)
2417 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2418 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2420 else if (req_state & REQ_CONFIRM)
2422 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2424 else if (req_state & REQ_PLAYER)
2426 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2427 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2428 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2429 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2432 /* copy request gadgets to door backbuffer */
2433 BlitBitmap(drawto, pix[PIX_DB_DOOR],
2434 DX, DY, DXSIZE, DYSIZE,
2435 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2437 OpenDoor(DOOR_OPEN_1);
2443 if (!(req_state & REQUEST_WAIT_FOR))
2446 if (game_status != MAINMENU)
2449 button_status = MB_RELEASED;
2451 request_gadget_id = -1;
2463 case EVENT_BUTTONPRESS:
2464 case EVENT_BUTTONRELEASE:
2465 case EVENT_MOTIONNOTIFY:
2467 if (event.type == EVENT_MOTIONNOTIFY)
2469 if (!PointerInWindow(window))
2470 continue; /* window and pointer are on different screens */
2475 motion_status = TRUE;
2476 mx = ((MotionEvent *) &event)->x;
2477 my = ((MotionEvent *) &event)->y;
2481 motion_status = FALSE;
2482 mx = ((ButtonEvent *) &event)->x;
2483 my = ((ButtonEvent *) &event)->y;
2484 if (event.type == EVENT_BUTTONPRESS)
2485 button_status = ((ButtonEvent *) &event)->button;
2487 button_status = MB_RELEASED;
2490 /* this sets 'request_gadget_id' */
2491 HandleGadgets(mx, my, button_status);
2493 switch(request_gadget_id)
2495 case TOOL_CTRL_ID_YES:
2498 case TOOL_CTRL_ID_NO:
2501 case TOOL_CTRL_ID_CONFIRM:
2502 result = TRUE | FALSE;
2505 case TOOL_CTRL_ID_PLAYER_1:
2508 case TOOL_CTRL_ID_PLAYER_2:
2511 case TOOL_CTRL_ID_PLAYER_3:
2514 case TOOL_CTRL_ID_PLAYER_4:
2525 case EVENT_KEYPRESS:
2526 switch(GetEventKey((KeyEvent *)&event, TRUE))
2539 if (req_state & REQ_PLAYER)
2543 case EVENT_KEYRELEASE:
2544 ClearPlayerAction();
2548 HandleOtherEvents(&event);
2552 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2554 int joy = AnyJoystick();
2556 if (joy & JOY_BUTTON_1)
2558 else if (joy & JOY_BUTTON_2)
2564 /* don't eat all CPU time */
2568 if (game_status != MAINMENU)
2573 if (!(req_state & REQ_STAY_OPEN))
2575 CloseDoor(DOOR_CLOSE_1);
2577 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2579 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2580 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2581 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2582 OpenDoor(DOOR_OPEN_1);
2588 #if defined(PLATFORM_UNIX)
2589 /* continue network game after request */
2590 if (options.network &&
2591 game_status == PLAYING &&
2592 req_state & REQUEST_WAIT_FOR)
2593 SendToServer_ContinuePlaying();
2599 unsigned int OpenDoor(unsigned int door_state)
2601 unsigned int new_door_state;
2603 if (door_state & DOOR_COPY_BACK)
2605 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2606 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2607 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2608 door_state &= ~DOOR_COPY_BACK;
2611 new_door_state = MoveDoor(door_state);
2613 return(new_door_state);
2616 unsigned int CloseDoor(unsigned int door_state)
2618 unsigned int new_door_state;
2620 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2621 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2622 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2623 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2625 new_door_state = MoveDoor(door_state);
2627 return(new_door_state);
2630 unsigned int GetDoorState()
2632 return MoveDoor(DOOR_GET_STATE);
2635 unsigned int SetDoorState(unsigned int door_state)
2637 return MoveDoor(door_state | DOOR_SET_STATE);
2640 unsigned int MoveDoor(unsigned int door_state)
2642 static int door1 = DOOR_OPEN_1;
2643 static int door2 = DOOR_CLOSE_2;
2644 static unsigned long door_delay = 0;
2645 int x, start, stepsize = 2;
2646 unsigned long door_delay_value = stepsize * 5;
2648 if (door_state == DOOR_GET_STATE)
2649 return(door1 | door2);
2651 if (door_state & DOOR_SET_STATE)
2653 if (door_state & DOOR_ACTION_1)
2654 door1 = door_state & DOOR_ACTION_1;
2655 if (door_state & DOOR_ACTION_2)
2656 door2 = door_state & DOOR_ACTION_2;
2658 return(door1 | door2);
2661 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2662 door_state &= ~DOOR_OPEN_1;
2663 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2664 door_state &= ~DOOR_CLOSE_1;
2665 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2666 door_state &= ~DOOR_OPEN_2;
2667 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2668 door_state &= ~DOOR_CLOSE_2;
2670 if (setup.quick_doors)
2673 door_delay_value = 0;
2674 StopSound(SND_MENU_DOOR_OPENING);
2675 StopSound(SND_MENU_DOOR_CLOSING);
2678 if (door_state & DOOR_ACTION)
2680 if (!(door_state & DOOR_NO_DELAY))
2682 /* opening door sound has priority over simultaneously closing door */
2683 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2684 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2685 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2686 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2689 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2691 for(x=start; x<=DXSIZE; x+=stepsize)
2693 Bitmap *bitmap = pix[PIX_DOOR];
2694 GC gc = bitmap->stored_clip_gc;
2696 WaitUntilDelayReached(&door_delay, door_delay_value);
2698 if (door_state & DOOR_ACTION_1)
2700 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2701 int j = (DXSIZE - i) / 3;
2703 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2704 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2705 DXSIZE,DYSIZE - i/2, DX, DY);
2707 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2709 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2710 BlitBitmapMasked(bitmap, drawto,
2711 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2712 DX + DXSIZE - i, DY + j);
2713 BlitBitmapMasked(bitmap, drawto,
2714 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2715 DX + DXSIZE - i, DY + 140 + j);
2716 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2717 BlitBitmapMasked(bitmap, drawto,
2718 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2720 BlitBitmapMasked(bitmap, drawto,
2721 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2724 BlitBitmapMasked(bitmap, drawto,
2725 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2727 BlitBitmapMasked(bitmap, drawto,
2728 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2730 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2731 BlitBitmapMasked(bitmap, drawto,
2732 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2733 DX + DXSIZE - i, DY + 77 + j);
2734 BlitBitmapMasked(bitmap, drawto,
2735 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2736 DX + DXSIZE - i, DY + 203 + j);
2738 redraw_mask |= REDRAW_DOOR_1;
2741 if (door_state & DOOR_ACTION_2)
2743 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2744 int j = (VXSIZE - i) / 3;
2746 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2747 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2748 VXSIZE, VYSIZE - i/2, VX, VY);
2750 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2752 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2753 BlitBitmapMasked(bitmap, drawto,
2754 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2755 VX + VXSIZE-i, VY+j);
2756 SetClipOrigin(bitmap, gc,
2757 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2758 BlitBitmapMasked(bitmap, drawto,
2759 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2762 BlitBitmapMasked(bitmap, drawto,
2763 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2764 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2765 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2766 BlitBitmapMasked(bitmap, drawto,
2767 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2769 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2771 redraw_mask |= REDRAW_DOOR_2;
2776 if (game_status == MAINMENU)
2781 if (setup.quick_doors)
2783 StopSound(SND_MENU_DOOR_OPENING);
2784 StopSound(SND_MENU_DOOR_CLOSING);
2787 if (door_state & DOOR_ACTION_1)
2788 door1 = door_state & DOOR_ACTION_1;
2789 if (door_state & DOOR_ACTION_2)
2790 door2 = door_state & DOOR_ACTION_2;
2792 return (door1 | door2);
2795 void DrawSpecialEditorDoor()
2797 /* draw bigger toolbox window */
2798 BlitBitmap(pix[PIX_DOOR], drawto,
2799 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2801 redraw_mask |= REDRAW_ALL;
2804 void UndrawSpecialEditorDoor()
2806 /* draw normal tape recorder window */
2807 BlitBitmap(pix[PIX_BACK], drawto,
2808 562, 344, 108, 56, EX - 4, EY - 12);
2810 redraw_mask |= REDRAW_ALL;
2814 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2816 XImage *pixel_image;
2817 unsigned long pixel_value;
2819 pixel_image = XGetImage(display, bitmap->drawable,
2820 x, y, 1, 1, AllPlanes, ZPixmap);
2821 pixel_value = XGetPixel(pixel_image, 0, 0);
2823 XDestroyImage(pixel_image);
2829 /* ---------- new tool button stuff ---------------------------------------- */
2831 /* graphic position values for tool buttons */
2832 #define TOOL_BUTTON_YES_XPOS 2
2833 #define TOOL_BUTTON_YES_YPOS 250
2834 #define TOOL_BUTTON_YES_GFX_YPOS 0
2835 #define TOOL_BUTTON_YES_XSIZE 46
2836 #define TOOL_BUTTON_YES_YSIZE 28
2837 #define TOOL_BUTTON_NO_XPOS 52
2838 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2839 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2840 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2841 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2842 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2843 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2844 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2845 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2846 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2847 #define TOOL_BUTTON_PLAYER_XSIZE 30
2848 #define TOOL_BUTTON_PLAYER_YSIZE 30
2849 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2850 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2851 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2852 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2853 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2854 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2855 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2856 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2857 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2858 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2859 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2860 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2861 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2862 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2863 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2864 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2865 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2866 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2867 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2868 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2877 } toolbutton_info[NUM_TOOL_BUTTONS] =
2880 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2881 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2882 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2887 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2888 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2889 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2894 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2895 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2896 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2897 TOOL_CTRL_ID_CONFIRM,
2901 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2902 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2903 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2904 TOOL_CTRL_ID_PLAYER_1,
2908 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2909 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2910 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2911 TOOL_CTRL_ID_PLAYER_2,
2915 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2916 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2917 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2918 TOOL_CTRL_ID_PLAYER_3,
2922 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2923 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2924 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2925 TOOL_CTRL_ID_PLAYER_4,
2930 void CreateToolButtons()
2934 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2936 Bitmap *gd_bitmap = pix[PIX_DOOR];
2937 Bitmap *deco_bitmap = None;
2938 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2939 struct GadgetInfo *gi;
2940 unsigned long event_mask;
2941 int gd_xoffset, gd_yoffset;
2942 int gd_x1, gd_x2, gd_y;
2945 event_mask = GD_EVENT_RELEASED;
2947 gd_xoffset = toolbutton_info[i].xpos;
2948 gd_yoffset = toolbutton_info[i].ypos;
2949 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2950 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2951 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2953 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2955 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2956 &deco_bitmap, &deco_x, &deco_y);
2957 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2958 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2961 gi = CreateGadget(GDI_CUSTOM_ID, id,
2962 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2963 GDI_X, DX + toolbutton_info[i].x,
2964 GDI_Y, DY + toolbutton_info[i].y,
2965 GDI_WIDTH, toolbutton_info[i].width,
2966 GDI_HEIGHT, toolbutton_info[i].height,
2967 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2968 GDI_STATE, GD_BUTTON_UNPRESSED,
2969 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2970 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2971 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2972 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2973 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2974 GDI_DECORATION_SHIFTING, 1, 1,
2975 GDI_EVENT_MASK, event_mask,
2976 GDI_CALLBACK_ACTION, HandleToolButtons,
2980 Error(ERR_EXIT, "cannot create gadget");
2982 tool_gadget[id] = gi;
2986 static void UnmapToolButtons()
2990 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2991 UnmapGadget(tool_gadget[i]);
2994 static void HandleToolButtons(struct GadgetInfo *gi)
2996 request_gadget_id = gi->custom_id;
2999 int get_next_element(int element)
3003 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
3004 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
3005 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
3006 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_EMPTY;
3007 case EL_MAGIC_WALL_BD_FILLING: return EL_MAGIC_WALL_BD_FULL;
3008 case EL_MAGIC_WALL_BD_EMPTYING: return EL_MAGIC_WALL_BD_EMPTY;
3009 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
3011 default: return element;
3015 int el2gfx_OLD(int element)
3019 case EL_EMPTY: return -1;
3020 case EL_SAND: return GFX_ERDREICH;
3021 case EL_WALL: return GFX_MAUERWERK;
3022 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
3023 case EL_ROCK: return GFX_FELSBROCKEN;
3024 case EL_KEY: return GFX_SCHLUESSEL;
3025 case EL_EMERALD: return GFX_EDELSTEIN;
3026 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
3027 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
3028 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
3029 case EL_PLAYER: return GFX_SPIELFIGUR;
3030 case EL_PLAYER1: return GFX_SPIELER1;
3031 case EL_PLAYER2: return GFX_SPIELER2;
3032 case EL_PLAYER3: return GFX_SPIELER3;
3033 case EL_PLAYER4: return GFX_SPIELER4;
3034 case EL_BUG: return GFX_KAEFER;
3035 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
3036 case EL_BUG_UP: return GFX_KAEFER_UP;
3037 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
3038 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
3039 case EL_SPACESHIP: return GFX_FLIEGER;
3040 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
3041 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
3042 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
3043 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
3044 case EL_BUTTERFLY: return GFX_BUTTERFLY;
3045 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
3046 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
3047 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
3048 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
3049 case EL_FIREFLY: return GFX_FIREFLY;
3050 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
3051 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
3052 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
3053 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
3054 case EL_YAMYAM: return GFX_MAMPFER;
3055 case EL_ROBOT: return GFX_ROBOT;
3056 case EL_STEELWALL: return GFX_BETON;
3057 case EL_DIAMOND: return GFX_DIAMANT;
3058 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
3059 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
3060 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
3061 case EL_AMOEBA_DROP: return GFX_TROPFEN;
3062 case EL_BOMB: return GFX_BOMBE;
3063 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
3064 case EL_MAGIC_WALL_EMPTY: return GFX_MAGIC_WALL_EMPTY;
3065 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
3066 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
3067 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
3068 case EL_ACID: return GFX_SALZSAEURE;
3069 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
3070 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
3071 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
3072 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
3073 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
3074 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
3075 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
3076 case EL_NUT: return GFX_KOKOSNUSS;
3077 case EL_GAMEOFLIFE: return GFX_LIFE;
3078 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
3079 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
3080 case EL_STONEBLOCK: return GFX_BADEWANNE;
3081 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
3082 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
3083 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
3084 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
3085 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
3086 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
3087 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
3088 case EL_KEY1: return GFX_SCHLUESSEL1;
3089 case EL_KEY2: return GFX_SCHLUESSEL2;
3090 case EL_KEY3: return GFX_SCHLUESSEL3;
3091 case EL_KEY4: return GFX_SCHLUESSEL4;
3092 case EL_GATE1: return GFX_PFORTE1;
3093 case EL_GATE2: return GFX_PFORTE2;
3094 case EL_GATE3: return GFX_PFORTE3;
3095 case EL_GATE4: return GFX_PFORTE4;
3096 case EL_GATE1_GRAY: return GFX_PFORTE1X;
3097 case EL_GATE2_GRAY: return GFX_PFORTE2X;
3098 case EL_GATE3_GRAY: return GFX_PFORTE3X;
3099 case EL_GATE4_GRAY: return GFX_PFORTE4X;
3100 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
3101 case EL_PACMAN: return GFX_PACMAN;
3102 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
3103 case EL_PACMAN_UP: return GFX_PACMAN_UP;
3104 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
3105 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
3106 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
3107 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
3108 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
3109 case EL_LAMP: return GFX_BIRNE_AUS;
3110 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
3111 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
3112 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
3113 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
3114 case EL_WALL_GROWING_X: return GFX_MAUER_X;
3115 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
3116 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
3117 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
3118 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
3119 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
3120 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
3121 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
3122 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
3123 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
3124 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
3125 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
3126 case EL_MAGIC_WALL_BD_OFF: return GFX_MAGIC_WALL_BD_OFF;
3127 case EL_MAGIC_WALL_BD_EMPTY: return GFX_MAGIC_WALL_BD_EMPTY;
3128 case EL_MAGIC_WALL_BD_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
3129 case EL_MAGIC_WALL_BD_FULL: return GFX_MAGIC_WALL_BD_FULL;
3130 case EL_MAGIC_WALL_BD_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
3131 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
3132 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
3133 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
3134 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
3135 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
3136 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
3137 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
3138 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
3139 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
3140 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
3141 case EL_MOLE: return GFX_MOLE;
3142 case EL_PENGUIN: return GFX_PINGUIN;
3143 case EL_PIG: return GFX_SCHWEIN;
3144 case EL_DRAGON: return GFX_DRACHE;
3145 case EL_SATELLITE: return GFX_SONDE;
3146 case EL_ARROW_LEFT: return GFX_PFEIL_LEFT;
3147 case EL_ARROW_RIGHT: return GFX_PFEIL_RIGHT;
3148 case EL_ARROW_UP: return GFX_PFEIL_UP;
3149 case EL_ARROW_DOWN: return GFX_PFEIL_DOWN;
3150 case EL_SPEED_PILL: return GFX_SPEED_PILL;
3151 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
3152 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
3153 case EL_SP_ZONK: return GFX_SP_ZONK;
3154 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3155 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
3156 case EL_BLACK_ORB: return GFX_BLACK_ORB;
3157 case EL_EM_GATE1: return GFX_EM_GATE_1;
3158 case EL_EM_GATE2: return GFX_EM_GATE_2;
3159 case EL_EM_GATE3: return GFX_EM_GATE_3;
3160 case EL_EM_GATE4: return GFX_EM_GATE_4;
3161 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
3162 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
3163 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
3164 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
3165 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
3166 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
3167 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
3168 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
3169 case EL_EM_KEY1: return GFX_EM_KEY_1;
3170 case EL_EM_KEY2: return GFX_EM_KEY_2;
3171 case EL_EM_KEY3: return GFX_EM_KEY_3;
3172 case EL_EM_KEY4: return GFX_EM_KEY_4;
3173 case EL_PEARL: return GFX_PEARL;
3174 case EL_CRYSTAL: return GFX_CRYSTAL;
3175 case EL_WALL_PEARL: return GFX_WALL_PEARL;
3176 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
3177 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
3178 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
3179 case EL_KEY_WHITE: return GFX_KEY_WHITE;
3180 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
3181 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
3182 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
3183 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
3184 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
3185 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
3186 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
3187 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
3188 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
3189 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
3190 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3191 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3192 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3193 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
3194 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
3195 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
3196 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3197 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3198 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3199 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
3200 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
3201 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
3202 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3203 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3204 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3205 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
3206 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
3207 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
3208 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3209 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3210 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3211 case EL_LANDMINE: return GFX_LANDMINE;
3212 case EL_ENVELOPE: return GFX_ENVELOPE;
3213 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
3214 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
3215 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
3216 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
3217 case EL_SIGN_STOP: return GFX_SIGN_STOP;
3218 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
3219 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
3220 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
3221 case EL_SIGN_HEART: return GFX_SIGN_HEART;
3222 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
3223 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
3224 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
3225 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
3226 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
3227 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
3228 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
3229 case EL_MOLE_UP: return GFX_MOLE_UP;
3230 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
3231 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
3232 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
3233 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
3234 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
3235 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
3236 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
3237 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
3238 case EL_TIMEGATE_SWITCH_OFF: return GFX_TIMEGATE_SWITCH;
3239 case EL_BALLOON: return GFX_BALLOON;
3240 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
3241 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
3242 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
3243 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
3244 case EL_BALLOON_SEND_ANY: return GFX_BALLOON_SEND_ANY;
3245 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
3246 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
3247 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
3248 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
3249 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
3250 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
3251 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
3252 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
3253 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
3254 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
3255 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
3256 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
3257 case EL_TUBE_CROSS: return GFX_TUBE_CROSS;
3258 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
3259 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
3260 case EL_TUBE_VERT_LEFT: return GFX_TUBE_VERT_LEFT;
3261 case EL_TUBE_VERT_RIGHT: return GFX_TUBE_VERT_RIGHT;
3262 case EL_TUBE_HORIZ_UP: return GFX_TUBE_HORIZ_UP;
3263 case EL_TUBE_HORIZ_DOWN: return GFX_TUBE_HORIZ_DOWN;
3264 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
3265 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
3266 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
3267 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
3268 case EL_SPRING: return GFX_SPRING;
3269 case EL_SPRING_MOVING: return GFX_SPRING;
3270 case EL_TRAP_INACTIVE: return GFX_TRAP_INACTIVE;
3271 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
3272 case EL_BD_WALL: return GFX_BD_WALL;
3273 case EL_BD_ROCK: return GFX_BD_ROCK;
3274 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
3275 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
3279 if (IS_CHAR(element))
3280 return GFX_CHAR_START + (element - EL_CHAR_START);
3281 else if (element >= EL_SP_START && element <= EL_SP_END)
3283 int nr_element = element - EL_SP_START;
3284 int gfx_per_line = 8;
3286 (nr_element / gfx_per_line) * SP_PER_LINE +
3287 (nr_element % gfx_per_line);
3289 return GFX_START_ROCKSSP + nr_graphic;
3297 int el2gfx(int element)
3299 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3302 int graphic_OLD = el2gfx_OLD(element);
3304 if (element >= MAX_ELEMENTS)
3306 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3309 if (graphic_NEW != graphic_OLD)
3311 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3312 graphic_NEW, graphic_OLD);
3319 int el2img(int element)
3323 case EL_BUTTERFLY: return IMG_BD_BUTTERFLY;
3324 case EL_FIREFLY: return IMG_BD_FIREFLY;
3325 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
3331 return IMG_EMPTY_SPACE;
3334 int el_dir2img(int element, int direction)
3336 if (element_info[element].has_direction_graphic[GFX_ACTION_DEFAULT])
3338 int i = LOG_MV_DIR(direction);
3340 return element_info[element].direction_graphic[GFX_ACTION_DEFAULT][i];
3343 return el2img(element);