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 = Frame[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 if (!IN_SCR_FIELD(x, y) ||
805 (FrameCounter % new_graphic_info[graphic].anim_delay) != 0)
808 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
809 graphic, NO_MASKING);
814 void getOldGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
816 if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
818 *bitmap = graphic_info[graphic].bitmap;
819 *x = graphic_info[graphic].src_x;
820 *y = graphic_info[graphic].src_y;
822 else if (graphic >= GFX_START_ROCKSELEMENTS &&
823 graphic <= GFX_END_ROCKSELEMENTS)
825 graphic -= GFX_START_ROCKSELEMENTS;
826 *bitmap = new_graphic_info[IMG_OLD_PIX_ELEMENTS].bitmap;
827 *x = (graphic % GFX_PER_LINE) * TILEX;
828 *y = (graphic / GFX_PER_LINE) * TILEY;
830 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
832 graphic -= GFX_START_ROCKSHEROES;
833 *bitmap = new_graphic_info[IMG_OLD_PIX_HEROES].bitmap;
834 *x = (graphic % HEROES_PER_LINE) * TILEX;
835 *y = (graphic / HEROES_PER_LINE) * TILEY;
837 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
839 graphic -= GFX_START_ROCKSSP;
840 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
841 *x = (graphic % SP_PER_LINE) * TILEX;
842 *y = (graphic / SP_PER_LINE) * TILEY;
844 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
846 graphic -= GFX_START_ROCKSDC;
847 *bitmap = new_graphic_info[IMG_OLD_PIX_DC].bitmap;
848 *x = (graphic % DC_PER_LINE) * TILEX;
849 *y = (graphic / DC_PER_LINE) * TILEY;
851 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
853 graphic -= GFX_START_ROCKSMORE;
854 *bitmap = new_graphic_info[IMG_OLD_PIX_MORE].bitmap;
855 *x = (graphic % MORE_PER_LINE) * TILEX;
856 *y = (graphic / MORE_PER_LINE) * TILEY;
858 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
860 graphic -= GFX_START_ROCKSFONT;
861 *bitmap = new_graphic_info[IMG_OLD_PIX_FONT_EM].bitmap;
862 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
863 *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
867 *bitmap = new_graphic_info[IMG_OLD_PIX_SP].bitmap;
874 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
876 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
877 int offset_x = new_graphic_info[graphic].offset_x;
878 int offset_y = new_graphic_info[graphic].offset_y;
879 int src_x = new_graphic_info[graphic].src_x + frame * offset_x;
880 int src_y = new_graphic_info[graphic].src_y + frame * offset_y;
882 *bitmap = src_bitmap;
887 void DrawGraphic(int x, int y, int graphic, int frame)
890 if (!IN_SCR_FIELD(x, y))
892 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
893 printf("DrawGraphic(): This should never happen!\n");
898 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
903 void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
908 getOldGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
909 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
913 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
920 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
922 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
923 int src_x = new_graphic_info[graphic].src_x;
924 int src_y = new_graphic_info[graphic].src_y;
925 int offset_x = new_graphic_info[graphic].offset_x;
926 int offset_y = new_graphic_info[graphic].offset_y;
928 src_x += frame * offset_x;
929 src_y += frame * offset_y;
932 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
935 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
938 if (!IN_SCR_FIELD(x, y))
940 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
941 printf("DrawGraphicThruMask(): This should never happen!\n");
946 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
951 void DrawGraphicThruMaskExt(DrawBuffer *d, int dest_x, int dest_y, int graphic,
959 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
960 drawing_gc = src_bitmap->stored_clip_gc;
962 GC drawing_gc = src_bitmap->stored_clip_gc;
963 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
964 int src_x = new_graphic_info[graphic].src_x;
965 int src_y = new_graphic_info[graphic].src_y;
966 int offset_x = new_graphic_info[graphic].offset_x;
967 int offset_y = new_graphic_info[graphic].offset_y;
969 src_x += frame * offset_x;
970 src_y += frame * offset_y;
974 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
975 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dest_x, dest_y);
978 void DrawMiniGraphic(int x, int y, int graphic)
980 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
981 MarkTileDirty(x / 2, y / 2);
984 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
986 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
988 int mini_starty = src_bitmap->height * 2 / 3;
989 int src_x = mini_startx + new_graphic_info[graphic].src_x / 2;
990 int src_y = mini_starty + new_graphic_info[graphic].src_y / 2;
992 if (src_x + MINI_TILEX > src_bitmap->width ||
993 src_y + MINI_TILEY > src_bitmap->height)
995 /* graphic of desired size seems not to be contained in this image;
996 dirty workaround: get it from the middle of the normal sized image */
998 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
999 src_x += (TILEX / 2 - MINI_TILEX / 2);
1000 src_y += (TILEY / 2 - MINI_TILEY / 2);
1003 *bitmap = src_bitmap;
1008 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1013 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1014 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1017 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int frame,
1018 int cut_mode, int mask_mode)
1027 int width = TILEX, height = TILEY;
1033 DrawGraphic(x, y, graphic, frame);
1037 if (dx || dy) /* shifted graphic */
1039 if (x < BX1) /* object enters playfield from the left */
1046 else if (x > BX2) /* object enters playfield from the right */
1052 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1058 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1060 else if (dx) /* general horizontal movement */
1061 MarkTileDirty(x + SIGN(dx), y);
1063 if (y < BY1) /* object enters playfield from the top */
1065 if (cut_mode==CUT_BELOW) /* object completely above top border */
1073 else if (y > BY2) /* object enters playfield from the bottom */
1079 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1085 else if (dy > 0 && cut_mode == CUT_ABOVE)
1087 if (y == BY2) /* object completely above bottom border */
1093 MarkTileDirty(x, y + 1);
1094 } /* object leaves playfield to the bottom */
1095 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1097 else if (dy) /* general vertical movement */
1098 MarkTileDirty(x, y + SIGN(dy));
1101 src_bitmap = new_graphic_info[graphic].bitmap;
1102 src_x = new_graphic_info[graphic].src_x;
1103 src_y = new_graphic_info[graphic].src_y;
1104 offset_x = new_graphic_info[graphic].offset_x;
1105 offset_y = new_graphic_info[graphic].offset_y;
1107 drawing_gc = src_bitmap->stored_clip_gc;
1109 src_x += frame * offset_x;
1110 src_y += frame * offset_y;
1115 dest_x = FX + x * TILEX + dx;
1116 dest_y = FY + y * TILEY + dy;
1119 if (!IN_SCR_FIELD(x,y))
1121 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1122 printf("DrawGraphicShifted(): This should never happen!\n");
1127 if (mask_mode == USE_MASKING)
1129 SetClipOrigin(src_bitmap, drawing_gc, dest_x - src_x, dest_y - src_y);
1130 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1134 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1140 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1141 int frame, int cut_mode)
1143 DrawGraphicShifted(x,y, dx,dy, graphic, frame, cut_mode, USE_MASKING);
1147 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1148 int cut_mode, int mask_mode)
1150 int ux = LEVELX(x), uy = LEVELY(y);
1151 int graphic = el2gfx(element);
1152 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1153 int phase4 = phase8 / 2;
1154 int phase2 = phase8 / 4;
1155 int dir = MovDir[ux][uy];
1157 if (element == EL_PACMAN || element == EL_BUG || element == EL_SPACESHIP)
1159 graphic += 1 * !phase2;
1163 else if (dir == MV_LEFT)
1165 else if (dir == MV_DOWN)
1168 else if (element == EL_SP_SNIKSNAK)
1171 graphic = GFX_SP_SNIKSNAK_LEFT;
1172 else if (dir == MV_RIGHT)
1173 graphic = GFX_SP_SNIKSNAK_RIGHT;
1174 else if (dir == MV_UP)
1175 graphic = GFX_SP_SNIKSNAK_UP;
1177 graphic = GFX_SP_SNIKSNAK_DOWN;
1179 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1181 else if (element == EL_SP_ELECTRON)
1183 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1185 else if (element == EL_MOLE || element == EL_PENGUIN ||
1186 element == EL_PIG || element == EL_DRAGON)
1189 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1190 element == EL_PENGUIN ? GFX_PINGUIN_LEFT :
1191 element == EL_PIG ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1192 else if (dir == MV_RIGHT)
1193 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1194 element == EL_PENGUIN ? GFX_PINGUIN_RIGHT :
1195 element == EL_PIG ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1196 else if (dir == MV_UP)
1197 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1198 element == EL_PENGUIN ? GFX_PINGUIN_UP :
1199 element == EL_PIG ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1201 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1202 element == EL_PENGUIN ? GFX_PINGUIN_DOWN :
1203 element == EL_PIG ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1207 else if (element == EL_SATELLITE)
1209 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_LOOP);
1211 else if (element == EL_ACID)
1213 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_LOOP);
1215 else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
1219 else if (element == EL_BALLOON)
1223 else if ((element == EL_ROCK ||
1224 element == EL_SP_ZONK ||
1225 element == EL_BD_ROCK ||
1226 element == EL_SP_INFOTRON ||
1230 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1232 if (element == EL_ROCK ||
1233 element == EL_SP_ZONK ||
1234 element == EL_BD_ROCK)
1237 graphic += (4 - phase4) % 4;
1238 else if (dir == MV_RIGHT)
1241 graphic += phase2 * 2;
1243 else if (element != EL_SP_INFOTRON)
1247 else if (element == EL_MAGIC_WALL_ACTIVE ||
1248 element == EL_MAGIC_WALL_EMPTYING ||
1249 element == EL_BD_MAGIC_WALL_ACTIVE ||
1250 element == EL_BD_MAGIC_WALL_EMPTYING ||
1251 element == EL_MAGIC_WALL_FULL ||
1252 element == EL_BD_MAGIC_WALL_FULL)
1254 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1256 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1258 graphic = (element == EL_AMOEBA_DEAD ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1259 graphic += (x + 2 * y + 4) % 4;
1261 else if (element == EL_WALL_GROWING)
1263 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1265 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1266 links_massiv = TRUE;
1267 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1268 rechts_massiv = TRUE;
1270 if (links_massiv && rechts_massiv)
1271 graphic = GFX_MAUERWERK;
1272 else if (links_massiv)
1273 graphic = GFX_MAUER_R;
1274 else if (rechts_massiv)
1275 graphic = GFX_MAUER_L;
1278 else if ((element == EL_INVISIBLE_STEELWALL ||
1279 element == EL_INVISIBLE_WALL ||
1280 element == EL_INVISIBLE_SAND) && game.light_time_left)
1282 graphic = (element == EL_INVISIBLE_STEELWALL ? GFX_INVISIBLE_STEEL_ON :
1283 element == EL_INVISIBLE_WALL ? GFX_UNSICHTBAR_ON :
1284 GFX_SAND_INVISIBLE_ON);
1289 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1290 else if (mask_mode == USE_MASKING)
1291 DrawGraphicThruMask(x, y, graphic);
1293 DrawGraphic(x, y, graphic);
1297 inline static int getFramePosition(int x, int y)
1299 int frame_pos = -1; /* default: global synchronization */
1301 int element = Feld[x][y];
1303 if (element == EL_QUICKSAND_FULL ||
1304 element == EL_MAGIC_WALL_FULL ||
1305 element == EL_BD_MAGIC_WALL_FULL)
1307 else if (IS_MOVING(x, y) || CAN_MOVE(element) || CAN_FALL(element))
1308 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1310 frame_pos = ABS(MovPos[x][y]) / (TILEX / 8);
1316 inline static int getGfxAction(int x, int y)
1318 int gfx_action = GFX_ACTION_DEFAULT;
1321 if (GfxAction[x][y] != GFX_ACTION_DEFAULT)
1322 gfx_action = GfxAction[x][y];
1323 else if (IS_MOVING(x, y))
1324 gfx_action = GFX_ACTION_MOVING;
1326 gfx_action = GfxAction[x][y];
1331 printf("getGfxAction: THIS SHOULD NEVER HAPPEN: GfxAction[%d][%d] == %d\n",
1338 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1339 int cut_mode, int mask_mode)
1341 int ux = LEVELX(x), uy = LEVELY(y);
1345 if (IN_LEV_FIELD(ux, uy))
1347 int move_dir = MovDir[ux][uy];
1348 int move_pos = getFramePosition(ux, uy);
1349 int gfx_action = getGfxAction(ux, uy);
1351 graphic = el_dir_act2img(element, move_dir, gfx_action);
1352 frame = getGraphicAnimationFrame(graphic, move_pos);
1356 graphic = el2img(element);
1357 frame = getGraphicAnimationFrame(graphic, 0);
1360 if (element == EL_WALL_GROWING)
1362 boolean left_stopped = FALSE, right_stopped = FALSE;
1364 if (!IN_LEV_FIELD(ux - 1, uy) || IS_MAUER(Feld[ux - 1][uy]))
1365 left_stopped = TRUE;
1366 if (!IN_LEV_FIELD(ux + 1, uy) || IS_MAUER(Feld[ux + 1][uy]))
1367 right_stopped = TRUE;
1369 if (left_stopped && right_stopped)
1371 else if (left_stopped)
1373 graphic = IMG_WALL_GROWING_ACTIVE_RIGHT;
1374 frame = new_graphic_info[graphic].anim_frames - 1;
1376 else if (right_stopped)
1378 graphic = IMG_WALL_GROWING_ACTIVE_LEFT;
1379 frame = new_graphic_info[graphic].anim_frames - 1;
1382 else if (IS_AMOEBOID(element) || element == EL_AMOEBA_DRIPPING)
1384 graphic = (element == EL_BD_AMOEBA ? IMG_BD_AMOEBA_PART1 :
1385 element == EL_AMOEBA_WET ? IMG_AMOEBA_WET_PART1 :
1386 element == EL_AMOEBA_DRY ? IMG_AMOEBA_DRY_PART1 :
1387 element == EL_AMOEBA_FULL ? IMG_AMOEBA_FULL_PART1 :
1388 IMG_AMOEBA_DEAD_PART1);
1390 graphic += (x + 2 * y + 4) % 4;
1394 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1395 else if (mask_mode == USE_MASKING)
1396 DrawGraphicThruMask(x, y, graphic, frame);
1398 DrawGraphic(x, y, graphic, frame);
1401 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1402 int cut_mode, int mask_mode)
1404 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1405 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1406 cut_mode, mask_mode);
1409 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1412 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1415 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1418 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1422 void DrawOldScreenElementThruMask(int x, int y, int element)
1424 DrawOldScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1427 void DrawScreenElementThruMask(int x, int y, int element)
1429 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1433 void DrawLevelElementThruMask(int x, int y, int element)
1435 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1438 void DrawLevelFieldThruMask(int x, int y)
1440 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1443 void DrawCrumbledSand(int x, int y)
1447 int i, width, height, cx,cy;
1448 int ux = LEVELX(x), uy = LEVELY(y);
1449 int element, graphic;
1451 static int xy[4][2] =
1459 if (!IN_LEV_FIELD(ux, uy))
1462 element = Feld[ux][uy];
1464 if (element == EL_SAND ||
1465 element == EL_LANDMINE ||
1466 element == EL_TRAP ||
1467 element == EL_TRAP_ACTIVE)
1469 if (!IN_SCR_FIELD(x, y))
1472 graphic = IMG_SAND_CRUMBLED;
1474 src_bitmap = new_graphic_info[graphic].bitmap;
1475 src_x = new_graphic_info[graphic].src_x;
1476 src_y = new_graphic_info[graphic].src_y;
1482 uxx = ux + xy[i][0];
1483 uyy = uy + xy[i][1];
1484 if (!IN_LEV_FIELD(uxx, uyy))
1485 element = EL_STEELWALL;
1487 element = Feld[uxx][uyy];
1489 if (element == EL_SAND ||
1490 element == EL_LANDMINE ||
1491 element == EL_TRAP ||
1492 element == EL_TRAP_ACTIVE)
1495 if (i == 1 || i == 2)
1499 cx = (i == 2 ? TILEX - snip : 0);
1507 cy = (i == 3 ? TILEY - snip : 0);
1510 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1511 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1514 MarkTileDirty(x, y);
1518 graphic = IMG_SAND_CRUMBLED;
1520 src_bitmap = new_graphic_info[graphic].bitmap;
1521 src_x = new_graphic_info[graphic].src_x;
1522 src_y = new_graphic_info[graphic].src_y;
1526 int xx, yy, uxx, uyy;
1530 uxx = ux + xy[i][0];
1531 uyy = uy + xy[i][1];
1533 if (!IN_LEV_FIELD(uxx, uyy) ||
1534 (Feld[uxx][uyy] != EL_SAND &&
1535 Feld[uxx][uyy] != EL_LANDMINE &&
1536 Feld[uxx][uyy] != EL_TRAP &&
1537 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1538 !IN_SCR_FIELD(xx, yy))
1541 if (i == 1 || i == 2)
1545 cx = (i == 1 ? TILEX - snip : 0);
1553 cy = (i==0 ? TILEY-snip : 0);
1556 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1557 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1559 MarkTileDirty(xx, yy);
1564 void DrawScreenElement(int x, int y, int element)
1566 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1567 DrawCrumbledSand(x, y);
1570 void DrawLevelElement(int x, int y, int element)
1572 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1573 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1576 void DrawScreenField(int x, int y)
1578 int ux = LEVELX(x), uy = LEVELY(y);
1579 int element, content;
1581 if (!IN_LEV_FIELD(ux, uy))
1583 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1586 element = BorderElement;
1588 DrawScreenElement(x, y, element);
1592 element = Feld[ux][uy];
1593 content = Store[ux][uy];
1595 if (IS_MOVING(ux, uy))
1597 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1598 boolean cut_mode = NO_CUTTING;
1600 if (element == EL_QUICKSAND_EMPTYING ||
1601 element == EL_MAGIC_WALL_EMPTYING ||
1602 element == EL_BD_MAGIC_WALL_EMPTYING ||
1603 element == EL_AMOEBA_DRIPPING)
1604 cut_mode = CUT_ABOVE;
1605 else if (element == EL_QUICKSAND_FILLING ||
1606 element == EL_MAGIC_WALL_FILLING ||
1607 element == EL_BD_MAGIC_WALL_FILLING)
1608 cut_mode = CUT_BELOW;
1610 if (cut_mode == CUT_ABOVE)
1611 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1613 DrawScreenElement(x, y, EL_EMPTY);
1616 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1617 else if (cut_mode == NO_CUTTING)
1618 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1620 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], content, cut_mode);
1622 if (content == EL_ACID)
1623 DrawLevelElementThruMask(ux, uy + 1, EL_ACID);
1625 else if (IS_BLOCKED(ux, uy))
1630 boolean cut_mode = NO_CUTTING;
1631 int element_old, content_old;
1633 Blocked2Moving(ux, uy, &oldx, &oldy);
1636 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1637 MovDir[oldx][oldy] == MV_RIGHT);
1639 element_old = Feld[oldx][oldy];
1640 content_old = Store[oldx][oldy];
1642 if (element_old == EL_QUICKSAND_EMPTYING ||
1643 element_old == EL_MAGIC_WALL_EMPTYING ||
1644 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1645 element_old == EL_AMOEBA_DRIPPING)
1646 cut_mode = CUT_ABOVE;
1648 DrawScreenElement(x, y, EL_EMPTY);
1651 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1653 else if (cut_mode == NO_CUTTING)
1654 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1657 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1660 else if (IS_DRAWABLE(element))
1661 DrawScreenElement(x, y, element);
1663 DrawScreenElement(x, y, EL_EMPTY);
1666 void DrawLevelField(int x, int y)
1668 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1669 DrawScreenField(SCREENX(x), SCREENY(y));
1670 else if (IS_MOVING(x, y))
1674 Moving2Blocked(x, y, &newx, &newy);
1675 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1676 DrawScreenField(SCREENX(newx), SCREENY(newy));
1678 else if (IS_BLOCKED(x, y))
1682 Blocked2Moving(x, y, &oldx, &oldy);
1683 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1684 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1688 void DrawMiniElement(int x, int y, int element)
1692 graphic = el2img(element);
1693 DrawMiniGraphic(x, y, graphic);
1696 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1698 int x = sx + scroll_x, y = sy + scroll_y;
1700 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1701 DrawMiniElement(sx, sy, EL_EMPTY);
1702 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1703 DrawMiniElement(sx, sy, Feld[x][y]);
1706 int steel_type, steel_position;
1709 { IMG_STEELWALL_TOPLEFT, IMG_INVISIBLE_STEELWALL_TOPLEFT },
1710 { IMG_STEELWALL_TOPRIGHT, IMG_INVISIBLE_STEELWALL_TOPRIGHT },
1711 { IMG_STEELWALL_BOTTOMLEFT, IMG_INVISIBLE_STEELWALL_BOTTOMLEFT },
1712 { IMG_STEELWALL_BOTTOMRIGHT, IMG_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1713 { IMG_STEELWALL_VERTICAL, IMG_INVISIBLE_STEELWALL_VERTICAL },
1714 { IMG_STEELWALL_HORIZONTAL, IMG_INVISIBLE_STEELWALL_HORIZONTAL }
1717 steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1718 steel_position = (x == -1 && y == -1 ? 0 :
1719 x == lev_fieldx && y == -1 ? 1 :
1720 x == -1 && y == lev_fieldy ? 2 :
1721 x == lev_fieldx && y == lev_fieldy ? 3 :
1722 x == -1 || x == lev_fieldx ? 4 :
1723 y == -1 || y == lev_fieldy ? 5 : -1);
1725 if (steel_position != -1)
1726 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1730 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1732 Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
1733 int mini_startx = src_bitmap->width * 3 / 4;
1734 int mini_starty = src_bitmap->height * 2 / 3;
1735 int src_x = mini_startx + new_graphic_info[graphic].src_x / 8;
1736 int src_y = mini_starty + new_graphic_info[graphic].src_y / 8;
1738 if (src_x + MICRO_TILEX > src_bitmap->width ||
1739 src_y + MICRO_TILEY > src_bitmap->height)
1741 /* graphic of desired size seems not to be contained in this image;
1742 dirty workaround: get it from the middle of the normal sized image */
1744 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1745 src_x += (TILEX / 2 - MICRO_TILEX / 2);
1746 src_y += (TILEY / 2 - MICRO_TILEY / 2);
1749 *bitmap = src_bitmap;
1754 void DrawMicroElement(int xpos, int ypos, int element)
1758 int graphic = el2img(element);
1760 getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1761 BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1769 SetDrawBackgroundMask(REDRAW_NONE);
1772 for(x=BX1; x<=BX2; x++)
1773 for(y=BY1; y<=BY2; y++)
1774 DrawScreenField(x, y);
1776 redraw_mask |= REDRAW_FIELD;
1779 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1783 for(x=0; x<size_x; x++)
1784 for(y=0; y<size_y; y++)
1785 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1787 redraw_mask |= REDRAW_FIELD;
1790 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1794 DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1796 if (lev_fieldx < STD_LEV_FIELDX)
1797 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1798 if (lev_fieldy < STD_LEV_FIELDY)
1799 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1801 xpos += MICRO_TILEX;
1802 ypos += MICRO_TILEY;
1804 for(x=-1; x<=STD_LEV_FIELDX; x++)
1806 for(y=-1; y<=STD_LEV_FIELDY; y++)
1808 int lx = from_x + x, ly = from_y + y;
1810 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1811 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1813 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1814 && BorderElement != EL_EMPTY)
1815 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1820 redraw_mask |= REDRAW_MICROLEVEL;
1823 #define MICROLABEL_EMPTY 0
1824 #define MICROLABEL_LEVEL_NAME 1
1825 #define MICROLABEL_CREATED_BY 2
1826 #define MICROLABEL_LEVEL_AUTHOR 3
1827 #define MICROLABEL_IMPORTED_FROM 4
1828 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1830 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1832 static void DrawMicroLevelLabelExt(int mode)
1834 char label_text[MAX_MICROLABEL_SIZE + 1];
1836 DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1838 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1839 mode == MICROLABEL_CREATED_BY ? "created by" :
1840 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1841 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1842 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1843 leveldir_current->imported_from : ""),
1844 MAX_MICROLABEL_SIZE);
1845 label_text[MAX_MICROLABEL_SIZE] = '\0';
1847 if (strlen(label_text) > 0)
1849 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1850 int lypos = MICROLABEL_YPOS;
1852 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1855 redraw_mask |= REDRAW_MICROLEVEL;
1858 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1860 static unsigned long scroll_delay = 0;
1861 static unsigned long label_delay = 0;
1862 static int from_x, from_y, scroll_direction;
1863 static int label_state, label_counter;
1867 from_x = from_y = 0;
1868 scroll_direction = MV_RIGHT;
1872 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1873 DrawMicroLevelLabelExt(label_state);
1875 /* initialize delay counters */
1876 DelayReached(&scroll_delay, 0);
1877 DelayReached(&label_delay, 0);
1882 /* scroll micro level, if needed */
1883 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1884 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1886 switch (scroll_direction)
1892 scroll_direction = MV_UP;
1896 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1899 scroll_direction = MV_DOWN;
1906 scroll_direction = MV_RIGHT;
1910 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1913 scroll_direction = MV_LEFT;
1920 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1923 /* redraw micro level label, if needed */
1924 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1925 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1926 strcmp(level.author, leveldir_current->name) != 0 &&
1927 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1929 int max_label_counter = 23;
1931 if (leveldir_current->imported_from != NULL)
1932 max_label_counter += 14;
1934 label_counter = (label_counter + 1) % max_label_counter;
1935 label_state = (label_counter >= 0 && label_counter <= 7 ?
1936 MICROLABEL_LEVEL_NAME :
1937 label_counter >= 9 && label_counter <= 12 ?
1938 MICROLABEL_CREATED_BY :
1939 label_counter >= 14 && label_counter <= 21 ?
1940 MICROLABEL_LEVEL_AUTHOR :
1941 label_counter >= 23 && label_counter <= 26 ?
1942 MICROLABEL_IMPORTED_FROM :
1943 label_counter >= 28 && label_counter <= 35 ?
1944 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1945 DrawMicroLevelLabelExt(label_state);
1949 int REQ_in_range(int x, int y)
1951 if (y > DY+249 && y < DY+278)
1953 if (x > DX+1 && x < DX+48)
1955 else if (x > DX+51 && x < DX+98)
1961 #define MAX_REQUEST_LINES 13
1962 #define MAX_REQUEST_LINE_LEN 7
1964 boolean Request(char *text, unsigned int req_state)
1966 int mx, my, ty, result = -1;
1967 unsigned int old_door_state;
1969 #if defined(PLATFORM_UNIX)
1970 /* pause network game while waiting for request to answer */
1971 if (options.network &&
1972 game_status == PLAYING &&
1973 req_state & REQUEST_WAIT_FOR)
1974 SendToServer_PausePlaying();
1977 old_door_state = GetDoorState();
1981 CloseDoor(DOOR_CLOSE_1);
1983 /* save old door content */
1984 BlitBitmap(bitmap_db_door, bitmap_db_door,
1985 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1986 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1988 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
1990 /* clear door drawing field */
1991 DrawBackground(DX, DY, DXSIZE, DYSIZE);
1993 /* write text for request */
1994 for(ty=0; ty < MAX_REQUEST_LINES; ty++)
1996 char text_line[MAX_REQUEST_LINE_LEN + 1];
2002 for(tl=0,tx=0; tx < MAX_REQUEST_LINE_LEN; tl++,tx++)
2005 if (!tc || tc == ' ')
2016 strncpy(text_line, text, tl);
2019 DrawText(DX + 50 - (tl * 14)/2, DY + 8 + ty * 16,
2020 text_line, FS_SMALL, FC_YELLOW);
2022 text += tl + (tc == ' ' ? 1 : 0);
2025 if (req_state & REQ_ASK)
2027 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2028 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2030 else if (req_state & REQ_CONFIRM)
2032 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2034 else if (req_state & REQ_PLAYER)
2036 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2037 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2038 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2039 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2042 /* copy request gadgets to door backbuffer */
2043 BlitBitmap(drawto, bitmap_db_door,
2044 DX, DY, DXSIZE, DYSIZE,
2045 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2047 OpenDoor(DOOR_OPEN_1);
2053 if (!(req_state & REQUEST_WAIT_FOR))
2055 SetDrawBackgroundMask(REDRAW_FIELD);
2060 if (game_status != MAINMENU)
2063 button_status = MB_RELEASED;
2065 request_gadget_id = -1;
2067 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2079 case EVENT_BUTTONPRESS:
2080 case EVENT_BUTTONRELEASE:
2081 case EVENT_MOTIONNOTIFY:
2083 if (event.type == EVENT_MOTIONNOTIFY)
2085 if (!PointerInWindow(window))
2086 continue; /* window and pointer are on different screens */
2091 motion_status = TRUE;
2092 mx = ((MotionEvent *) &event)->x;
2093 my = ((MotionEvent *) &event)->y;
2097 motion_status = FALSE;
2098 mx = ((ButtonEvent *) &event)->x;
2099 my = ((ButtonEvent *) &event)->y;
2100 if (event.type == EVENT_BUTTONPRESS)
2101 button_status = ((ButtonEvent *) &event)->button;
2103 button_status = MB_RELEASED;
2106 /* this sets 'request_gadget_id' */
2107 HandleGadgets(mx, my, button_status);
2109 switch(request_gadget_id)
2111 case TOOL_CTRL_ID_YES:
2114 case TOOL_CTRL_ID_NO:
2117 case TOOL_CTRL_ID_CONFIRM:
2118 result = TRUE | FALSE;
2121 case TOOL_CTRL_ID_PLAYER_1:
2124 case TOOL_CTRL_ID_PLAYER_2:
2127 case TOOL_CTRL_ID_PLAYER_3:
2130 case TOOL_CTRL_ID_PLAYER_4:
2141 case EVENT_KEYPRESS:
2142 switch(GetEventKey((KeyEvent *)&event, TRUE))
2155 if (req_state & REQ_PLAYER)
2159 case EVENT_KEYRELEASE:
2160 ClearPlayerAction();
2164 HandleOtherEvents(&event);
2168 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2170 int joy = AnyJoystick();
2172 if (joy & JOY_BUTTON_1)
2174 else if (joy & JOY_BUTTON_2)
2180 /* don't eat all CPU time */
2184 if (game_status != MAINMENU)
2189 if (!(req_state & REQ_STAY_OPEN))
2191 CloseDoor(DOOR_CLOSE_1);
2193 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2195 BlitBitmap(bitmap_db_door, bitmap_db_door,
2196 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2197 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2198 OpenDoor(DOOR_OPEN_1);
2204 SetDrawBackgroundMask(REDRAW_FIELD);
2206 #if defined(PLATFORM_UNIX)
2207 /* continue network game after request */
2208 if (options.network &&
2209 game_status == PLAYING &&
2210 req_state & REQUEST_WAIT_FOR)
2211 SendToServer_ContinuePlaying();
2217 unsigned int OpenDoor(unsigned int door_state)
2219 unsigned int new_door_state;
2221 if (door_state & DOOR_COPY_BACK)
2223 BlitBitmap(bitmap_db_door, bitmap_db_door,
2224 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2225 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2226 door_state &= ~DOOR_COPY_BACK;
2229 new_door_state = MoveDoor(door_state);
2231 return(new_door_state);
2234 unsigned int CloseDoor(unsigned int door_state)
2236 unsigned int new_door_state;
2238 BlitBitmap(backbuffer, bitmap_db_door,
2239 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2240 BlitBitmap(backbuffer, bitmap_db_door,
2241 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2243 new_door_state = MoveDoor(door_state);
2245 return(new_door_state);
2248 unsigned int GetDoorState()
2250 return MoveDoor(DOOR_GET_STATE);
2253 unsigned int SetDoorState(unsigned int door_state)
2255 return MoveDoor(door_state | DOOR_SET_STATE);
2258 unsigned int MoveDoor(unsigned int door_state)
2260 static int door1 = DOOR_OPEN_1;
2261 static int door2 = DOOR_CLOSE_2;
2262 static unsigned long door_delay = 0;
2263 int x, start, stepsize = 2;
2264 unsigned long door_delay_value = stepsize * 5;
2266 if (door_state == DOOR_GET_STATE)
2267 return(door1 | door2);
2269 if (door_state & DOOR_SET_STATE)
2271 if (door_state & DOOR_ACTION_1)
2272 door1 = door_state & DOOR_ACTION_1;
2273 if (door_state & DOOR_ACTION_2)
2274 door2 = door_state & DOOR_ACTION_2;
2276 return(door1 | door2);
2279 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2280 door_state &= ~DOOR_OPEN_1;
2281 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2282 door_state &= ~DOOR_CLOSE_1;
2283 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2284 door_state &= ~DOOR_OPEN_2;
2285 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2286 door_state &= ~DOOR_CLOSE_2;
2288 if (setup.quick_doors)
2291 door_delay_value = 0;
2293 StopSound(SND_MENU_DOOR_OPENING);
2294 StopSound(SND_MENU_DOOR_CLOSING);
2297 if (global.autoplay_leveldir)
2299 door_state |= DOOR_NO_DELAY;
2300 door_state &= ~DOOR_CLOSE_ALL;
2303 if (door_state & DOOR_ACTION)
2305 if (!(door_state & DOOR_NO_DELAY))
2307 /* opening door sound has priority over simultaneously closing door */
2308 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2309 PlaySoundStereo(SND_MENU_DOOR_OPENING, SOUND_MAX_RIGHT);
2310 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2311 PlaySoundStereo(SND_MENU_DOOR_CLOSING, SOUND_MAX_RIGHT);
2314 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2316 for(x=start; x<=DXSIZE; x+=stepsize)
2318 Bitmap *bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2319 GC gc = bitmap->stored_clip_gc;
2321 if (!(door_state & DOOR_NO_DELAY))
2322 WaitUntilDelayReached(&door_delay, door_delay_value);
2324 if (door_state & DOOR_ACTION_1)
2326 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2327 int j = (DXSIZE - i) / 3;
2329 BlitBitmap(bitmap_db_door, drawto,
2330 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2331 DXSIZE,DYSIZE - i/2, DX, DY);
2333 ClearRectangle(drawto, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2335 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2336 BlitBitmapMasked(bitmap, drawto,
2337 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2338 DX + DXSIZE - i, DY + j);
2339 BlitBitmapMasked(bitmap, drawto,
2340 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2341 DX + DXSIZE - i, DY + 140 + j);
2342 SetClipOrigin(bitmap, gc, DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2343 BlitBitmapMasked(bitmap, drawto,
2344 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2346 BlitBitmapMasked(bitmap, drawto,
2347 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2350 BlitBitmapMasked(bitmap, drawto,
2351 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2353 BlitBitmapMasked(bitmap, drawto,
2354 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2356 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2357 BlitBitmapMasked(bitmap, drawto,
2358 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2359 DX + DXSIZE - i, DY + 77 + j);
2360 BlitBitmapMasked(bitmap, drawto,
2361 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2362 DX + DXSIZE - i, DY + 203 + j);
2364 redraw_mask |= REDRAW_DOOR_1;
2367 if (door_state & DOOR_ACTION_2)
2369 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2370 int j = (VXSIZE - i) / 3;
2372 BlitBitmap(bitmap_db_door, drawto,
2373 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2374 VXSIZE, VYSIZE - i/2, VX, VY);
2376 ClearRectangle(drawto, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2378 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2379 BlitBitmapMasked(bitmap, drawto,
2380 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2381 VX + VXSIZE-i, VY+j);
2382 SetClipOrigin(bitmap, gc,
2383 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2384 BlitBitmapMasked(bitmap, drawto,
2385 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2388 BlitBitmapMasked(bitmap, drawto,
2389 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2390 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2391 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2392 BlitBitmapMasked(bitmap, drawto,
2393 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2395 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2397 redraw_mask |= REDRAW_DOOR_2;
2402 if (game_status == MAINMENU)
2407 if (setup.quick_doors)
2409 StopSound(SND_MENU_DOOR_OPENING);
2410 StopSound(SND_MENU_DOOR_CLOSING);
2413 if (door_state & DOOR_ACTION_1)
2414 door1 = door_state & DOOR_ACTION_1;
2415 if (door_state & DOOR_ACTION_2)
2416 door2 = door_state & DOOR_ACTION_2;
2418 return (door1 | door2);
2421 void DrawSpecialEditorDoor()
2423 /* draw bigger toolbox window */
2424 BlitBitmap(new_graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2425 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2427 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2428 EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2431 redraw_mask |= REDRAW_ALL;
2434 void UndrawSpecialEditorDoor()
2436 /* draw normal tape recorder window */
2437 BlitBitmap(new_graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2438 EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2441 redraw_mask |= REDRAW_ALL;
2445 int ReadPixel(DrawBuffer *bitmap, int x, int y)
2447 XImage *pixel_image;
2448 unsigned long pixel_value;
2450 pixel_image = XGetImage(display, bitmap->drawable,
2451 x, y, 1, 1, AllPlanes, ZPixmap);
2452 pixel_value = XGetPixel(pixel_image, 0, 0);
2454 XDestroyImage(pixel_image);
2460 /* ---------- new tool button stuff ---------------------------------------- */
2462 /* graphic position values for tool buttons */
2463 #define TOOL_BUTTON_YES_XPOS 2
2464 #define TOOL_BUTTON_YES_YPOS 250
2465 #define TOOL_BUTTON_YES_GFX_YPOS 0
2466 #define TOOL_BUTTON_YES_XSIZE 46
2467 #define TOOL_BUTTON_YES_YSIZE 28
2468 #define TOOL_BUTTON_NO_XPOS 52
2469 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2470 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2471 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2472 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2473 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2474 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2475 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2476 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2477 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2478 #define TOOL_BUTTON_PLAYER_XSIZE 30
2479 #define TOOL_BUTTON_PLAYER_YSIZE 30
2480 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2481 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2482 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2483 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2484 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2485 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2486 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2487 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2488 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2489 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2490 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2491 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2492 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2493 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2494 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2495 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2496 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2497 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2498 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2499 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2508 } toolbutton_info[NUM_TOOL_BUTTONS] =
2511 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2512 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2513 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2518 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2519 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2520 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2525 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2526 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2527 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2528 TOOL_CTRL_ID_CONFIRM,
2532 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2533 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2534 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2535 TOOL_CTRL_ID_PLAYER_1,
2539 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2540 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2541 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2542 TOOL_CTRL_ID_PLAYER_2,
2546 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2547 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2548 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2549 TOOL_CTRL_ID_PLAYER_3,
2553 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2554 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2555 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2556 TOOL_CTRL_ID_PLAYER_4,
2561 void CreateToolButtons()
2565 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2567 Bitmap *gd_bitmap = new_graphic_info[IMG_GLOBAL_DOOR].bitmap;
2568 Bitmap *deco_bitmap = None;
2569 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2570 struct GadgetInfo *gi;
2571 unsigned long event_mask;
2572 int gd_xoffset, gd_yoffset;
2573 int gd_x1, gd_x2, gd_y;
2576 event_mask = GD_EVENT_RELEASED;
2578 gd_xoffset = toolbutton_info[i].xpos;
2579 gd_yoffset = toolbutton_info[i].ypos;
2580 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2581 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2582 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2584 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2586 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2588 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER1, player_nr),
2589 &deco_bitmap, &deco_x, &deco_y);
2590 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2591 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2594 gi = CreateGadget(GDI_CUSTOM_ID, id,
2595 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2596 GDI_X, DX + toolbutton_info[i].x,
2597 GDI_Y, DY + toolbutton_info[i].y,
2598 GDI_WIDTH, toolbutton_info[i].width,
2599 GDI_HEIGHT, toolbutton_info[i].height,
2600 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2601 GDI_STATE, GD_BUTTON_UNPRESSED,
2602 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2603 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2604 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2605 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2606 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2607 GDI_DECORATION_SHIFTING, 1, 1,
2608 GDI_EVENT_MASK, event_mask,
2609 GDI_CALLBACK_ACTION, HandleToolButtons,
2613 Error(ERR_EXIT, "cannot create gadget");
2615 tool_gadget[id] = gi;
2619 void FreeToolButtons()
2623 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2624 FreeGadget(tool_gadget[i]);
2627 static void UnmapToolButtons()
2631 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2632 UnmapGadget(tool_gadget[i]);
2635 static void HandleToolButtons(struct GadgetInfo *gi)
2637 request_gadget_id = gi->custom_id;
2640 int get_next_element(int element)
2644 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
2645 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
2646 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
2647 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
2648 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
2649 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
2650 case EL_AMOEBA_DRIPPING: return EL_AMOEBA_WET;
2652 default: return element;
2656 int el2gfx_OLD(int element)
2660 case EL_EMPTY: return -1;
2661 case EL_SAND: return GFX_ERDREICH;
2662 case EL_WALL: return GFX_MAUERWERK;
2663 case EL_WALL_CRUMBLED: return GFX_FELSBODEN;
2664 case EL_ROCK: return GFX_FELSBROCKEN;
2665 case EL_EMERALD: return GFX_EDELSTEIN;
2666 case EL_EXIT_CLOSED: return GFX_AUSGANG_ZU;
2667 case EL_EXIT_OPENING: return GFX_AUSGANG_ACT;
2668 case EL_EXIT_OPEN: return GFX_AUSGANG_AUF;
2669 case EL_SP_EXIT_OPEN: return GFX_SP_EXIT;
2670 case EL_PLAYER1: return GFX_SPIELER1;
2671 case EL_PLAYER2: return GFX_SPIELER2;
2672 case EL_PLAYER3: return GFX_SPIELER3;
2673 case EL_PLAYER4: return GFX_SPIELER4;
2674 case EL_BUG: return GFX_KAEFER;
2675 case EL_BUG_RIGHT: return GFX_KAEFER_RIGHT;
2676 case EL_BUG_UP: return GFX_KAEFER_UP;
2677 case EL_BUG_LEFT: return GFX_KAEFER_LEFT;
2678 case EL_BUG_DOWN: return GFX_KAEFER_DOWN;
2679 case EL_SPACESHIP: return GFX_FLIEGER;
2680 case EL_SPACESHIP_RIGHT: return GFX_FLIEGER_RIGHT;
2681 case EL_SPACESHIP_UP: return GFX_FLIEGER_UP;
2682 case EL_SPACESHIP_LEFT: return GFX_FLIEGER_LEFT;
2683 case EL_SPACESHIP_DOWN: return GFX_FLIEGER_DOWN;
2684 case EL_BD_BUTTERFLY: return GFX_BUTTERFLY;
2685 case EL_BD_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2686 case EL_BD_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2687 case EL_BD_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2688 case EL_BD_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2689 case EL_BD_FIREFLY: return GFX_FIREFLY;
2690 case EL_BD_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2691 case EL_BD_FIREFLY_UP: return GFX_FIREFLY_UP;
2692 case EL_BD_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2693 case EL_BD_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2694 case EL_YAMYAM: return GFX_MAMPFER;
2695 case EL_ROBOT: return GFX_ROBOT;
2696 case EL_STEELWALL: return GFX_BETON;
2697 case EL_DIAMOND: return GFX_DIAMANT;
2698 case EL_QUICKSAND_EMPTY: return GFX_MORAST_LEER;
2699 case EL_QUICKSAND_FULL: return GFX_MORAST_VOLL;
2700 case EL_QUICKSAND_EMPTYING: return GFX_MORAST_LEER;
2701 case EL_AMOEBA_DROP: return GFX_TROPFEN;
2702 case EL_BOMB: return GFX_BOMBE;
2703 case EL_MAGIC_WALL: return GFX_MAGIC_WALL_OFF;
2704 case EL_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_EMPTY;
2705 case EL_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_EMPTY;
2706 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2707 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2708 case EL_ACID: return GFX_SALZSAEURE;
2709 case EL_AMOEBA_DEAD: return GFX_AMOEBE_TOT;
2710 case EL_AMOEBA_WET: return GFX_AMOEBE_NASS;
2711 case EL_AMOEBA_DRY: return GFX_AMOEBE_NORM;
2712 case EL_AMOEBA_FULL: return GFX_AMOEBE_VOLL;
2713 case EL_BD_AMOEBA: return GFX_AMOEBE_BD;
2714 case EL_AMOEBA_TO_DIAMOND: return GFX_AMOEBA2DIAM;
2715 case EL_AMOEBA_DRIPPING: return GFX_AMOEBE_NASS;
2716 case EL_NUT: return GFX_KOKOSNUSS;
2717 case EL_GAMEOFLIFE: return GFX_LIFE;
2718 case EL_BIOMAZE: return GFX_LIFE_ASYNC;
2719 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2720 case EL_STONEBLOCK: return GFX_BADEWANNE;
2721 case EL_ACIDPOOL_TOPLEFT: return GFX_BADEWANNE1;
2722 case EL_ACIDPOOL_TOPRIGHT: return GFX_BADEWANNE2;
2723 case EL_ACIDPOOL_BOTTOMLEFT: return GFX_BADEWANNE3;
2724 case EL_ACIDPOOL_BOTTOM: return GFX_BADEWANNE4;
2725 case EL_ACIDPOOL_BOTTOMRIGHT: return GFX_BADEWANNE5;
2726 case EL_ROBOT_WHEEL: return GFX_ABLENK_AUS;
2727 case EL_ROBOT_WHEEL_ACTIVE: return GFX_ABLENK_EIN;
2728 case EL_KEY1: return GFX_SCHLUESSEL1;
2729 case EL_KEY2: return GFX_SCHLUESSEL2;
2730 case EL_KEY3: return GFX_SCHLUESSEL3;
2731 case EL_KEY4: return GFX_SCHLUESSEL4;
2732 case EL_GATE1: return GFX_PFORTE1;
2733 case EL_GATE2: return GFX_PFORTE2;
2734 case EL_GATE3: return GFX_PFORTE3;
2735 case EL_GATE4: return GFX_PFORTE4;
2736 case EL_GATE1_GRAY: return GFX_PFORTE1X;
2737 case EL_GATE2_GRAY: return GFX_PFORTE2X;
2738 case EL_GATE3_GRAY: return GFX_PFORTE3X;
2739 case EL_GATE4_GRAY: return GFX_PFORTE4X;
2740 case EL_DYNAMITE: return GFX_DYNAMIT_AUS;
2741 case EL_PACMAN: return GFX_PACMAN;
2742 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2743 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2744 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2745 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2746 case EL_INVISIBLE_WALL: return GFX_UNSICHTBAR;
2747 case EL_INVISIBLE_WALL_ACTIVE: return GFX_UNSICHTBAR_ON;
2748 case EL_WALL_EMERALD: return GFX_ERZ_EDEL;
2749 case EL_WALL_DIAMOND: return GFX_ERZ_DIAM;
2750 case EL_LAMP: return GFX_BIRNE_AUS;
2751 case EL_LAMP_ACTIVE: return GFX_BIRNE_EIN;
2752 case EL_TIME_ORB_FULL: return GFX_ZEIT_VOLL;
2753 case EL_TIME_ORB_EMPTY: return GFX_ZEIT_LEER;
2754 case EL_WALL_GROWING: return GFX_MAUER_LEBT;
2755 case EL_WALL_GROWING_X: return GFX_MAUER_X;
2756 case EL_WALL_GROWING_Y: return GFX_MAUER_Y;
2757 case EL_WALL_GROWING_XY: return GFX_MAUER_XY;
2758 case EL_BD_DIAMOND: return GFX_EDELSTEIN_BD;
2759 case EL_EMERALD_YELLOW: return GFX_EDELSTEIN_GELB;
2760 case EL_EMERALD_RED: return GFX_EDELSTEIN_ROT;
2761 case EL_EMERALD_PURPLE: return GFX_EDELSTEIN_LILA;
2762 case EL_WALL_BD_DIAMOND: return GFX_ERZ_EDEL_BD;
2763 case EL_WALL_EMERALD_YELLOW: return GFX_ERZ_EDEL_GELB;
2764 case EL_WALL_EMERALD_RED: return GFX_ERZ_EDEL_ROT;
2765 case EL_WALL_EMERALD_PURPLE: return GFX_ERZ_EDEL_LILA;
2766 case EL_DARK_YAMYAM: return GFX_MAMPFER2;
2767 case EL_BD_MAGIC_WALL: return GFX_MAGIC_WALL_BD_OFF;
2768 case EL_BD_MAGIC_WALL_ACTIVE: return GFX_MAGIC_WALL_BD_EMPTY;
2769 case EL_BD_MAGIC_WALL_EMPTYING: return GFX_MAGIC_WALL_BD_EMPTY;
2770 case EL_BD_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_BD_FULL;
2771 case EL_BD_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2772 case EL_DYNABOMB_PLAYER1_ACTIVE: return GFX_DYNABOMB;
2773 case EL_DYNABOMB_PLAYER2_ACTIVE: return GFX_DYNABOMB;
2774 case EL_DYNABOMB_PLAYER3_ACTIVE: return GFX_DYNABOMB;
2775 case EL_DYNABOMB_PLAYER4_ACTIVE: return GFX_DYNABOMB;
2776 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2777 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2778 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2779 case EL_SOKOBAN_OBJECT: return GFX_SOKOBAN_OBJEKT;
2780 case EL_SOKOBAN_FIELD_EMPTY: return GFX_SOKOBAN_FELD_LEER;
2781 case EL_SOKOBAN_FIELD_FULL: return GFX_SOKOBAN_FELD_VOLL;
2782 case EL_MOLE: return GFX_MOLE;
2783 case EL_PENGUIN: return GFX_PINGUIN;
2784 case EL_PIG: return GFX_SCHWEIN;
2785 case EL_DRAGON: return GFX_DRACHE;
2786 case EL_SATELLITE: return GFX_SONDE;
2787 case EL_ARROW_BLUE_LEFT: return GFX_PFEIL_LEFT;
2788 case EL_ARROW_BLUE_RIGHT: return GFX_PFEIL_RIGHT;
2789 case EL_ARROW_BLUE_UP: return GFX_PFEIL_UP;
2790 case EL_ARROW_BLUE_DOWN: return GFX_PFEIL_DOWN;
2791 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2792 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2793 case EL_SP_BUGGY_BASE_ACTIVE: return GFX_SP_BUG_ACTIVE;
2794 case EL_SP_ZONK: return GFX_SP_ZONK;
2795 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2796 case EL_INVISIBLE_STEELWALL: return GFX_INVISIBLE_STEEL;
2797 case EL_INVISIBLE_STEELWALL_ACTIVE: return GFX_INVISIBLE_STEEL_ON;
2798 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2799 case EL_EM_GATE1: return GFX_EM_GATE_1;
2800 case EL_EM_GATE2: return GFX_EM_GATE_2;
2801 case EL_EM_GATE3: return GFX_EM_GATE_3;
2802 case EL_EM_GATE4: return GFX_EM_GATE_4;
2803 case EL_EM_GATE1_GRAY: return GFX_EM_GATE_1X;
2804 case EL_EM_GATE2_GRAY: return GFX_EM_GATE_2X;
2805 case EL_EM_GATE3_GRAY: return GFX_EM_GATE_3X;
2806 case EL_EM_GATE4_GRAY: return GFX_EM_GATE_4X;
2807 case EL_EM_KEY1_FILE: return GFX_EM_KEY_1;
2808 case EL_EM_KEY2_FILE: return GFX_EM_KEY_2;
2809 case EL_EM_KEY3_FILE: return GFX_EM_KEY_3;
2810 case EL_EM_KEY4_FILE: return GFX_EM_KEY_4;
2811 case EL_EM_KEY1: return GFX_EM_KEY_1;
2812 case EL_EM_KEY2: return GFX_EM_KEY_2;
2813 case EL_EM_KEY3: return GFX_EM_KEY_3;
2814 case EL_EM_KEY4: return GFX_EM_KEY_4;
2815 case EL_PEARL: return GFX_PEARL;
2816 case EL_CRYSTAL: return GFX_CRYSTAL;
2817 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2818 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2819 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2820 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2821 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2822 case EL_SHIELD_NORMAL: return GFX_SHIELD_PASSIVE;
2823 case EL_SHIELD_DEADLY: return GFX_SHIELD_ACTIVE;
2824 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2825 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2826 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2827 case EL_SWITCHGATE_SWITCH_UP: return GFX_SWITCHGATE_SWITCH_1;
2828 case EL_SWITCHGATE_SWITCH_DOWN: return GFX_SWITCHGATE_SWITCH_2;
2829 case EL_CONVEYOR_BELT1_LEFT: return GFX_BELT1_LEFT;
2830 case EL_CONVEYOR_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2831 case EL_CONVEYOR_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2832 case EL_CONVEYOR_BELT1_LEFT_ACTIVE: return GFX_BELT1_LEFT;
2833 case EL_CONVEYOR_BELT1_MIDDLE_ACTIVE:return GFX_BELT1_MIDDLE;
2834 case EL_CONVEYOR_BELT1_RIGHT_ACTIVE:return GFX_BELT1_RIGHT;
2835 case EL_CONVEYOR_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2836 case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2837 case EL_CONVEYOR_BELT1_SWITCH_RIGHT:return GFX_BELT1_SWITCH_RIGHT;
2838 case EL_CONVEYOR_BELT2_LEFT: return GFX_BELT2_LEFT;
2839 case EL_CONVEYOR_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2840 case EL_CONVEYOR_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2841 case EL_CONVEYOR_BELT2_LEFT_ACTIVE: return GFX_BELT2_LEFT;
2842 case EL_CONVEYOR_BELT2_MIDDLE_ACTIVE:return GFX_BELT2_MIDDLE;
2843 case EL_CONVEYOR_BELT2_RIGHT_ACTIVE:return GFX_BELT2_RIGHT;
2844 case EL_CONVEYOR_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2845 case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2846 case EL_CONVEYOR_BELT2_SWITCH_RIGHT:return GFX_BELT2_SWITCH_RIGHT;
2847 case EL_CONVEYOR_BELT3_LEFT: return GFX_BELT3_LEFT;
2848 case EL_CONVEYOR_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2849 case EL_CONVEYOR_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2850 case EL_CONVEYOR_BELT3_LEFT_ACTIVE: return GFX_BELT3_LEFT;
2851 case EL_CONVEYOR_BELT3_MIDDLE_ACTIVE:return GFX_BELT3_MIDDLE;
2852 case EL_CONVEYOR_BELT3_RIGHT_ACTIVE:return GFX_BELT3_RIGHT;
2853 case EL_CONVEYOR_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2854 case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2855 case EL_CONVEYOR_BELT3_SWITCH_RIGHT:return GFX_BELT3_SWITCH_RIGHT;
2856 case EL_CONVEYOR_BELT4_LEFT: return GFX_BELT4_LEFT;
2857 case EL_CONVEYOR_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2858 case EL_CONVEYOR_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2859 case EL_CONVEYOR_BELT4_LEFT_ACTIVE: return GFX_BELT4_LEFT;
2860 case EL_CONVEYOR_BELT4_MIDDLE_ACTIVE:return GFX_BELT4_MIDDLE;
2861 case EL_CONVEYOR_BELT4_RIGHT_ACTIVE:return GFX_BELT4_RIGHT;
2862 case EL_CONVEYOR_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2863 case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2864 case EL_CONVEYOR_BELT4_SWITCH_RIGHT:return GFX_BELT4_SWITCH_RIGHT;
2865 case EL_LANDMINE: return GFX_LANDMINE;
2866 case EL_ENVELOPE: return GFX_ENVELOPE;
2867 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH_OFF;
2868 case EL_LIGHT_SWITCH_ACTIVE: return GFX_LIGHT_SWITCH_ON;
2869 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2870 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2871 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2872 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2873 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2874 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2875 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2876 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2877 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2878 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2879 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2880 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2881 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2882 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2883 case EL_MOLE_UP: return GFX_MOLE_UP;
2884 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2885 case EL_STEELWALL_SLANTED: return GFX_STEEL_SLANTED;
2886 case EL_INVISIBLE_SAND: return GFX_SAND_INVISIBLE;
2887 case EL_INVISIBLE_SAND_ACTIVE: return GFX_SAND_INVISIBLE_ON;
2888 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2889 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2890 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2891 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2892 case EL_TIMEGATE_SWITCH_ACTIVE: return GFX_TIMEGATE_SWITCH;
2893 case EL_TIMEGATE_SWITCH: return GFX_TIMEGATE_SWITCH;
2894 case EL_BALLOON: return GFX_BALLOON;
2895 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2896 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2897 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2898 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2899 case EL_BALLOON_SEND_ANY_DIRECTION: return GFX_BALLOON_SEND_ANY;
2900 case EL_EMC_STEELWALL1: return GFX_EMC_STEEL_WALL_1;
2901 case EL_EMC_STEELWALL2: return GFX_EMC_STEEL_WALL_2;
2902 case EL_EMC_STEELWALL3: return GFX_EMC_STEEL_WALL_3;
2903 case EL_EMC_STEELWALL4: return GFX_EMC_STEEL_WALL_4;
2904 case EL_EMC_WALL_PILLAR_UPPER: return GFX_EMC_WALL_1;
2905 case EL_EMC_WALL_PILLAR_MIDDLE: return GFX_EMC_WALL_2;
2906 case EL_EMC_WALL_PILLAR_LOWER: return GFX_EMC_WALL_3;
2907 case EL_EMC_WALL4: return GFX_EMC_WALL_4;
2908 case EL_EMC_WALL5: return GFX_EMC_WALL_5;
2909 case EL_EMC_WALL6: return GFX_EMC_WALL_6;
2910 case EL_EMC_WALL7: return GFX_EMC_WALL_7;
2911 case EL_EMC_WALL8: return GFX_EMC_WALL_8;
2912 case EL_TUBE_ALL: return GFX_TUBE_CROSS;
2913 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2914 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2915 case EL_TUBE_VERTICAL_LEFT: return GFX_TUBE_VERT_LEFT;
2916 case EL_TUBE_VERTICAL_RIGHT: return GFX_TUBE_VERT_RIGHT;
2917 case EL_TUBE_HORIZONTAL_UP: return GFX_TUBE_HORIZ_UP;
2918 case EL_TUBE_HORIZONTAL_DOWN: return GFX_TUBE_HORIZ_DOWN;
2919 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2920 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2921 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2922 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2923 case EL_SPRING: return GFX_SPRING;
2924 case EL_TRAP: return GFX_TRAP_INACTIVE;
2925 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2926 case EL_BD_WALL: return GFX_BD_WALL;
2927 case EL_BD_ROCK: return GFX_BD_ROCK;
2928 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2929 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2933 if (IS_CHAR(element))
2934 return GFX_CHAR_START + (element - EL_CHAR_START);
2935 else if (element >= EL_SP_START && element <= EL_SP_END)
2937 int nr_element = element - EL_SP_START;
2938 int gfx_per_line = 8;
2940 (nr_element / gfx_per_line) * SP_PER_LINE +
2941 (nr_element % gfx_per_line);
2943 return GFX_START_ROCKSSP + nr_graphic;
2951 int el2gfx(int element)
2954 int graphic_OLD = el2gfx_OLD(element);
2959 int graphic_NEW = element_info[element].graphic[GFX_ACTION_DEFAULT];
2962 int graphic_OLD = el2gfx_OLD(element);
2964 if (element >= MAX_ELEMENTS)
2966 Error(ERR_WARN, "el2gfx: element == %d >= MAX_ELEMENTS", element);
2969 if (graphic_NEW != graphic_OLD)
2971 Error(ERR_WARN, "el2gfx: graphic_NEW (%d) != graphic_OLD (%d)",
2972 graphic_NEW, graphic_OLD);
2980 int el2img(int element)
2982 int graphic = element_info[element].graphic[GFX_ACTION_DEFAULT];
2986 Error(ERR_WARN, "element %d -> graphic %d -- probably crashing now...",
2993 int el_dir2img(int element, int direction)
2995 return el_dir_act2img(element, direction, GFX_ACTION_DEFAULT);
2998 int el_dir_act2img(int element, int direction, int action)
3003 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: element == %d\n",
3011 printf("el_dir_act2img: THIS SHOULD NEVER HAPPEN: action == %d\n",
3018 action = graphics_action_mapping[action];
3019 direction = MV_DIR_BIT(direction);
3021 return element_info[element].direction_graphic[action][direction];