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);
246 if (redraw_mask & REDRAW_DOOR_3)
247 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
248 redraw_mask &= ~REDRAW_DOORS;
251 if (redraw_mask & REDRAW_MICROLEVEL)
253 BlitBitmap(backbuffer, window,
254 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
255 MICROLEV_XPOS, MICROLEV_YPOS);
256 BlitBitmap(backbuffer, window,
257 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
258 SX, MICROLABEL_YPOS);
259 redraw_mask &= ~REDRAW_MICROLEVEL;
262 if (redraw_mask & REDRAW_TILES)
264 for(x=0; x<SCR_FIELDX; x++)
265 for(y=0; y<SCR_FIELDY; y++)
266 if (redraw[redraw_x1 + x][redraw_y1 + y])
267 BlitBitmap(buffer, window,
268 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
269 SX + x * TILEX, SY + y * TILEY);
272 if (redraw_mask & REDRAW_FPS) /* display frames per second */
277 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
278 if (!global.fps_slowdown)
281 sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
282 DrawTextExt(window, SX, SY, text, FS_SMALL, FC_YELLOW, FONT_OPAQUE);
287 for(x=0; x<MAX_BUF_XSIZE; x++)
288 for(y=0; y<MAX_BUF_YSIZE; y++)
291 redraw_mask = REDRAW_NONE;
297 long fading_delay = 300;
299 if (setup.fading && (redraw_mask & REDRAW_FIELD))
306 ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
309 for(i=0;i<2*FULL_SYSIZE;i++)
311 for(y=0;y<FULL_SYSIZE;y++)
313 BlitBitmap(backbuffer, window,
314 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
322 for(i=1;i<FULL_SYSIZE;i+=2)
323 BlitBitmap(backbuffer, window,
324 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
330 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
331 BlitBitmapMasked(backbuffer, window,
332 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
337 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
338 BlitBitmapMasked(backbuffer, window,
339 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
344 SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
345 BlitBitmapMasked(backbuffer, window,
346 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
351 SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
352 BlitBitmapMasked(backbuffer, window,
353 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
358 redraw_mask &= ~REDRAW_MAIN;
365 void SetMainBackgroundImage(int graphic)
367 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
368 graphic_info[graphic].bitmap ?
369 graphic_info[graphic].bitmap :
370 graphic_info[IMG_BACKGROUND_DEFAULT].bitmap);
373 void SetDoorBackgroundImage(int graphic)
375 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
376 graphic_info[graphic].bitmap ?
377 graphic_info[graphic].bitmap :
378 graphic_info[IMG_BACKGROUND_DEFAULT].bitmap);
381 void DrawBackground(int dest_x, int dest_y, int width, int height)
383 ClearRectangleOnBackground(backbuffer, dest_x, dest_y, width, height);
385 redraw_mask |= REDRAW_FIELD;
390 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
392 if (setup.soft_scrolling && game_status == PLAYING)
394 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
395 SetDrawtoField(DRAW_BUFFERED);
398 SetDrawtoField(DRAW_BACKBUFFER);
400 if (setup.direct_draw && game_status == PLAYING)
402 ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
403 SetDrawtoField(DRAW_DIRECT);
407 void MarkTileDirty(int x, int y)
409 int xx = redraw_x1 + x;
410 int yy = redraw_y1 + y;
415 redraw[xx][yy] = TRUE;
416 redraw_mask |= REDRAW_TILES;
419 void SetBorderElement()
423 BorderElement = EL_EMPTY;
425 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
427 for(x=0; x<lev_fieldx; x++)
429 if (!IS_MASSIVE(Feld[x][y]))
430 BorderElement = EL_STEELWALL;
432 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
438 void SetRandomAnimationValue(int x, int y)
440 anim.random_frame = GfxRandom[x][y];
443 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
445 /* animation synchronized with global frame counter, not move position */
446 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
447 sync_frame = FrameCounter;
449 return getAnimationFrame(graphic_info[graphic].anim_frames,
450 graphic_info[graphic].anim_delay,
451 graphic_info[graphic].anim_mode,
452 graphic_info[graphic].anim_start_frame,
456 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
457 int graphic, int sync_frame, int mask_mode)
459 int frame = getGraphicAnimationFrame(graphic, sync_frame);
461 if (mask_mode == USE_MASKING)
462 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
464 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
467 inline void DrawGraphicAnimation(int x, int y, int graphic)
469 int lx = LEVELX(x), ly = LEVELY(y);
471 if (!IN_SCR_FIELD(x, y))
474 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
475 graphic, GfxFrame[lx][ly], NO_MASKING);
479 void DrawLevelGraphicAnimation(int x, int y, int graphic)
481 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
484 void DrawLevelElementAnimation(int x, int y, int element)
486 DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
489 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
491 int sx = SCREENX(x), sy = SCREENY(y);
493 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
496 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
499 DrawGraphicAnimation(sx, sy, graphic);
502 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
504 int sx = SCREENX(x), sy = SCREENY(y);
507 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
510 graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
512 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
515 DrawGraphicAnimation(sx, sy, graphic);
518 void DrawAllPlayers()
522 for(i=0; i<MAX_PLAYERS; i++)
523 if (stored_player[i].active)
524 DrawPlayer(&stored_player[i]);
527 void DrawPlayerField(int x, int y)
529 if (!IS_PLAYER(x, y))
532 DrawPlayer(PLAYERINFO(x, y));
535 void DrawPlayer(struct PlayerInfo *player)
537 int jx = player->jx, jy = player->jy;
538 int last_jx = player->last_jx, last_jy = player->last_jy;
539 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
540 int sx = SCREENX(jx), sy = SCREENY(jy);
541 int sxx = 0, syy = 0;
542 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
545 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
547 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
551 if (!IN_LEV_FIELD(jx,jy))
553 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
554 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
555 printf("DrawPlayerField(): This should never happen!\n");
560 if (element == EL_EXPLOSION)
563 /* draw things in the field the player is leaving, if needed */
565 if (player_is_moving)
567 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
569 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
571 if (last_element == EL_DYNAMITE_ACTIVE)
572 DrawDynamite(last_jx, last_jy);
574 DrawLevelFieldThruMask(last_jx, last_jy);
576 else if (last_element == EL_DYNAMITE_ACTIVE)
577 DrawDynamite(last_jx, last_jy);
579 DrawLevelField(last_jx, last_jy);
581 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
585 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
586 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
588 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
591 DrawLevelField(next_jx, next_jy);
595 if (!IN_SCR_FIELD(sx, sy))
598 if (setup.direct_draw)
599 SetDrawtoField(DRAW_BUFFERED);
601 /* draw things behind the player, if needed */
604 DrawLevelElement(jx, jy, Store[jx][jy]);
605 else if (!IS_ACTIVE_BOMB(element))
606 DrawLevelField(jx, jy);
608 DrawLevelElement(jx, jy, EL_EMPTY);
610 /* draw player himself */
612 if (game.emulation == EMU_SUPAPLEX)
614 static int last_dir = MV_LEFT;
615 int action = (player->programmed_action ? player->programmed_action :
617 boolean action_moving =
619 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
620 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
622 graphic = IMG_SP_MURPHY;
626 if (player->MovDir == MV_LEFT)
627 graphic = IMG_SP_MURPHY_PUSHING_LEFT;
628 else if (player->MovDir == MV_RIGHT)
629 graphic = IMG_SP_MURPHY_PUSHING_RIGHT;
630 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
631 graphic = IMG_SP_MURPHY_PUSHING_LEFT;
632 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
633 graphic = IMG_SP_MURPHY_PUSHING_RIGHT;
635 else if (player->snapped)
637 if (player->MovDir == MV_LEFT)
638 graphic = IMG_SP_MURPHY_SNAPPING_LEFT;
639 else if (player->MovDir == MV_RIGHT)
640 graphic = IMG_SP_MURPHY_SNAPPING_RIGHT;
641 else if (player->MovDir == MV_UP)
642 graphic = IMG_SP_MURPHY_SNAPPING_UP;
643 else if (player->MovDir == MV_DOWN)
644 graphic = IMG_SP_MURPHY_SNAPPING_DOWN;
646 else if (action_moving)
648 if (player->MovDir == MV_LEFT)
649 graphic = IMG_SP_MURPHY_MOVING_LEFT;
650 else if (player->MovDir == MV_RIGHT)
651 graphic = IMG_SP_MURPHY_MOVING_RIGHT;
652 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
653 graphic = IMG_SP_MURPHY_MOVING_LEFT;
654 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
655 graphic = IMG_SP_MURPHY_MOVING_RIGHT;
657 graphic = IMG_SP_MURPHY_MOVING_LEFT;
659 frame = getGraphicAnimationFrame(graphic, -1);
662 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
663 last_dir = player->MovDir;
667 if (player->MovDir == MV_LEFT)
668 graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_LEFT :
669 player->is_moving ? IMG_PLAYER1_MOVING_LEFT :
671 else if (player->MovDir == MV_RIGHT)
672 graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_RIGHT :
673 player->is_moving ? IMG_PLAYER1_MOVING_RIGHT :
675 else if (player->MovDir == MV_UP)
676 graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_UP :
677 player->is_moving ? IMG_PLAYER1_MOVING_UP :
679 else /* MV_DOWN || MV_NO_MOVING */
680 graphic = (player->Pushing ? IMG_PLAYER1_PUSHING_DOWN :
681 player->is_moving ? IMG_PLAYER1_MOVING_DOWN :
684 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
687 frame = player->Frame;
689 frame = getGraphicAnimationFrame(graphic, player->Frame);
695 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
696 sxx = player->GfxPos;
698 syy = player->GfxPos;
701 if (!setup.soft_scrolling && ScreenMovPos)
706 printf("-> %d\n", player->Frame);
709 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
711 if (SHIELD_ON(player))
713 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
714 IMG_SHIELD_NORMAL_ACTIVE);
715 int frame = getGraphicAnimationFrame(graphic, -1);
717 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
721 if (player->Pushing && player->GfxPos)
723 if (player->Pushing && player_is_moving)
726 int px = SCREENX(next_jx), py = SCREENY(next_jy);
729 (element == EL_SOKOBAN_FIELD_EMPTY ||
730 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
731 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
735 int element = Feld[next_jx][next_jy];
736 int graphic = el2img(element);
741 if ((sxx || syy) && IS_PUSHABLE(element))
743 graphic = el_act_dir2img(element, ACTION_MOVING, player->MovDir);
745 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
747 frame = getGraphicAnimationFrame(graphic, player->Frame);
751 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
756 if (player->MovDir == MV_LEFT)
761 frame = (player->GfxPos / (TILEX / 4));
763 if (player->MovDir == MV_RIGHT)
764 frame = (frame + 4) % 4;
768 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
769 NO_CUTTING, NO_MASKING);
773 /* draw things in front of player (active dynamite or dynabombs) */
775 if (IS_ACTIVE_BOMB(element))
777 graphic = el2img(element);
780 if (element == EL_DYNAMITE_ACTIVE)
782 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
787 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
793 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
795 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
800 if (game.emulation == EMU_SUPAPLEX)
801 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
803 DrawGraphicThruMask(sx, sy, graphic, frame);
806 if (player_is_moving && last_element == EL_EXPLOSION)
808 int stored = Store[last_jx][last_jy];
809 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
810 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
812 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
813 int phase = ExplodePhase[last_jx][last_jy] - 1;
814 int frame = getGraphicAnimationFrame(graphic, phase - delay);
817 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
820 /* draw elements that stay over the player */
821 /* handle the field the player is leaving ... */
822 if (player_is_moving && IS_OVER_PLAYER(last_element))
823 DrawLevelField(last_jx, last_jy);
825 /* ... and the field the player is entering */
826 if (IS_OVER_PLAYER(element))
827 DrawLevelField(jx, jy);
829 if (setup.direct_draw)
831 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
832 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
833 int x_size = TILEX * (1 + ABS(jx - last_jx));
834 int y_size = TILEY * (1 + ABS(jy - last_jy));
836 BlitBitmap(drawto_field, window,
837 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
838 SetDrawtoField(DRAW_DIRECT);
841 MarkTileDirty(sx,sy);
844 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
846 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
847 int offset_x = graphic_info[graphic].offset_x;
848 int offset_y = graphic_info[graphic].offset_y;
849 int src_x = graphic_info[graphic].src_x + frame * offset_x;
850 int src_y = graphic_info[graphic].src_y + frame * offset_y;
852 *bitmap = src_bitmap;
857 void DrawGraphic(int x, int y, int graphic, int frame)
860 if (!IN_SCR_FIELD(x, y))
862 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
863 printf("DrawGraphic(): This should never happen!\n");
868 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
873 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
878 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
879 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
883 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
890 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
892 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
893 int src_x = graphic_info[graphic].src_x;
894 int src_y = graphic_info[graphic].src_y;
895 int offset_x = graphic_info[graphic].offset_x;
896 int offset_y = graphic_info[graphic].offset_y;
898 src_x += frame * offset_x;
899 src_y += frame * offset_y;
902 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
905 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
908 if (!IN_SCR_FIELD(x, y))
910 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
911 printf("DrawGraphicThruMask(): This should never happen!\n");
916 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
921 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
929 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
930 drawing_gc = src_bitmap->stored_clip_gc;
932 GC drawing_gc = src_bitmap->stored_clip_gc;
933 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
934 int src_x = graphic_info[graphic].src_x;
935 int src_y = graphic_info[graphic].src_y;
936 int offset_x = graphic_info[graphic].offset_x;
937 int offset_y = graphic_info[graphic].offset_y;
939 src_x += frame * offset_x;
940 src_y += frame * offset_y;
944 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
945 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
948 void DrawMiniGraphic(int x, int y, int graphic)
950 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
951 MarkTileDirty(x / 2, y / 2);
954 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
956 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
958 int mini_starty = src_bitmap->height * 2 / 3;
959 int src_x = mini_startx + graphic_info[graphic].src_x / 2;
960 int src_y = mini_starty + graphic_info[graphic].src_y / 2;
962 if (src_x + MINI_TILEX > src_bitmap->width ||
963 src_y + MINI_TILEY > src_bitmap->height)
965 /* graphic of desired size seems not to be contained in this image;
966 dirty workaround: get it from the middle of the normal sized image */
968 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
969 src_x += (TILEX / 2 - MINI_TILEX / 2);
970 src_y += (TILEY / 2 - MINI_TILEY / 2);
973 *bitmap = src_bitmap;
978 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
983 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
984 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
987 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
988 int cut_mode, int mask_mode)
997 int width = TILEX, height = TILEY;
1003 DrawGraphic(x, y, graphic, frame);
1007 if (dx || dy) /* shifted graphic */
1009 if (x < BX1) /* object enters playfield from the left */
1016 else if (x > BX2) /* object enters playfield from the right */
1022 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1028 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1030 else if (dx) /* general horizontal movement */
1031 MarkTileDirty(x + SIGN(dx), y);
1033 if (y < BY1) /* object enters playfield from the top */
1035 if (cut_mode==CUT_BELOW) /* object completely above top border */
1043 else if (y > BY2) /* object enters playfield from the bottom */
1049 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1055 else if (dy > 0 && cut_mode == CUT_ABOVE)
1057 if (y == BY2) /* object completely above bottom border */
1063 MarkTileDirty(x, y + 1);
1064 } /* object leaves playfield to the bottom */
1065 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1067 else if (dy) /* general vertical movement */
1068 MarkTileDirty(x, y + SIGN(dy));
1071 src_bitmap = graphic_info[graphic].bitmap;
1072 src_x = graphic_info[graphic].src_x;
1073 src_y = graphic_info[graphic].src_y;
1074 offset_x = graphic_info[graphic].offset_x;
1075 offset_y = graphic_info[graphic].offset_y;
1077 drawing_gc = src_bitmap->stored_clip_gc;
1079 src_x += frame * offset_x;
1080 src_y += frame * offset_y;
1085 dest_x = FX + x * TILEX + dx;
1086 dest_y = FY + y * TILEY + dy;
1089 if (!IN_SCR_FIELD(x,y))
1091 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1092 printf("DrawGraphicShifted(): This should never happen!\n");
1097 if (mask_mode == USE_MASKING)
1099 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1100 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1104 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1110 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1111 int frame, int cut_mode)
1113 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1116 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1117 int cut_mode, int mask_mode)
1119 int lx = LEVELX(x), ly = LEVELY(y);
1123 if (IN_LEV_FIELD(lx, ly))
1125 SetRandomAnimationValue(lx, ly);
1127 graphic = el_act_dir2img(element, GfxAction[lx][ly], MovDir[lx][ly]);
1128 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1130 else /* border element */
1132 graphic = el2img(element);
1133 frame = getGraphicAnimationFrame(graphic, -1);
1136 if (element == EL_WALL_GROWING)
1138 boolean left_stopped = FALSE, right_stopped = FALSE;
1140 if (!IN_LEV_FIELD(lx - 1, ly) || IS_MAUER(Feld[lx - 1][ly]))
1141 left_stopped = TRUE;
1142 if (!IN_LEV_FIELD(lx + 1, ly) || IS_MAUER(Feld[lx + 1][ly]))
1143 right_stopped = TRUE;
1145 if (left_stopped && right_stopped)
1147 else if (left_stopped)
1149 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1150 frame = graphic_info[graphic].anim_frames - 1;
1152 else if (right_stopped)
1154 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1155 frame = graphic_info[graphic].anim_frames - 1;
1158 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1160 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1161 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1162 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1163 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1164 IMG_AMOEBA_DEAD_PART1);
1166 graphic += (x + 2 * y + 4) % 4;
1170 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1171 else if (mask_mode == USE_MASKING)
1172 DrawGraphicThruMask(x, y, graphic, frame);
1174 DrawGraphic(x, y, graphic, frame);
1177 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1178 int cut_mode, int mask_mode)
1180 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1181 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1182 cut_mode, mask_mode);
1185 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1188 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1191 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1194 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1198 void DrawOldScreenElementThruMask(int x, int y, int element)
1200 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1203 void DrawScreenElementThruMask(int x, int y, int element)
1205 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1209 void DrawLevelElementThruMask(int x, int y, int element)
1211 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1214 void DrawLevelFieldThruMask(int x, int y)
1216 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1219 void DrawCrumbledSand(int x, int y)
1223 int i, width, height, cx,cy;
1224 int lx = LEVELX(x), ly = LEVELY(y);
1225 int element, graphic;
1227 static int xy[4][2] =
1235 if (!IN_LEV_FIELD(lx, ly))
1238 element = Feld[lx][ly];
1240 if (element == EL_SAND ||
1241 element == EL_LANDMINE ||
1242 element == EL_TRAP ||
1243 element == EL_TRAP_ACTIVE)
1245 if (!IN_SCR_FIELD(x, y))
1248 graphic = IMG_SAND_CRUMBLED;
1250 src_bitmap = graphic_info[graphic].bitmap;
1251 src_x = graphic_info[graphic].src_x;
1252 src_y = graphic_info[graphic].src_y;
1258 lxx = lx + xy[i][0];
1259 lyy = ly + xy[i][1];
1260 if (!IN_LEV_FIELD(lxx, lyy))
1261 element = EL_STEELWALL;
1263 element = Feld[lxx][lyy];
1265 if (element == EL_SAND ||
1266 element == EL_LANDMINE ||
1267 element == EL_TRAP ||
1268 element == EL_TRAP_ACTIVE)
1271 if (i == 1 || i == 2)
1275 cx = (i == 2 ? TILEX - snip : 0);
1283 cy = (i == 3 ? TILEY - snip : 0);
1286 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1287 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1290 MarkTileDirty(x, y);
1294 graphic = IMG_SAND_CRUMBLED;
1296 src_bitmap = graphic_info[graphic].bitmap;
1297 src_x = graphic_info[graphic].src_x;
1298 src_y = graphic_info[graphic].src_y;
1302 int xx, yy, lxx, lyy;
1306 lxx = lx + xy[i][0];
1307 lyy = ly + xy[i][1];
1309 if (!IN_LEV_FIELD(lxx, lyy) ||
1310 (Feld[lxx][lyy] != EL_SAND &&
1311 Feld[lxx][lyy] != EL_LANDMINE &&
1312 Feld[lxx][lyy] != EL_TRAP &&
1313 Feld[lxx][lyy] != EL_TRAP_ACTIVE) ||
1314 !IN_SCR_FIELD(xx, yy))
1317 if (i == 1 || i == 2)
1321 cx = (i == 1 ? TILEX - snip : 0);
1329 cy = (i==0 ? TILEY-snip : 0);
1332 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1333 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1335 MarkTileDirty(xx, yy);
1340 void DrawScreenElement(int x, int y, int element)
1342 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1343 DrawCrumbledSand(x, y);
1346 void DrawLevelElement(int x, int y, int element)
1348 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1349 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1352 void DrawScreenField(int x, int y)
1354 int lx = LEVELX(x), ly = LEVELY(y);
1355 int element, content;
1357 if (!IN_LEV_FIELD(lx, ly))
1359 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1362 element = BorderElement;
1364 DrawScreenElement(x, y, element);
1368 element = Feld[lx][ly];
1369 content = Store[lx][ly];
1371 if (IS_MOVING(lx, ly))
1373 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1374 boolean cut_mode = NO_CUTTING;
1376 if (element == EL_QUICKSAND_EMPTYING ||
1377 element == EL_MAGIC_WALL_EMPTYING ||
1378 element == EL_BD_MAGIC_WALL_EMPTYING ||
1379 element == EL_AMOEBA_DRIPPING)
1380 cut_mode = CUT_ABOVE;
1381 else if (element == EL_QUICKSAND_FILLING ||
1382 element == EL_MAGIC_WALL_FILLING ||
1383 element == EL_BD_MAGIC_WALL_FILLING)
1384 cut_mode = CUT_BELOW;
1386 if (cut_mode == CUT_ABOVE)
1387 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1389 DrawScreenElement(x, y, EL_EMPTY);
1392 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1393 else if (cut_mode == NO_CUTTING)
1394 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1396 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1398 if (content == EL_ACID)
1399 DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
1401 else if (IS_BLOCKED(lx, ly))
1406 boolean cut_mode = NO_CUTTING;
1407 int element_old, content_old;
1409 Blocked2Moving(lx, ly, &oldx, &oldy);
1412 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1413 MovDir[oldx][oldy] == MV_RIGHT);
1415 element_old = Feld[oldx][oldy];
1416 content_old = Store[oldx][oldy];
1418 if (element_old == EL_QUICKSAND_EMPTYING ||
1419 element_old == EL_MAGIC_WALL_EMPTYING ||
1420 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1421 element_old == EL_AMOEBA_DRIPPING)
1422 cut_mode = CUT_ABOVE;
1424 DrawScreenElement(x, y, EL_EMPTY);
1427 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1429 else if (cut_mode == NO_CUTTING)
1430 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1433 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1436 else if (IS_DRAWABLE(element))
1437 DrawScreenElement(x, y, element);
1439 DrawScreenElement(x, y, EL_EMPTY);
1442 void DrawLevelField(int x, int y)
1444 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1445 DrawScreenField(SCREENX(x), SCREENY(y));
1446 else if (IS_MOVING(x, y))
1450 Moving2Blocked(x, y, &newx, &newy);
1451 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1452 DrawScreenField(SCREENX(newx), SCREENY(newy));
1454 else if (IS_BLOCKED(x, y))
1458 Blocked2Moving(x, y, &oldx, &oldy);
1459 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1460 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1464 void DrawMiniElement(int x, int y, int element)
1468 graphic = el2edimg(element);
1469 DrawMiniGraphic(x, y, graphic);
1472 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1474 int x = sx + scroll_x, y = sy + scroll_y;
1476 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1477 DrawMiniElement(sx, sy, EL_EMPTY);
1478 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1479 DrawMiniElement(sx, sy, Feld[x][y]);
1482 int steel_type, steel_position;
1485 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1486 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1487 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1488 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1489 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1490 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1493 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1494 steel_position = (x == -1 && y == -1 ? 0 :
1495 x == lev_fieldx && y == -1 ? 1 :
1496 x == -1 && y == lev_fieldy ? 2 :
1497 x == lev_fieldx && y == lev_fieldy ? 3 :
1498 x == -1 || x == lev_fieldx ? 4 :
1499 y == -1 || y == lev_fieldy ? 5 : -1);
1501 if (steel_position != -1)
1502 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1506 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1508 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1509 int mini_startx = src_bitmap->width * 3 / 4;
1510 int mini_starty = src_bitmap->height * 2 / 3;
1511 int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1512 int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1514 if (src_x + MICRO_TILEX > src_bitmap->width ||
1515 src_y + MICRO_TILEY > src_bitmap->height)
1517 /* graphic of desired size seems not to be contained in this image;
1518 dirty workaround: get it from the middle of the normal sized image */
1520 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1521 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1522 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1525 *bitmap = src_bitmap;
1530 void DrawMicroElement(int xpos, int ypos, int element)
1534 int graphic = el2img(element);
1536 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1537 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1545 SetDrawBackgroundMask(REDRAW_NONE);
1548 for(x=BX1; x<=BX2; x++)
1549 for(y=BY1; y<=BY2; y++)
1550 DrawScreenField(x, y);
1552 redraw_mask |= REDRAW_FIELD;
1555 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1559 for(x=0; x<size_x; x++)
1560 for(y=0; y<size_y; y++)
1561 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1563 redraw_mask |= REDRAW_FIELD;
1566 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1570 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1572 if (lev_fieldx < STD_LEV_FIELDX)
1573 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1574 if (lev_fieldy < STD_LEV_FIELDY)
1575 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1577 xpos += MICRO_TILEX;
1578 ypos += MICRO_TILEY;
1580 for(x=-1; x<=STD_LEV_FIELDX; x++)
1582 for(y=-1; y<=STD_LEV_FIELDY; y++)
1584 int lx = from_x + x, ly = from_y + y;
1586 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1587 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1589 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1590 && BorderElement != EL_EMPTY)
1591 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1596 redraw_mask |= REDRAW_MICROLEVEL;
1599 #define MICROLABEL_EMPTY 0
1600 #define MICROLABEL_LEVEL_NAME 1
1601 #define MICROLABEL_CREATED_BY 2
1602 #define MICROLABEL_LEVEL_AUTHOR 3
1603 #define MICROLABEL_IMPORTED_FROM 4
1604 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1606 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1608 static void DrawMicroLevelLabelExt(int mode)
1610 char label_text[MAX_MICROLABEL_SIZE + 1];
1612 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1614 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1615 mode == MICROLABEL_CREATED_BY ? "created by" :
1616 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1617 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1618 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1619 leveldir_current->imported_from : ""),
1620 MAX_MICROLABEL_SIZE);
1621 label_text[MAX_MICROLABEL_SIZE] = '\0';
1623 if (strlen(label_text) > 0)
1625 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1626 int lypos = MICROLABEL_YPOS;
1628 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1631 redraw_mask |= REDRAW_MICROLEVEL;
1634 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1636 static unsigned long scroll_delay = 0;
1637 static unsigned long label_delay = 0;
1638 static int from_x, from_y, scroll_direction;
1639 static int label_state, label_counter;
1643 from_x = from_y = 0;
1644 scroll_direction = MV_RIGHT;
1648 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1649 DrawMicroLevelLabelExt(label_state);
1651 /* initialize delay counters */
1652 DelayReached(&scroll_delay, 0);
1653 DelayReached(&label_delay, 0);
1658 /* scroll micro level, if needed */
1659 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1660 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1662 switch (scroll_direction)
1668 scroll_direction = MV_UP;
1672 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1675 scroll_direction = MV_DOWN;
1682 scroll_direction = MV_RIGHT;
1686 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1689 scroll_direction = MV_LEFT;
1696 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1699 /* redraw micro level label, if needed */
1700 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1701 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1702 strcmp(level.author, leveldir_current->name) != 0 &&
1703 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1705 int max_label_counter = 23;
1707 if (leveldir_current->imported_from != NULL)
1708 max_label_counter += 14;
1710 label_counter = (label_counter + 1) % max_label_counter;
1711 label_state = (label_counter >= 0 && label_counter <= 7 ?
1712 MICROLABEL_LEVEL_NAME :
1713 label_counter >= 9 && label_counter <= 12 ?
1714 MICROLABEL_CREATED_BY :
1715 label_counter >= 14 && label_counter <= 21 ?
1716 MICROLABEL_LEVEL_AUTHOR :
1717 label_counter >= 23 && label_counter <= 26 ?
1718 MICROLABEL_IMPORTED_FROM :
1719 label_counter >= 28 && label_counter <= 35 ?
1720 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1721 DrawMicroLevelLabelExt(label_state);
1725 int REQ_in_range(int x, int y)
1727 if (y > DY+249 && y < DY+278)
1729 if (x > DX+1 && x < DX+48)
1731 else if (x > DX+51 && x < DX+98)
1737 #define MAX_REQUEST_LINES 13
1738 #define MAX_REQUEST_LINE_LEN 7
1740 boolean Request(char *text, unsigned int req_state)
1742 int mx, my, ty, result = -1;
1743 unsigned int old_door_state;
1745 #if defined(PLATFORM_UNIX)
1746 /* pause network game while waiting for request to answer */
1747 if (options.network &&
1748 game_status == PLAYING &&
1749 req_state & REQUEST_WAIT_FOR)
1750 SendToServer_PausePlaying();
1753 old_door_state = GetDoorState();
1757 CloseDoor(DOOR_CLOSE_1);
1759 /* save old door content */
1760 BlitBitmap(bitmap_db_door, bitmap_db_door,
1761 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1762 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1764 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1766 /* clear door drawing field */
1767 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1769 /* write text for request */
1770 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1772 char text_line[MAX_REQUEST_LINE_LEN + 1];
1778 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
1781 if (!tc || tc == ' ')
1792 strncpy(text_line, text, tl);
1795 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
1796 text_line, FS_SMALL, FC_YELLOW);
1798 text += tl + (tc == ' ' ? 1 : 0);
1801 if (req_state & REQ_ASK)
1803 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1804 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1806 else if (req_state & REQ_CONFIRM)
1808 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1810 else if (req_state & REQ_PLAYER)
1812 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1813 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1814 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1815 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1818 /* copy request gadgets to door backbuffer */
1819 BlitBitmap(drawto, bitmap_db_door,
1820 DX, DY, DXSIZE, DYSIZE,
1821 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1823 OpenDoor(DOOR_OPEN_1);
1829 if (!(req_state & REQUEST_WAIT_FOR))
1831 SetDrawBackgroundMask(REDRAW_FIELD);
1836 if (game_status != MAINMENU)
1839 button_status = MB_RELEASED;
1841 request_gadget_id = -1;
1843 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1855 case EVENT_BUTTONPRESS:
1856 case EVENT_BUTTONRELEASE:
1857 case EVENT_MOTIONNOTIFY:
1859 if (event.type == EVENT_MOTIONNOTIFY)
1861 if (!PointerInWindow(window))
1862 continue; /* window and pointer are on different screens */
1867 motion_status = TRUE;
1868 mx = ((MotionEvent *) &event)->x;
1869 my = ((MotionEvent *) &event)->y;
1873 motion_status = FALSE;
1874 mx = ((ButtonEvent *) &event)->x;
1875 my = ((ButtonEvent *) &event)->y;
1876 if (event.type == EVENT_BUTTONPRESS)
1877 button_status = ((ButtonEvent *) &event)->button;
1879 button_status = MB_RELEASED;
1882 /* this sets 'request_gadget_id' */
1883 HandleGadgets(mx, my, button_status);
1885 switch(request_gadget_id)
1887 case TOOL_CTRL_ID_YES:
1890 case TOOL_CTRL_ID_NO:
1893 case TOOL_CTRL_ID_CONFIRM:
1894 result = TRUE | FALSE;
1897 case TOOL_CTRL_ID_PLAYER_1:
1900 case TOOL_CTRL_ID_PLAYER_2:
1903 case TOOL_CTRL_ID_PLAYER_3:
1906 case TOOL_CTRL_ID_PLAYER_4:
1917 case EVENT_KEYPRESS:
1918 switch(GetEventKey((KeyEvent *)&event, TRUE))
1931 if (req_state & REQ_PLAYER)
1935 case EVENT_KEYRELEASE:
1936 ClearPlayerAction();
1940 HandleOtherEvents(&event);
1944 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1946 int joy = AnyJoystick();
1948 if (joy & JOY_BUTTON_1)
1950 else if (joy & JOY_BUTTON_2)
1956 /* don't eat all CPU time */
1960 if (game_status != MAINMENU)
1965 if (!(req_state & REQ_STAY_OPEN))
1967 CloseDoor(DOOR_CLOSE_1);
1969 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1971 BlitBitmap(bitmap_db_door, bitmap_db_door,
1972 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1973 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1974 OpenDoor(DOOR_OPEN_1);
1980 SetDrawBackgroundMask(REDRAW_FIELD);
1982 #if defined(PLATFORM_UNIX)
1983 /* continue network game after request */
1984 if (options.network &&
1985 game_status == PLAYING &&
1986 req_state & REQUEST_WAIT_FOR)
1987 SendToServer_ContinuePlaying();
1993 unsigned int OpenDoor(unsigned int door_state)
1995 unsigned int new_door_state;
1997 if (door_state & DOOR_COPY_BACK)
1999 BlitBitmap(bitmap_db_door, bitmap_db_door,
2000 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2001 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2002 door_state &= ~DOOR_COPY_BACK;
2005 new_door_state = MoveDoor(door_state);
2007 return(new_door_state);
2010 unsigned int CloseDoor(unsigned int door_state)
2012 unsigned int new_door_state;
2014 BlitBitmap(backbuffer, bitmap_db_door,
2015 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2016 BlitBitmap(backbuffer, bitmap_db_door,
2017 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2019 new_door_state = MoveDoor(door_state);
2021 return(new_door_state);
2024 unsigned int GetDoorState()
2026 return MoveDoor(DOOR_GET_STATE);
2029 unsigned int SetDoorState(unsigned int door_state)
2031 return MoveDoor(door_state | DOOR_SET_STATE);
2034 unsigned int MoveDoor(unsigned int door_state)
2036 static int door1 = DOOR_OPEN_1;
2037 static int door2 = DOOR_CLOSE_2;
2038 static unsigned long door_delay = 0;
2039 int x, start, stepsize = 2;
2040 unsigned long door_delay_value = stepsize * 5;
2042 if (door_state == DOOR_GET_STATE)
2043 return(door1 | door2);
2045 if (door_state & DOOR_SET_STATE)
2047 if (door_state & DOOR_ACTION_1)
2048 door1 = door_state & DOOR_ACTION_1;
2049 if (door_state & DOOR_ACTION_2)
2050 door2 = door_state & DOOR_ACTION_2;
2052 return(door1 | door2);
2055 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2056 door_state &= ~DOOR_OPEN_1;
2057 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2058 door_state &= ~DOOR_CLOSE_1;
2059 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2060 door_state &= ~DOOR_OPEN_2;
2061 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2062 door_state &= ~DOOR_CLOSE_2;
2064 if (setup.quick_doors)
2067 door_delay_value = 0;
2069 StopSound(SND_MENU_DOOR_OPENING);
2070 StopSound(SND_MENU_DOOR_CLOSING);
2073 if (global.autoplay_leveldir)
2075 door_state |= DOOR_NO_DELAY;
2076 door_state &= ~DOOR_CLOSE_ALL;
2079 if (door_state & DOOR_ACTION)
2081 if (!(door_state & DOOR_NO_DELAY))
2083 /* opening door sound has priority over simultaneously closing door */
2084 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2085 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2086 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2087 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2090 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2092 for(x=start; x<=DXSIZE; x+=stepsize)
2094 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2095 GC gc = bitmap->stored_clip_gc;
2097 if (!(door_state & DOOR_NO_DELAY))
2098 WaitUntilDelayReached(&door_delay, door_delay_value);
2100 if (door_state & DOOR_ACTION_1)
2102 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2103 int j = (DXSIZE - i) / 3;
2105 BlitBitmap(bitmap_db_door, drawto,
2106 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2107 DXSIZE,DYSIZE - i/2, DX, DY);
2109 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2111 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2112 BlitBitmapMasked(bitmap, drawto,
2113 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2114 DX + DXSIZE - i, DY + j);
2115 BlitBitmapMasked(bitmap, drawto,
2116 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2117 DX + DXSIZE - i, DY + 140 + j);
2118 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2119 BlitBitmapMasked(bitmap, drawto,
2120 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2122 BlitBitmapMasked(bitmap, drawto,
2123 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2126 BlitBitmapMasked(bitmap, drawto,
2127 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2129 BlitBitmapMasked(bitmap, drawto,
2130 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2132 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2133 BlitBitmapMasked(bitmap, drawto,
2134 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2135 DX + DXSIZE - i, DY + 77 + j);
2136 BlitBitmapMasked(bitmap, drawto,
2137 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2138 DX + DXSIZE - i, DY + 203 + j);
2140 redraw_mask |= REDRAW_DOOR_1;
2143 if (door_state & DOOR_ACTION_2)
2145 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2146 int j = (VXSIZE - i) / 3;
2148 BlitBitmap(bitmap_db_door, drawto,
2149 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2150 VXSIZE, VYSIZE - i/2, VX, VY);
2152 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2154 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2155 BlitBitmapMasked(bitmap, drawto,
2156 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2157 VX + VXSIZE-i, VY+j);
2158 SetClipOrigin(bitmap, gc,
2159 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2160 BlitBitmapMasked(bitmap, drawto,
2161 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2164 BlitBitmapMasked(bitmap, drawto,
2165 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2166 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2167 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2168 BlitBitmapMasked(bitmap, drawto,
2169 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2171 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2173 redraw_mask |= REDRAW_DOOR_2;
2178 if (game_status == MAINMENU)
2183 if (setup.quick_doors)
2185 StopSound(SND_MENU_DOOR_OPENING);
2186 StopSound(SND_MENU_DOOR_CLOSING);
2189 if (door_state & DOOR_ACTION_1)
2190 door1 = door_state & DOOR_ACTION_1;
2191 if (door_state & DOOR_ACTION_2)
2192 door2 = door_state & DOOR_ACTION_2;
2194 return (door1 | door2);
2197 void DrawSpecialEditorDoor()
2199 /* draw bigger toolbox window */
2200 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2201 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2203 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2204 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2207 redraw_mask |= REDRAW_ALL;
2210 void UndrawSpecialEditorDoor()
2212 /* draw normal tape recorder window */
2213 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2214 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2217 redraw_mask |= REDRAW_ALL;
2221 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2223 XImage *pixel_image;
2224 unsigned long pixel_value;
2226 pixel_image = XGetImage(display, bitmap->drawable,
2227 x, y, 1, 1, AllPlanes, ZPixmap);
2228 pixel_value = XGetPixel(pixel_image, 0, 0);
2230 XDestroyImage(pixel_image);
2236 /* ---------- new tool button stuff ---------------------------------------- */
2238 /* graphic position values for tool buttons */
2239 #define TOOL_BUTTON_YES_XPOS 2
2240 #define TOOL_BUTTON_YES_YPOS 250
2241 #define TOOL_BUTTON_YES_GFX_YPOS 0
2242 #define TOOL_BUTTON_YES_XSIZE 46
2243 #define TOOL_BUTTON_YES_YSIZE 28
2244 #define TOOL_BUTTON_NO_XPOS 52
2245 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2246 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2247 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2248 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2249 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2250 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2251 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2252 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2253 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2254 #define TOOL_BUTTON_PLAYER_XSIZE 30
2255 #define TOOL_BUTTON_PLAYER_YSIZE 30
2256 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2257 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2258 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2259 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2260 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2261 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2262 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2263 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2264 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2265 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2266 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2267 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2268 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2269 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2270 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2271 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2272 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2273 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2274 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2275 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2284 } toolbutton_info[NUM_TOOL_BUTTONS] =
2287 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2288 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2289 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2294 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2295 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2296 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2301 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2302 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2303 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2304 TOOL_CTRL_ID_CONFIRM,
2308 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2309 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2310 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2311 TOOL_CTRL_ID_PLAYER_1,
2315 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2316 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2317 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2318 TOOL_CTRL_ID_PLAYER_2,
2322 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2323 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2324 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2325 TOOL_CTRL_ID_PLAYER_3,
2329 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2330 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2331 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2332 TOOL_CTRL_ID_PLAYER_4,
2337 void CreateToolButtons()
2341 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2343 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2344 Bitmap *deco_bitmap = None;
2345 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2346 struct GadgetInfo *gi;
2347 unsigned long event_mask;
2348 int gd_xoffset, gd_yoffset;
2349 int gd_x1, gd_x2, gd_y;
2352 event_mask = GD_EVENT_RELEASED;
2354 gd_xoffset = toolbutton_info[i].xpos;
2355 gd_yoffset = toolbutton_info[i].ypos;
2356 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2357 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2358 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2360 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2362 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2364 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2365 &deco_bitmap, &deco_x, &deco_y);
2366 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2367 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2370 gi = CreateGadget(GDI_CUSTOM_ID, id,
2371 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2372 GDI_X, DX + toolbutton_info[i].x,
2373 GDI_Y, DY + toolbutton_info[i].y,
2374 GDI_WIDTH, toolbutton_info[i].width,
2375 GDI_HEIGHT, toolbutton_info[i].height,
2376 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2377 GDI_STATE, GD_BUTTON_UNPRESSED,
2378 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2379 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2380 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2381 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2382 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2383 GDI_DECORATION_SHIFTING, 1, 1,
2384 GDI_EVENT_MASK, event_mask,
2385 GDI_CALLBACK_ACTION, HandleToolButtons,
2389 Error(ERR_EXIT, "cannot create gadget");
2391 tool_gadget[id] = gi;
2395 void FreeToolButtons()
2399 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2400 FreeGadget(tool_gadget[i]);
2403 static void UnmapToolButtons()
2407 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2408 UnmapGadget(tool_gadget[i]);
2411 static void HandleToolButtons(struct GadgetInfo *gi)
2413 request_gadget_id = gi->custom_id;
2416 int get_next_element(int element)
2420 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2421 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2422 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2423 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2424 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2425 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2426 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2428 default: return element;
2432 int el_act_dir2img(int element, int action, int direction)
2434 direction = MV_DIR_BIT(direction);
2436 return element_info[element].direction_graphic[action][direction];
2439 int el_act2img(int element, int action)
2441 return element_info[element].graphic[action];
2444 int el_dir2img(int element, int direction)
2446 return el_act_dir2img(element, ACTION_DEFAULT, direction);
2449 int el2img(int element)
2451 return element_info[element].graphic[ACTION_DEFAULT];
2454 int el2edimg(int element)
2456 return element_info[element].editor_graphic;