1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2001 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 #if defined(PLATFORM_MSDOS)
24 extern boolean wait_for_vsync;
27 /* tool button identifiers */
28 #define TOOL_CTRL_ID_YES 0
29 #define TOOL_CTRL_ID_NO 1
30 #define TOOL_CTRL_ID_CONFIRM 2
31 #define TOOL_CTRL_ID_PLAYER_1 3
32 #define TOOL_CTRL_ID_PLAYER_2 4
33 #define TOOL_CTRL_ID_PLAYER_3 5
34 #define TOOL_CTRL_ID_PLAYER_4 6
36 #define NUM_TOOL_BUTTONS 7
38 /* forward declaration for internal use */
39 static int getGraphicAnimationPhase(int, int, int);
40 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
42 static void UnmapToolButtons();
43 static void HandleToolButtons(struct GadgetInfo *);
45 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
46 static int request_gadget_id = -1;
48 void SetDrawtoField(int mode)
50 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
61 drawto_field = fieldbuffer;
63 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
74 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
81 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
83 if (setup.direct_draw && game_status == PLAYING)
84 redraw_mask &= ~REDRAW_MAIN;
86 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
87 redraw_mask |= REDRAW_FIELD;
89 if (redraw_mask & REDRAW_FIELD)
90 redraw_mask &= ~REDRAW_TILES;
95 if (global.fps_slowdown && game_status == PLAYING)
97 static boolean last_frame_skipped = FALSE;
98 boolean skip_even_when_not_scrolling = TRUE;
99 boolean just_scrolling = (ScreenMovDir != 0);
100 boolean verbose = FALSE;
102 if (global.fps_slowdown_factor > 1 &&
103 (FrameCounter % global.fps_slowdown_factor) &&
104 (just_scrolling || skip_even_when_not_scrolling))
106 redraw_mask &= ~REDRAW_MAIN;
108 last_frame_skipped = TRUE;
111 printf("FRAME SKIPPED\n");
115 if (last_frame_skipped)
116 redraw_mask |= REDRAW_FIELD;
118 last_frame_skipped = FALSE;
121 printf("frame not skipped\n");
125 /* synchronize X11 graphics at this point; if we would synchronize the
126 display immediately after the buffer switching (after the XFlush),
127 this could mean that we have to wait for the graphics to complete,
128 although we could go on doing calculations for the next frame */
132 if (redraw_mask & REDRAW_ALL)
134 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
138 if (redraw_mask & REDRAW_FIELD)
140 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
142 BlitBitmap(backbuffer, window,
143 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
147 int fx = FX, fy = FY;
149 if (setup.soft_scrolling)
151 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
152 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
155 if (setup.soft_scrolling ||
156 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
157 ABS(ScreenMovPos) == ScrollStepSize ||
158 redraw_tiles > REDRAWTILES_THRESHOLD)
160 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
164 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
166 (setup.soft_scrolling ?
167 "setup.soft_scrolling" :
168 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
169 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
170 ABS(ScreenGfxPos) == ScrollStepSize ?
171 "ABS(ScreenGfxPos) == ScrollStepSize" :
172 "redraw_tiles > REDRAWTILES_THRESHOLD"));
178 redraw_mask &= ~REDRAW_MAIN;
181 if (redraw_mask & REDRAW_DOORS)
183 if (redraw_mask & REDRAW_DOOR_1)
184 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
185 if (redraw_mask & REDRAW_DOOR_2)
187 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
188 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
191 if (redraw_mask & REDRAW_VIDEO_1)
192 BlitBitmap(backbuffer, window,
193 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
194 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
195 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
196 if (redraw_mask & REDRAW_VIDEO_2)
197 BlitBitmap(backbuffer, window,
198 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
199 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
200 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
201 if (redraw_mask & REDRAW_VIDEO_3)
202 BlitBitmap(backbuffer, window,
203 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
204 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
205 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
208 if (redraw_mask & REDRAW_DOOR_3)
209 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
210 redraw_mask &= ~REDRAW_DOORS;
213 if (redraw_mask & REDRAW_MICROLEVEL)
215 BlitBitmap(backbuffer, window,
216 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
217 MICROLEV_XPOS, MICROLEV_YPOS);
218 BlitBitmap(backbuffer, window,
219 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
220 SX, MICROLABEL_YPOS);
221 redraw_mask &= ~REDRAW_MICROLEVEL;
224 if (redraw_mask & REDRAW_TILES)
226 for(x=0; x<SCR_FIELDX; x++)
227 for(y=0; y<SCR_FIELDY; y++)
228 if (redraw[redraw_x1 + x][redraw_y1 + y])
229 BlitBitmap(buffer, window,
230 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
231 SX + x * TILEX, SY + y * TILEY);
234 if (redraw_mask & REDRAW_FPS) /* display frames per second */
239 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
240 if (!global.fps_slowdown)
243 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
244 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW);
249 for(x=0; x<MAX_BUF_XSIZE; x++)
250 for(y=0; y<MAX_BUF_YSIZE; y++)
259 long fading_delay = 300;
261 if (setup.fading && (redraw_mask & REDRAW_FIELD))
268 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
271 for(i=0;i<2*FULL_SYSIZE;i++)
273 for(y=0;y<FULL_SYSIZE;y++)
275 BlitBitmap(backbuffer, window,
276 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
284 for(i=1;i<FULL_SYSIZE;i+=2)
285 BlitBitmap(backbuffer, window,
286 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
292 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
293 BlitBitmapMasked(backbuffer, window,
294 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
299 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
300 BlitBitmapMasked(backbuffer, window,
301 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
306 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
307 BlitBitmapMasked(backbuffer, window,
308 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
313 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
314 BlitBitmapMasked(backbuffer, window,
315 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
320 redraw_mask &= ~REDRAW_MAIN;
329 ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
331 if (setup.soft_scrolling && game_status == PLAYING)
333 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
334 SetDrawtoField(DRAW_BUFFERED);
337 SetDrawtoField(DRAW_BACKBUFFER);
339 if (setup.direct_draw && game_status == PLAYING)
341 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
342 SetDrawtoField(DRAW_DIRECT);
345 redraw_mask |= REDRAW_FIELD;
348 void MarkTileDirty(int x, int y)
350 int xx = redraw_x1 + x;
351 int yy = redraw_y1 + y;
356 redraw[xx][yy] = TRUE;
357 redraw_mask |= REDRAW_TILES;
360 void SetBorderElement()
364 BorderElement = EL_LEERRAUM;
366 for(y=0; y<lev_fieldy && BorderElement == EL_LEERRAUM; y++)
368 for(x=0; x<lev_fieldx; x++)
370 if (!IS_MASSIVE(Feld[x][y]))
371 BorderElement = EL_BETON;
373 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
379 void DrawAllPlayers()
383 for(i=0; i<MAX_PLAYERS; i++)
384 if (stored_player[i].active)
385 DrawPlayer(&stored_player[i]);
388 void DrawPlayerField(int x, int y)
390 if (!IS_PLAYER(x, y))
393 DrawPlayer(PLAYERINFO(x, y));
396 void DrawPlayer(struct PlayerInfo *player)
398 int jx = player->jx, jy = player->jy;
399 int last_jx = player->last_jx, last_jy = player->last_jy;
400 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
401 int sx = SCREENX(jx), sy = SCREENY(jy);
402 int sxx = 0, syy = 0;
403 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
405 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
407 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
411 if (!IN_LEV_FIELD(jx,jy))
413 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
414 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
415 printf("DrawPlayerField(): This should never happen!\n");
420 if (element == EL_EXPLODING)
423 /* draw things in the field the player is leaving, if needed */
425 if (player_is_moving)
427 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
429 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
430 if (last_element == EL_DYNAMITE_ACTIVE)
431 DrawDynamite(last_jx, last_jy);
433 DrawLevelFieldThruMask(last_jx, last_jy);
435 else if (last_element == EL_DYNAMITE_ACTIVE)
436 DrawDynamite(last_jx, last_jy);
438 DrawLevelField(last_jx, last_jy);
440 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
444 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
445 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
447 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
450 DrawLevelField(next_jx, next_jy);
454 if (!IN_SCR_FIELD(sx, sy))
457 if (setup.direct_draw)
458 SetDrawtoField(DRAW_BUFFERED);
460 /* draw things behind the player, if needed */
463 DrawLevelElement(jx, jy, Store[jx][jy]);
464 else if (!IS_ACTIVE_BOMB(element))
465 DrawLevelField(jx, jy);
467 DrawLevelElement(jx, jy, EL_LEERRAUM);
469 /* draw player himself */
471 if (game.emulation == EMU_SUPAPLEX)
473 static int last_dir = MV_LEFT;
474 int action = (player->programmed_action ? player->programmed_action :
476 boolean action_moving =
478 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
479 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
481 graphic = GFX_SP_MURPHY;
485 if (player->MovDir == MV_LEFT)
486 graphic = GFX_MURPHY_PUSH_LEFT;
487 else if (player->MovDir == MV_RIGHT)
488 graphic = GFX_MURPHY_PUSH_RIGHT;
489 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
490 graphic = GFX_MURPHY_PUSH_LEFT;
491 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
492 graphic = GFX_MURPHY_PUSH_RIGHT;
494 else if (player->snapped)
496 if (player->MovDir == MV_LEFT)
497 graphic = GFX_MURPHY_SNAP_LEFT;
498 else if (player->MovDir == MV_RIGHT)
499 graphic = GFX_MURPHY_SNAP_RIGHT;
500 else if (player->MovDir == MV_UP)
501 graphic = GFX_MURPHY_SNAP_UP;
502 else if (player->MovDir == MV_DOWN)
503 graphic = GFX_MURPHY_SNAP_DOWN;
505 else if (action_moving)
507 if (player->MovDir == MV_LEFT)
508 graphic = GFX_MURPHY_GO_LEFT;
509 else if (player->MovDir == MV_RIGHT)
510 graphic = GFX_MURPHY_GO_RIGHT;
511 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
512 graphic = GFX_MURPHY_GO_LEFT;
513 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
514 graphic = GFX_MURPHY_GO_RIGHT;
516 graphic = GFX_MURPHY_GO_LEFT;
518 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
521 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
522 last_dir = player->MovDir;
526 if (player->MovDir == MV_LEFT)
528 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
529 else if (player->MovDir == MV_RIGHT)
531 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
532 else if (player->MovDir == MV_UP)
533 graphic = GFX_SPIELER1_UP;
534 else /* MV_DOWN || MV_NO_MOVING */
535 graphic = GFX_SPIELER1_DOWN;
537 graphic += player->index_nr * 3 * HEROES_PER_LINE;
538 graphic += player->Frame;
543 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
544 sxx = player->GfxPos;
546 syy = player->GfxPos;
549 if (!setup.soft_scrolling && ScreenMovPos)
552 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
554 if (SHIELD_ON(player))
556 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
557 GFX2_SHIELD_PASSIVE);
559 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
560 3, 8, ANIM_OSCILLATE);
563 if (player->Pushing && player->GfxPos)
565 int px = SCREENX(next_jx), py = SCREENY(next_jy);
567 if (element == EL_SOKOBAN_FELD_LEER ||
568 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
569 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
573 int element = Feld[next_jx][next_jy];
574 int graphic = el2gfx(element);
576 if ((element == EL_FELSBROCKEN ||
577 element == EL_SP_ZONK ||
578 element == EL_BD_ROCK) && sxx)
580 int phase = (player->GfxPos / (TILEX / 4));
582 if (player->MovDir == MV_LEFT)
585 graphic += (phase + 4) % 4;
588 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
592 /* draw things in front of player (active dynamite or dynabombs) */
594 if (IS_ACTIVE_BOMB(element))
596 graphic = el2gfx(element);
598 if (element == EL_DYNAMITE_ACTIVE)
600 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
605 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
609 if (game.emulation == EMU_SUPAPLEX)
610 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
612 DrawGraphicThruMask(sx, sy, graphic + phase);
615 if (player_is_moving && last_element == EL_EXPLODING)
617 int phase = Frame[last_jx][last_jy];
621 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
622 GFX_EXPLOSION + ((phase - 1) / delay - 1));
625 /* draw elements that stay over the player */
626 /* handle the field the player is leaving ... */
627 if (player_is_moving && IS_OVER_PLAYER(last_element))
628 DrawLevelField(last_jx, last_jy);
629 /* ... and the field the player is entering */
630 if (IS_OVER_PLAYER(element))
631 DrawLevelField(jx, jy);
633 if (setup.direct_draw)
635 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
636 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
637 int x_size = TILEX * (1 + ABS(jx - last_jx));
638 int y_size = TILEY * (1 + ABS(jy - last_jy));
640 BlitBitmap(drawto_field, window,
641 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
642 SetDrawtoField(DRAW_DIRECT);
645 MarkTileDirty(sx,sy);
648 static int getGraphicAnimationPhase(int frames, int delay, int mode)
652 if (mode == ANIM_OSCILLATE)
654 int max_anim_frames = 2 * frames - 2;
655 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
656 phase = (phase < frames ? phase : max_anim_frames - phase);
659 phase = (FrameCounter % (delay * frames)) / delay;
661 if (mode == ANIM_REVERSE)
667 void DrawGraphicAnimationExt(int x, int y, int graphic,
668 int frames, int delay, int mode, int mask_mode)
670 int phase = getGraphicAnimationPhase(frames, delay, mode);
672 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
674 if (mask_mode == USE_MASKING)
675 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
677 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
681 void DrawGraphicAnimation(int x, int y, int graphic,
682 int frames, int delay, int mode)
684 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
687 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
688 int frames, int delay, int mode)
690 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
693 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
696 int frames, int delay,
699 int phase = getGraphicAnimationPhase(frames, delay, mode);
701 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
704 void getGraphicSource(int graphic, int *bitmap_nr, int *x, int *y)
706 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
708 graphic -= GFX_START_ROCKSSCREEN;
709 *bitmap_nr = PIX_BACK;
710 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
711 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
713 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
715 graphic -= GFX_START_ROCKSHEROES;
716 *bitmap_nr = PIX_HEROES;
717 *x = (graphic % HEROES_PER_LINE) * TILEX;
718 *y = (graphic / HEROES_PER_LINE) * TILEY;
720 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
722 graphic -= GFX_START_ROCKSSP;
724 *x = (graphic % SP_PER_LINE) * TILEX;
725 *y = (graphic / SP_PER_LINE) * TILEY;
727 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
729 graphic -= GFX_START_ROCKSDC;
731 *x = (graphic % DC_PER_LINE) * TILEX;
732 *y = (graphic / DC_PER_LINE) * TILEY;
734 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
736 graphic -= GFX_START_ROCKSMORE;
737 *bitmap_nr = PIX_MORE;
738 *x = (graphic % MORE_PER_LINE) * TILEX;
739 *y = (graphic / MORE_PER_LINE) * TILEY;
741 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
743 graphic -= GFX_START_ROCKSFONT;
744 *bitmap_nr = PIX_BIGFONT;
745 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
746 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
747 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
757 void DrawGraphic(int x, int y, int graphic)
760 if (!IN_SCR_FIELD(x,y))
762 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
763 printf("DrawGraphic(): This should never happen!\n");
768 DrawGraphicExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
772 void DrawGraphicExt(DrawBuffer *bitmap, int x, int y, int graphic)
777 getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
778 BlitBitmap(pix[bitmap_nr], bitmap, src_x, src_y, TILEX, TILEY, x, y);
781 void DrawGraphicThruMask(int x, int y, int graphic)
784 if (!IN_SCR_FIELD(x,y))
786 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
787 printf("DrawGraphicThruMask(): This should never happen!\n");
792 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
796 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic)
804 if (graphic == GFX_LEERRAUM)
807 getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
808 src_bitmap = pix[bitmap_nr];
809 drawing_gc = pix[bitmap_nr]->stored_clip_gc;
811 if (tile_clipmask[tile] != None)
813 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
814 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
815 BlitBitmapMasked(src_bitmap, d,
816 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
822 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
826 SetClipOrigin(src_bitmap, drawing_gc, dest_x-src_x, dest_y-src_y);
827 BlitBitmapMasked(src_bitmap, d,
828 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
832 void DrawMiniGraphic(int x, int y, int graphic)
834 DrawMiniGraphicExt(drawto, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
835 MarkTileDirty(x/2, y/2);
838 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
840 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
842 graphic -= GFX_START_ROCKSSCREEN;
843 *bitmap = pix[PIX_BACK];
844 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
845 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
847 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
849 graphic -= GFX_START_ROCKSSP;
850 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
851 *bitmap = pix[PIX_SP];
852 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
853 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
855 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
857 graphic -= GFX_START_ROCKSDC;
858 *bitmap = pix[PIX_DC];
859 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
860 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
862 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
864 graphic -= GFX_START_ROCKSMORE;
865 *bitmap = pix[PIX_MORE];
866 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
867 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
869 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
871 graphic -= GFX_START_ROCKSFONT;
872 *bitmap = pix[PIX_SMALLFONT];
873 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
874 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
875 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
879 *bitmap = pix[PIX_SP];
885 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
890 getMiniGraphicSource(graphic, &bitmap, &src_x, &src_y);
891 BlitBitmap(bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
894 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
895 int cut_mode, int mask_mode)
897 int width = TILEX, height = TILEY;
899 int src_x, src_y, dest_x, dest_y;
907 DrawGraphic(x, y, graphic);
911 if (dx || dy) /* Verschiebung der Grafik? */
913 if (x < BX1) /* Element kommt von links ins Bild */
920 else if (x > BX2) /* Element kommt von rechts ins Bild */
926 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
932 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
934 else if (dx) /* allg. Bewegung in x-Richtung */
935 MarkTileDirty(x + SIGN(dx), y);
937 if (y < BY1) /* Element kommt von oben ins Bild */
939 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
947 else if (y > BY2) /* Element kommt von unten ins Bild */
953 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
959 else if (dy > 0 && cut_mode == CUT_ABOVE)
961 if (y == BY2) /* Element unterhalb des Bildes */
967 MarkTileDirty(x, y + 1);
968 } /* Element verläßt unten das Bild */
969 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
971 else if (dy) /* allg. Bewegung in y-Richtung */
972 MarkTileDirty(x, y + SIGN(dy));
975 getGraphicSource(graphic, &bitmap_nr, &src_x, &src_y);
976 src_bitmap = pix[bitmap_nr];
977 drawing_gc = pix[bitmap_nr]->stored_clip_gc;
982 dest_x = FX + x * TILEX + dx;
983 dest_y = FY + y * TILEY + dy;
986 if (!IN_SCR_FIELD(x,y))
988 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
989 printf("DrawGraphicShifted(): This should never happen!\n");
994 if (mask_mode == USE_MASKING)
996 if (tile_clipmask[tile] != None)
998 SetClipMask(src_bitmap, tile_clip_gc, tile_clipmask[tile]);
999 SetClipOrigin(src_bitmap, tile_clip_gc, dest_x, dest_y);
1000 BlitBitmapMasked(src_bitmap, drawto_field,
1001 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1007 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1011 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1012 BlitBitmapMasked(src_bitmap, drawto_field,
1013 src_x, src_y, width, height, dest_x, dest_y);
1017 BlitBitmap(pix[bitmap_nr], drawto_field,
1018 src_x, src_y, width, height, dest_x, dest_y);
1023 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1026 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1029 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1030 int cut_mode, int mask_mode)
1032 int ux = LEVELX(x), uy = LEVELY(y);
1033 int graphic = el2gfx(element);
1034 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1035 int phase4 = phase8 / 2;
1036 int phase2 = phase8 / 4;
1037 int dir = MovDir[ux][uy];
1039 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1041 graphic += 4 * !phase2;
1045 else if (dir == MV_LEFT)
1047 else if (dir == MV_DOWN)
1050 else if (element == EL_SP_SNIKSNAK)
1053 graphic = GFX_SP_SNIKSNAK_LEFT;
1054 else if (dir == MV_RIGHT)
1055 graphic = GFX_SP_SNIKSNAK_RIGHT;
1056 else if (dir == MV_UP)
1057 graphic = GFX_SP_SNIKSNAK_UP;
1059 graphic = GFX_SP_SNIKSNAK_DOWN;
1061 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1063 else if (element == EL_SP_ELECTRON)
1065 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1067 else if (element == EL_MOLE || element == EL_PINGUIN ||
1068 element == EL_SCHWEIN || element == EL_DRACHE)
1071 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1072 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1073 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1074 else if (dir == MV_RIGHT)
1075 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1076 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1077 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1078 else if (dir == MV_UP)
1079 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1080 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1081 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1083 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1084 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1085 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1089 else if (element == EL_SONDE)
1091 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1093 else if (element == EL_SALZSAEURE)
1095 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1097 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1101 else if (element == EL_BALLOON)
1105 else if ((element == EL_FELSBROCKEN ||
1106 element == EL_SP_ZONK ||
1107 element == EL_BD_ROCK ||
1108 element == EL_SP_INFOTRON ||
1112 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1114 if (element == EL_FELSBROCKEN ||
1115 element == EL_SP_ZONK ||
1116 element == EL_BD_ROCK)
1119 graphic += (4 - phase4) % 4;
1120 else if (dir == MV_RIGHT)
1123 graphic += phase2 * 2;
1125 else if (element != EL_SP_INFOTRON)
1129 else if (element == EL_MAGIC_WALL_EMPTY ||
1130 element == EL_MAGIC_WALL_EMPTYING ||
1131 element == EL_MAGIC_WALL_BD_EMPTY ||
1132 element == EL_MAGIC_WALL_BD_EMPTYING ||
1133 element == EL_MAGIC_WALL_FULL ||
1134 element == EL_MAGIC_WALL_BD_FULL)
1136 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1138 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1140 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1141 graphic += (x + 2 * y + 4) % 4;
1143 else if (element == EL_MAUER_LEBT)
1145 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1147 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1148 links_massiv = TRUE;
1149 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1150 rechts_massiv = TRUE;
1152 if (links_massiv && rechts_massiv)
1153 graphic = GFX_MAUERWERK;
1154 else if (links_massiv)
1155 graphic = GFX_MAUER_R;
1156 else if (rechts_massiv)
1157 graphic = GFX_MAUER_L;
1159 else if ((element == EL_INVISIBLE_STEEL ||
1160 element == EL_UNSICHTBAR ||
1161 element == EL_SAND_INVISIBLE) && game.light_time_left)
1163 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1164 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1165 GFX_SAND_INVISIBLE_ON);
1169 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1170 else if (mask_mode == USE_MASKING)
1171 DrawGraphicThruMask(x, y, graphic);
1173 DrawGraphic(x, y, graphic);
1176 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1177 int cut_mode, int mask_mode)
1179 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1180 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1181 cut_mode, mask_mode);
1184 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1187 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1190 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1193 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1196 void DrawScreenElementThruMask(int x, int y, int element)
1198 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1201 void DrawLevelElementThruMask(int x, int y, int element)
1203 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1206 void DrawLevelFieldThruMask(int x, int y)
1208 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1211 void ErdreichAnbroeckeln(int x, int y)
1213 int i, width, height, cx,cy;
1214 int ux = LEVELX(x), uy = LEVELY(y);
1215 int element, graphic;
1217 static int xy[4][2] =
1225 if (!IN_LEV_FIELD(ux, uy))
1228 element = Feld[ux][uy];
1230 if (element == EL_ERDREICH ||
1231 element == EL_LANDMINE ||
1232 element == EL_TRAP_INACTIVE ||
1233 element == EL_TRAP_ACTIVE)
1235 if (!IN_SCR_FIELD(x, y))
1238 graphic = GFX_ERDENRAND;
1244 uxx = ux + xy[i][0];
1245 uyy = uy + xy[i][1];
1246 if (!IN_LEV_FIELD(uxx, uyy))
1249 element = Feld[uxx][uyy];
1251 if (element == EL_ERDREICH ||
1252 element == EL_LANDMINE ||
1253 element == EL_TRAP_INACTIVE ||
1254 element == EL_TRAP_ACTIVE)
1257 if (i == 1 || i == 2)
1261 cx = (i == 2 ? TILEX - snip : 0);
1269 cy = (i == 3 ? TILEY - snip : 0);
1272 BlitBitmap(pix[PIX_BACK], drawto_field,
1273 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1274 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1275 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1278 MarkTileDirty(x, y);
1282 graphic = GFX_ERDENRAND;
1286 int xx, yy, uxx, uyy;
1290 uxx = ux + xy[i][0];
1291 uyy = uy + xy[i][1];
1293 if (!IN_LEV_FIELD(uxx, uyy) ||
1294 (Feld[uxx][uyy] != EL_ERDREICH &&
1295 Feld[uxx][uyy] != EL_LANDMINE &&
1296 Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1297 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1298 !IN_SCR_FIELD(xx, yy))
1301 if (i == 1 || i == 2)
1305 cx = (i == 1 ? TILEX - snip : 0);
1313 cy = (i==0 ? TILEY-snip : 0);
1316 BlitBitmap(pix[PIX_BACK], drawto_field,
1317 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1318 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1319 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1321 MarkTileDirty(xx, yy);
1326 void DrawScreenElement(int x, int y, int element)
1328 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1329 ErdreichAnbroeckeln(x, y);
1332 void DrawLevelElement(int x, int y, int element)
1334 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1335 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1338 void DrawScreenField(int x, int y)
1340 int ux = LEVELX(x), uy = LEVELY(y);
1341 int element, content;
1343 if (!IN_LEV_FIELD(ux, uy))
1345 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1346 element = EL_LEERRAUM;
1348 element = BorderElement;
1350 DrawScreenElement(x, y, element);
1354 element = Feld[ux][uy];
1355 content = Store[ux][uy];
1357 if (IS_MOVING(ux, uy))
1359 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1360 boolean cut_mode = NO_CUTTING;
1362 if (element == EL_QUICKSAND_EMPTYING ||
1363 element == EL_MAGIC_WALL_EMPTYING ||
1364 element == EL_MAGIC_WALL_BD_EMPTYING ||
1365 element == EL_AMOEBA_DRIPPING)
1366 cut_mode = CUT_ABOVE;
1367 else if (element == EL_QUICKSAND_FILLING ||
1368 element == EL_MAGIC_WALL_FILLING ||
1369 element == EL_MAGIC_WALL_BD_FILLING)
1370 cut_mode = CUT_BELOW;
1372 if (cut_mode == CUT_ABOVE)
1373 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1375 DrawScreenElement(x, y, EL_LEERRAUM);
1378 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1379 else if (cut_mode == NO_CUTTING)
1380 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1382 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1384 if (content == EL_SALZSAEURE)
1385 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1387 else if (IS_BLOCKED(ux, uy))
1392 boolean cut_mode = NO_CUTTING;
1393 int element_old, content_old;
1395 Blocked2Moving(ux, uy, &oldx, &oldy);
1398 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1399 MovDir[oldx][oldy] == MV_RIGHT);
1401 element_old = Feld[oldx][oldy];
1402 content_old = Store[oldx][oldy];
1404 if (element_old == EL_QUICKSAND_EMPTYING ||
1405 element_old == EL_MAGIC_WALL_EMPTYING ||
1406 element_old == EL_MAGIC_WALL_BD_EMPTYING ||
1407 element_old == EL_AMOEBA_DRIPPING)
1408 cut_mode = CUT_ABOVE;
1410 DrawScreenElement(x, y, EL_LEERRAUM);
1413 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1415 else if (cut_mode == NO_CUTTING)
1416 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1419 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1422 else if (IS_DRAWABLE(element))
1423 DrawScreenElement(x, y, element);
1425 DrawScreenElement(x, y, EL_LEERRAUM);
1428 void DrawLevelField(int x, int y)
1430 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1431 DrawScreenField(SCREENX(x), SCREENY(y));
1432 else if (IS_MOVING(x, y))
1436 Moving2Blocked(x, y, &newx, &newy);
1437 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1438 DrawScreenField(SCREENX(newx), SCREENY(newy));
1440 else if (IS_BLOCKED(x, y))
1444 Blocked2Moving(x, y, &oldx, &oldy);
1445 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1446 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1450 void DrawMiniElement(int x, int y, int element)
1456 DrawMiniGraphic(x, y, -1);
1460 graphic = el2gfx(element);
1461 DrawMiniGraphic(x, y, graphic);
1464 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1466 int x = sx + scroll_x, y = sy + scroll_y;
1468 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1469 DrawMiniElement(sx, sy, EL_LEERRAUM);
1470 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1471 DrawMiniElement(sx, sy, Feld[x][y]);
1474 int steel_type, steel_position;
1477 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1478 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1479 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1480 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1481 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1482 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1485 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1486 steel_position = (x == -1 && y == -1 ? 0 :
1487 x == lev_fieldx && y == -1 ? 1 :
1488 x == -1 && y == lev_fieldy ? 2 :
1489 x == lev_fieldx && y == lev_fieldy ? 3 :
1490 x == -1 || x == lev_fieldx ? 4 :
1491 y == -1 || y == lev_fieldy ? 5 : -1);
1493 if (steel_position != -1)
1494 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1498 void DrawMicroElement(int xpos, int ypos, int element)
1502 if (element == EL_LEERRAUM)
1505 graphic = el2gfx(element);
1507 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1509 graphic -= GFX_START_ROCKSSP;
1510 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1511 BlitBitmap(pix[PIX_SP], drawto,
1512 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1513 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1514 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1516 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1518 graphic -= GFX_START_ROCKSDC;
1519 BlitBitmap(pix[PIX_DC], drawto,
1520 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1521 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1522 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1524 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1526 graphic -= GFX_START_ROCKSMORE;
1527 BlitBitmap(pix[PIX_MORE], drawto,
1528 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE)*MICRO_TILEX,
1529 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE)*MICRO_TILEY,
1530 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1533 BlitBitmap(pix[PIX_BACK], drawto,
1534 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1535 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1536 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1545 for(x=BX1; x<=BX2; x++)
1546 for(y=BY1; y<=BY2; y++)
1547 DrawScreenField(x, y);
1549 redraw_mask |= REDRAW_FIELD;
1552 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1556 for(x=0; x<size_x; x++)
1557 for(y=0; y<size_y; y++)
1558 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1560 redraw_mask |= REDRAW_FIELD;
1563 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1567 ClearRectangle(drawto, xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1569 if (lev_fieldx < STD_LEV_FIELDX)
1570 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1571 if (lev_fieldy < STD_LEV_FIELDY)
1572 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1574 xpos += MICRO_TILEX;
1575 ypos += MICRO_TILEY;
1577 for(x=-1; x<=STD_LEV_FIELDX; x++)
1579 for(y=-1; y<=STD_LEV_FIELDY; y++)
1581 int lx = from_x + x, ly = from_y + y;
1583 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1584 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1586 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1587 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1592 redraw_mask |= REDRAW_MICROLEVEL;
1595 #define MICROLABEL_EMPTY 0
1596 #define MICROLABEL_LEVEL_NAME 1
1597 #define MICROLABEL_CREATED_BY 2
1598 #define MICROLABEL_LEVEL_AUTHOR 3
1599 #define MICROLABEL_IMPORTED_FROM 4
1600 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1602 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1604 static void DrawMicroLevelLabelExt(int mode)
1606 char label_text[MAX_MICROLABEL_SIZE + 1];
1608 ClearRectangle(drawto, SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1610 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1611 mode == MICROLABEL_CREATED_BY ? "created by" :
1612 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1613 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1614 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1615 leveldir_current->imported_from : ""),
1616 MAX_MICROLABEL_SIZE);
1617 label_text[MAX_MICROLABEL_SIZE] = '\0';
1619 if (strlen(label_text) > 0)
1621 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1622 int lypos = MICROLABEL_YPOS;
1624 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1627 redraw_mask |= REDRAW_MICROLEVEL;
1630 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1632 static unsigned long scroll_delay = 0;
1633 static unsigned long label_delay = 0;
1634 static int from_x, from_y, scroll_direction;
1635 static int label_state, label_counter;
1639 from_x = from_y = 0;
1640 scroll_direction = MV_RIGHT;
1644 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1645 DrawMicroLevelLabelExt(label_state);
1647 /* initialize delay counters */
1648 DelayReached(&scroll_delay, 0);
1649 DelayReached(&label_delay, 0);
1654 /* scroll micro level, if needed */
1655 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1656 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1658 switch (scroll_direction)
1664 scroll_direction = MV_UP;
1668 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1671 scroll_direction = MV_DOWN;
1678 scroll_direction = MV_RIGHT;
1682 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1685 scroll_direction = MV_LEFT;
1692 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1695 /* redraw micro level label, if needed */
1696 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1697 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1698 strcmp(level.author, leveldir_current->name) != 0 &&
1699 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1701 int max_label_counter = 23;
1703 if (leveldir_current->imported_from != NULL)
1704 max_label_counter += 14;
1706 label_counter = (label_counter + 1) % max_label_counter;
1707 label_state = (label_counter >= 0 && label_counter <= 7 ?
1708 MICROLABEL_LEVEL_NAME :
1709 label_counter >= 9 && label_counter <= 12 ?
1710 MICROLABEL_CREATED_BY :
1711 label_counter >= 14 && label_counter <= 21 ?
1712 MICROLABEL_LEVEL_AUTHOR :
1713 label_counter >= 23 && label_counter <= 26 ?
1714 MICROLABEL_IMPORTED_FROM :
1715 label_counter >= 28 && label_counter <= 35 ?
1716 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1717 DrawMicroLevelLabelExt(label_state);
1721 int REQ_in_range(int x, int y)
1723 if (y > DY+249 && y < DY+278)
1725 if (x > DX+1 && x < DX+48)
1727 else if (x > DX+51 && x < DX+98)
1733 boolean Request(char *text, unsigned int req_state)
1735 int mx, my, ty, result = -1;
1736 unsigned int old_door_state;
1738 #if defined(PLATFORM_UNIX)
1739 /* pause network game while waiting for request to answer */
1740 if (options.network &&
1741 game_status == PLAYING &&
1742 req_state & REQUEST_WAIT_FOR)
1743 SendToServer_PausePlaying();
1746 old_door_state = GetDoorState();
1750 CloseDoor(DOOR_CLOSE_1);
1752 /* save old door content */
1753 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1754 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1755 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1757 /* clear door drawing field */
1758 ClearRectangle(drawto, DX, DY, DXSIZE, DYSIZE);
1760 /* write text for request */
1761 for(ty=0; ty<13; ty++)
1769 for(tl=0,tx=0; tx<7; tl++,tx++)
1772 if (!tc || tc == 32)
1783 DrawTextExt(drawto, DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1784 txt, FS_SMALL, FC_YELLOW);
1785 text += tl + (tc == 32 ? 1 : 0);
1788 if (req_state & REQ_ASK)
1790 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1791 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1793 else if (req_state & REQ_CONFIRM)
1795 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1797 else if (req_state & REQ_PLAYER)
1799 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1800 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1801 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1802 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1805 /* copy request gadgets to door backbuffer */
1806 BlitBitmap(drawto, pix[PIX_DB_DOOR],
1807 DX, DY, DXSIZE, DYSIZE,
1808 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1810 OpenDoor(DOOR_OPEN_1);
1816 if (!(req_state & REQUEST_WAIT_FOR))
1819 if (game_status != MAINMENU)
1822 button_status = MB_RELEASED;
1824 request_gadget_id = -1;
1836 case EVENT_BUTTONPRESS:
1837 case EVENT_BUTTONRELEASE:
1838 case EVENT_MOTIONNOTIFY:
1840 if (event.type == EVENT_MOTIONNOTIFY)
1842 if (!PointerInWindow(window))
1843 continue; /* window and pointer are on different screens */
1848 motion_status = TRUE;
1849 mx = ((MotionEvent *) &event)->x;
1850 my = ((MotionEvent *) &event)->y;
1854 motion_status = FALSE;
1855 mx = ((ButtonEvent *) &event)->x;
1856 my = ((ButtonEvent *) &event)->y;
1857 if (event.type == EVENT_BUTTONPRESS)
1858 button_status = ((ButtonEvent *) &event)->button;
1860 button_status = MB_RELEASED;
1863 /* this sets 'request_gadget_id' */
1864 HandleGadgets(mx, my, button_status);
1866 switch(request_gadget_id)
1868 case TOOL_CTRL_ID_YES:
1871 case TOOL_CTRL_ID_NO:
1874 case TOOL_CTRL_ID_CONFIRM:
1875 result = TRUE | FALSE;
1878 case TOOL_CTRL_ID_PLAYER_1:
1881 case TOOL_CTRL_ID_PLAYER_2:
1884 case TOOL_CTRL_ID_PLAYER_3:
1887 case TOOL_CTRL_ID_PLAYER_4:
1898 case EVENT_KEYPRESS:
1899 switch(GetEventKey((KeyEvent *)&event, TRUE))
1912 if (req_state & REQ_PLAYER)
1916 case EVENT_KEYRELEASE:
1917 key_joystick_mapping = 0;
1921 HandleOtherEvents(&event);
1925 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1927 int joy = AnyJoystick();
1929 if (joy & JOY_BUTTON_1)
1931 else if (joy & JOY_BUTTON_2)
1937 /* don't eat all CPU time */
1941 if (game_status != MAINMENU)
1946 if (!(req_state & REQ_STAY_OPEN))
1948 CloseDoor(DOOR_CLOSE_1);
1950 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1952 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1953 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1954 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1955 OpenDoor(DOOR_OPEN_1);
1961 #if defined(PLATFORM_UNIX)
1962 /* continue network game after request */
1963 if (options.network &&
1964 game_status == PLAYING &&
1965 req_state & REQUEST_WAIT_FOR)
1966 SendToServer_ContinuePlaying();
1972 unsigned int OpenDoor(unsigned int door_state)
1974 unsigned int new_door_state;
1976 if (door_state & DOOR_COPY_BACK)
1978 BlitBitmap(pix[PIX_DB_DOOR], pix[PIX_DB_DOOR],
1979 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1980 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1981 door_state &= ~DOOR_COPY_BACK;
1984 new_door_state = MoveDoor(door_state);
1986 return(new_door_state);
1989 unsigned int CloseDoor(unsigned int door_state)
1991 unsigned int new_door_state;
1993 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
1994 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1995 BlitBitmap(backbuffer, pix[PIX_DB_DOOR],
1996 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1998 new_door_state = MoveDoor(door_state);
2000 return(new_door_state);
2003 unsigned int GetDoorState()
2005 return(MoveDoor(DOOR_GET_STATE));
2008 unsigned int MoveDoor(unsigned int door_state)
2010 static int door1 = DOOR_OPEN_1;
2011 static int door2 = DOOR_CLOSE_2;
2012 static unsigned long door_delay = 0;
2013 int x, start, stepsize = 2;
2014 unsigned long door_delay_value = stepsize * 5;
2016 if (door_state == DOOR_GET_STATE)
2017 return(door1 | door2);
2019 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2020 door_state &= ~DOOR_OPEN_1;
2021 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2022 door_state &= ~DOOR_CLOSE_1;
2023 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2024 door_state &= ~DOOR_OPEN_2;
2025 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2026 door_state &= ~DOOR_CLOSE_2;
2028 if (setup.quick_doors)
2031 door_delay_value = 0;
2032 StopSound(SND_OEFFNEN);
2035 if (door_state & DOOR_ACTION)
2037 if (!(door_state & DOOR_NO_DELAY))
2038 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2040 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2042 for(x=start; x<=DXSIZE; x+=stepsize)
2044 Bitmap *bitmap = pix[PIX_DOOR];
2045 GC gc = bitmap->stored_clip_gc;
2047 WaitUntilDelayReached(&door_delay, door_delay_value);
2049 if (door_state & DOOR_ACTION_1)
2051 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2052 int j = (DXSIZE - i) / 3;
2054 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2055 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2056 DXSIZE,DYSIZE - i/2, DX, DY);
2058 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2060 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2061 BlitBitmapMasked(bitmap, drawto,
2062 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2063 DX + DXSIZE - i, DY + j);
2064 BlitBitmapMasked(bitmap, drawto,
2065 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2066 DX + DXSIZE - i, DY + 140 + j);
2067 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2068 BlitBitmapMasked(bitmap, drawto,
2069 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2071 BlitBitmapMasked(bitmap, drawto,
2072 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2075 BlitBitmapMasked(bitmap, drawto,
2076 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2078 BlitBitmapMasked(bitmap, drawto,
2079 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2081 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2082 BlitBitmapMasked(bitmap, drawto,
2083 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2084 DX + DXSIZE - i, DY + 77 + j);
2085 BlitBitmapMasked(bitmap, drawto,
2086 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2087 DX + DXSIZE - i, DY + 203 + j);
2089 redraw_mask |= REDRAW_DOOR_1;
2092 if (door_state & DOOR_ACTION_2)
2094 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2095 int j = (VXSIZE - i) / 3;
2097 BlitBitmap(pix[PIX_DB_DOOR], drawto,
2098 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2099 VXSIZE, VYSIZE - i/2, VX, VY);
2101 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2103 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2104 BlitBitmapMasked(bitmap, drawto,
2105 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2106 VX + VXSIZE-i, VY+j);
2107 SetClipOrigin(bitmap, gc,
2108 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2109 BlitBitmapMasked(bitmap, drawto,
2110 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2113 BlitBitmapMasked(bitmap, drawto,
2114 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2115 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2116 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2117 BlitBitmapMasked(bitmap, drawto,
2118 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2120 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2122 redraw_mask |= REDRAW_DOOR_2;
2127 if (game_status == MAINMENU)
2132 if (setup.quick_doors)
2133 StopSound(SND_OEFFNEN);
2135 if (door_state & DOOR_ACTION_1)
2136 door1 = door_state & DOOR_ACTION_1;
2137 if (door_state & DOOR_ACTION_2)
2138 door2 = door_state & DOOR_ACTION_2;
2140 return (door1 | door2);
2143 void DrawSpecialEditorDoor()
2145 /* draw bigger toolbox window */
2146 BlitBitmap(pix[PIX_DOOR], drawto,
2147 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2149 redraw_mask |= REDRAW_ALL;
2152 void UndrawSpecialEditorDoor()
2154 /* draw normal tape recorder window */
2155 BlitBitmap(pix[PIX_BACK], drawto,
2156 562, 344, 108, 56, EX - 4, EY - 12);
2158 redraw_mask |= REDRAW_ALL;
2162 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2164 XImage *pixel_image;
2165 unsigned long pixel_value;
2167 pixel_image = XGetImage(display, bitmap->drawable,
2168 x, y, 1, 1, AllPlanes, ZPixmap);
2169 pixel_value = XGetPixel(pixel_image, 0, 0);
2171 XDestroyImage(pixel_image);
2177 /* ---------- new tool button stuff ---------------------------------------- */
2179 /* graphic position values for tool buttons */
2180 #define TOOL_BUTTON_YES_XPOS 2
2181 #define TOOL_BUTTON_YES_YPOS 250
2182 #define TOOL_BUTTON_YES_GFX_YPOS 0
2183 #define TOOL_BUTTON_YES_XSIZE 46
2184 #define TOOL_BUTTON_YES_YSIZE 28
2185 #define TOOL_BUTTON_NO_XPOS 52
2186 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2187 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2188 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2189 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2190 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2191 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2192 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2193 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2194 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2195 #define TOOL_BUTTON_PLAYER_XSIZE 30
2196 #define TOOL_BUTTON_PLAYER_YSIZE 30
2197 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2198 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2199 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2200 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2201 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2202 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2203 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2204 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2205 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2206 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2207 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2208 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2209 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2210 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2211 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2212 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2213 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2214 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2215 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2216 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2225 } toolbutton_info[NUM_TOOL_BUTTONS] =
2228 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2229 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2230 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2235 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2236 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2237 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2242 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2243 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2244 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2245 TOOL_CTRL_ID_CONFIRM,
2249 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2250 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2251 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2252 TOOL_CTRL_ID_PLAYER_1,
2256 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2257 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2258 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2259 TOOL_CTRL_ID_PLAYER_2,
2263 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2264 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2265 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2266 TOOL_CTRL_ID_PLAYER_3,
2270 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2271 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2272 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2273 TOOL_CTRL_ID_PLAYER_4,
2278 void CreateToolButtons()
2282 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2284 Bitmap *gd_bitmap = pix[PIX_DOOR];
2285 Bitmap *deco_bitmap = None;
2286 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2287 struct GadgetInfo *gi;
2288 unsigned long event_mask;
2289 int gd_xoffset, gd_yoffset;
2290 int gd_x1, gd_x2, gd_y;
2293 event_mask = GD_EVENT_RELEASED;
2295 gd_xoffset = toolbutton_info[i].xpos;
2296 gd_yoffset = toolbutton_info[i].ypos;
2297 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2298 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2299 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2301 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2303 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2304 &deco_bitmap, &deco_x, &deco_y);
2305 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2306 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2309 gi = CreateGadget(GDI_CUSTOM_ID, id,
2310 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2311 GDI_X, DX + toolbutton_info[i].x,
2312 GDI_Y, DY + toolbutton_info[i].y,
2313 GDI_WIDTH, toolbutton_info[i].width,
2314 GDI_HEIGHT, toolbutton_info[i].height,
2315 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2316 GDI_STATE, GD_BUTTON_UNPRESSED,
2317 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2318 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2319 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2320 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2321 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2322 GDI_DECORATION_SHIFTING, 1, 1,
2323 GDI_EVENT_MASK, event_mask,
2324 GDI_CALLBACK_ACTION, HandleToolButtons,
2328 Error(ERR_EXIT, "cannot create gadget");
2330 tool_gadget[id] = gi;
2334 static void UnmapToolButtons()
2338 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2339 UnmapGadget(tool_gadget[i]);
2342 static void HandleToolButtons(struct GadgetInfo *gi)
2344 request_gadget_id = gi->custom_id;
2347 int get_next_element(int element)
2351 case EL_QUICKSAND_FILLING: return EL_MORAST_VOLL;
2352 case EL_QUICKSAND_EMPTYING: return EL_MORAST_LEER;
2353 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2354 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_EMPTY;
2355 case EL_MAGIC_WALL_BD_FILLING: return EL_MAGIC_WALL_BD_FULL;
2356 case EL_MAGIC_WALL_BD_EMPTYING: return EL_MAGIC_WALL_BD_EMPTY;
2357 case EL_AMOEBA_DRIPPING: return EL_AMOEBE_NASS;
2359 default: return element;
2363 int el2gfx(int element)
2367 case EL_LEERRAUM: return -1;
2368 case EL_ERDREICH: return GFX_ERDREICH;
2369 case EL_MAUERWERK: return GFX_MAUERWERK;
2370 case EL_FELSBODEN: return GFX_FELSBODEN;
2371 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2372 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2373 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2374 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2375 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2376 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2377 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2378 case EL_SPIELER1: return GFX_SPIELER1;
2379 case EL_SPIELER2: return GFX_SPIELER2;
2380 case EL_SPIELER3: return GFX_SPIELER3;
2381 case EL_SPIELER4: return GFX_SPIELER4;
2382 case EL_KAEFER: return GFX_KAEFER;
2383 case EL_KAEFER_RIGHT: return GFX_KAEFER_RIGHT;
2384 case EL_KAEFER_UP: return GFX_KAEFER_UP;
2385 case EL_KAEFER_LEFT: return GFX_KAEFER_LEFT;
2386 case EL_KAEFER_DOWN: return GFX_KAEFER_DOWN;
2387 case EL_FLIEGER: return GFX_FLIEGER;
2388 case EL_FLIEGER_RIGHT: return GFX_FLIEGER_RIGHT;
2389 case EL_FLIEGER_UP: return GFX_FLIEGER_UP;
2390 case EL_FLIEGER_LEFT: return GFX_FLIEGER_LEFT;
2391 case EL_FLIEGER_DOWN: return GFX_FLIEGER_DOWN;
2392 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2393 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2394 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2395 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2396 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2397 case EL_FIREFLY: return GFX_FIREFLY;
2398 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2399 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
2400 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2401 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2402 case EL_MAMPFER: return GFX_MAMPFER;
2403 case EL_ROBOT: return GFX_ROBOT;
2404 case EL_BETON: return GFX_BETON;
2405 case EL_DIAMANT: return GFX_DIAMANT;
2406 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2407 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2408 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2409 case EL_TROPFEN: return GFX_TROPFEN;
2410 case EL_BOMBE: return GFX_BOMBE;
2411 case EL_MAGIC_WALL_OFF: return GFX_MAGIC_WALL_OFF;
2412 case EL_MAGIC_WALL_EMPTY: return GFX_MAGIC_WALL_EMPTY;
2413 case EL_MAGIC_WALL_EMPTYING:return GFX_MAGIC_WALL_EMPTY;
2414 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2415 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2416 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2417 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2418 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2419 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2420 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2421 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2422 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2423 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2424 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2425 case EL_LIFE: return GFX_LIFE;
2426 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2427 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2428 case EL_BADEWANNE: return GFX_BADEWANNE;
2429 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2430 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2431 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2432 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2433 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2434 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2435 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2436 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2437 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2438 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2439 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2440 case EL_PFORTE1: return GFX_PFORTE1;
2441 case EL_PFORTE2: return GFX_PFORTE2;
2442 case EL_PFORTE3: return GFX_PFORTE3;
2443 case EL_PFORTE4: return GFX_PFORTE4;
2444 case EL_PFORTE1X: return GFX_PFORTE1X;
2445 case EL_PFORTE2X: return GFX_PFORTE2X;
2446 case EL_PFORTE3X: return GFX_PFORTE3X;
2447 case EL_PFORTE4X: return GFX_PFORTE4X;
2448 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2449 case EL_PACMAN: return GFX_PACMAN;
2450 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2451 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2452 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2453 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2454 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2455 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2456 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2457 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2458 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2459 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2460 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2461 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2462 case EL_MAUER_X: return GFX_MAUER_X;
2463 case EL_MAUER_Y: return GFX_MAUER_Y;
2464 case EL_MAUER_XY: return GFX_MAUER_XY;
2465 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2466 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2467 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2468 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2469 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2470 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2471 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2472 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2473 case EL_MAMPFER2: return GFX_MAMPFER2;
2474 case EL_MAGIC_WALL_BD_OFF: return GFX_MAGIC_WALL_BD_OFF;
2475 case EL_MAGIC_WALL_BD_EMPTY:return GFX_MAGIC_WALL_BD_EMPTY;
2476 case EL_MAGIC_WALL_BD_EMPTYING:return GFX_MAGIC_WALL_BD_EMPTY;
2477 case EL_MAGIC_WALL_BD_FULL: return GFX_MAGIC_WALL_BD_FULL;
2478 case EL_MAGIC_WALL_BD_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2479 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2480 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2481 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2482 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2483 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2484 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2485 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2486 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2487 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2488 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2489 case EL_MOLE: return GFX_MOLE;
2490 case EL_PINGUIN: return GFX_PINGUIN;
2491 case EL_SCHWEIN: return GFX_SCHWEIN;
2492 case EL_DRACHE: return GFX_DRACHE;
2493 case EL_SONDE: return GFX_SONDE;
2494 case EL_PFEIL_LEFT: return GFX_PFEIL_LEFT;
2495 case EL_PFEIL_RIGHT: return GFX_PFEIL_RIGHT;
2496 case EL_PFEIL_UP: return GFX_PFEIL_UP;
2497 case EL_PFEIL_DOWN: return GFX_PFEIL_DOWN;
2498 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2499 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2500 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2501 case EL_SP_ZONK: return GFX_SP_ZONK;
2502 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2503 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2504 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2505 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2506 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2507 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2508 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2509 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2510 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2511 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2512 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2513 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2514 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2515 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2516 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2517 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2518 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2519 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2520 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2521 case EL_PEARL: return GFX_PEARL;
2522 case EL_CRYSTAL: return GFX_CRYSTAL;
2523 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2524 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2525 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2526 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2527 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2528 case EL_SHIELD_PASSIVE: return GFX_SHIELD_PASSIVE;
2529 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
2530 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2531 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2532 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2533 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2534 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2535 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2536 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2537 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2538 case EL_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2539 case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2540 case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2541 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2542 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2543 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2544 case EL_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2545 case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2546 case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2547 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2548 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2549 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2550 case EL_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2551 case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2552 case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2553 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2554 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2555 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2556 case EL_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2557 case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2558 case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2559 case EL_LANDMINE: return GFX_LANDMINE;
2560 case EL_ENVELOPE: return GFX_ENVELOPE;
2561 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2562 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2563 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2564 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2565 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2566 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2567 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2568 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2569 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2570 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2571 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2572 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2573 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2574 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2575 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2576 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2577 case EL_MOLE_UP: return GFX_MOLE_UP;
2578 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2579 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2580 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2581 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2582 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2583 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2584 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2585 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2586 case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2587 case EL_BALLOON: return GFX_BALLOON;
2588 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2589 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2590 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2591 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2592 case EL_BALLOON_SEND_ANY: return GFX_BALLOON_SEND_ANY;
2593 case EL_EMC_STEEL_WALL_1: return GFX_EMC_STEEL_WALL_1;
2594 case EL_EMC_STEEL_WALL_2: return GFX_EMC_STEEL_WALL_2;
2595 case EL_EMC_STEEL_WALL_3: return GFX_EMC_STEEL_WALL_3;
2596 case EL_EMC_STEEL_WALL_4: return GFX_EMC_STEEL_WALL_4;
2597 case EL_EMC_WALL_1: return GFX_EMC_WALL_1;
2598 case EL_EMC_WALL_2: return GFX_EMC_WALL_2;
2599 case EL_EMC_WALL_3: return GFX_EMC_WALL_3;
2600 case EL_EMC_WALL_4: return GFX_EMC_WALL_4;
2601 case EL_EMC_WALL_5: return GFX_EMC_WALL_5;
2602 case EL_EMC_WALL_6: return GFX_EMC_WALL_6;
2603 case EL_EMC_WALL_7: return GFX_EMC_WALL_7;
2604 case EL_EMC_WALL_8: return GFX_EMC_WALL_8;
2605 case EL_TUBE_CROSS: return GFX_TUBE_CROSS;
2606 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2607 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2608 case EL_TUBE_VERT_LEFT: return GFX_TUBE_VERT_LEFT;
2609 case EL_TUBE_VERT_RIGHT: return GFX_TUBE_VERT_RIGHT;
2610 case EL_TUBE_HORIZ_UP: return GFX_TUBE_HORIZ_UP;
2611 case EL_TUBE_HORIZ_DOWN: return GFX_TUBE_HORIZ_DOWN;
2612 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2613 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2614 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2615 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2616 case EL_SPRING: return GFX_SPRING;
2617 case EL_SPRING_MOVING: return GFX_SPRING;
2618 case EL_TRAP_INACTIVE: return GFX_TRAP_INACTIVE;
2619 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2620 case EL_BD_WALL: return GFX_BD_WALL;
2621 case EL_BD_ROCK: return GFX_BD_ROCK;
2622 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2623 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2627 if (IS_CHAR(element))
2628 return GFX_CHAR_START + (element - EL_CHAR_START);
2629 else if (element >= EL_SP_START && element <= EL_SP_END)
2631 int nr_element = element - EL_SP_START;
2632 int gfx_per_line = 8;
2634 (nr_element / gfx_per_line) * SP_PER_LINE +
2635 (nr_element % gfx_per_line);
2637 return GFX_START_ROCKSSP + nr_graphic;