1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
14 #include "libgame/libgame.h"
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES 0
25 #define TOOL_CTRL_ID_NO 1
26 #define TOOL_CTRL_ID_CONFIRM 2
27 #define TOOL_CTRL_ID_PLAYER_1 3
28 #define TOOL_CTRL_ID_PLAYER_2 4
29 #define TOOL_CTRL_ID_PLAYER_3 5
30 #define TOOL_CTRL_ID_PLAYER_4 6
32 #define NUM_TOOL_BUTTONS 7
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
38 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
39 static int request_gadget_id = -1;
41 void SetDrawtoField(int mode)
43 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
54 drawto_field = fieldbuffer;
56 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
67 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
71 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
73 if (game_status == PLAYING)
79 width = gfx.sxsize + 2 * TILEX;
80 height = gfx.sysize + 2 * TILEY;
83 if (force_redraw || setup.direct_draw)
86 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
87 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
89 if (setup.direct_draw)
90 SetDrawtoField(DRAW_BACKBUFFER);
92 for(xx=BX1; xx<=BX2; xx++)
93 for(yy=BY1; yy<=BY2; yy++)
94 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
95 DrawScreenField(xx, yy);
98 if (setup.direct_draw)
99 SetDrawtoField(DRAW_DIRECT);
102 if (setup.soft_scrolling)
104 int fx = FX, fy = FY;
106 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
107 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
109 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
113 BlitBitmap(drawto, window, x, y, width, height, x, y);
119 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
121 if (setup.direct_draw && game_status == PLAYING)
122 redraw_mask &= ~REDRAW_MAIN;
124 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
125 redraw_mask |= REDRAW_FIELD;
127 if (redraw_mask & REDRAW_FIELD)
128 redraw_mask &= ~REDRAW_TILES;
130 if (redraw_mask == REDRAW_NONE)
133 if (global.fps_slowdown && game_status == PLAYING)
135 static boolean last_frame_skipped = FALSE;
136 boolean skip_even_when_not_scrolling = TRUE;
137 boolean just_scrolling = (ScreenMovDir != 0);
138 boolean verbose = FALSE;
140 if (global.fps_slowdown_factor > 1 &&
141 (FrameCounter % global.fps_slowdown_factor) &&
142 (just_scrolling || skip_even_when_not_scrolling))
144 redraw_mask &= ~REDRAW_MAIN;
146 last_frame_skipped = TRUE;
149 printf("FRAME SKIPPED\n");
153 if (last_frame_skipped)
154 redraw_mask |= REDRAW_FIELD;
156 last_frame_skipped = FALSE;
159 printf("frame not skipped\n");
163 /* synchronize X11 graphics at this point; if we would synchronize the
164 display immediately after the buffer switching (after the XFlush),
165 this could mean that we have to wait for the graphics to complete,
166 although we could go on doing calculations for the next frame */
170 if (redraw_mask & REDRAW_ALL)
172 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
176 if (redraw_mask & REDRAW_FIELD)
178 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
180 BlitBitmap(backbuffer, window,
181 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
185 int fx = FX, fy = FY;
187 if (setup.soft_scrolling)
189 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
190 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
193 if (setup.soft_scrolling ||
194 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
195 ABS(ScreenMovPos) == ScrollStepSize ||
196 redraw_tiles > REDRAWTILES_THRESHOLD)
198 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
202 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
204 (setup.soft_scrolling ?
205 "setup.soft_scrolling" :
206 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
207 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
208 ABS(ScreenGfxPos) == ScrollStepSize ?
209 "ABS(ScreenGfxPos) == ScrollStepSize" :
210 "redraw_tiles > REDRAWTILES_THRESHOLD"));
216 redraw_mask &= ~REDRAW_MAIN;
219 if (redraw_mask & REDRAW_DOORS)
221 if (redraw_mask & REDRAW_DOOR_1)
222 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
223 if (redraw_mask & REDRAW_DOOR_2)
225 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
226 BlitBitmap(backbuffer, window, VX,VY, VXSIZE,VYSIZE, VX,VY);
229 if (redraw_mask & REDRAW_VIDEO_1)
230 BlitBitmap(backbuffer, window,
231 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
232 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
233 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
234 if (redraw_mask & REDRAW_VIDEO_2)
235 BlitBitmap(backbuffer, window,
236 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
237 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
238 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
239 if (redraw_mask & REDRAW_VIDEO_3)
240 BlitBitmap(backbuffer, window,
241 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
242 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
243 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
247 if (redraw_mask & REDRAW_DOOR_3)
248 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
250 redraw_mask &= ~REDRAW_DOORS;
253 if (redraw_mask & REDRAW_MICROLEVEL)
255 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
256 SX, SY + 10 * TILEY);
258 redraw_mask &= ~REDRAW_MICROLEVEL;
261 if (redraw_mask & REDRAW_TILES)
263 for(x=0; x<SCR_FIELDX; x++)
264 for(y=0; y<SCR_FIELDY; y++)
265 if (redraw[redraw_x1 + x][redraw_y1 + y])
266 BlitBitmap(buffer, window,
267 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
268 SX + x * TILEX, SY + y * TILEY);
271 if (redraw_mask & REDRAW_FPS) /* display frames per second */
276 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
277 if (!global.fps_slowdown)
280 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
281 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, FONT_OPAQUE);
286 for(x=0; x<MAX_BUF_XSIZE; x++)
287 for(y=0; y<MAX_BUF_YSIZE; y++)
290 redraw_mask = REDRAW_NONE;
296 long fading_delay = 300;
298 if (setup.fading && (redraw_mask & REDRAW_FIELD))
305 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
308 for(i=0;i<2*FULL_SYSIZE;i++)
310 for(y=0;y<FULL_SYSIZE;y++)
312 BlitBitmap(backbuffer, window,
313 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
321 for(i=1;i<FULL_SYSIZE;i+=2)
322 BlitBitmap(backbuffer, window,
323 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
329 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
330 BlitBitmapMasked(backbuffer, window,
331 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
336 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
337 BlitBitmapMasked(backbuffer, window,
338 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
343 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
344 BlitBitmapMasked(backbuffer, window,
345 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
350 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
351 BlitBitmapMasked(backbuffer, window,
352 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
357 redraw_mask &= ~REDRAW_MAIN;
364 void SetMainBackgroundImage(int graphic)
366 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
367 graphic_info[graphic].bitmap ?
368 graphic_info[graphic].bitmap :
369 graphic_info[IMG_BACKGROUND].bitmap);
372 void SetDoorBackgroundImage(int graphic)
374 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
375 graphic_info[graphic].bitmap ?
376 graphic_info[graphic].bitmap :
377 graphic_info[IMG_BACKGROUND].bitmap);
380 void DrawBackground(int dest_x, int dest_y, int width, int height)
382 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
384 redraw_mask |= REDRAW_FIELD;
389 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
391 if (setup.soft_scrolling && game_status == PLAYING)
393 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
394 SetDrawtoField(DRAW_BUFFERED);
397 SetDrawtoField(DRAW_BACKBUFFER);
399 if (setup.direct_draw && game_status == PLAYING)
401 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
402 SetDrawtoField(DRAW_DIRECT);
406 void MarkTileDirty(int x, int y)
408 int xx = redraw_x1 + x;
409 int yy = redraw_y1 + y;
414 redraw[xx][yy] = TRUE;
415 redraw_mask |= REDRAW_TILES;
418 void SetBorderElement()
422 BorderElement = EL_EMPTY;
424 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
426 for(x=0; x<lev_fieldx; x++)
428 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
429 BorderElement = EL_STEELWALL;
431 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
437 void SetRandomAnimationValue(int x, int y)
439 gfx.anim_random_frame = GfxRandom[x][y];
442 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
444 /* animation synchronized with global frame counter, not move position */
445 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
446 sync_frame = FrameCounter;
448 return getAnimationFrame(graphic_info[graphic].anim_frames,
449 graphic_info[graphic].anim_delay,
450 graphic_info[graphic].anim_mode,
451 graphic_info[graphic].anim_start_frame,
455 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
456 int graphic, int sync_frame, int mask_mode)
458 int frame = getGraphicAnimationFrame(graphic, sync_frame);
460 if (mask_mode == USE_MASKING)
461 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
463 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
466 inline void DrawGraphicAnimation(int x, int y, int graphic)
468 int lx = LEVELX(x), ly = LEVELY(y);
470 if (!IN_SCR_FIELD(x, y))
473 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
474 graphic, GfxFrame[lx][ly], NO_MASKING);
478 void DrawLevelGraphicAnimation(int x, int y, int graphic)
480 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
483 void DrawLevelElementAnimation(int x, int y, int element)
485 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
488 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
490 int sx = SCREENX(x), sy = SCREENY(y);
492 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
495 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
498 DrawGraphicAnimation(sx, sy, graphic);
501 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
503 int sx = SCREENX(x), sy = SCREENY(y);
506 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
509 graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
511 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
514 DrawGraphicAnimation(sx, sy, graphic);
517 void DrawAllPlayers()
521 for(i=0; i<MAX_PLAYERS; i++)
522 if (stored_player[i].active)
523 DrawPlayer(&stored_player[i]);
526 void DrawPlayerField(int x, int y)
528 if (!IS_PLAYER(x, y))
531 DrawPlayer(PLAYERINFO(x, y));
534 void DrawPlayer(struct PlayerInfo *player)
536 int jx = player->jx, jy = player->jy;
537 int last_jx = player->last_jx, last_jy = player->last_jy;
538 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
539 int sx = SCREENX(jx), sy = SCREENY(jy);
540 int sxx = 0, syy = 0;
541 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
544 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
546 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
550 if (!IN_LEV_FIELD(jx,jy))
552 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
553 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
554 printf("DrawPlayerField(): This should never happen!\n");
559 if (element == EL_EXPLOSION)
562 /* ----------------------------------------------------------------------- */
563 /* draw things in the field the player is leaving, if needed */
564 /* ----------------------------------------------------------------------- */
566 if (player_is_moving)
568 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
570 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
572 if (last_element == EL_DYNAMITE_ACTIVE ||
573 last_element == EL_SP_DISK_RED_ACTIVE)
574 DrawDynamite(last_jx, last_jy);
576 DrawLevelFieldThruMask(last_jx, last_jy);
578 else if (last_element == EL_DYNAMITE_ACTIVE ||
579 last_element == EL_SP_DISK_RED_ACTIVE)
580 DrawDynamite(last_jx, last_jy);
582 DrawLevelField(last_jx, last_jy);
584 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
588 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
589 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
591 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
594 DrawLevelField(next_jx, next_jy);
598 if (!IN_SCR_FIELD(sx, sy))
601 if (setup.direct_draw)
602 SetDrawtoField(DRAW_BUFFERED);
604 /* ----------------------------------------------------------------------- */
605 /* draw things behind the player, if needed */
606 /* ----------------------------------------------------------------------- */
609 DrawLevelElement(jx, jy, Store[jx][jy]);
610 else if (!IS_ACTIVE_BOMB(element))
611 DrawLevelField(jx, jy);
613 DrawLevelElement(jx, jy, EL_EMPTY);
615 /* ----------------------------------------------------------------------- */
616 /* draw player himself */
617 /* ----------------------------------------------------------------------- */
619 player->GfxAction = (player->Pushing ? ACTION_PUSHING :
620 player->is_digging ? ACTION_DIGGING :
621 player->is_moving ? ACTION_MOVING :
622 player->snapped ? ACTION_SNAPPING : ACTION_DEFAULT);
624 if (player->use_murphy_graphic)
626 static int last_horizontal_dir = MV_LEFT;
629 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
630 last_horizontal_dir = player->MovDir;
632 direction = (player->snapped ? player->MovDir : last_horizontal_dir);
634 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
637 graphic = el_act_dir2img(player->element_nr, player->GfxAction,
640 frame = getGraphicAnimationFrame(graphic, player->Frame);
644 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
645 sxx = player->GfxPos;
647 syy = player->GfxPos;
650 if (!setup.soft_scrolling && ScreenMovPos)
653 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
655 if (SHIELD_ON(player))
657 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
658 IMG_SHIELD_NORMAL_ACTIVE);
659 int frame = getGraphicAnimationFrame(graphic, -1);
661 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
664 /* ----------------------------------------------------------------------- */
665 /* draw things the player is pushing, if needed */
666 /* ----------------------------------------------------------------------- */
668 if (player->Pushing && player_is_moving)
670 int px = SCREENX(next_jx), py = SCREENY(next_jy);
673 (element == EL_SOKOBAN_FIELD_EMPTY ||
674 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
675 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
679 int element = Feld[next_jx][next_jy];
680 int graphic = el2img(element);
683 if ((sxx || syy) && IS_PUSHABLE(element))
685 graphic = el_act_dir2img(element, ACTION_MOVING, player->MovDir);
686 frame = getGraphicAnimationFrame(graphic, player->Frame);
689 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
690 NO_CUTTING, NO_MASKING);
694 /* ----------------------------------------------------------------------- */
695 /* draw things in front of player (active dynamite or dynabombs) */
696 /* ----------------------------------------------------------------------- */
698 if (IS_ACTIVE_BOMB(element))
700 graphic = el2img(element);
701 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
703 if (game.emulation == EMU_SUPAPLEX)
704 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
706 DrawGraphicThruMask(sx, sy, graphic, frame);
709 if (player_is_moving && last_element == EL_EXPLOSION)
711 int stored = Store[last_jx][last_jy];
712 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
713 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
715 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
716 int phase = ExplodePhase[last_jx][last_jy] - 1;
717 int frame = getGraphicAnimationFrame(graphic, phase - delay);
720 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
723 /* ----------------------------------------------------------------------- */
724 /* draw elements that stay over the player */
725 /* ----------------------------------------------------------------------- */
727 /* handle the field the player is leaving ... */
728 if (player_is_moving && IS_OVER_PLAYER(last_element))
729 DrawLevelField(last_jx, last_jy);
731 /* ... and the field the player is entering */
732 if (IS_OVER_PLAYER(element))
733 DrawLevelField(jx, jy);
735 if (setup.direct_draw)
737 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
738 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
739 int x_size = TILEX * (1 + ABS(jx - last_jx));
740 int y_size = TILEY * (1 + ABS(jy - last_jy));
742 BlitBitmap(drawto_field, window,
743 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
744 SetDrawtoField(DRAW_DIRECT);
747 MarkTileDirty(sx,sy);
750 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
752 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
753 int offset_x = graphic_info[graphic].offset_x;
754 int offset_y = graphic_info[graphic].offset_y;
755 int src_x = graphic_info[graphic].src_x + frame * offset_x;
756 int src_y = graphic_info[graphic].src_y + frame * offset_y;
758 *bitmap = src_bitmap;
763 void DrawGraphic(int x, int y, int graphic, int frame)
766 if (!IN_SCR_FIELD(x, y))
768 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
769 printf("DrawGraphic(): This should never happen!\n");
774 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
779 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
784 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
785 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
789 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
796 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
798 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
799 int src_x = graphic_info[graphic].src_x;
800 int src_y = graphic_info[graphic].src_y;
801 int offset_x = graphic_info[graphic].offset_x;
802 int offset_y = graphic_info[graphic].offset_y;
804 src_x += frame * offset_x;
805 src_y += frame * offset_y;
808 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
811 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
814 if (!IN_SCR_FIELD(x, y))
816 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
817 printf("DrawGraphicThruMask(): This should never happen!\n");
822 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
827 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
835 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
836 drawing_gc = src_bitmap->stored_clip_gc;
838 GC drawing_gc = src_bitmap->stored_clip_gc;
839 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
840 int src_x = graphic_info[graphic].src_x;
841 int src_y = graphic_info[graphic].src_y;
842 int offset_x = graphic_info[graphic].offset_x;
843 int offset_y = graphic_info[graphic].offset_y;
845 src_x += frame * offset_x;
846 src_y += frame * offset_y;
850 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
851 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
854 void DrawMiniGraphic(int x, int y, int graphic)
856 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
857 MarkTileDirty(x / 2, y / 2);
860 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
862 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
864 int mini_starty = src_bitmap->height * 2 / 3;
865 int src_x = mini_startx + graphic_info[graphic].src_x / 2;
866 int src_y = mini_starty + graphic_info[graphic].src_y / 2;
869 /* !!! not needed anymore, because of automatically created mini graphics */
870 if (src_x + MINI_TILEX > src_bitmap->width ||
871 src_y + MINI_TILEY > src_bitmap->height)
873 /* graphic of desired size seems not to be contained in this image;
874 dirty workaround: get it from the middle of the normal sized image */
876 printf("::: using dirty workaround for %d (%d, %d)\n",
877 graphic, src_bitmap->width, src_bitmap->height);
879 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
880 src_x += (TILEX / 2 - MINI_TILEX / 2);
881 src_y += (TILEY / 2 - MINI_TILEY / 2);
885 *bitmap = src_bitmap;
890 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
895 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
896 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
899 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
900 int cut_mode, int mask_mode)
909 int width = TILEX, height = TILEY;
915 DrawGraphic(x, y, graphic, frame);
919 if (dx || dy) /* shifted graphic */
921 if (x < BX1) /* object enters playfield from the left */
928 else if (x > BX2) /* object enters playfield from the right */
934 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
940 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
942 else if (dx) /* general horizontal movement */
943 MarkTileDirty(x + SIGN(dx), y);
945 if (y < BY1) /* object enters playfield from the top */
947 if (cut_mode==CUT_BELOW) /* object completely above top border */
955 else if (y > BY2) /* object enters playfield from the bottom */
961 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
967 else if (dy > 0 && cut_mode == CUT_ABOVE)
969 if (y == BY2) /* object completely above bottom border */
975 MarkTileDirty(x, y + 1);
976 } /* object leaves playfield to the bottom */
977 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
979 else if (dy) /* general vertical movement */
980 MarkTileDirty(x, y + SIGN(dy));
983 src_bitmap = graphic_info[graphic].bitmap;
984 src_x = graphic_info[graphic].src_x;
985 src_y = graphic_info[graphic].src_y;
986 offset_x = graphic_info[graphic].offset_x;
987 offset_y = graphic_info[graphic].offset_y;
989 drawing_gc = src_bitmap->stored_clip_gc;
991 src_x += frame * offset_x;
992 src_y += frame * offset_y;
997 dest_x = FX + x * TILEX + dx;
998 dest_y = FY + y * TILEY + dy;
1001 if (!IN_SCR_FIELD(x,y))
1003 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1004 printf("DrawGraphicShifted(): This should never happen!\n");
1009 if (mask_mode == USE_MASKING)
1011 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1012 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1016 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1022 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1023 int frame, int cut_mode)
1025 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1028 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1029 int cut_mode, int mask_mode)
1031 int lx = LEVELX(x), ly = LEVELY(y);
1035 if (IN_LEV_FIELD(lx, ly))
1037 SetRandomAnimationValue(lx, ly);
1039 graphic = el_act_dir2img(element, GfxAction[lx][ly], MovDir[lx][ly]);
1040 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1042 else /* border element */
1044 graphic = el2img(element);
1045 frame = getGraphicAnimationFrame(graphic, -1);
1048 if (element == EL_EXPANDABLE_WALL)
1050 boolean left_stopped = FALSE, right_stopped = FALSE;
1052 if (!IN_LEV_FIELD(lx - 1, ly) || IS_MAUER(Feld[lx - 1][ly]))
1053 left_stopped = TRUE;
1054 if (!IN_LEV_FIELD(lx + 1, ly) || IS_MAUER(Feld[lx + 1][ly]))
1055 right_stopped = TRUE;
1057 if (left_stopped && right_stopped)
1059 else if (left_stopped)
1061 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1062 frame = graphic_info[graphic].anim_frames - 1;
1064 else if (right_stopped)
1066 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1067 frame = graphic_info[graphic].anim_frames - 1;
1071 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DROPPING)
1073 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1074 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1075 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1076 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1077 IMG_AMOEBA_DEAD_PART1);
1079 graphic += (x + 2 * y + 4) % 4;
1084 if (IS_AMOEBOID(element) || element == EL_AMOEBA_DROPPING)
1086 if (Feld[lx][ly] == EL_AMOEBA_DROPPING)
1087 printf("---> %d -> %d / %d [%d]\n",
1088 element, graphic, frame, GfxRandom[lx][ly]);
1093 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1094 else if (mask_mode == USE_MASKING)
1095 DrawGraphicThruMask(x, y, graphic, frame);
1097 DrawGraphic(x, y, graphic, frame);
1100 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1101 int cut_mode, int mask_mode)
1103 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1104 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1105 cut_mode, mask_mode);
1108 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1111 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1114 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1117 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1121 void DrawOldScreenElementThruMask(int x, int y, int element)
1123 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1126 void DrawScreenElementThruMask(int x, int y, int element)
1128 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1132 void DrawLevelElementThruMask(int x, int y, int element)
1134 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1137 void DrawLevelFieldThruMask(int x, int y)
1139 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1142 void DrawCrumbledSand(int x, int y)
1146 int i, width, height, cx,cy;
1147 int lx = LEVELX(x), ly = LEVELY(y);
1148 int element, graphic;
1150 static int xy[4][2] =
1158 if (!IN_LEV_FIELD(lx, ly))
1161 element = Feld[lx][ly];
1163 if (element == EL_SAND ||
1164 element == EL_LANDMINE ||
1165 element == EL_TRAP ||
1166 element == EL_TRAP_ACTIVE)
1168 if (!IN_SCR_FIELD(x, y))
1171 graphic = IMG_SAND_CRUMBLED;
1173 src_bitmap = graphic_info[graphic].bitmap;
1174 src_x = graphic_info[graphic].src_x;
1175 src_y = graphic_info[graphic].src_y;
1181 lxx = lx + xy[i][0];
1182 lyy = ly + xy[i][1];
1183 if (!IN_LEV_FIELD(lxx, lyy))
1184 element = EL_STEELWALL;
1186 element = Feld[lxx][lyy];
1188 if (element == EL_SAND ||
1189 element == EL_LANDMINE ||
1190 element == EL_TRAP ||
1191 element == EL_TRAP_ACTIVE)
1194 if (i == 1 || i == 2)
1198 cx = (i == 2 ? TILEX - snip : 0);
1206 cy = (i == 3 ? TILEY - snip : 0);
1209 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1210 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1213 MarkTileDirty(x, y);
1217 graphic = IMG_SAND_CRUMBLED;
1219 src_bitmap = graphic_info[graphic].bitmap;
1220 src_x = graphic_info[graphic].src_x;
1221 src_y = graphic_info[graphic].src_y;
1225 int xx, yy, lxx, lyy;
1229 lxx = lx + xy[i][0];
1230 lyy = ly + xy[i][1];
1232 if (!IN_LEV_FIELD(lxx, lyy) ||
1233 (Feld[lxx][lyy] != EL_SAND &&
1234 Feld[lxx][lyy] != EL_LANDMINE &&
1235 Feld[lxx][lyy] != EL_TRAP &&
1236 Feld[lxx][lyy] != EL_TRAP_ACTIVE) ||
1237 !IN_SCR_FIELD(xx, yy))
1240 if (i == 1 || i == 2)
1244 cx = (i == 1 ? TILEX - snip : 0);
1252 cy = (i==0 ? TILEY-snip : 0);
1255 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1256 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1258 MarkTileDirty(xx, yy);
1263 static int getBorderElement(int x, int y)
1267 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
1268 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
1269 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
1270 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1271 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
1272 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
1273 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
1275 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1276 int steel_position = (x == -1 && y == -1 ? 0 :
1277 x == lev_fieldx && y == -1 ? 1 :
1278 x == -1 && y == lev_fieldy ? 2 :
1279 x == lev_fieldx && y == lev_fieldy ? 3 :
1280 x == -1 || x == lev_fieldx ? 4 :
1281 y == -1 || y == lev_fieldy ? 5 : 6);
1283 return border[steel_position][steel_type];
1286 void DrawScreenElement(int x, int y, int element)
1288 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1289 DrawCrumbledSand(x, y);
1292 void DrawLevelElement(int x, int y, int element)
1294 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1295 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1298 void DrawScreenField(int x, int y)
1300 int lx = LEVELX(x), ly = LEVELY(y);
1301 int element, content;
1303 if (!IN_LEV_FIELD(lx, ly))
1305 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1308 element = getBorderElement(lx, ly);
1310 DrawScreenElement(x, y, element);
1314 element = Feld[lx][ly];
1315 content = Store[lx][ly];
1317 if (IS_MOVING(lx, ly))
1319 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1320 boolean cut_mode = NO_CUTTING;
1322 if (element == EL_QUICKSAND_EMPTYING ||
1323 element == EL_MAGIC_WALL_EMPTYING ||
1324 element == EL_BD_MAGIC_WALL_EMPTYING ||
1325 element == EL_AMOEBA_DROPPING)
1326 cut_mode = CUT_ABOVE;
1327 else if (element == EL_QUICKSAND_FILLING ||
1328 element == EL_MAGIC_WALL_FILLING ||
1329 element == EL_BD_MAGIC_WALL_FILLING)
1330 cut_mode = CUT_BELOW;
1332 if (cut_mode == CUT_ABOVE)
1333 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1335 DrawScreenElement(x, y, EL_EMPTY);
1338 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1339 else if (cut_mode == NO_CUTTING)
1340 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1342 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1344 if (content == EL_ACID)
1345 DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
1347 else if (IS_BLOCKED(lx, ly))
1352 boolean cut_mode = NO_CUTTING;
1353 int element_old, content_old;
1355 Blocked2Moving(lx, ly, &oldx, &oldy);
1358 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1359 MovDir[oldx][oldy] == MV_RIGHT);
1361 element_old = Feld[oldx][oldy];
1362 content_old = Store[oldx][oldy];
1364 if (element_old == EL_QUICKSAND_EMPTYING ||
1365 element_old == EL_MAGIC_WALL_EMPTYING ||
1366 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1367 element_old == EL_AMOEBA_DROPPING)
1368 cut_mode = CUT_ABOVE;
1370 DrawScreenElement(x, y, EL_EMPTY);
1373 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1375 else if (cut_mode == NO_CUTTING)
1376 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1379 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1382 else if (IS_DRAWABLE(element))
1383 DrawScreenElement(x, y, element);
1385 DrawScreenElement(x, y, EL_EMPTY);
1388 void DrawLevelField(int x, int y)
1390 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1391 DrawScreenField(SCREENX(x), SCREENY(y));
1392 else if (IS_MOVING(x, y))
1396 Moving2Blocked(x, y, &newx, &newy);
1397 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1398 DrawScreenField(SCREENX(newx), SCREENY(newy));
1400 else if (IS_BLOCKED(x, y))
1404 Blocked2Moving(x, y, &oldx, &oldy);
1405 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1406 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1410 void DrawMiniElement(int x, int y, int element)
1414 graphic = el2edimg(element);
1415 DrawMiniGraphic(x, y, graphic);
1418 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1420 int x = sx + scroll_x, y = sy + scroll_y;
1422 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1423 DrawMiniElement(sx, sy, EL_EMPTY);
1424 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1425 DrawMiniElement(sx, sy, Feld[x][y]);
1427 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1430 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1432 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1433 int mini_startx = src_bitmap->width * 3 / 4;
1434 int mini_starty = src_bitmap->height * 2 / 3;
1435 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1436 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1438 if (src_x + MICRO_TILEX > src_bitmap->width ||
1439 src_y + MICRO_TILEY > src_bitmap->height)
1441 /* graphic of desired size seems not to be contained in this image;
1442 dirty workaround: get it from the middle of the normal sized image */
1444 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1445 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1446 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1449 *bitmap = src_bitmap;
1454 void DrawMicroElement(int xpos, int ypos, int element)
1458 int graphic = el2preimg(element);
1460 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1461 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1469 SetDrawBackgroundMask(REDRAW_NONE);
1472 for(x=BX1; x<=BX2; x++)
1473 for(y=BY1; y<=BY2; y++)
1474 DrawScreenField(x, y);
1476 redraw_mask |= REDRAW_FIELD;
1479 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1483 for(x=0; x<size_x; x++)
1484 for(y=0; y<size_y; y++)
1485 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1487 redraw_mask |= REDRAW_FIELD;
1490 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1494 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1496 if (lev_fieldx < STD_LEV_FIELDX)
1497 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1498 if (lev_fieldy < STD_LEV_FIELDY)
1499 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1501 xpos += MICRO_TILEX;
1502 ypos += MICRO_TILEY;
1504 for(x=-1; x<=STD_LEV_FIELDX; x++)
1506 for(y=-1; y<=STD_LEV_FIELDY; y++)
1508 int lx = from_x + x, ly = from_y + y;
1510 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1511 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1513 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1514 && BorderElement != EL_EMPTY)
1515 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1516 getBorderElement(lx, ly));
1520 redraw_mask |= REDRAW_MICROLEVEL;
1523 #define MICROLABEL_EMPTY 0
1524 #define MICROLABEL_LEVEL_NAME 1
1525 #define MICROLABEL_CREATED_BY 2
1526 #define MICROLABEL_LEVEL_AUTHOR 3
1527 #define MICROLABEL_IMPORTED_FROM 4
1528 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1530 static void DrawMicroLevelLabelExt(int mode)
1532 char label_text[MAX_OUTPUT_LINESIZE + 1];
1533 int max_len_label_text;
1534 int font_nr = FONT_TEXT_2;
1536 if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1537 font_nr = FONT_TEXT_3;
1539 max_len_label_text = SXSIZE / getFontWidth(font_nr);
1541 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1543 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1544 mode == MICROLABEL_CREATED_BY ? "created by" :
1545 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1546 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1547 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1548 leveldir_current->imported_from : ""),
1549 max_len_label_text);
1550 label_text[max_len_label_text] = '\0';
1552 if (strlen(label_text) > 0)
1554 int text_width = strlen(label_text) * getFontWidth(font_nr);
1555 int lxpos = SX + (SXSIZE - text_width) / 2;
1556 int lypos = MICROLABEL_YPOS;
1558 DrawText(lxpos, lypos, label_text, font_nr);
1561 redraw_mask |= REDRAW_MICROLEVEL;
1564 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1566 static unsigned long scroll_delay = 0;
1567 static unsigned long label_delay = 0;
1568 static int from_x, from_y, scroll_direction;
1569 static int label_state, label_counter;
1570 int last_game_status = game_status; /* save current game status */
1572 game_status = PSEUDO_PREVIEW; /* force PREVIEW font on preview level */
1576 from_x = from_y = 0;
1577 scroll_direction = MV_RIGHT;
1581 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1582 DrawMicroLevelLabelExt(label_state);
1584 /* initialize delay counters */
1585 DelayReached(&scroll_delay, 0);
1586 DelayReached(&label_delay, 0);
1588 if (leveldir_current->name)
1590 int len = strlen(leveldir_current->name);
1591 int lxpos = SX + (SXSIZE - len * getFontWidth(FONT_TEXT_1)) / 2;
1592 int lypos = SY + 352;
1594 DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1597 game_status = last_game_status; /* restore current game status */
1602 /* scroll micro level, if needed */
1603 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1604 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1606 switch (scroll_direction)
1612 scroll_direction = MV_UP;
1616 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1619 scroll_direction = MV_DOWN;
1626 scroll_direction = MV_RIGHT;
1630 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1633 scroll_direction = MV_LEFT;
1640 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1643 /* redraw micro level label, if needed */
1644 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1645 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1646 strcmp(level.author, leveldir_current->name) != 0 &&
1647 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1649 int max_label_counter = 23;
1651 if (leveldir_current->imported_from != NULL)
1652 max_label_counter += 14;
1654 label_counter = (label_counter + 1) % max_label_counter;
1655 label_state = (label_counter >= 0 && label_counter <= 7 ?
1656 MICROLABEL_LEVEL_NAME :
1657 label_counter >= 9 && label_counter <= 12 ?
1658 MICROLABEL_CREATED_BY :
1659 label_counter >= 14 && label_counter <= 21 ?
1660 MICROLABEL_LEVEL_AUTHOR :
1661 label_counter >= 23 && label_counter <= 26 ?
1662 MICROLABEL_IMPORTED_FROM :
1663 label_counter >= 28 && label_counter <= 35 ?
1664 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1665 DrawMicroLevelLabelExt(label_state);
1668 game_status = last_game_status; /* restore current game status */
1671 int REQ_in_range(int x, int y)
1673 if (y > DY+249 && y < DY+278)
1675 if (x > DX+1 && x < DX+48)
1677 else if (x > DX+51 && x < DX+98)
1683 #define MAX_REQUEST_LINES 13
1684 #define MAX_REQUEST_LINE_LEN 7
1686 boolean Request(char *text, unsigned int req_state)
1688 int mx, my, ty, result = -1;
1689 unsigned int old_door_state;
1690 int last_game_status = game_status; /* save current game status */
1692 #if defined(PLATFORM_UNIX)
1693 /* pause network game while waiting for request to answer */
1694 if (options.network &&
1695 game_status == PLAYING &&
1696 req_state & REQUEST_WAIT_FOR)
1697 SendToServer_PausePlaying();
1700 old_door_state = GetDoorState();
1704 CloseDoor(DOOR_CLOSE_1);
1706 /* save old door content */
1707 BlitBitmap(bitmap_db_door, bitmap_db_door,
1708 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1709 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1711 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1713 /* clear door drawing field */
1714 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1716 game_status = PSEUDO_DOOR; /* force DOOR font on preview level */
1718 /* write text for request */
1719 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1721 char text_line[MAX_REQUEST_LINE_LEN + 1];
1727 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1730 if (!tc || tc == ' ')
1741 strncpy(text_line, text, tl);
1744 DrawText(DX + (DXSIZE - tl * getFontWidth(FONT_TEXT_2)) / 2,
1745 DY + 8 + ty * (getFontHeight(FONT_TEXT_2) + 2),
1746 text_line, FONT_TEXT_2);
1748 text += tl + (tc == ' ' ? 1 : 0);
1751 game_status = last_game_status; /* restore current game status */
1753 if (req_state & REQ_ASK)
1755 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1756 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1758 else if (req_state & REQ_CONFIRM)
1760 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1762 else if (req_state & REQ_PLAYER)
1764 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1765 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1766 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1767 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1770 /* copy request gadgets to door backbuffer */
1771 BlitBitmap(drawto, bitmap_db_door,
1772 DX, DY, DXSIZE, DYSIZE,
1773 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1775 OpenDoor(DOOR_OPEN_1);
1781 if (!(req_state & REQUEST_WAIT_FOR))
1783 SetDrawBackgroundMask(REDRAW_FIELD);
1788 if (game_status != MAINMENU)
1791 button_status = MB_RELEASED;
1793 request_gadget_id = -1;
1795 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1807 case EVENT_BUTTONPRESS:
1808 case EVENT_BUTTONRELEASE:
1809 case EVENT_MOTIONNOTIFY:
1811 if (event.type == EVENT_MOTIONNOTIFY)
1813 if (!PointerInWindow(window))
1814 continue; /* window and pointer are on different screens */
1819 motion_status = TRUE;
1820 mx = ((MotionEvent *) &event)->x;
1821 my = ((MotionEvent *) &event)->y;
1825 motion_status = FALSE;
1826 mx = ((ButtonEvent *) &event)->x;
1827 my = ((ButtonEvent *) &event)->y;
1828 if (event.type == EVENT_BUTTONPRESS)
1829 button_status = ((ButtonEvent *) &event)->button;
1831 button_status = MB_RELEASED;
1834 /* this sets 'request_gadget_id' */
1835 HandleGadgets(mx, my, button_status);
1837 switch(request_gadget_id)
1839 case TOOL_CTRL_ID_YES:
1842 case TOOL_CTRL_ID_NO:
1845 case TOOL_CTRL_ID_CONFIRM:
1846 result = TRUE | FALSE;
1849 case TOOL_CTRL_ID_PLAYER_1:
1852 case TOOL_CTRL_ID_PLAYER_2:
1855 case TOOL_CTRL_ID_PLAYER_3:
1858 case TOOL_CTRL_ID_PLAYER_4:
1869 case EVENT_KEYPRESS:
1870 switch(GetEventKey((KeyEvent *)&event, TRUE))
1883 if (req_state & REQ_PLAYER)
1887 case EVENT_KEYRELEASE:
1888 ClearPlayerAction();
1892 HandleOtherEvents(&event);
1896 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1898 int joy = AnyJoystick();
1900 if (joy & JOY_BUTTON_1)
1902 else if (joy & JOY_BUTTON_2)
1908 /* don't eat all CPU time */
1912 if (game_status != MAINMENU)
1917 if (!(req_state & REQ_STAY_OPEN))
1919 CloseDoor(DOOR_CLOSE_1);
1921 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1923 BlitBitmap(bitmap_db_door, bitmap_db_door,
1924 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1925 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1926 OpenDoor(DOOR_OPEN_1);
1932 SetDrawBackgroundMask(REDRAW_FIELD);
1934 #if defined(PLATFORM_UNIX)
1935 /* continue network game after request */
1936 if (options.network &&
1937 game_status == PLAYING &&
1938 req_state & REQUEST_WAIT_FOR)
1939 SendToServer_ContinuePlaying();
1945 unsigned int OpenDoor(unsigned int door_state)
1947 unsigned int new_door_state;
1949 if (door_state & DOOR_COPY_BACK)
1951 BlitBitmap(bitmap_db_door, bitmap_db_door,
1952 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1953 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1954 door_state &= ~DOOR_COPY_BACK;
1957 new_door_state = MoveDoor(door_state);
1959 return(new_door_state);
1962 unsigned int CloseDoor(unsigned int door_state)
1964 unsigned int new_door_state;
1966 BlitBitmap(backbuffer, bitmap_db_door,
1967 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1968 BlitBitmap(backbuffer, bitmap_db_door,
1969 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1971 new_door_state = MoveDoor(door_state);
1973 return(new_door_state);
1976 unsigned int GetDoorState()
1978 return MoveDoor(DOOR_GET_STATE);
1981 unsigned int SetDoorState(unsigned int door_state)
1983 return MoveDoor(door_state | DOOR_SET_STATE);
1986 unsigned int MoveDoor(unsigned int door_state)
1988 static int door1 = DOOR_OPEN_1;
1989 static int door2 = DOOR_CLOSE_2;
1990 static unsigned long door_delay = 0;
1991 int x, start, stepsize = 2;
1992 unsigned long door_delay_value = stepsize * 5;
1994 if (door_state == DOOR_GET_STATE)
1995 return(door1 | door2);
1997 if (door_state & DOOR_SET_STATE)
1999 if (door_state & DOOR_ACTION_1)
2000 door1 = door_state & DOOR_ACTION_1;
2001 if (door_state & DOOR_ACTION_2)
2002 door2 = door_state & DOOR_ACTION_2;
2004 return(door1 | door2);
2007 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2008 door_state &= ~DOOR_OPEN_1;
2009 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2010 door_state &= ~DOOR_CLOSE_1;
2011 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2012 door_state &= ~DOOR_OPEN_2;
2013 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2014 door_state &= ~DOOR_CLOSE_2;
2016 if (setup.quick_doors)
2019 door_delay_value = 0;
2021 StopSound(SND_MENU_DOOR_OPENING);
2022 StopSound(SND_MENU_DOOR_CLOSING);
2025 if (global.autoplay_leveldir)
2027 door_state |= DOOR_NO_DELAY;
2028 door_state &= ~DOOR_CLOSE_ALL;
2031 if (door_state & DOOR_ACTION)
2033 if (!(door_state & DOOR_NO_DELAY))
2035 /* opening door sound has priority over simultaneously closing door */
2036 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2037 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2038 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2039 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2042 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2044 for(x=start; x<=DXSIZE; x+=stepsize)
2046 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2047 GC gc = bitmap->stored_clip_gc;
2049 if (!(door_state & DOOR_NO_DELAY))
2050 WaitUntilDelayReached(&door_delay, door_delay_value);
2052 if (door_state & DOOR_ACTION_1)
2054 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2055 int j = (DXSIZE - i) / 3;
2057 BlitBitmap(bitmap_db_door, drawto,
2058 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2059 DXSIZE,DYSIZE - i/2, DX, DY);
2061 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2063 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2064 BlitBitmapMasked(bitmap, drawto,
2065 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2066 DX + DXSIZE - i, DY + j);
2067 BlitBitmapMasked(bitmap, drawto,
2068 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2069 DX + DXSIZE - i, DY + 140 + j);
2070 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2071 BlitBitmapMasked(bitmap, drawto,
2072 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2074 BlitBitmapMasked(bitmap, drawto,
2075 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2078 BlitBitmapMasked(bitmap, drawto,
2079 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2081 BlitBitmapMasked(bitmap, drawto,
2082 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2084 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2085 BlitBitmapMasked(bitmap, drawto,
2086 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2087 DX + DXSIZE - i, DY + 77 + j);
2088 BlitBitmapMasked(bitmap, drawto,
2089 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2090 DX + DXSIZE - i, DY + 203 + j);
2092 redraw_mask |= REDRAW_DOOR_1;
2095 if (door_state & DOOR_ACTION_2)
2097 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2098 int j = (VXSIZE - i) / 3;
2100 BlitBitmap(bitmap_db_door, drawto,
2101 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2102 VXSIZE, VYSIZE - i/2, VX, VY);
2104 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2106 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2107 BlitBitmapMasked(bitmap, drawto,
2108 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2109 VX + VXSIZE-i, VY+j);
2110 SetClipOrigin(bitmap, gc,
2111 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2112 BlitBitmapMasked(bitmap, drawto,
2113 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2116 BlitBitmapMasked(bitmap, drawto,
2117 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2118 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2119 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2120 BlitBitmapMasked(bitmap, drawto,
2121 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2123 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2125 redraw_mask |= REDRAW_DOOR_2;
2130 if (game_status == MAINMENU)
2135 if (setup.quick_doors)
2137 StopSound(SND_MENU_DOOR_OPENING);
2138 StopSound(SND_MENU_DOOR_CLOSING);
2141 if (door_state & DOOR_ACTION_1)
2142 door1 = door_state & DOOR_ACTION_1;
2143 if (door_state & DOOR_ACTION_2)
2144 door2 = door_state & DOOR_ACTION_2;
2146 return (door1 | door2);
2149 void DrawSpecialEditorDoor()
2151 /* draw bigger toolbox window */
2152 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2153 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2155 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2156 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2159 redraw_mask |= REDRAW_ALL;
2162 void UndrawSpecialEditorDoor()
2164 /* draw normal tape recorder window */
2165 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2166 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2169 redraw_mask |= REDRAW_ALL;
2173 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2175 XImage *pixel_image;
2176 unsigned long pixel_value;
2178 pixel_image = XGetImage(display, bitmap->drawable,
2179 x, y, 1, 1, AllPlanes, ZPixmap);
2180 pixel_value = XGetPixel(pixel_image, 0, 0);
2182 XDestroyImage(pixel_image);
2188 /* ---------- new tool button stuff ---------------------------------------- */
2190 /* graphic position values for tool buttons */
2191 #define TOOL_BUTTON_YES_XPOS 2
2192 #define TOOL_BUTTON_YES_YPOS 250
2193 #define TOOL_BUTTON_YES_GFX_YPOS 0
2194 #define TOOL_BUTTON_YES_XSIZE 46
2195 #define TOOL_BUTTON_YES_YSIZE 28
2196 #define TOOL_BUTTON_NO_XPOS 52
2197 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2198 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2199 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2200 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2201 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2202 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2203 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2204 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2205 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2206 #define TOOL_BUTTON_PLAYER_XSIZE 30
2207 #define TOOL_BUTTON_PLAYER_YSIZE 30
2208 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2209 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2210 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2211 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2212 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2213 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2214 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2215 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2216 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2217 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2218 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2219 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2220 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2221 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2222 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2223 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2224 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2225 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2226 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2227 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2236 } toolbutton_info[NUM_TOOL_BUTTONS] =
2239 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2240 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2241 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2246 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2247 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2248 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2253 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2254 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2255 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2256 TOOL_CTRL_ID_CONFIRM,
2260 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2261 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2262 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2263 TOOL_CTRL_ID_PLAYER_1,
2267 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2268 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2269 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2270 TOOL_CTRL_ID_PLAYER_2,
2274 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2275 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2276 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2277 TOOL_CTRL_ID_PLAYER_3,
2281 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2282 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2283 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2284 TOOL_CTRL_ID_PLAYER_4,
2289 void CreateToolButtons()
2293 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2295 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2296 Bitmap *deco_bitmap = None;
2297 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2298 struct GadgetInfo *gi;
2299 unsigned long event_mask;
2300 int gd_xoffset, gd_yoffset;
2301 int gd_x1, gd_x2, gd_y;
2304 event_mask = GD_EVENT_RELEASED;
2306 gd_xoffset = toolbutton_info[i].xpos;
2307 gd_yoffset = toolbutton_info[i].ypos;
2308 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2309 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2310 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2312 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2314 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2316 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2317 &deco_bitmap, &deco_x, &deco_y);
2318 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2319 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2322 gi = CreateGadget(GDI_CUSTOM_ID, id,
2323 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2324 GDI_X, DX + toolbutton_info[i].x,
2325 GDI_Y, DY + toolbutton_info[i].y,
2326 GDI_WIDTH, toolbutton_info[i].width,
2327 GDI_HEIGHT, toolbutton_info[i].height,
2328 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2329 GDI_STATE, GD_BUTTON_UNPRESSED,
2330 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2331 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2332 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2333 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2334 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2335 GDI_DECORATION_SHIFTING, 1, 1,
2336 GDI_EVENT_MASK, event_mask,
2337 GDI_CALLBACK_ACTION, HandleToolButtons,
2341 Error(ERR_EXIT, "cannot create gadget");
2343 tool_gadget[id] = gi;
2347 void FreeToolButtons()
2351 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2352 FreeGadget(tool_gadget[i]);
2355 static void UnmapToolButtons()
2359 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2360 UnmapGadget(tool_gadget[i]);
2363 static void HandleToolButtons(struct GadgetInfo *gi)
2365 request_gadget_id = gi->custom_id;
2368 int get_next_element(int element)
2372 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2373 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2374 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2375 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2376 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2377 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2378 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
2380 default: return element;
2384 int el_act_dir2img(int element, int action, int direction)
2386 direction = MV_DIR_BIT(direction);
2388 return element_info[element].direction_graphic[action][direction];
2391 int el_act2img(int element, int action)
2393 return element_info[element].graphic[action];
2396 int el_dir2img(int element, int direction)
2398 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2401 int el2img(int element)
2403 return element_info[element].graphic[ACTION_DEFAULT];
2406 int el2edimg(int element)
2408 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
2411 int el2preimg(int element)
2413 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];