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_NONE ? NULL :
368 new_graphic_info[graphic].bitmap ?
369 new_graphic_info[graphic].bitmap :
370 new_graphic_info[IMG_BACKGROUND_DEFAULT].bitmap);
373 void SetDoorBackgroundImage(int graphic)
375 SetDoorBackgroundBitmap(graphic == IMG_NONE ? NULL :
376 new_graphic_info[graphic].bitmap ?
377 new_graphic_info[graphic].bitmap :
378 new_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 static int getGraphicAnimationPhase(int frames, int delay, int mode)
411 if (mode & ANIM_PINGPONG)
413 int max_anim_frames = 2 * frames - 2;
415 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
416 phase = (phase < frames ? phase : max_anim_frames - phase);
419 phase = (FrameCounter % (delay * frames)) / delay;
421 if (mode & ANIM_REVERSE)
427 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
429 /* animation synchronized with global frame counter, not move position */
430 if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
431 sync_frame = FrameCounter;
433 return getAnimationFrame(new_graphic_info[graphic].anim_frames,
434 new_graphic_info[graphic].anim_delay,
435 new_graphic_info[graphic].anim_mode,
436 new_graphic_info[graphic].anim_start_frame,
440 void MarkTileDirty(int x, int y)
442 int xx = redraw_x1 + x;
443 int yy = redraw_y1 + y;
448 redraw[xx][yy] = TRUE;
449 redraw_mask |= REDRAW_TILES;
452 void SetBorderElement()
456 BorderElement = EL_EMPTY;
458 for(y=0; y<lev_fieldy && BorderElement == EL_EMPTY; y++)
460 for(x=0; x<lev_fieldx; x++)
462 if (!IS_MASSIVE(Feld[x][y]))
463 BorderElement = EL_STEELWALL;
465 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
471 void DrawAllPlayers()
475 for(i=0; i<MAX_PLAYERS; i++)
476 if (stored_player[i].active)
477 DrawPlayer(&stored_player[i]);
480 void DrawPlayerField(int x, int y)
482 if (!IS_PLAYER(x, y))
485 DrawPlayer(PLAYERINFO(x, y));
488 void DrawPlayer(struct PlayerInfo *player)
490 int jx = player->jx, jy = player->jy;
491 int last_jx = player->last_jx, last_jy = player->last_jy;
492 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
493 int sx = SCREENX(jx), sy = SCREENY(jy);
494 int sxx = 0, syy = 0;
495 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
498 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
500 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
504 if (!IN_LEV_FIELD(jx,jy))
506 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
507 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
508 printf("DrawPlayerField(): This should never happen!\n");
513 if (element == EL_EXPLOSION)
516 /* draw things in the field the player is leaving, if needed */
518 if (player_is_moving)
520 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
522 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
524 if (last_element == EL_DYNAMITE_ACTIVE)
525 DrawDynamite(last_jx, last_jy);
527 DrawLevelFieldThruMask(last_jx, last_jy);
529 else if (last_element == EL_DYNAMITE_ACTIVE)
530 DrawDynamite(last_jx, last_jy);
532 DrawLevelField(last_jx, last_jy);
534 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
538 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
539 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FIELD_EMPTY);
541 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
544 DrawLevelField(next_jx, next_jy);
548 if (!IN_SCR_FIELD(sx, sy))
551 if (setup.direct_draw)
552 SetDrawtoField(DRAW_BUFFERED);
554 /* draw things behind the player, if needed */
557 DrawLevelElement(jx, jy, Store[jx][jy]);
558 else if (!IS_ACTIVE_BOMB(element))
559 DrawLevelField(jx, jy);
561 DrawLevelElement(jx, jy, EL_EMPTY);
563 /* draw player himself */
565 if (game.emulation == EMU_SUPAPLEX)
567 static int last_dir = MV_LEFT;
568 int action = (player->programmed_action ? player->programmed_action :
570 boolean action_moving =
572 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
573 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
575 graphic = IMG_SP_MURPHY;
579 if (player->MovDir == MV_LEFT)
580 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
581 else if (player->MovDir == MV_RIGHT)
582 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
583 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
584 graphic = IMG_SP_MURPHY_LEFT_PUSHING;
585 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
586 graphic = IMG_SP_MURPHY_RIGHT_PUSHING;
588 else if (player->snapped)
590 if (player->MovDir == MV_LEFT)
591 graphic = IMG_SP_MURPHY_LEFT_SNAPPING;
592 else if (player->MovDir == MV_RIGHT)
593 graphic = IMG_SP_MURPHY_RIGHT_SNAPPING;
594 else if (player->MovDir == MV_UP)
595 graphic = IMG_SP_MURPHY_UP_SNAPPING;
596 else if (player->MovDir == MV_DOWN)
597 graphic = IMG_SP_MURPHY_DOWN_SNAPPING;
599 else if (action_moving)
601 if (player->MovDir == MV_LEFT)
602 graphic = IMG_SP_MURPHY_LEFT_MOVING;
603 else if (player->MovDir == MV_RIGHT)
604 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
605 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
606 graphic = IMG_SP_MURPHY_LEFT_MOVING;
607 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
608 graphic = IMG_SP_MURPHY_RIGHT_MOVING;
610 graphic = IMG_SP_MURPHY_LEFT_MOVING;
612 frame = getGraphicAnimationFrame(graphic, -1);
615 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
616 last_dir = player->MovDir;
620 if (player->MovDir == MV_LEFT)
621 graphic = (player->Pushing ? IMG_PLAYER1_LEFT_PUSHING :
622 player->is_moving ? IMG_PLAYER1_LEFT_MOVING :
624 else if (player->MovDir == MV_RIGHT)
625 graphic = (player->Pushing ? IMG_PLAYER1_RIGHT_PUSHING :
626 player->is_moving ? IMG_PLAYER1_RIGHT_MOVING :
628 else if (player->MovDir == MV_UP)
629 graphic = (player->Pushing ? IMG_PLAYER1_UP_PUSHING :
630 player->is_moving ? IMG_PLAYER1_UP_MOVING :
632 else /* MV_DOWN || MV_NO_MOVING */
633 graphic = (player->Pushing ? IMG_PLAYER1_DOWN_PUSHING :
634 player->is_moving ? IMG_PLAYER1_DOWN_MOVING :
637 graphic = PLAYER_NR_GFX(graphic, player->index_nr);
640 frame = player->Frame;
642 frame = getGraphicAnimationFrame(graphic, player->Frame);
648 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
649 sxx = player->GfxPos;
651 syy = player->GfxPos;
654 if (!setup.soft_scrolling && ScreenMovPos)
659 printf("-> %d\n", player->Frame);
662 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
664 if (SHIELD_ON(player))
666 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
667 IMG_SHIELD_NORMAL_ACTIVE);
668 int frame = getGraphicAnimationFrame(graphic, -1);
670 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
674 if (player->Pushing && player->GfxPos)
676 if (player->Pushing && player_is_moving)
679 int px = SCREENX(next_jx), py = SCREENY(next_jy);
682 (element == EL_SOKOBAN_FIELD_EMPTY ||
683 Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL))
684 DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
688 int element = Feld[next_jx][next_jy];
689 int graphic = el2img(element);
694 if ((sxx || syy) && IS_PUSHABLE(element))
696 graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_MOVING);
698 frame = getGraphicAnimationFrame(graphic, player->GfxPos);
700 frame = getGraphicAnimationFrame(graphic, player->Frame);
704 printf("-> %d [%d]\n", player->Frame, player->GfxPos);
709 if (player->MovDir == MV_LEFT)
714 frame = (player->GfxPos / (TILEX / 4));
716 if (player->MovDir == MV_RIGHT)
717 frame = (frame + 4) % 4;
721 DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
722 NO_CUTTING, NO_MASKING);
726 /* draw things in front of player (active dynamite or dynabombs) */
728 if (IS_ACTIVE_BOMB(element))
730 graphic = el2img(element);
733 if (element == EL_DYNAMITE_ACTIVE)
735 if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
740 if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
744 frame = getGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
747 if (game.emulation == EMU_SUPAPLEX)
748 DrawGraphic(sx, sy, IMG_SP_DISK_RED, 0);
750 DrawGraphicThruMask(sx, sy, graphic, frame);
753 if (player_is_moving && last_element == EL_EXPLOSION)
755 int stored = Store[last_jx][last_jy];
756 int graphic = (game.emulation != EMU_SUPAPLEX ? IMG_EXPLOSION :
757 stored == EL_SP_INFOTRON ? IMG_SP_EXPLOSION_INFOTRON :
759 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
760 int phase = ExplodePhase[last_jx][last_jy] - 1;
761 int frame = getGraphicAnimationFrame(graphic, phase - delay);
764 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
767 /* draw elements that stay over the player */
768 /* handle the field the player is leaving ... */
769 if (player_is_moving && IS_OVER_PLAYER(last_element))
770 DrawLevelField(last_jx, last_jy);
772 /* ... and the field the player is entering */
773 if (IS_OVER_PLAYER(element))
774 DrawLevelField(jx, jy);
776 if (setup.direct_draw)
778 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
779 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
780 int x_size = TILEX * (1 + ABS(jx - last_jx));
781 int y_size = TILEY * (1 + ABS(jy - last_jy));
783 BlitBitmap(drawto_field, window,
784 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
785 SetDrawtoField(DRAW_DIRECT);
788 MarkTileDirty(sx,sy);
791 void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
792 int graphic, int mask_mode)
794 int frame = getGraphicAnimationFrame(graphic, -1);
796 if (mask_mode == USE_MASKING)
797 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
799 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
802 void DrawGraphicAnimation(int x, int y, int graphic)
804 int ux = LEVELX(x), uy = LEVELY(y);
806 if (!IN_SCR_FIELD(x, y) ||
807 (GfxFrame[ux][uy] % new_graphic_info[graphic].anim_delay) != 0)
810 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
811 graphic, NO_MASKING);
816 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
818 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
820 *bitmap = graphic_info[graphic].bitmap;
821 *x = graphic_info[graphic].src_x;
822 *y = graphic_info[graphic].src_y;
824 else if (graphic >= GFX_START_ROCKSELEMENTS &&
825 graphic <= GFX_END_ROCKSELEMENTS)
827 graphic -= GFX_START_ROCKSELEMENTS;
828 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
829 *x = (graphic % GFX_PER_LINE) * TILEX;
830 *y = (graphic / GFX_PER_LINE) * TILEY;
832 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
834 graphic -= GFX_START_ROCKSHEROES;
835 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
836 *x = (graphic % HEROES_PER_LINE) * TILEX;
837 *y = (graphic / HEROES_PER_LINE) * TILEY;
839 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
841 graphic -= GFX_START_ROCKSSP;
842 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
843 *x = (graphic % SP_PER_LINE) * TILEX;
844 *y = (graphic / SP_PER_LINE) * TILEY;
846 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
848 graphic -= GFX_START_ROCKSDC;
849 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
850 *x = (graphic % DC_PER_LINE) * TILEX;
851 *y = (graphic / DC_PER_LINE) * TILEY;
853 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
855 graphic -= GFX_START_ROCKSMORE;
856 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
857 *x = (graphic % MORE_PER_LINE) * TILEX;
858 *y = (graphic / MORE_PER_LINE) * TILEY;
860 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
862 graphic -= GFX_START_ROCKSFONT;
863 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
864 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
865 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
869 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
876 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
878 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
879 int offset_x = new_graphic_info[graphic].offset_x;
880 int offset_y = new_graphic_info[graphic].offset_y;
881 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
882 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
884 *bitmap = src_bitmap;
889 void DrawGraphic(int x, int y, int graphic, int frame)
892 if (!IN_SCR_FIELD(x, y))
894 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
895 printf("DrawGraphic(): This should never happen!\n");
900 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
905 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
910 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
911 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
915 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
922 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
924 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
925 int src_x = new_graphic_info[graphic].src_x;
926 int src_y = new_graphic_info[graphic].src_y;
927 int offset_x = new_graphic_info[graphic].offset_x;
928 int offset_y = new_graphic_info[graphic].offset_y;
930 src_x += frame * offset_x;
931 src_y += frame * offset_y;
934 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
937 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
940 if (!IN_SCR_FIELD(x, y))
942 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
943 printf("DrawGraphicThruMask(): This should never happen!\n");
948 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
953 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
961 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
962 drawing_gc = src_bitmap->stored_clip_gc;
964 GC drawing_gc = src_bitmap->stored_clip_gc;
965 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
966 int src_x = new_graphic_info[graphic].src_x;
967 int src_y = new_graphic_info[graphic].src_y;
968 int offset_x = new_graphic_info[graphic].offset_x;
969 int offset_y = new_graphic_info[graphic].offset_y;
971 src_x += frame * offset_x;
972 src_y += frame * offset_y;
976 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
977 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
980 void DrawMiniGraphic(int x, int y, int graphic)
982 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
983 MarkTileDirty(x / 2, y / 2);
986 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
988 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
990 int mini_starty = src_bitmap->height * 2 / 3;
991 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
992 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
994 if (src_x + MINI_TILEX > src_bitmap->width ||
995 src_y + MINI_TILEY > src_bitmap->height)
997 /* graphic of desired size seems not to be contained in this image;
998 dirty workaround: get it from the middle of the normal sized image */
1000 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1001 src_x += (TILEX / 2 - MINI_TILEX / 2);
1002 src_y += (TILEY / 2 - MINI_TILEY / 2);
1005 *bitmap = src_bitmap;
1010 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1015 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1016 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1019 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1020 int cut_mode, int mask_mode)
1029 int width = TILEX, height = TILEY;
1035 DrawGraphic(x, y, graphic, frame);
1039 if (dx || dy) /* shifted graphic */
1041 if (x < BX1) /* object enters playfield from the left */
1048 else if (x > BX2) /* object enters playfield from the right */
1054 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1060 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1062 else if (dx) /* general horizontal movement */
1063 MarkTileDirty(x + SIGN(dx), y);
1065 if (y < BY1) /* object enters playfield from the top */
1067 if (cut_mode==CUT_BELOW) /* object completely above top border */
1075 else if (y > BY2) /* object enters playfield from the bottom */
1081 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1087 else if (dy > 0 && cut_mode == CUT_ABOVE)
1089 if (y == BY2) /* object completely above bottom border */
1095 MarkTileDirty(x, y + 1);
1096 } /* object leaves playfield to the bottom */
1097 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1099 else if (dy) /* general vertical movement */
1100 MarkTileDirty(x, y + SIGN(dy));
1103 src_bitmap = new_graphic_info[graphic].bitmap;
1104 src_x = new_graphic_info[graphic].src_x;
1105 src_y = new_graphic_info[graphic].src_y;
1106 offset_x = new_graphic_info[graphic].offset_x;
1107 offset_y = new_graphic_info[graphic].offset_y;
1109 drawing_gc = src_bitmap->stored_clip_gc;
1111 src_x += frame * offset_x;
1112 src_y += frame * offset_y;
1117 dest_x = FX + x * TILEX + dx;
1118 dest_y = FY + y * TILEY + dy;
1121 if (!IN_SCR_FIELD(x,y))
1123 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1124 printf("DrawGraphicShifted(): This should never happen!\n");
1129 if (mask_mode == USE_MASKING)
1131 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1132 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1136 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1142 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1143 int frame, int cut_mode)
1145 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1149 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1150 int cut_mode, int mask_mode)
1152 int ux = LEVELX(x), uy = LEVELY(y);
1153 int graphic = el2gfx(element);
1154 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1155 int phase4 = phase8 / 2;
1156 int phase2 = phase8 / 4;
1157 int dir = MovDir[ux][uy];
1159 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1161 graphic += 1 * !phase2;
1165 else if (dir == MV_LEFT)
1167 else if (dir == MV_DOWN)
1170 else if (element == EL_SP_SNIKSNAK)
1173 graphic = GFX_SP_SNIKSNAK_LEFT;
1174 else if (dir == MV_RIGHT)
1175 graphic = GFX_SP_SNIKSNAK_RIGHT;
1176 else if (dir == MV_UP)
1177 graphic = GFX_SP_SNIKSNAK_UP;
1179 graphic = GFX_SP_SNIKSNAK_DOWN;
1181 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1183 else if (element == EL_SP_ELECTRON)
1185 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1187 else if (element == EL_MOLE || element == EL_PENGUIN ||
1188 element == EL_PIG || element == EL_DRAGON)
1191 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1192 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1193 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1194 else if (dir == MV_RIGHT)
1195 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1196 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1197 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1198 else if (dir == MV_UP)
1199 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1200 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1201 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1203 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1204 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1205 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1209 else if (element == EL_SATELLITE)
1211 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1213 else if (element == EL_ACID)
1215 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1217 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1221 else if (element == EL_BALLOON)
1225 else if ((element == EL_ROCK ||
1226 element == EL_SP_ZONK ||
1227 element == EL_BD_ROCK ||
1228 element == EL_SP_INFOTRON ||
1232 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1234 if (element == EL_ROCK ||
1235 element == EL_SP_ZONK ||
1236 element == EL_BD_ROCK)
1239 graphic += (4 - phase4) % 4;
1240 else if (dir == MV_RIGHT)
1243 graphic += phase2 * 2;
1245 else if (element != EL_SP_INFOTRON)
1249 else if (element == EL_MAGIC_WALL_ACTIVE ||
1250 element == EL_MAGIC_WALL_EMPTYING ||
1251 element == EL_BD_MAGIC_WALL_ACTIVE ||
1252 element == EL_BD_MAGIC_WALL_EMPTYING ||
1253 element == EL_MAGIC_WALL_FULL ||
1254 element == EL_BD_MAGIC_WALL_FULL)
1256 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1258 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1260 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1261 graphic += (x + 2 * y + 4) % 4;
1263 else if (element == EL_WALL_GROWING)
1265 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1267 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1268 links_massiv = TRUE;
1269 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1270 rechts_massiv = TRUE;
1272 if (links_massiv && rechts_massiv)
1273 graphic = GFX_MAUERWERK;
1274 else if (links_massiv)
1275 graphic = GFX_MAUER_R;
1276 else if (rechts_massiv)
1277 graphic = GFX_MAUER_L;
1280 else if ((element == EL_INVISIBLE_STEELWALL ||
1281 element == EL_INVISIBLE_WALL ||
1282 element == EL_INVISIBLE_SAND) && game.light_time_left)
1284 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1285 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1286 GFX_SAND_INVISIBLE_ON);
1291 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1292 else if (mask_mode == USE_MASKING)
1293 DrawGraphicThruMask(x, y, graphic);
1295 DrawGraphic(x, y, graphic);
1299 inline static int getFramePosition(int x, int y)
1301 int frame_pos = -1; /* default: global synchronization */
1303 int element = Feld[x][y];
1305 if (element == EL_QUICKSAND_FULL ||
1306 element == EL_MAGIC_WALL_FULL ||
1307 element == EL_BD_MAGIC_WALL_FULL)
1309 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1310 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1313 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1315 frame_pos = GfxFrame[x][y];
1322 inline static int getGfxAction(int x, int y)
1324 int gfx_action = GFX_ACTION_DEFAULT;
1327 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1328 gfx_action = GfxAction[x][y];
1329 else if (IS_MOVING(x, y))
1330 gfx_action = GFX_ACTION_MOVING;
1332 gfx_action = GfxAction[x][y];
1337 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1344 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1345 int cut_mode, int mask_mode)
1347 int ux = LEVELX(x), uy = LEVELY(y);
1351 if (IN_LEV_FIELD(ux, uy))
1353 int move_dir = MovDir[ux][uy];
1354 int move_pos = getFramePosition(ux, uy);
1355 int gfx_action = getGfxAction(ux, uy);
1357 graphic = el_dir_act2img(element, move_dir, gfx_action);
1358 frame = getGraphicAnimationFrame(graphic, move_pos);
1362 graphic = el2img(element);
1363 frame = getGraphicAnimationFrame(graphic, 0);
1366 if (element == EL_WALL_GROWING)
1368 boolean left_stopped = FALSE, right_stopped = FALSE;
1370 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1371 left_stopped = TRUE;
1372 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1373 right_stopped = TRUE;
1375 if (left_stopped && right_stopped)
1377 else if (left_stopped)
1379 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1380 frame = new_graphic_info[graphic].anim_frames - 1;
1382 else if (right_stopped)
1384 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1385 frame = new_graphic_info[graphic].anim_frames - 1;
1388 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1390 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1391 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1392 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1393 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1394 IMG_AMOEBA_DEAD_PART1);
1396 graphic += (x + 2 * y + 4) % 4;
1400 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1401 else if (mask_mode == USE_MASKING)
1402 DrawGraphicThruMask(x, y, graphic, frame);
1404 DrawGraphic(x, y, graphic, frame);
1407 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1408 int cut_mode, int mask_mode)
1410 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1411 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1412 cut_mode, mask_mode);
1415 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1418 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1421 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1424 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1428 void DrawOldScreenElementThruMask(int x, int y, int element)
1430 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1433 void DrawScreenElementThruMask(int x, int y, int element)
1435 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1439 void DrawLevelElementThruMask(int x, int y, int element)
1441 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1444 void DrawLevelFieldThruMask(int x, int y)
1446 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1449 void DrawCrumbledSand(int x, int y)
1453 int i, width, height, cx,cy;
1454 int ux = LEVELX(x), uy = LEVELY(y);
1455 int element, graphic;
1457 static int xy[4][2] =
1465 if (!IN_LEV_FIELD(ux, uy))
1468 element = Feld[ux][uy];
1470 if (element == EL_SAND ||
1471 element == EL_LANDMINE ||
1472 element == EL_TRAP ||
1473 element == EL_TRAP_ACTIVE)
1475 if (!IN_SCR_FIELD(x, y))
1478 graphic = IMG_SAND_CRUMBLED;
1480 src_bitmap = new_graphic_info[graphic].bitmap;
1481 src_x = new_graphic_info[graphic].src_x;
1482 src_y = new_graphic_info[graphic].src_y;
1488 uxx = ux + xy[i][0];
1489 uyy = uy + xy[i][1];
1490 if (!IN_LEV_FIELD(uxx, uyy))
1491 element = EL_STEELWALL;
1493 element = Feld[uxx][uyy];
1495 if (element == EL_SAND ||
1496 element == EL_LANDMINE ||
1497 element == EL_TRAP ||
1498 element == EL_TRAP_ACTIVE)
1501 if (i == 1 || i == 2)
1505 cx = (i == 2 ? TILEX - snip : 0);
1513 cy = (i == 3 ? TILEY - snip : 0);
1516 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1517 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1520 MarkTileDirty(x, y);
1524 graphic = IMG_SAND_CRUMBLED;
1526 src_bitmap = new_graphic_info[graphic].bitmap;
1527 src_x = new_graphic_info[graphic].src_x;
1528 src_y = new_graphic_info[graphic].src_y;
1532 int xx, yy, uxx, uyy;
1536 uxx = ux + xy[i][0];
1537 uyy = uy + xy[i][1];
1539 if (!IN_LEV_FIELD(uxx, uyy) ||
1540 (Feld[uxx][uyy] != EL_SAND &&
1541 Feld[uxx][uyy] != EL_LANDMINE &&
1542 Feld[uxx][uyy] != EL_TRAP &&
1543 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1544 !IN_SCR_FIELD(xx, yy))
1547 if (i == 1 || i == 2)
1551 cx = (i == 1 ? TILEX - snip : 0);
1559 cy = (i==0 ? TILEY-snip : 0);
1562 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1563 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1565 MarkTileDirty(xx, yy);
1570 void DrawScreenElement(int x, int y, int element)
1572 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1573 DrawCrumbledSand(x, y);
1576 void DrawLevelElement(int x, int y, int element)
1578 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1579 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1582 void DrawScreenField(int x, int y)
1584 int ux = LEVELX(x), uy = LEVELY(y);
1585 int element, content;
1587 if (!IN_LEV_FIELD(ux, uy))
1589 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1592 element = BorderElement;
1594 DrawScreenElement(x, y, element);
1598 element = Feld[ux][uy];
1599 content = Store[ux][uy];
1601 if (IS_MOVING(ux, uy))
1603 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1604 boolean cut_mode = NO_CUTTING;
1606 if (element == EL_QUICKSAND_EMPTYING ||
1607 element == EL_MAGIC_WALL_EMPTYING ||
1608 element == EL_BD_MAGIC_WALL_EMPTYING ||
1609 element == EL_AMOEBA_DRIPPING)
1610 cut_mode = CUT_ABOVE;
1611 else if (element == EL_QUICKSAND_FILLING ||
1612 element == EL_MAGIC_WALL_FILLING ||
1613 element == EL_BD_MAGIC_WALL_FILLING)
1614 cut_mode = CUT_BELOW;
1616 if (cut_mode == CUT_ABOVE)
1617 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1619 DrawScreenElement(x, y, EL_EMPTY);
1622 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1623 else if (cut_mode == NO_CUTTING)
1624 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1626 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1628 if (content == EL_ACID)
1629 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1631 else if (IS_BLOCKED(ux, uy))
1636 boolean cut_mode = NO_CUTTING;
1637 int element_old, content_old;
1639 Blocked2Moving(ux, uy, &oldx, &oldy);
1642 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1643 MovDir[oldx][oldy] == MV_RIGHT);
1645 element_old = Feld[oldx][oldy];
1646 content_old = Store[oldx][oldy];
1648 if (element_old == EL_QUICKSAND_EMPTYING ||
1649 element_old == EL_MAGIC_WALL_EMPTYING ||
1650 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1651 element_old == EL_AMOEBA_DRIPPING)
1652 cut_mode = CUT_ABOVE;
1654 DrawScreenElement(x, y, EL_EMPTY);
1657 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1659 else if (cut_mode == NO_CUTTING)
1660 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1663 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1666 else if (IS_DRAWABLE(element))
1667 DrawScreenElement(x, y, element);
1669 DrawScreenElement(x, y, EL_EMPTY);
1672 void DrawLevelField(int x, int y)
1674 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1675 DrawScreenField(SCREENX(x), SCREENY(y));
1676 else if (IS_MOVING(x, y))
1680 Moving2Blocked(x, y, &newx, &newy);
1681 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1682 DrawScreenField(SCREENX(newx), SCREENY(newy));
1684 else if (IS_BLOCKED(x, y))
1688 Blocked2Moving(x, y, &oldx, &oldy);
1689 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1690 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1694 void DrawMiniElement(int x, int y, int element)
1698 graphic = el2img(element);
1699 DrawMiniGraphic(x, y, graphic);
1702 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1704 int x = sx + scroll_x, y = sy + scroll_y;
1706 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1707 DrawMiniElement(sx, sy, EL_EMPTY);
1708 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1709 DrawMiniElement(sx, sy, Feld[x][y]);
1712 int steel_type, steel_position;
1715 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1716 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1717 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1718 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1719 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1720 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1723 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1724 steel_position = (x == -1 && y == -1 ? 0 :
1725 x == lev_fieldx && y == -1 ? 1 :
1726 x == -1 && y == lev_fieldy ? 2 :
1727 x == lev_fieldx && y == lev_fieldy ? 3 :
1728 x == -1 || x == lev_fieldx ? 4 :
1729 y == -1 || y == lev_fieldy ? 5 : -1);
1731 if (steel_position != -1)
1732 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1736 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1738 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1739 int mini_startx = src_bitmap->width * 3 / 4;
1740 int mini_starty = src_bitmap->height * 2 / 3;
1741 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1742 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1744 if (src_x + MICRO_TILEX > src_bitmap->width ||
1745 src_y + MICRO_TILEY > src_bitmap->height)
1747 /* graphic of desired size seems not to be contained in this image;
1748 dirty workaround: get it from the middle of the normal sized image */
1750 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1751 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1752 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1755 *bitmap = src_bitmap;
1760 void DrawMicroElement(int xpos, int ypos, int element)
1764 int graphic = el2img(element);
1766 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1767 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1775 SetDrawBackgroundMask(REDRAW_NONE);
1778 for(x=BX1; x<=BX2; x++)
1779 for(y=BY1; y<=BY2; y++)
1780 DrawScreenField(x, y);
1782 redraw_mask |= REDRAW_FIELD;
1785 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1789 for(x=0; x<size_x; x++)
1790 for(y=0; y<size_y; y++)
1791 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1793 redraw_mask |= REDRAW_FIELD;
1796 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1800 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1802 if (lev_fieldx < STD_LEV_FIELDX)
1803 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1804 if (lev_fieldy < STD_LEV_FIELDY)
1805 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1807 xpos += MICRO_TILEX;
1808 ypos += MICRO_TILEY;
1810 for(x=-1; x<=STD_LEV_FIELDX; x++)
1812 for(y=-1; y<=STD_LEV_FIELDY; y++)
1814 int lx = from_x + x, ly = from_y + y;
1816 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1817 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1819 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1820 && BorderElement != EL_EMPTY)
1821 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1826 redraw_mask |= REDRAW_MICROLEVEL;
1829 #define MICROLABEL_EMPTY 0
1830 #define MICROLABEL_LEVEL_NAME 1
1831 #define MICROLABEL_CREATED_BY 2
1832 #define MICROLABEL_LEVEL_AUTHOR 3
1833 #define MICROLABEL_IMPORTED_FROM 4
1834 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1836 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1838 static void DrawMicroLevelLabelExt(int mode)
1840 char label_text[MAX_MICROLABEL_SIZE + 1];
1842 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1844 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1845 mode == MICROLABEL_CREATED_BY ? "created by" :
1846 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1847 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1848 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1849 leveldir_current->imported_from : ""),
1850 MAX_MICROLABEL_SIZE);
1851 label_text[MAX_MICROLABEL_SIZE] = '\0';
1853 if (strlen(label_text) > 0)
1855 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1856 int lypos = MICROLABEL_YPOS;
1858 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1861 redraw_mask |= REDRAW_MICROLEVEL;
1864 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1866 static unsigned long scroll_delay = 0;
1867 static unsigned long label_delay = 0;
1868 static int from_x, from_y, scroll_direction;
1869 static int label_state, label_counter;
1873 from_x = from_y = 0;
1874 scroll_direction = MV_RIGHT;
1878 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1879 DrawMicroLevelLabelExt(label_state);
1881 /* initialize delay counters */
1882 DelayReached(&scroll_delay, 0);
1883 DelayReached(&label_delay, 0);
1888 /* scroll micro level, if needed */
1889 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1890 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1892 switch (scroll_direction)
1898 scroll_direction = MV_UP;
1902 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1905 scroll_direction = MV_DOWN;
1912 scroll_direction = MV_RIGHT;
1916 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1919 scroll_direction = MV_LEFT;
1926 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1929 /* redraw micro level label, if needed */
1930 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1931 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1932 strcmp(level.author, leveldir_current->name) != 0 &&
1933 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1935 int max_label_counter = 23;
1937 if (leveldir_current->imported_from != NULL)
1938 max_label_counter += 14;
1940 label_counter = (label_counter + 1) % max_label_counter;
1941 label_state = (label_counter >= 0 && label_counter <= 7 ?
1942 MICROLABEL_LEVEL_NAME :
1943 label_counter >= 9 && label_counter <= 12 ?
1944 MICROLABEL_CREATED_BY :
1945 label_counter >= 14 && label_counter <= 21 ?
1946 MICROLABEL_LEVEL_AUTHOR :
1947 label_counter >= 23 && label_counter <= 26 ?
1948 MICROLABEL_IMPORTED_FROM :
1949 label_counter >= 28 && label_counter <= 35 ?
1950 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1951 DrawMicroLevelLabelExt(label_state);
1955 int REQ_in_range(int x, int y)
1957 if (y > DY+249 && y < DY+278)
1959 if (x > DX+1 && x < DX+48)
1961 else if (x > DX+51 && x < DX+98)
1967 #define MAX_REQUEST_LINES 13
1968 #define MAX_REQUEST_LINE_LEN 7
1970 boolean Request(char *text, unsigned int req_state)
1972 int mx, my, ty, result = -1;
1973 unsigned int old_door_state;
1975 #if defined(PLATFORM_UNIX)
1976 /* pause network game while waiting for request to answer */
1977 if (options.network &&
1978 game_status == PLAYING &&
1979 req_state & REQUEST_WAIT_FOR)
1980 SendToServer_PausePlaying();
1983 old_door_state = GetDoorState();
1987 CloseDoor(DOOR_CLOSE_1);
1989 /* save old door content */
1990 BlitBitmap(bitmap_db_door, bitmap_db_door,
1991 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1992 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1994 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1996 /* clear door drawing field */
1997 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1999 /* write text for request */
2000 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
2002 char text_line[MAX_REQUEST_LINE_LEN + 1];
2008 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2011 if (!tc || tc == ' ')
2022 strncpy(text_line, text, tl);
2025 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2026 text_line, FS_SMALL, FC_YELLOW);
2028 text += tl + (tc == ' ' ? 1 : 0);
2031 if (req_state & REQ_ASK)
2033 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2034 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2036 else if (req_state & REQ_CONFIRM)
2038 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2040 else if (req_state & REQ_PLAYER)
2042 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2043 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2044 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2045 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2048 /* copy request gadgets to door backbuffer */
2049 BlitBitmap(drawto, bitmap_db_door,
2050 DX, DY, DXSIZE, DYSIZE,
2051 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2053 OpenDoor(DOOR_OPEN_1);
2059 if (!(req_state & REQUEST_WAIT_FOR))
2061 SetDrawBackgroundMask(REDRAW_FIELD);
2066 if (game_status != MAINMENU)
2069 button_status = MB_RELEASED;
2071 request_gadget_id = -1;
2073 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2085 case EVENT_BUTTONPRESS:
2086 case EVENT_BUTTONRELEASE:
2087 case EVENT_MOTIONNOTIFY:
2089 if (event.type == EVENT_MOTIONNOTIFY)
2091 if (!PointerInWindow(window))
2092 continue; /* window and pointer are on different screens */
2097 motion_status = TRUE;
2098 mx = ((MotionEvent *) &event)->x;
2099 my = ((MotionEvent *) &event)->y;
2103 motion_status = FALSE;
2104 mx = ((ButtonEvent *) &event)->x;
2105 my = ((ButtonEvent *) &event)->y;
2106 if (event.type == EVENT_BUTTONPRESS)
2107 button_status = ((ButtonEvent *) &event)->button;
2109 button_status = MB_RELEASED;
2112 /* this sets 'request_gadget_id' */
2113 HandleGadgets(mx, my, button_status);
2115 switch(request_gadget_id)
2117 case TOOL_CTRL_ID_YES:
2120 case TOOL_CTRL_ID_NO:
2123 case TOOL_CTRL_ID_CONFIRM:
2124 result = TRUE | FALSE;
2127 case TOOL_CTRL_ID_PLAYER_1:
2130 case TOOL_CTRL_ID_PLAYER_2:
2133 case TOOL_CTRL_ID_PLAYER_3:
2136 case TOOL_CTRL_ID_PLAYER_4:
2147 case EVENT_KEYPRESS:
2148 switch(GetEventKey((KeyEvent *)&event, TRUE))
2161 if (req_state & REQ_PLAYER)
2165 case EVENT_KEYRELEASE:
2166 ClearPlayerAction();
2170 HandleOtherEvents(&event);
2174 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2176 int joy = AnyJoystick();
2178 if (joy & JOY_BUTTON_1)
2180 else if (joy & JOY_BUTTON_2)
2186 /* don't eat all CPU time */
2190 if (game_status != MAINMENU)
2195 if (!(req_state & REQ_STAY_OPEN))
2197 CloseDoor(DOOR_CLOSE_1);
2199 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2201 BlitBitmap(bitmap_db_door, bitmap_db_door,
2202 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2203 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2204 OpenDoor(DOOR_OPEN_1);
2210 SetDrawBackgroundMask(REDRAW_FIELD);
2212 #if defined(PLATFORM_UNIX)
2213 /* continue network game after request */
2214 if (options.network &&
2215 game_status == PLAYING &&
2216 req_state & REQUEST_WAIT_FOR)
2217 SendToServer_ContinuePlaying();
2223 unsigned int OpenDoor(unsigned int door_state)
2225 unsigned int new_door_state;
2227 if (door_state & DOOR_COPY_BACK)
2229 BlitBitmap(bitmap_db_door, bitmap_db_door,
2230 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2231 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2232 door_state &= ~DOOR_COPY_BACK;
2235 new_door_state = MoveDoor(door_state);
2237 return(new_door_state);
2240 unsigned int CloseDoor(unsigned int door_state)
2242 unsigned int new_door_state;
2244 BlitBitmap(backbuffer, bitmap_db_door,
2245 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2246 BlitBitmap(backbuffer, bitmap_db_door,
2247 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2249 new_door_state = MoveDoor(door_state);
2251 return(new_door_state);
2254 unsigned int GetDoorState()
2256 return MoveDoor(DOOR_GET_STATE);
2259 unsigned int SetDoorState(unsigned int door_state)
2261 return MoveDoor(door_state | DOOR_SET_STATE);
2264 unsigned int MoveDoor(unsigned int door_state)
2266 static int door1 = DOOR_OPEN_1;
2267 static int door2 = DOOR_CLOSE_2;
2268 static unsigned long door_delay = 0;
2269 int x, start, stepsize = 2;
2270 unsigned long door_delay_value = stepsize * 5;
2272 if (door_state == DOOR_GET_STATE)
2273 return(door1 | door2);
2275 if (door_state & DOOR_SET_STATE)
2277 if (door_state & DOOR_ACTION_1)
2278 door1 = door_state & DOOR_ACTION_1;
2279 if (door_state & DOOR_ACTION_2)
2280 door2 = door_state & DOOR_ACTION_2;
2282 return(door1 | door2);
2285 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2286 door_state &= ~DOOR_OPEN_1;
2287 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2288 door_state &= ~DOOR_CLOSE_1;
2289 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2290 door_state &= ~DOOR_OPEN_2;
2291 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2292 door_state &= ~DOOR_CLOSE_2;
2294 if (setup.quick_doors)
2297 door_delay_value = 0;
2299 StopSound(SND_MENU_DOOR_OPENING);
2300 StopSound(SND_MENU_DOOR_CLOSING);
2303 if (global.autoplay_leveldir)
2305 door_state |= DOOR_NO_DELAY;
2306 door_state &= ~DOOR_CLOSE_ALL;
2309 if (door_state & DOOR_ACTION)
2311 if (!(door_state & DOOR_NO_DELAY))
2313 /* opening door sound has priority over simultaneously closing door */
2314 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2315 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2316 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2317 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2320 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2322 for(x=start; x<=DXSIZE; x+=stepsize)
2324 Bitmap *bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2325 GC gc = bitmap->stored_clip_gc;
2327 if (!(door_state & DOOR_NO_DELAY))
2328 WaitUntilDelayReached(&door_delay, door_delay_value);
2330 if (door_state & DOOR_ACTION_1)
2332 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2333 int j = (DXSIZE - i) / 3;
2335 BlitBitmap(bitmap_db_door, drawto,
2336 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2337 DXSIZE,DYSIZE - i/2, DX, DY);
2339 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2341 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2342 BlitBitmapMasked(bitmap, drawto,
2343 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2344 DX + DXSIZE - i, DY + j);
2345 BlitBitmapMasked(bitmap, drawto,
2346 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2347 DX + DXSIZE - i, DY + 140 + j);
2348 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2349 BlitBitmapMasked(bitmap, drawto,
2350 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2352 BlitBitmapMasked(bitmap, drawto,
2353 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2356 BlitBitmapMasked(bitmap, drawto,
2357 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2359 BlitBitmapMasked(bitmap, drawto,
2360 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2362 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2363 BlitBitmapMasked(bitmap, drawto,
2364 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2365 DX + DXSIZE - i, DY + 77 + j);
2366 BlitBitmapMasked(bitmap, drawto,
2367 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2368 DX + DXSIZE - i, DY + 203 + j);
2370 redraw_mask |= REDRAW_DOOR_1;
2373 if (door_state & DOOR_ACTION_2)
2375 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2376 int j = (VXSIZE - i) / 3;
2378 BlitBitmap(bitmap_db_door, drawto,
2379 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2380 VXSIZE, VYSIZE - i/2, VX, VY);
2382 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2384 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2385 BlitBitmapMasked(bitmap, drawto,
2386 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2387 VX + VXSIZE-i, VY+j);
2388 SetClipOrigin(bitmap, gc,
2389 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2390 BlitBitmapMasked(bitmap, drawto,
2391 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2394 BlitBitmapMasked(bitmap, drawto,
2395 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2396 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2397 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2398 BlitBitmapMasked(bitmap, drawto,
2399 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2401 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2403 redraw_mask |= REDRAW_DOOR_2;
2408 if (game_status == MAINMENU)
2413 if (setup.quick_doors)
2415 StopSound(SND_MENU_DOOR_OPENING);
2416 StopSound(SND_MENU_DOOR_CLOSING);
2419 if (door_state & DOOR_ACTION_1)
2420 door1 = door_state & DOOR_ACTION_1;
2421 if (door_state & DOOR_ACTION_2)
2422 door2 = door_state & DOOR_ACTION_2;
2424 return (door1 | door2);
2427 void DrawSpecialEditorDoor()
2429 /* draw bigger toolbox window */
2430 BlitBitmap(new_graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2431 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2433 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2434 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2437 redraw_mask |= REDRAW_ALL;
2440 void UndrawSpecialEditorDoor()
2442 /* draw normal tape recorder window */
2443 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2444 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2447 redraw_mask |= REDRAW_ALL;
2451 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2453 XImage *pixel_image;
2454 unsigned long pixel_value;
2456 pixel_image = XGetImage(display, bitmap->drawable,
2457 x, y, 1, 1, AllPlanes, ZPixmap);
2458 pixel_value = XGetPixel(pixel_image, 0, 0);
2460 XDestroyImage(pixel_image);
2466 /* ---------- new tool button stuff ---------------------------------------- */
2468 /* graphic position values for tool buttons */
2469 #define TOOL_BUTTON_YES_XPOS 2
2470 #define TOOL_BUTTON_YES_YPOS 250
2471 #define TOOL_BUTTON_YES_GFX_YPOS 0
2472 #define TOOL_BUTTON_YES_XSIZE 46
2473 #define TOOL_BUTTON_YES_YSIZE 28
2474 #define TOOL_BUTTON_NO_XPOS 52
2475 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2476 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2477 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2478 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2479 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2480 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2481 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2482 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2483 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2484 #define TOOL_BUTTON_PLAYER_XSIZE 30
2485 #define TOOL_BUTTON_PLAYER_YSIZE 30
2486 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2487 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2488 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2489 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2490 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2491 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2492 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2493 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2494 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2495 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2496 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2497 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2498 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2499 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2500 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2501 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2502 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2503 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2504 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2505 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2514 } toolbutton_info[NUM_TOOL_BUTTONS] =
2517 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2518 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2519 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2524 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2525 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2526 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2531 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2532 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2533 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2534 TOOL_CTRL_ID_CONFIRM,
2538 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2539 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2540 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2541 TOOL_CTRL_ID_PLAYER_1,
2545 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2546 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2547 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2548 TOOL_CTRL_ID_PLAYER_2,
2552 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2553 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2554 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2555 TOOL_CTRL_ID_PLAYER_3,
2559 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2560 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2561 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2562 TOOL_CTRL_ID_PLAYER_4,
2567 void CreateToolButtons()
2571 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2573 Bitmap *gd_bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2574 Bitmap *deco_bitmap = None;
2575 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2576 struct GadgetInfo *gi;
2577 unsigned long event_mask;
2578 int gd_xoffset, gd_yoffset;
2579 int gd_x1, gd_x2, gd_y;
2582 event_mask = GD_EVENT_RELEASED;
2584 gd_xoffset = toolbutton_info[i].xpos;
2585 gd_yoffset = toolbutton_info[i].ypos;
2586 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2587 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2588 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2590 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2592 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2594 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2595 &deco_bitmap, &deco_x, &deco_y);
2596 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2597 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2600 gi = CreateGadget(GDI_CUSTOM_ID, id,
2601 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2602 GDI_X, DX + toolbutton_info[i].x,
2603 GDI_Y, DY + toolbutton_info[i].y,
2604 GDI_WIDTH, toolbutton_info[i].width,
2605 GDI_HEIGHT, toolbutton_info[i].height,
2606 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2607 GDI_STATE, GD_BUTTON_UNPRESSED,
2608 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2609 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2610 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2611 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2612 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2613 GDI_DECORATION_SHIFTING, 1, 1,
2614 GDI_EVENT_MASK, event_mask,
2615 GDI_CALLBACK_ACTION, HandleToolButtons,
2619 Error(ERR_EXIT, "cannot create gadget");
2621 tool_gadget[id] = gi;
2625 void FreeToolButtons()
2629 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2630 FreeGadget(tool_gadget[i]);
2633 static void UnmapToolButtons()
2637 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2638 UnmapGadget(tool_gadget[i]);
2641 static void HandleToolButtons(struct GadgetInfo *gi)
2643 request_gadget_id = gi->custom_id;
2646 int get_next_element(int element)
2650 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2651 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2652 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2653 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2654 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2655 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2656 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2658 default: return element;
2662 int el2gfx_OLD(int element)
2666 case EL_EMPTY: return -1;
2667 case EL_SAND: return GFX_ERDREICH;
2668 case EL_WALL: return GFX_MAUERWERK;
2669 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2670 case EL_ROCK: return GFX_FELSBROCKEN;
2671 case EL_EMERALD: return GFX_EDELSTEIN;
2672 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2673 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2674 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2675 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2676 case EL_PLAYER1: return GFX_SPIELER1;
2677 case EL_PLAYER2: return GFX_SPIELER2;
2678 case EL_PLAYER3: return GFX_SPIELER3;
2679 case EL_PLAYER4: return GFX_SPIELER4;
2680 case EL_BUG: return GFX_KAEFER;
2681 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2682 case EL_BUG_UP: return GFX_KAEFER_UP;
2683 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2684 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2685 case EL_SPACESHIP: return GFX_FLIEGER;
2686 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2687 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2688 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2689 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2690 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2691 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2692 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2693 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2694 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2695 case EL_BD_FIREFLY: return GFX_FIREFLY;
2696 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2697 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2698 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2699 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2700 case EL_YAMYAM: return GFX_MAMPFER;
2701 case EL_ROBOT: return GFX_ROBOT;
2702 case EL_STEELWALL: return GFX_BETON;
2703 case EL_DIAMOND: return GFX_DIAMANT;
2704 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2705 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2706 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2707 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2708 case EL_BOMB: return GFX_BOMBE;
2709 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2710 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2711 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2712 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2713 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2714 case EL_ACID: return GFX_SALZSAEURE;
2715 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2716 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2717 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2718 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2719 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2720 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2721 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2722 case EL_NUT: return GFX_KOKOSNUSS;
2723 case EL_GAMEOFLIFE: return GFX_LIFE;
2724 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2725 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2726 case EL_STONEBLOCK: return GFX_BADEWANNE;
2727 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2728 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2729 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2730 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2731 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2732 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2733 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2734 case EL_KEY1: return GFX_SCHLUESSEL1;
2735 case EL_KEY2: return GFX_SCHLUESSEL2;
2736 case EL_KEY3: return GFX_SCHLUESSEL3;
2737 case EL_KEY4: return GFX_SCHLUESSEL4;
2738 case EL_GATE1: return GFX_PFORTE1;
2739 case EL_GATE2: return GFX_PFORTE2;
2740 case EL_GATE3: return GFX_PFORTE3;
2741 case EL_GATE4: return GFX_PFORTE4;
2742 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2743 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2744 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2745 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2746 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2747 case EL_PACMAN: return GFX_PACMAN;
2748 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2749 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2750 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2751 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2752 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2753 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2754 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2755 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2756 case EL_LAMP: return GFX_BIRNE_AUS;
2757 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2758 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2759 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2760 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2761 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2762 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2763 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2764 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2765 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2766 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2767 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2768 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2769 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2770 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2771 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2772 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2773 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2774 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2775 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2776 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2777 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2778 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2779 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2780 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2781 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2782 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2783 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2784 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2785 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2786 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2787 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2788 case EL_MOLE: return GFX_MOLE;
2789 case EL_PENGUIN: return GFX_PINGUIN;
2790 case EL_PIG: return GFX_SCHWEIN;
2791 case EL_DRAGON: return GFX_DRACHE;
2792 case EL_SATELLITE: return GFX_SONDE;
2793 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2794 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2795 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2796 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2797 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2798 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2799 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2800 case EL_SP_ZONK: return GFX_SP_ZONK;
2801 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2802 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2803 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2804 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2805 case EL_EM_GATE1: return GFX_EM_GATE_1;
2806 case EL_EM_GATE2: return GFX_EM_GATE_2;
2807 case EL_EM_GATE3: return GFX_EM_GATE_3;
2808 case EL_EM_GATE4: return GFX_EM_GATE_4;
2809 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2810 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2811 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2812 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2813 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2814 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2815 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2816 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2817 case EL_EM_KEY1: return GFX_EM_KEY_1;
2818 case EL_EM_KEY2: return GFX_EM_KEY_2;
2819 case EL_EM_KEY3: return GFX_EM_KEY_3;
2820 case EL_EM_KEY4: return GFX_EM_KEY_4;
2821 case EL_PEARL: return GFX_PEARL;
2822 case EL_CRYSTAL: return GFX_CRYSTAL;
2823 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2824 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2825 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2826 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2827 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2828 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2829 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2830 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2831 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2832 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2833 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2834 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2835 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2836 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2837 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2838 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2839 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2840 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2841 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2842 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2843 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2844 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2845 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2846 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2847 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2848 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2849 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2850 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2851 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2852 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2853 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2854 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2855 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2856 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2857 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2858 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2859 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2860 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2861 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2862 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2863 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2864 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2865 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2866 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2867 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2868 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2869 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2870 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2871 case EL_LANDMINE: return GFX_LANDMINE;
2872 case EL_ENVELOPE: return GFX_ENVELOPE;
2873 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2874 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2875 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2876 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2877 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2878 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2879 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2880 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2881 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2882 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2883 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2884 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2885 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2886 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2887 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2888 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2889 case EL_MOLE_UP: return GFX_MOLE_UP;
2890 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2891 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2892 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2893 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2894 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2895 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2896 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2897 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2898 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2899 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2900 case EL_BALLOON: return GFX_BALLOON;
2901 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2902 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2903 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2904 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2905 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2906 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2907 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2908 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2909 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2910 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2911 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2912 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2913 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2914 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2915 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2916 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2917 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2918 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2919 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2920 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2921 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2922 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2923 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2924 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2925 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2926 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2927 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2928 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2929 case EL_SPRING: return GFX_SPRING;
2930 case EL_TRAP: return GFX_TRAP_INACTIVE;
2931 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2932 case EL_BD_WALL: return GFX_BD_WALL;
2933 case EL_BD_ROCK: return GFX_BD_ROCK;
2934 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2935 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2939 if (IS_CHAR(element))
2940 return GFX_CHAR_START + (element - EL_CHAR_START);
2941 else if (element >= EL_SP_START && element <= EL_SP_END)
2943 int nr_element = element - EL_SP_START;
2944 int gfx_per_line = 8;
2946 (nr_element / gfx_per_line) * SP_PER_LINE +
2947 (nr_element % gfx_per_line);
2949 return GFX_START_ROCKSSP + nr_graphic;
2957 int el2gfx(int element)
2960 int graphic_OLD = el2gfx_OLD(element);
2965 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2968 int graphic_OLD = el2gfx_OLD(element);
2970 if (element >= MAX_ELEMENTS)
2972 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2975 if (graphic_NEW != graphic_OLD)
2977 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2978 graphic_NEW, graphic_OLD);
2986 int el2img(int element)
2988 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2992 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2999 int el_dir2img(int element, int direction)
3001 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
3004 int el_dir_act2img(int element, int direction, int action)
3009 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
3017 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
3024 action = graphics_action_mapping[action];
3025 direction = MV_DIR_BIT(direction);
3027 return element_info[element].direction_graphic[action][direction];