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_EXPLOSION)
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_FIELD_FULL)
486 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
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_FIELD_EMPTY ||
609 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
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_EXPLOSION)
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 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_LOOP) /* normal, looping animation */
722 frame = (sync_frame % (delay * num_frames)) / delay;
724 else if (mode & ANIM_LINEAR) /* normal, non-looping animation */
726 frame = sync_frame / delay;
728 if (frame > num_frames - 1)
729 frame = num_frames - 1;
731 else if (mode & ANIM_PINGPONG) /* use border frames once */
733 int max_anim_frames = 2 * num_frames - 2;
735 frame = (sync_frame % (delay * max_anim_frames)) / delay;
736 frame = (frame < num_frames ? frame : max_anim_frames - frame);
738 else if (mode & ANIM_PINGPONG2) /* use border frames twice */
740 int max_anim_frames = 2 * num_frames;
742 frame = (sync_frame % (delay * max_anim_frames)) / delay;
743 frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
746 if (mode & ANIM_REVERSE) /* use reverse animation direction */
747 frame = num_frames - frame - 1;
752 void DrawGraphicAnimationExt(int x, int y, int graphic,
753 int frames, int delay, int mode, int mask_mode)
755 int phase = getGraphicAnimationPhase(frames, delay, mode);
757 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
759 if (mask_mode == USE_MASKING)
760 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
762 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
766 void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
769 int delay = new_graphic_info[graphic].anim_delay;
771 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
773 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
776 int frame = getNewGraphicAnimationFrame(graphic, -1);
778 if (mask_mode == USE_MASKING)
779 DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
781 DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
785 void DrawGraphicAnimation(int x, int y, int graphic,
786 int frames, int delay, int mode)
788 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
791 void DrawNewGraphicAnimation(int x, int y, int graphic)
793 DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
796 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
797 int frames, int delay, int mode)
799 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
802 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
805 int frames, int delay,
808 int phase = getGraphicAnimationPhase(frames, delay, mode);
810 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
813 void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
815 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
817 *bitmap = graphic_info[graphic].bitmap;
818 *x = graphic_info[graphic].src_x;
819 *y = graphic_info[graphic].src_y;
821 else if (graphic >= GFX_START_ROCKSELEMENTS &&
822 graphic <= GFX_END_ROCKSELEMENTS)
824 graphic -= GFX_START_ROCKSELEMENTS;
825 *bitmap = pix[PIX_ELEMENTS];
826 *x = (graphic % GFX_PER_LINE) * TILEX;
827 *y = (graphic / GFX_PER_LINE) * TILEY;
829 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
831 graphic -= GFX_START_ROCKSHEROES;
832 *bitmap = pix[PIX_HEROES];
833 *x = (graphic % HEROES_PER_LINE) * TILEX;
834 *y = (graphic / HEROES_PER_LINE) * TILEY;
836 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
838 graphic -= GFX_START_ROCKSSP;
839 *bitmap = pix[PIX_SP];
840 *x = (graphic % SP_PER_LINE) * TILEX;
841 *y = (graphic / SP_PER_LINE) * TILEY;
843 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
845 graphic -= GFX_START_ROCKSDC;
846 *bitmap = pix[PIX_DC];
847 *x = (graphic % DC_PER_LINE) * TILEX;
848 *y = (graphic / DC_PER_LINE) * TILEY;
850 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
852 graphic -= GFX_START_ROCKSMORE;
853 *bitmap = pix[PIX_MORE];
854 *x = (graphic % MORE_PER_LINE) * TILEX;
855 *y = (graphic / MORE_PER_LINE) * TILEY;
857 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
859 graphic -= GFX_START_ROCKSFONT;
860 *bitmap = pix[PIX_FONT_EM];
861 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
862 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
866 *bitmap = pix[PIX_SP];
872 void DrawGraphic(int x, int y, int graphic)
875 if (!IN_SCR_FIELD(x, y))
877 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
878 printf("DrawGraphic(): This should never happen!\n");
883 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
887 void DrawNewGraphic(int x, int y, int graphic, int frame)
890 if (!IN_SCR_FIELD(x, y))
892 printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
893 printf("DrawNewGraphic(): This should never happen!\n");
898 DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
903 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
908 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
909 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
912 void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
915 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
916 int src_x = new_graphic_info[graphic].src_x;
917 int src_y = new_graphic_info[graphic].src_y;
918 int offset_x = new_graphic_info[graphic].offset_x;
919 int offset_y = new_graphic_info[graphic].offset_y;
921 src_x += frame * offset_x;
922 src_y += frame * offset_y;
924 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
927 void DrawGraphicThruMask(int x, int y, int graphic)
930 if (!IN_SCR_FIELD(x, y))
932 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
933 printf("DrawGraphicThruMask(): This should never happen!\n");
938 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic);
942 void DrawNewGraphicThruMask(int x, int y, int graphic, int frame)
945 if (!IN_SCR_FIELD(x, y))
947 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
948 printf("DrawGraphicThruMask(): This should never happen!\n");
953 DrawNewGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY,
958 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
965 if (graphic == GFX_LEERRAUM)
968 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
969 drawing_gc = src_bitmap->stored_clip_gc;
971 if (tile_clipmask[tile] != None)
973 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
974 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
975 BlitBitmapMasked(src_bitmap, d,
976 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
982 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
986 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
987 BlitBitmapMasked(src_bitmap, d,
988 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
992 void DrawNewGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y,
993 int graphic, int frame)
995 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
996 GC drawing_gc = src_bitmap->stored_clip_gc;
997 int src_x = new_graphic_info[graphic].src_x;
998 int src_y = new_graphic_info[graphic].src_y;
999 int offset_x = new_graphic_info[graphic].offset_x;
1000 int offset_y = new_graphic_info[graphic].offset_y;
1002 src_x += frame * offset_x;
1003 src_y += frame * offset_y;
1005 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1006 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1009 void DrawMiniGraphic(int x, int y, int graphic)
1011 DrawMiniGraphicExt(drawto,
1012 SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
1013 MarkTileDirty(x / 2, y / 2);
1016 void DrawNewMiniGraphic(int x, int y, int graphic)
1018 DrawNewMiniGraphicExt(drawto,
1019 SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
1020 MarkTileDirty(x / 2, y / 2);
1023 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1025 if (graphic >= GFX_START_ROCKSELEMENTS && graphic <= GFX_END_ROCKSELEMENTS)
1027 graphic -= GFX_START_ROCKSELEMENTS;
1028 *bitmap = pix[PIX_ELEMENTS];
1029 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
1030 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
1032 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1034 graphic -= GFX_START_ROCKSSP;
1035 *bitmap = pix[PIX_SP];
1036 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
1037 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
1039 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1041 graphic -= GFX_START_ROCKSDC;
1042 *bitmap = pix[PIX_DC];
1043 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
1044 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
1046 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1048 graphic -= GFX_START_ROCKSMORE;
1049 *bitmap = pix[PIX_MORE];
1050 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
1051 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
1053 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1055 graphic -= GFX_START_ROCKSFONT;
1056 *bitmap = pix[PIX_FONT_EM];
1057 *x = MINI_FONT_STARTX + (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
1058 *y = MINI_FONT_STARTY + (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE;
1062 *bitmap = pix[PIX_SP];
1063 *x = MINI_SP_STARTX;
1064 *y = MINI_SP_STARTY;
1068 void getNewMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1070 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1071 int mini_startx = 0;
1072 int mini_starty = src_bitmap->height * 2 / 3;
1073 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1074 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1076 *bitmap = src_bitmap;
1081 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1086 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
1087 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1090 void DrawNewMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1096 getNewMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1098 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1099 int mini_startx = src_bitmap->width * 2 / 3;
1100 int mini_starty = src_bitmap->height * 2 / 3;
1101 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
1102 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
1105 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1108 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1109 int cut_mode, int mask_mode)
1111 int width = TILEX, height = TILEY;
1113 int src_x, src_y, dest_x, dest_y;
1120 DrawGraphic(x, y, graphic);
1124 if (dx || dy) /* Verschiebung der Grafik? */
1126 if (x < BX1) /* Element kommt von links ins Bild */
1133 else if (x > BX2) /* Element kommt von rechts ins Bild */
1139 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1145 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1147 else if (dx) /* allg. Bewegung in x-Richtung */
1148 MarkTileDirty(x + SIGN(dx), y);
1150 if (y < BY1) /* Element kommt von oben ins Bild */
1152 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1160 else if (y > BY2) /* Element kommt von unten ins Bild */
1166 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1172 else if (dy > 0 && cut_mode == CUT_ABOVE)
1174 if (y == BY2) /* Element unterhalb des Bildes */
1180 MarkTileDirty(x, y + 1);
1181 } /* Element verläßt unten das Bild */
1182 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1184 else if (dy) /* allg. Bewegung in y-Richtung */
1185 MarkTileDirty(x, y + SIGN(dy));
1188 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1189 drawing_gc = src_bitmap->stored_clip_gc;
1194 dest_x = FX + x * TILEX + dx;
1195 dest_y = FY + y * TILEY + dy;
1198 if (!IN_SCR_FIELD(x,y))
1200 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1201 printf("DrawGraphicShifted(): This should never happen!\n");
1206 if (mask_mode == USE_MASKING)
1208 if (tile_clipmask[tile] != None)
1210 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
1211 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1212 BlitBitmapMasked(src_bitmap, drawto_field,
1213 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1219 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1223 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1224 BlitBitmapMasked(src_bitmap, drawto_field,
1225 src_x, src_y, width, height, dest_x, dest_y);
1229 BlitBitmap(src_bitmap, drawto_field,
1230 src_x, src_y, width, height, dest_x, dest_y);
1235 void DrawNewGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1236 int cut_mode, int mask_mode)
1245 int width = TILEX, height = TILEY;
1251 DrawNewGraphic(x, y, graphic, frame);
1255 if (dx || dy) /* Verschiebung der Grafik? */
1257 if (x < BX1) /* Element kommt von links ins Bild */
1264 else if (x > BX2) /* Element kommt von rechts ins Bild */
1270 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1276 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1278 else if (dx) /* allg. Bewegung in x-Richtung */
1279 MarkTileDirty(x + SIGN(dx), y);
1281 if (y < BY1) /* Element kommt von oben ins Bild */
1283 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1291 else if (y > BY2) /* Element kommt von unten ins Bild */
1297 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1303 else if (dy > 0 && cut_mode == CUT_ABOVE)
1305 if (y == BY2) /* Element unterhalb des Bildes */
1311 MarkTileDirty(x, y + 1);
1312 } /* Element verläßt unten das Bild */
1313 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1315 else if (dy) /* allg. Bewegung in y-Richtung */
1316 MarkTileDirty(x, y + SIGN(dy));
1319 src_bitmap = new_graphic_info[graphic].bitmap;
1320 drawing_gc = src_bitmap->stored_clip_gc;
1321 src_x = new_graphic_info[graphic].src_x;
1322 src_y = new_graphic_info[graphic].src_y;
1323 offset_x = new_graphic_info[graphic].offset_x;
1324 offset_y = new_graphic_info[graphic].offset_y;
1326 src_x += frame * offset_x;
1327 src_y += frame * offset_y;
1332 dest_x = FX + x * TILEX + dx;
1333 dest_y = FY + y * TILEY + dy;
1336 if (!IN_SCR_FIELD(x,y))
1338 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1339 printf("DrawGraphicShifted(): This should never happen!\n");
1344 if (mask_mode == USE_MASKING)
1345 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1347 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1353 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1356 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1359 void DrawNewGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1360 int frame, int cut_mode)
1362 DrawNewGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1365 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1366 int cut_mode, int mask_mode)
1368 int ux = LEVELX(x), uy = LEVELY(y);
1369 int graphic = el2gfx(element);
1370 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1371 int phase4 = phase8 / 2;
1372 int phase2 = phase8 / 4;
1373 int dir = MovDir[ux][uy];
1375 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1377 graphic += 1 * !phase2;
1381 else if (dir == MV_LEFT)
1383 else if (dir == MV_DOWN)
1386 else if (element == EL_SP_SNIKSNAK)
1389 graphic = GFX_SP_SNIKSNAK_LEFT;
1390 else if (dir == MV_RIGHT)
1391 graphic = GFX_SP_SNIKSNAK_RIGHT;
1392 else if (dir == MV_UP)
1393 graphic = GFX_SP_SNIKSNAK_UP;
1395 graphic = GFX_SP_SNIKSNAK_DOWN;
1397 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1399 else if (element == EL_SP_ELECTRON)
1401 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1403 else if (element == EL_MOLE || element == EL_PENGUIN ||
1404 element == EL_PIG || element == EL_DRAGON)
1407 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1408 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1409 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1410 else if (dir == MV_RIGHT)
1411 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1412 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1413 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1414 else if (dir == MV_UP)
1415 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1416 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1417 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1419 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1420 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1421 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1425 else if (element == EL_SATELLITE)
1427 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1429 else if (element == EL_ACID)
1431 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1433 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1437 else if (element == EL_BALLOON)
1441 else if ((element == EL_ROCK ||
1442 element == EL_SP_ZONK ||
1443 element == EL_BD_ROCK ||
1444 element == EL_SP_INFOTRON ||
1448 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1450 if (element == EL_ROCK ||
1451 element == EL_SP_ZONK ||
1452 element == EL_BD_ROCK)
1455 graphic += (4 - phase4) % 4;
1456 else if (dir == MV_RIGHT)
1459 graphic += phase2 * 2;
1461 else if (element != EL_SP_INFOTRON)
1465 else if (element == EL_MAGIC_WALL_ACTIVE ||
1466 element == EL_MAGIC_WALL_EMPTYING ||
1467 element == EL_BD_MAGIC_WALL_ACTIVE ||
1468 element == EL_BD_MAGIC_WALL_EMPTYING ||
1469 element == EL_MAGIC_WALL_FULL ||
1470 element == EL_BD_MAGIC_WALL_FULL)
1472 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1474 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1476 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1477 graphic += (x + 2 * y + 4) % 4;
1479 else if (element == EL_WALL_GROWING)
1481 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1483 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1484 links_massiv = TRUE;
1485 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1486 rechts_massiv = TRUE;
1488 if (links_massiv && rechts_massiv)
1489 graphic = GFX_MAUERWERK;
1490 else if (links_massiv)
1491 graphic = GFX_MAUER_R;
1492 else if (rechts_massiv)
1493 graphic = GFX_MAUER_L;
1496 else if ((element == EL_INVISIBLE_STEELWALL ||
1497 element == EL_INVISIBLE_WALL ||
1498 element == EL_INVISIBLE_SAND) && game.light_time_left)
1500 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1501 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1502 GFX_SAND_INVISIBLE_ON);
1507 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1508 else if (mask_mode == USE_MASKING)
1509 DrawGraphicThruMask(x, y, graphic);
1511 DrawGraphic(x, y, graphic);
1514 inline static int getFramePosition(int x, int y)
1516 int element = Feld[x][y];
1519 if (element == EL_QUICKSAND_FULL ||
1520 element == EL_MAGIC_WALL_FULL ||
1521 element == EL_BD_MAGIC_WALL_FULL)
1523 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1524 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1529 inline static int getGfxAction(int x, int y)
1531 int gfx_action = GFX_ACTION_DEFAULT;
1533 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1534 gfx_action = GfxAction[x][y];
1535 else if (IS_MOVING(x, y))
1536 gfx_action = GFX_ACTION_MOVING;
1541 void DrawNewScreenElementExt(int x, int y, int dx, int dy, int element,
1542 int cut_mode, int mask_mode)
1544 int ux = LEVELX(x), uy = LEVELY(y);
1545 int move_dir = MovDir[ux][uy];
1546 int move_pos = getFramePosition(ux, uy);
1547 int gfx_action = getGfxAction(ux, uy);
1548 int graphic = el_dir_act2img(element, move_dir, gfx_action);
1549 int frame = getNewGraphicAnimationFrame(graphic, move_pos);
1551 if (element == EL_WALL_GROWING)
1553 boolean left_stopped = FALSE, right_stopped = FALSE;
1555 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1556 left_stopped = TRUE;
1557 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1558 right_stopped = TRUE;
1560 if (left_stopped && right_stopped)
1562 else if (left_stopped)
1564 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1565 frame = new_graphic_info[graphic].anim_frames - 1;
1567 else if (right_stopped)
1569 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1570 frame = new_graphic_info[graphic].anim_frames - 1;
1574 else if ((element == EL_ROCK ||
1575 element == EL_SP_ZONK ||
1576 element == EL_BD_ROCK ||
1577 element == EL_SP_INFOTRON ||
1581 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1583 if (element == EL_ROCK ||
1584 element == EL_SP_ZONK ||
1585 element == EL_BD_ROCK)
1587 if (move_dir == MV_LEFT)
1588 graphic += (4 - phase4) % 4;
1589 else if (move_dir == MV_RIGHT)
1592 graphic += phase2 * 2;
1594 else if (element != EL_SP_INFOTRON)
1599 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1601 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1602 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1603 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1604 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1605 IMG_AMOEBA_DEAD_PART1);
1607 graphic += (x + 2 * y + 4) % 4;
1611 DrawNewGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1612 else if (mask_mode == USE_MASKING)
1613 DrawNewGraphicThruMask(x, y, graphic, frame);
1615 DrawNewGraphic(x, y, graphic, frame);
1618 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1619 int cut_mode, int mask_mode)
1621 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1622 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1623 cut_mode, mask_mode);
1626 void DrawNewLevelElementExt(int x, int y, int dx, int dy, int element,
1627 int cut_mode, int mask_mode)
1629 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1630 DrawNewScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1631 cut_mode, mask_mode);
1634 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1637 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1640 void DrawNewScreenElementShifted(int x, int y, int dx, int dy, int element,
1643 DrawNewScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1646 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1649 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1652 void DrawNewLevelElementShifted(int x, int y, int dx, int dy, int element,
1655 DrawNewLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1658 void DrawScreenElementThruMask(int x, int y, int element)
1660 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1663 void DrawNewScreenElementThruMask(int x, int y, int element)
1665 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1668 void DrawLevelElementThruMask(int x, int y, int element)
1670 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1673 void DrawNewLevelElementThruMask(int x, int y, int element)
1675 DrawNewLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1678 void DrawLevelFieldThruMask(int x, int y)
1680 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1683 void DrawNewLevelFieldThruMask(int x, int y)
1685 DrawNewLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1688 void ErdreichAnbroeckeln(int x, int y)
1692 int i, width, height, cx,cy;
1693 int ux = LEVELX(x), uy = LEVELY(y);
1694 int element, graphic;
1696 static int xy[4][2] =
1704 if (!IN_LEV_FIELD(ux, uy))
1707 element = Feld[ux][uy];
1709 if (element == EL_SAND ||
1710 element == EL_LANDMINE ||
1711 element == EL_TRAP ||
1712 element == EL_TRAP_ACTIVE)
1714 if (!IN_SCR_FIELD(x, y))
1717 graphic = GFX_ERDENRAND;
1719 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1725 uxx = ux + xy[i][0];
1726 uyy = uy + xy[i][1];
1727 if (!IN_LEV_FIELD(uxx, uyy))
1728 element = EL_STEELWALL;
1730 element = Feld[uxx][uyy];
1732 if (element == EL_SAND ||
1733 element == EL_LANDMINE ||
1734 element == EL_TRAP ||
1735 element == EL_TRAP_ACTIVE)
1738 if (i == 1 || i == 2)
1742 cx = (i == 2 ? TILEX - snip : 0);
1750 cy = (i == 3 ? TILEY - snip : 0);
1753 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1754 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1757 MarkTileDirty(x, y);
1761 graphic = GFX_ERDENRAND;
1763 getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1767 int xx, yy, uxx, uyy;
1771 uxx = ux + xy[i][0];
1772 uyy = uy + xy[i][1];
1774 if (!IN_LEV_FIELD(uxx, uyy) ||
1775 (Feld[uxx][uyy] != EL_SAND &&
1776 Feld[uxx][uyy] != EL_LANDMINE &&
1777 Feld[uxx][uyy] != EL_TRAP &&
1778 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1779 !IN_SCR_FIELD(xx, yy))
1782 if (i == 1 || i == 2)
1786 cx = (i == 1 ? TILEX - snip : 0);
1794 cy = (i==0 ? TILEY-snip : 0);
1797 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1798 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1800 MarkTileDirty(xx, yy);
1805 void DrawScreenElement(int x, int y, int element)
1807 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1808 ErdreichAnbroeckeln(x, y);
1811 void DrawNewScreenElement(int x, int y, int element)
1813 DrawNewScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1814 ErdreichAnbroeckeln(x, y);
1817 void DrawLevelElement(int x, int y, int element)
1819 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1820 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1823 void DrawNewLevelElement(int x, int y, int element)
1825 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1826 DrawNewScreenElement(SCREENX(x), SCREENY(y), element);
1829 void DrawScreenField(int x, int y)
1831 int ux = LEVELX(x), uy = LEVELY(y);
1832 int element, content;
1834 if (!IN_LEV_FIELD(ux, uy))
1836 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1839 element = BorderElement;
1841 DrawScreenElement(x, y, element);
1845 element = Feld[ux][uy];
1846 content = Store[ux][uy];
1848 if (IS_MOVING(ux, uy))
1850 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1851 boolean cut_mode = NO_CUTTING;
1853 if (element == EL_QUICKSAND_EMPTYING ||
1854 element == EL_MAGIC_WALL_EMPTYING ||
1855 element == EL_BD_MAGIC_WALL_EMPTYING ||
1856 element == EL_AMOEBA_DRIPPING)
1857 cut_mode = CUT_ABOVE;
1858 else if (element == EL_QUICKSAND_FILLING ||
1859 element == EL_MAGIC_WALL_FILLING ||
1860 element == EL_BD_MAGIC_WALL_FILLING)
1861 cut_mode = CUT_BELOW;
1863 if (cut_mode == CUT_ABOVE)
1864 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1866 DrawScreenElement(x, y, EL_EMPTY);
1869 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1870 else if (cut_mode == NO_CUTTING)
1871 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1873 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1875 if (content == EL_ACID)
1876 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1878 else if (IS_BLOCKED(ux, uy))
1883 boolean cut_mode = NO_CUTTING;
1884 int element_old, content_old;
1886 Blocked2Moving(ux, uy, &oldx, &oldy);
1889 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1890 MovDir[oldx][oldy] == MV_RIGHT);
1892 element_old = Feld[oldx][oldy];
1893 content_old = Store[oldx][oldy];
1895 if (element_old == EL_QUICKSAND_EMPTYING ||
1896 element_old == EL_MAGIC_WALL_EMPTYING ||
1897 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1898 element_old == EL_AMOEBA_DRIPPING)
1899 cut_mode = CUT_ABOVE;
1901 DrawScreenElement(x, y, EL_EMPTY);
1904 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1906 else if (cut_mode == NO_CUTTING)
1907 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1910 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1913 else if (IS_DRAWABLE(element))
1914 DrawScreenElement(x, y, element);
1916 DrawScreenElement(x, y, EL_EMPTY);
1919 void DrawNewScreenField(int x, int y)
1921 int ux = LEVELX(x), uy = LEVELY(y);
1922 int element, content;
1924 if (!IN_LEV_FIELD(ux, uy))
1926 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1929 element = BorderElement;
1931 DrawNewScreenElement(x, y, element);
1935 element = Feld[ux][uy];
1936 content = Store[ux][uy];
1938 if (IS_MOVING(ux, uy))
1940 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1941 boolean cut_mode = NO_CUTTING;
1943 if (element == EL_QUICKSAND_EMPTYING ||
1944 element == EL_MAGIC_WALL_EMPTYING ||
1945 element == EL_BD_MAGIC_WALL_EMPTYING ||
1946 element == EL_AMOEBA_DRIPPING)
1947 cut_mode = CUT_ABOVE;
1948 else if (element == EL_QUICKSAND_FILLING ||
1949 element == EL_MAGIC_WALL_FILLING ||
1950 element == EL_BD_MAGIC_WALL_FILLING)
1951 cut_mode = CUT_BELOW;
1953 if (cut_mode == CUT_ABOVE)
1954 DrawNewScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1956 DrawNewScreenElement(x, y, EL_EMPTY);
1959 DrawNewScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1960 else if (cut_mode == NO_CUTTING)
1961 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1963 DrawNewScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1965 if (content == EL_ACID)
1966 DrawNewLevelElementThruMask(ux, uy + 1, EL_ACID);
1968 else if (IS_BLOCKED(ux, uy))
1973 boolean cut_mode = NO_CUTTING;
1974 int element_old, content_old;
1976 Blocked2Moving(ux, uy, &oldx, &oldy);
1979 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1980 MovDir[oldx][oldy] == MV_RIGHT);
1982 element_old = Feld[oldx][oldy];
1983 content_old = Store[oldx][oldy];
1985 if (element_old == EL_QUICKSAND_EMPTYING ||
1986 element_old == EL_MAGIC_WALL_EMPTYING ||
1987 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1988 element_old == EL_AMOEBA_DRIPPING)
1989 cut_mode = CUT_ABOVE;
1991 DrawNewScreenElement(x, y, EL_EMPTY);
1994 DrawNewScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1996 else if (cut_mode == NO_CUTTING)
1997 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2000 DrawNewScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2003 else if (IS_DRAWABLE(element))
2004 DrawNewScreenElement(x, y, element);
2006 DrawNewScreenElement(x, y, EL_EMPTY);
2009 void DrawLevelField(int x, int y)
2011 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2012 DrawScreenField(SCREENX(x), SCREENY(y));
2013 else if (IS_MOVING(x, y))
2017 Moving2Blocked(x, y, &newx, &newy);
2018 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2019 DrawScreenField(SCREENX(newx), SCREENY(newy));
2021 else if (IS_BLOCKED(x, y))
2025 Blocked2Moving(x, y, &oldx, &oldy);
2026 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2027 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2031 void DrawNewLevelField(int x, int y)
2033 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2034 DrawNewScreenField(SCREENX(x), SCREENY(y));
2035 else if (IS_MOVING(x, y))
2039 Moving2Blocked(x, y, &newx, &newy);
2040 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2041 DrawNewScreenField(SCREENX(newx), SCREENY(newy));
2043 else if (IS_BLOCKED(x, y))
2047 Blocked2Moving(x, y, &oldx, &oldy);
2048 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2049 DrawNewScreenField(SCREENX(oldx), SCREENY(oldy));
2053 void DrawMiniElement(int x, int y, int element)
2059 DrawMiniGraphic(x, y, -1);
2063 graphic = el2gfx(element);
2064 DrawMiniGraphic(x, y, graphic);
2067 void DrawNewMiniElement(int x, int y, int element)
2074 DrawNewMiniGraphic(x, y, -1);
2079 graphic = el2img(element);
2080 DrawNewMiniGraphic(x, y, graphic);
2083 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2085 int x = sx + scroll_x, y = sy + scroll_y;
2087 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2088 DrawMiniElement(sx, sy, EL_EMPTY);
2089 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2090 DrawMiniElement(sx, sy, Feld[x][y]);
2093 int steel_type, steel_position;
2096 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
2097 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
2098 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
2099 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
2100 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
2101 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
2104 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2105 steel_position = (x == -1 && y == -1 ? 0 :
2106 x == lev_fieldx && y == -1 ? 1 :
2107 x == -1 && y == lev_fieldy ? 2 :
2108 x == lev_fieldx && y == lev_fieldy ? 3 :
2109 x == -1 || x == lev_fieldx ? 4 :
2110 y == -1 || y == lev_fieldy ? 5 : -1);
2112 if (steel_position != -1)
2113 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
2117 void DrawNewMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2119 int x = sx + scroll_x, y = sy + scroll_y;
2121 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2122 DrawNewMiniElement(sx, sy, EL_EMPTY);
2123 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2124 DrawNewMiniElement(sx, sy, Feld[x][y]);
2127 int steel_type, steel_position;
2130 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
2131 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
2132 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
2133 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2134 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
2135 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
2138 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2139 steel_position = (x == -1 && y == -1 ? 0 :
2140 x == lev_fieldx && y == -1 ? 1 :
2141 x == -1 && y == lev_fieldy ? 2 :
2142 x == lev_fieldx && y == lev_fieldy ? 3 :
2143 x == -1 || x == lev_fieldx ? 4 :
2144 y == -1 || y == lev_fieldy ? 5 : -1);
2146 if (steel_position != -1)
2147 DrawNewMiniGraphic(sx, sy, border[steel_position][steel_type]);
2151 void DrawMicroElement(int xpos, int ypos, int element)
2155 if (element == EL_EMPTY)
2158 graphic = el2gfx(element);
2160 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
2162 graphic -= GFX_START_ROCKSSP;
2163 BlitBitmap(pix[PIX_SP], drawto,
2164 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
2165 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
2166 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2168 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
2170 graphic -= GFX_START_ROCKSDC;
2171 BlitBitmap(pix[PIX_DC], drawto,
2172 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
2173 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
2174 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2176 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
2178 graphic -= GFX_START_ROCKSMORE;
2179 BlitBitmap(pix[PIX_MORE], drawto,
2180 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
2181 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
2182 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2184 else if (graphic >= GFX_CHAR_START && graphic <= GFX_CHAR_END)
2186 graphic -= GFX_CHAR_START;
2187 BlitBitmap(pix[PIX_FONT_EM], drawto,
2188 MICRO_FONT_STARTX + (graphic % MICRO_GFX_PER_LINE)* MICRO_TILEX,
2189 MICRO_FONT_STARTY + (graphic / MICRO_GFX_PER_LINE)* MICRO_TILEY,
2190 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2193 BlitBitmap(pix[PIX_ELEMENTS], drawto,
2194 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
2195 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
2196 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
2199 void getNewMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
2201 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
2202 int mini_startx = src_bitmap->width * 3 / 4;
2203 int mini_starty = src_bitmap->height * 2 / 3;
2204 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
2205 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
2207 *bitmap = src_bitmap;
2212 void DrawNewMicroElement(int xpos, int ypos, int element)
2218 if (element == EL_EMPTY)
2221 graphic = el2img(element);
2223 getNewMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
2224 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
2234 for(x=BX1; x<=BX2; x++)
2235 for(y=BY1; y<=BY2; y++)
2236 DrawNewScreenField(x, y);
2238 redraw_mask |= REDRAW_FIELD;
2241 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2245 for(x=0; x<size_x; x++)
2246 for(y=0; y<size_y; y++)
2247 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2249 redraw_mask |= REDRAW_FIELD;
2252 void DrawNewMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2256 for(x=0; x<size_x; x++)
2257 for(y=0; y<size_y; y++)
2258 DrawNewMiniElementOrWall(x, y, scroll_x, scroll_y);
2260 redraw_mask |= REDRAW_FIELD;
2263 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2267 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2269 if (lev_fieldx < STD_LEV_FIELDX)
2270 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2271 if (lev_fieldy < STD_LEV_FIELDY)
2272 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2274 xpos += MICRO_TILEX;
2275 ypos += MICRO_TILEY;
2277 for(x=-1; x<=STD_LEV_FIELDX; x++)
2279 for(y=-1; y<=STD_LEV_FIELDY; y++)
2281 int lx = from_x + x, ly = from_y + y;
2283 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2284 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2286 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2287 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2292 redraw_mask |= REDRAW_MICROLEVEL;
2295 static void DrawNewMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
2299 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
2301 if (lev_fieldx < STD_LEV_FIELDX)
2302 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
2303 if (lev_fieldy < STD_LEV_FIELDY)
2304 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
2306 xpos += MICRO_TILEX;
2307 ypos += MICRO_TILEY;
2309 for(x=-1; x<=STD_LEV_FIELDX; x++)
2311 for(y=-1; y<=STD_LEV_FIELDY; y++)
2313 int lx = from_x + x, ly = from_y + y;
2315 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
2316 DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2318 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
2319 DrawNewMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
2324 redraw_mask |= REDRAW_MICROLEVEL;
2327 #define MICROLABEL_EMPTY 0
2328 #define MICROLABEL_LEVEL_NAME 1
2329 #define MICROLABEL_CREATED_BY 2
2330 #define MICROLABEL_LEVEL_AUTHOR 3
2331 #define MICROLABEL_IMPORTED_FROM 4
2332 #define MICROLABEL_LEVEL_IMPORT_INFO 5
2334 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
2336 static void DrawMicroLevelLabelExt(int mode)
2338 char label_text[MAX_MICROLABEL_SIZE + 1];
2340 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
2342 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
2343 mode == MICROLABEL_CREATED_BY ? "created by" :
2344 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2345 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
2346 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
2347 leveldir_current->imported_from : ""),
2348 MAX_MICROLABEL_SIZE);
2349 label_text[MAX_MICROLABEL_SIZE] = '\0';
2351 if (strlen(label_text) > 0)
2353 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
2354 int lypos = MICROLABEL_YPOS;
2356 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
2359 redraw_mask |= REDRAW_MICROLEVEL;
2362 void DrawMicroLevel(int xpos, int ypos, boolean restart)
2364 static unsigned long scroll_delay = 0;
2365 static unsigned long label_delay = 0;
2366 static int from_x, from_y, scroll_direction;
2367 static int label_state, label_counter;
2371 from_x = from_y = 0;
2372 scroll_direction = MV_RIGHT;
2376 DrawNewMicroLevelExt(xpos, ypos, from_x, from_y);
2377 DrawMicroLevelLabelExt(label_state);
2379 /* initialize delay counters */
2380 DelayReached(&scroll_delay, 0);
2381 DelayReached(&label_delay, 0);
2386 /* scroll micro level, if needed */
2387 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
2388 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
2390 switch (scroll_direction)
2396 scroll_direction = MV_UP;
2400 if (from_x < lev_fieldx - STD_LEV_FIELDX)
2403 scroll_direction = MV_DOWN;
2410 scroll_direction = MV_RIGHT;
2414 if (from_y < lev_fieldy - STD_LEV_FIELDY)
2417 scroll_direction = MV_LEFT;
2424 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
2427 /* redraw micro level label, if needed */
2428 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
2429 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
2430 strcmp(level.author, leveldir_current->name) != 0 &&
2431 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
2433 int max_label_counter = 23;
2435 if (leveldir_current->imported_from != NULL)
2436 max_label_counter += 14;
2438 label_counter = (label_counter + 1) % max_label_counter;
2439 label_state = (label_counter >= 0 && label_counter <= 7 ?
2440 MICROLABEL_LEVEL_NAME :
2441 label_counter >= 9 && label_counter <= 12 ?
2442 MICROLABEL_CREATED_BY :
2443 label_counter >= 14 && label_counter <= 21 ?
2444 MICROLABEL_LEVEL_AUTHOR :
2445 label_counter >= 23 && label_counter <= 26 ?
2446 MICROLABEL_IMPORTED_FROM :
2447 label_counter >= 28 && label_counter <= 35 ?
2448 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
2449 DrawMicroLevelLabelExt(label_state);
2453 int REQ_in_range(int x, int y)
2455 if (y > DY+249 && y < DY+278)
2457 if (x > DX+1 && x < DX+48)
2459 else if (x > DX+51 && x < DX+98)
2465 #define MAX_REQUEST_LINES 13
2466 #define MAX_REQUEST_LINE_LEN 7
2468 boolean Request(char *text, unsigned int req_state)
2470 int mx, my, ty, result = -1;
2471 unsigned int old_door_state;
2473 #if defined(PLATFORM_UNIX)
2474 /* pause network game while waiting for request to answer */
2475 if (options.network &&
2476 game_status == PLAYING &&
2477 req_state & REQUEST_WAIT_FOR)
2478 SendToServer_PausePlaying();
2481 old_door_state = GetDoorState();
2485 CloseDoor(DOOR_CLOSE_1);
2487 /* save old door content */
2488 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2489 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2490 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2492 /* clear door drawing field */
2493 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
2495 /* write text for request */
2496 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2498 char text_line[MAX_REQUEST_LINE_LEN + 1];
2504 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2507 if (!tc || tc == ' ')
2518 strncpy(text_line, text, tl);
2521 DrawTextExt(drawto, DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2522 text_line, FS_SMALL, FC_YELLOW);
2524 text += tl + (tc == ' ' ? 1 : 0);
2527 if (req_state & REQ_ASK)
2529 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2530 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2532 else if (req_state & REQ_CONFIRM)
2534 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2536 else if (req_state & REQ_PLAYER)
2538 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2539 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2540 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2541 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2544 /* copy request gadgets to door backbuffer */
2545 BlitBitmap(drawto, pix[PIX_DB_DOOR],
2546 DX, DY, DXSIZE, DYSIZE,
2547 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2549 OpenDoor(DOOR_OPEN_1);
2555 if (!(req_state & REQUEST_WAIT_FOR))
2558 if (game_status != MAINMENU)
2561 button_status = MB_RELEASED;
2563 request_gadget_id = -1;
2575 case EVENT_BUTTONPRESS:
2576 case EVENT_BUTTONRELEASE:
2577 case EVENT_MOTIONNOTIFY:
2579 if (event.type == EVENT_MOTIONNOTIFY)
2581 if (!PointerInWindow(window))
2582 continue; /* window and pointer are on different screens */
2587 motion_status = TRUE;
2588 mx = ((MotionEvent *) &event)->x;
2589 my = ((MotionEvent *) &event)->y;
2593 motion_status = FALSE;
2594 mx = ((ButtonEvent *) &event)->x;
2595 my = ((ButtonEvent *) &event)->y;
2596 if (event.type == EVENT_BUTTONPRESS)
2597 button_status = ((ButtonEvent *) &event)->button;
2599 button_status = MB_RELEASED;
2602 /* this sets 'request_gadget_id' */
2603 HandleGadgets(mx, my, button_status);
2605 switch(request_gadget_id)
2607 case TOOL_CTRL_ID_YES:
2610 case TOOL_CTRL_ID_NO:
2613 case TOOL_CTRL_ID_CONFIRM:
2614 result = TRUE | FALSE;
2617 case TOOL_CTRL_ID_PLAYER_1:
2620 case TOOL_CTRL_ID_PLAYER_2:
2623 case TOOL_CTRL_ID_PLAYER_3:
2626 case TOOL_CTRL_ID_PLAYER_4:
2637 case EVENT_KEYPRESS:
2638 switch(GetEventKey((KeyEvent *)&event, TRUE))
2651 if (req_state & REQ_PLAYER)
2655 case EVENT_KEYRELEASE:
2656 ClearPlayerAction();
2660 HandleOtherEvents(&event);
2664 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2666 int joy = AnyJoystick();
2668 if (joy & JOY_BUTTON_1)
2670 else if (joy & JOY_BUTTON_2)
2676 /* don't eat all CPU time */
2680 if (game_status != MAINMENU)
2685 if (!(req_state & REQ_STAY_OPEN))
2687 CloseDoor(DOOR_CLOSE_1);
2689 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2691 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2692 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2693 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2694 OpenDoor(DOOR_OPEN_1);
2700 #if defined(PLATFORM_UNIX)
2701 /* continue network game after request */
2702 if (options.network &&
2703 game_status == PLAYING &&
2704 req_state & REQUEST_WAIT_FOR)
2705 SendToServer_ContinuePlaying();
2711 unsigned int OpenDoor(unsigned int door_state)
2713 unsigned int new_door_state;
2715 if (door_state & DOOR_COPY_BACK)
2717 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
2718 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2719 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2720 door_state &= ~DOOR_COPY_BACK;
2723 new_door_state = MoveDoor(door_state);
2725 return(new_door_state);
2728 unsigned int CloseDoor(unsigned int door_state)
2730 unsigned int new_door_state;
2732 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2733 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2734 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
2735 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2737 new_door_state = MoveDoor(door_state);
2739 return(new_door_state);
2742 unsigned int GetDoorState()
2744 return MoveDoor(DOOR_GET_STATE);
2747 unsigned int SetDoorState(unsigned int door_state)
2749 return MoveDoor(door_state | DOOR_SET_STATE);
2752 unsigned int MoveDoor(unsigned int door_state)
2754 static int door1 = DOOR_OPEN_1;
2755 static int door2 = DOOR_CLOSE_2;
2756 static unsigned long door_delay = 0;
2757 int x, start, stepsize = 2;
2758 unsigned long door_delay_value = stepsize * 5;
2760 if (door_state == DOOR_GET_STATE)
2761 return(door1 | door2);
2763 if (door_state & DOOR_SET_STATE)
2765 if (door_state & DOOR_ACTION_1)
2766 door1 = door_state & DOOR_ACTION_1;
2767 if (door_state & DOOR_ACTION_2)
2768 door2 = door_state & DOOR_ACTION_2;
2770 return(door1 | door2);
2773 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2774 door_state &= ~DOOR_OPEN_1;
2775 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2776 door_state &= ~DOOR_CLOSE_1;
2777 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2778 door_state &= ~DOOR_OPEN_2;
2779 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2780 door_state &= ~DOOR_CLOSE_2;
2782 if (setup.quick_doors)
2785 door_delay_value = 0;
2786 StopSound(SND_MENU_DOOR_OPENING);
2787 StopSound(SND_MENU_DOOR_CLOSING);
2790 if (door_state & DOOR_ACTION)
2792 if (!(door_state & DOOR_NO_DELAY))
2794 /* opening door sound has priority over simultaneously closing door */
2795 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2796 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2797 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2798 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2801 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2803 for(x=start; x<=DXSIZE; x+=stepsize)
2805 Bitmap *bitmap = pix[PIX_DOOR];
2806 GC gc = bitmap->stored_clip_gc;
2808 WaitUntilDelayReached(&door_delay, door_delay_value);
2810 if (door_state & DOOR_ACTION_1)
2812 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2813 int j = (DXSIZE - i) / 3;
2815 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2816 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2817 DXSIZE,DYSIZE - i/2, DX, DY);
2819 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2821 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2822 BlitBitmapMasked(bitmap, drawto,
2823 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2824 DX + DXSIZE - i, DY + j);
2825 BlitBitmapMasked(bitmap, drawto,
2826 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2827 DX + DXSIZE - i, DY + 140 + j);
2828 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2829 BlitBitmapMasked(bitmap, drawto,
2830 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2832 BlitBitmapMasked(bitmap, drawto,
2833 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2836 BlitBitmapMasked(bitmap, drawto,
2837 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2839 BlitBitmapMasked(bitmap, drawto,
2840 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2842 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2843 BlitBitmapMasked(bitmap, drawto,
2844 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2845 DX + DXSIZE - i, DY + 77 + j);
2846 BlitBitmapMasked(bitmap, drawto,
2847 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2848 DX + DXSIZE - i, DY + 203 + j);
2850 redraw_mask |= REDRAW_DOOR_1;
2853 if (door_state & DOOR_ACTION_2)
2855 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2856 int j = (VXSIZE - i) / 3;
2858 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2859 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2860 VXSIZE, VYSIZE - i/2, VX, VY);
2862 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2864 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2865 BlitBitmapMasked(bitmap, drawto,
2866 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2867 VX + VXSIZE-i, VY+j);
2868 SetClipOrigin(bitmap, gc,
2869 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2870 BlitBitmapMasked(bitmap, drawto,
2871 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2874 BlitBitmapMasked(bitmap, drawto,
2875 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2876 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2877 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2878 BlitBitmapMasked(bitmap, drawto,
2879 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2881 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2883 redraw_mask |= REDRAW_DOOR_2;
2888 if (game_status == MAINMENU)
2893 if (setup.quick_doors)
2895 StopSound(SND_MENU_DOOR_OPENING);
2896 StopSound(SND_MENU_DOOR_CLOSING);
2899 if (door_state & DOOR_ACTION_1)
2900 door1 = door_state & DOOR_ACTION_1;
2901 if (door_state & DOOR_ACTION_2)
2902 door2 = door_state & DOOR_ACTION_2;
2904 return (door1 | door2);
2907 void DrawSpecialEditorDoor()
2909 /* draw bigger toolbox window */
2910 BlitBitmap(pix[PIX_DOOR], drawto,
2911 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2913 redraw_mask |= REDRAW_ALL;
2916 void UndrawSpecialEditorDoor()
2918 /* draw normal tape recorder window */
2919 BlitBitmap(pix[PIX_BACK], drawto,
2920 562, 344, 108, 56, EX - 4, EY - 12);
2922 redraw_mask |= REDRAW_ALL;
2926 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2928 XImage *pixel_image;
2929 unsigned long pixel_value;
2931 pixel_image = XGetImage(display, bitmap->drawable,
2932 x, y, 1, 1, AllPlanes, ZPixmap);
2933 pixel_value = XGetPixel(pixel_image, 0, 0);
2935 XDestroyImage(pixel_image);
2941 /* ---------- new tool button stuff ---------------------------------------- */
2943 /* graphic position values for tool buttons */
2944 #define TOOL_BUTTON_YES_XPOS 2
2945 #define TOOL_BUTTON_YES_YPOS 250
2946 #define TOOL_BUTTON_YES_GFX_YPOS 0
2947 #define TOOL_BUTTON_YES_XSIZE 46
2948 #define TOOL_BUTTON_YES_YSIZE 28
2949 #define TOOL_BUTTON_NO_XPOS 52
2950 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2951 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2952 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2953 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2954 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2955 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2956 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2957 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2958 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2959 #define TOOL_BUTTON_PLAYER_XSIZE 30
2960 #define TOOL_BUTTON_PLAYER_YSIZE 30
2961 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2962 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2963 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2964 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2965 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2966 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2967 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2968 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2969 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2970 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2971 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2972 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2973 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2974 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2975 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2976 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2977 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2978 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2979 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2980 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2989 } toolbutton_info[NUM_TOOL_BUTTONS] =
2992 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2993 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2994 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2999 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
3000 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
3001 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
3006 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
3007 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
3008 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
3009 TOOL_CTRL_ID_CONFIRM,
3013 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3014 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
3015 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3016 TOOL_CTRL_ID_PLAYER_1,
3020 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3021 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
3022 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3023 TOOL_CTRL_ID_PLAYER_2,
3027 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3028 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
3029 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3030 TOOL_CTRL_ID_PLAYER_3,
3034 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
3035 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
3036 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
3037 TOOL_CTRL_ID_PLAYER_4,
3042 void CreateToolButtons()
3046 for (i=0; i<NUM_TOOL_BUTTONS; i++)
3048 Bitmap *gd_bitmap = pix[PIX_DOOR];
3049 Bitmap *deco_bitmap = None;
3050 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
3051 struct GadgetInfo *gi;
3052 unsigned long event_mask;
3053 int gd_xoffset, gd_yoffset;
3054 int gd_x1, gd_x2, gd_y;
3057 event_mask = GD_EVENT_RELEASED;
3059 gd_xoffset = toolbutton_info[i].xpos;
3060 gd_yoffset = toolbutton_info[i].ypos;
3061 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
3062 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
3063 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
3065 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
3067 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
3068 &deco_bitmap, &deco_x, &deco_y);
3069 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
3070 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
3073 gi = CreateGadget(GDI_CUSTOM_ID, id,
3074 GDI_INFO_TEXT, toolbutton_info[i].infotext,
3075 GDI_X, DX + toolbutton_info[i].x,
3076 GDI_Y, DY + toolbutton_info[i].y,
3077 GDI_WIDTH, toolbutton_info[i].width,
3078 GDI_HEIGHT, toolbutton_info[i].height,
3079 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
3080 GDI_STATE, GD_BUTTON_UNPRESSED,
3081 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
3082 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
3083 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
3084 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
3085 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
3086 GDI_DECORATION_SHIFTING, 1, 1,
3087 GDI_EVENT_MASK, event_mask,
3088 GDI_CALLBACK_ACTION, HandleToolButtons,
3092 Error(ERR_EXIT, "cannot create gadget");
3094 tool_gadget[id] = gi;
3098 static void UnmapToolButtons()
3102 for (i=0; i<NUM_TOOL_BUTTONS; i++)
3103 UnmapGadget(tool_gadget[i]);
3106 static void HandleToolButtons(struct GadgetInfo *gi)
3108 request_gadget_id = gi->custom_id;
3111 int get_next_element(int element)
3115 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
3116 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
3117 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
3118 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
3119 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
3120 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
3121 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
3123 default: return element;
3127 int el2gfx_OLD(int element)
3131 case EL_EMPTY: return -1;
3132 case EL_SAND: return GFX_ERDREICH;
3133 case EL_WALL: return GFX_MAUERWERK;
3134 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
3135 case EL_ROCK: return GFX_FELSBROCKEN;
3136 case EL_EMERALD: return GFX_EDELSTEIN;
3137 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
3138 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
3139 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
3140 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
3141 case EL_PLAYER1: return GFX_SPIELER1;
3142 case EL_PLAYER2: return GFX_SPIELER2;
3143 case EL_PLAYER3: return GFX_SPIELER3;
3144 case EL_PLAYER4: return GFX_SPIELER4;
3145 case EL_BUG: return GFX_KAEFER;
3146 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
3147 case EL_BUG_UP: return GFX_KAEFER_UP;
3148 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
3149 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
3150 case EL_SPACESHIP: return GFX_FLIEGER;
3151 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
3152 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
3153 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
3154 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
3155 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
3156 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
3157 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
3158 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
3159 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
3160 case EL_BD_FIREFLY: return GFX_FIREFLY;
3161 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
3162 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
3163 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
3164 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
3165 case EL_YAMYAM: return GFX_MAMPFER;
3166 case EL_ROBOT: return GFX_ROBOT;
3167 case EL_STEELWALL: return GFX_BETON;
3168 case EL_DIAMOND: return GFX_DIAMANT;
3169 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
3170 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
3171 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
3172 case EL_AMOEBA_DROP: return GFX_TROPFEN;
3173 case EL_BOMB: return GFX_BOMBE;
3174 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
3175 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
3176 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
3177 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
3178 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
3179 case EL_ACID: return GFX_SALZSAEURE;
3180 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
3181 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
3182 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
3183 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
3184 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
3185 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
3186 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
3187 case EL_NUT: return GFX_KOKOSNUSS;
3188 case EL_GAMEOFLIFE: return GFX_LIFE;
3189 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
3190 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
3191 case EL_STONEBLOCK: return GFX_BADEWANNE;
3192 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
3193 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
3194 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
3195 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
3196 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
3197 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
3198 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
3199 case EL_KEY1: return GFX_SCHLUESSEL1;
3200 case EL_KEY2: return GFX_SCHLUESSEL2;
3201 case EL_KEY3: return GFX_SCHLUESSEL3;
3202 case EL_KEY4: return GFX_SCHLUESSEL4;
3203 case EL_GATE1: return GFX_PFORTE1;
3204 case EL_GATE2: return GFX_PFORTE2;
3205 case EL_GATE3: return GFX_PFORTE3;
3206 case EL_GATE4: return GFX_PFORTE4;
3207 case EL_GATE1_GRAY: return GFX_PFORTE1X;
3208 case EL_GATE2_GRAY: return GFX_PFORTE2X;
3209 case EL_GATE3_GRAY: return GFX_PFORTE3X;
3210 case EL_GATE4_GRAY: return GFX_PFORTE4X;
3211 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
3212 case EL_PACMAN: return GFX_PACMAN;
3213 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
3214 case EL_PACMAN_UP: return GFX_PACMAN_UP;
3215 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
3216 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
3217 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
3218 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
3219 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
3220 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
3221 case EL_LAMP: return GFX_BIRNE_AUS;
3222 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
3223 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
3224 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
3225 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
3226 case EL_WALL_GROWING_X: return GFX_MAUER_X;
3227 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
3228 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
3229 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
3230 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
3231 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
3232 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
3233 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
3234 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
3235 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
3236 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
3237 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
3238 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
3239 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
3240 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
3241 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
3242 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
3243 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
3244 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
3245 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
3246 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
3247 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
3248 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
3249 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
3250 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
3251 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
3252 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
3253 case EL_MOLE: return GFX_MOLE;
3254 case EL_PENGUIN: return GFX_PINGUIN;
3255 case EL_PIG: return GFX_SCHWEIN;
3256 case EL_DRAGON: return GFX_DRACHE;
3257 case EL_SATELLITE: return GFX_SONDE;
3258 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
3259 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
3260 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
3261 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
3262 case EL_SPEED_PILL: return GFX_SPEED_PILL;
3263 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
3264 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
3265 case EL_SP_ZONK: return GFX_SP_ZONK;
3266 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
3267 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
3268 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
3269 case EL_BLACK_ORB: return GFX_BLACK_ORB;
3270 case EL_EM_GATE1: return GFX_EM_GATE_1;
3271 case EL_EM_GATE2: return GFX_EM_GATE_2;
3272 case EL_EM_GATE3: return GFX_EM_GATE_3;
3273 case EL_EM_GATE4: return GFX_EM_GATE_4;
3274 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
3275 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
3276 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
3277 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
3278 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
3279 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
3280 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
3281 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
3282 case EL_EM_KEY1: return GFX_EM_KEY_1;
3283 case EL_EM_KEY2: return GFX_EM_KEY_2;
3284 case EL_EM_KEY3: return GFX_EM_KEY_3;
3285 case EL_EM_KEY4: return GFX_EM_KEY_4;
3286 case EL_PEARL: return GFX_PEARL;
3287 case EL_CRYSTAL: return GFX_CRYSTAL;
3288 case EL_WALL_PEARL: return GFX_WALL_PEARL;
3289 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
3290 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
3291 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
3292 case EL_KEY_WHITE: return GFX_KEY_WHITE;
3293 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
3294 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
3295 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
3296 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
3297 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
3298 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
3299 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
3300 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
3301 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
3302 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
3303 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
3304 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
3305 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
3306 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
3307 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
3308 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
3309 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
3310 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
3311 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
3312 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
3313 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
3314 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
3315 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
3316 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
3317 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
3318 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
3319 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
3320 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
3321 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
3322 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
3323 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
3324 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
3325 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
3326 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
3327 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
3328 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
3329 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
3330 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
3331 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
3332 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
3333 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
3334 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
3335 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
3336 case EL_LANDMINE: return GFX_LANDMINE;
3337 case EL_ENVELOPE: return GFX_ENVELOPE;
3338 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
3339 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
3340 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
3341 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
3342 case EL_SIGN_STOP: return GFX_SIGN_STOP;
3343 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
3344 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
3345 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
3346 case EL_SIGN_HEART: return GFX_SIGN_HEART;
3347 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
3348 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
3349 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
3350 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
3351 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
3352 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
3353 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
3354 case EL_MOLE_UP: return GFX_MOLE_UP;
3355 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
3356 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
3357 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
3358 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
3359 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
3360 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
3361 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
3362 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
3363 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
3364 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
3365 case EL_BALLOON: return GFX_BALLOON;
3366 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
3367 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
3368 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
3369 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
3370 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
3371 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
3372 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
3373 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
3374 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
3375 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
3376 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
3377 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
3378 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
3379 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
3380 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
3381 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
3382 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
3383 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
3384 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
3385 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
3386 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
3387 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
3388 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
3389 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
3390 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
3391 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
3392 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
3393 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
3394 case EL_SPRING: return GFX_SPRING;
3395 case EL_SPRING_MOVING: return GFX_SPRING;
3396 case EL_TRAP: return GFX_TRAP_INACTIVE;
3397 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
3398 case EL_BD_WALL: return GFX_BD_WALL;
3399 case EL_BD_ROCK: return GFX_BD_ROCK;
3400 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
3401 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
3405 if (IS_CHAR(element))
3406 return GFX_CHAR_START + (element - EL_CHAR_START);
3407 else if (element >= EL_SP_START && element <= EL_SP_END)
3409 int nr_element = element - EL_SP_START;
3410 int gfx_per_line = 8;
3412 (nr_element / gfx_per_line) * SP_PER_LINE +
3413 (nr_element % gfx_per_line);
3415 return GFX_START_ROCKSSP + nr_graphic;
3423 int el2gfx(int element)
3426 int graphic_OLD = el2gfx_OLD(element);
3431 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3434 int graphic_OLD = el2gfx_OLD(element);
3436 if (element >= MAX_ELEMENTS)
3438 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
3441 if (graphic_NEW != graphic_OLD)
3443 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
3444 graphic_NEW, graphic_OLD);
3452 int el2img(int element)
3455 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
3458 if (graphic_NEW < 0)
3459 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
3460 element, graphic_NEW);
3468 case EL_BD_BUTTERFLY: return IMG_BD_BUTTERFLY;
3469 case EL_BD_FIREFLY: return IMG_BD_FIREFLY;
3470 case EL_SP_ELECTRON: return IMG_SP_ELECTRON;
3480 int el_dir2img(int element, int direction)
3482 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3485 int el_dir_act2img(int element, int direction, int action)
3487 action = graphics_action_mapping[action];
3488 direction = MV_DIR_BIT(direction);
3490 return element_info[element].direction_graphic[action][direction];