+ if (SHIELD_ON(player))
+ {
+ int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+ IMG_SHIELD_NORMAL_ACTIVE);
+ int frame = getNewGraphicAnimationFrame(graphic, -1);
+
+ DrawNewGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+ }
+
+ if (player->Pushing && player->GfxPos)
+ {
+ int px = SCREENX(next_jx), py = SCREENY(next_jy);
+
+ if (element == EL_SOKOBAN_FIELD_EMPTY ||
+ Feld[next_jx][next_jy] == EL_SOKOBAN_FIELD_FULL)
+ DrawNewGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT, 0,
+ NO_CUTTING);
+ else
+ {
+ int element = Feld[next_jx][next_jy];
+ int graphic = el2img(element);
+ int frame = 0;
+
+ if ((element == EL_ROCK ||
+ element == EL_SP_ZONK ||
+ element == EL_BD_ROCK) && sxx)
+ {
+ graphic = el_dir_act2img(element, player->MovDir, GFX_ACTION_PUSHING);
+ frame = getNewGraphicAnimationFrame(graphic, player->GfxPos);
+
+ /* !!! FIX !!! */
+ if (player->MovDir == MV_LEFT)
+ frame = 3 - frame;
+
+#if 0
+ frame = (player->GfxPos / (TILEX / 4));
+
+ if (player->MovDir == MV_RIGHT)
+ frame = (frame + 4) % 4;
+#endif
+ }
+
+ DrawNewGraphicShifted(px, py, sxx, syy, graphic, frame,
+ NO_CUTTING, NO_MASKING);
+ }
+ }
+
+ /* draw things in front of player (active dynamite or dynabombs) */
+
+ if (IS_ACTIVE_BOMB(element))
+ {
+ graphic = el2img(element);
+
+#if 0
+ if (element == EL_DYNAMITE_ACTIVE)
+ {
+ if ((frame = (96 - MovDelay[jx][jy]) / 12) > 6)
+ frame = 6;
+ }
+ else
+ {
+ if ((frame = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
+ frame = 7 - frame;
+ }
+#else
+ frame = getNewGraphicAnimationFrame(graphic, 96 - MovDelay[jx][jy]);
+#endif
+
+ if (game.emulation == EMU_SUPAPLEX)
+ DrawNewGraphic(sx, sy, GFX_SP_DISK_RED, 0);
+ else
+ DrawNewGraphicThruMask(sx, sy, graphic, frame);
+ }
+
+ if (player_is_moving && last_element == EL_EXPLOSION)
+ {
+ int frame = Frame[last_jx][last_jy];
+ int delay = 2;
+
+ if (frame > 2)
+ DrawNewGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
+ GFX_EXPLOSION, ((frame - 1) / delay - 1));
+ }
+
+ /* draw elements that stay over the player */
+ /* handle the field the player is leaving ... */
+ if (player_is_moving && IS_OVER_PLAYER(last_element))
+ DrawNewLevelField(last_jx, last_jy);
+ /* ... and the field the player is entering */
+ if (IS_OVER_PLAYER(element))
+ DrawNewLevelField(jx, jy);
+
+ if (setup.direct_draw)
+ {
+ int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
+ int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
+ int x_size = TILEX * (1 + ABS(jx - last_jx));
+ int y_size = TILEY * (1 + ABS(jy - last_jy));
+
+ BlitBitmap(drawto_field, window,
+ dest_x, dest_y, x_size, y_size, dest_x, dest_y);
+ SetDrawtoField(DRAW_DIRECT);
+ }
+
+ MarkTileDirty(sx,sy);
+}
+#endif
+
+static int getGraphicAnimationPhase(int frames, int delay, int mode)
+{
+ int phase;
+
+ if (mode & ANIM_PINGPONG)
+ {
+ int max_anim_frames = 2 * frames - 2;
+
+ phase = (FrameCounter % (delay * max_anim_frames)) / delay;
+ phase = (phase < frames ? phase : max_anim_frames - phase);
+ }
+ else
+ phase = (FrameCounter % (delay * frames)) / delay;
+
+ if (mode & ANIM_REVERSE)
+ phase = -phase;
+
+ return phase;
+}
+
+int getNewGraphicAnimationFrame(int graphic, int sync_frame)
+{
+ int num_frames = new_graphic_info[graphic].anim_frames;
+ int delay = new_graphic_info[graphic].anim_delay;
+ int mode = new_graphic_info[graphic].anim_mode;
+ int frame = 0;
+
+ /* animation synchronized with global frame counter, not move position */
+ if (new_graphic_info[graphic].anim_global_sync || sync_frame < 0)
+ sync_frame = FrameCounter;
+
+ if (mode & ANIM_LOOP) /* normal, looping animation */
+ {
+ frame = (sync_frame % (delay * num_frames)) / delay;
+ }
+ else if (mode & ANIM_LINEAR) /* normal, non-looping animation */
+ {
+ frame = sync_frame / delay;
+
+ if (frame > num_frames - 1)
+ frame = num_frames - 1;
+ }
+ else if (mode & ANIM_PINGPONG) /* use border frames once */
+ {
+ int max_anim_frames = 2 * num_frames - 2;
+
+ frame = (sync_frame % (delay * max_anim_frames)) / delay;
+ frame = (frame < num_frames ? frame : max_anim_frames - frame);
+ }
+ else if (mode & ANIM_PINGPONG2) /* use border frames twice */
+ {
+ int max_anim_frames = 2 * num_frames;
+
+ frame = (sync_frame % (delay * max_anim_frames)) / delay;
+ frame = (frame < num_frames ? frame : max_anim_frames - frame - 1);
+ }
+
+ if (mode & ANIM_REVERSE) /* use reverse animation direction */
+ frame = num_frames - frame - 1;
+
+ return frame;
+}
+
+#if 0
+void DrawGraphicAnimationExt(int x, int y, int graphic,
+ int frames, int delay, int mode, int mask_mode)
+{
+ int phase = getGraphicAnimationPhase(frames, delay, mode);
+
+ if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+ {
+ if (mask_mode == USE_MASKING)
+ DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
+ else
+ DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
+ }
+}
+#endif
+
+void DrawNewGraphicAnimationExt(int x, int y, int graphic, int mask_mode)
+{
+#if 0
+ int delay = new_graphic_info[graphic].anim_delay;
+
+ if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+#else
+ if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+#endif
+ {
+ int frame = getNewGraphicAnimationFrame(graphic, -1);
+
+ if (mask_mode == USE_MASKING)
+ DrawNewGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
+ else
+ DrawNewGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+ }
+}
+
+#if 0
+void DrawGraphicAnimation(int x, int y, int graphic,
+ int frames, int delay, int mode)
+{
+ DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
+}
+#endif
+
+void DrawNewGraphicAnimation(int x, int y, int graphic)
+{
+ DrawNewGraphicAnimationExt(x, y, graphic, NO_MASKING);
+}
+
+#if 0
+void DrawGraphicAnimationThruMask(int x, int y, int graphic,
+ int frames, int delay, int mode)
+{
+ DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
+}
+#endif
+
+static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
+ int sxx, int syy,
+ int graphic,
+ int frames, int delay,
+ int mode)
+{
+ int phase = getGraphicAnimationPhase(frames, delay, mode);
+
+ DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
+}
+
+#if 1
+void getGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+{
+ if (graphic >= 0 && graphic_info[graphic].bitmap != NULL)
+ {
+ *bitmap = graphic_info[graphic].bitmap;
+ *x = graphic_info[graphic].src_x;
+ *y = graphic_info[graphic].src_y;
+ }
+ else if (graphic >= GFX_START_ROCKSELEMENTS &&
+ graphic <= GFX_END_ROCKSELEMENTS)
+ {
+ graphic -= GFX_START_ROCKSELEMENTS;
+ *bitmap = pix[PIX_ELEMENTS];
+ *x = (graphic % GFX_PER_LINE) * TILEX;
+ *y = (graphic / GFX_PER_LINE) * TILEY;
+ }
+ else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
+ {
+ graphic -= GFX_START_ROCKSHEROES;
+ *bitmap = pix[PIX_HEROES];
+ *x = (graphic % HEROES_PER_LINE) * TILEX;
+ *y = (graphic / HEROES_PER_LINE) * TILEY;
+ }
+ else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
+ {
+ graphic -= GFX_START_ROCKSSP;
+ *bitmap = pix[PIX_SP];
+ *x = (graphic % SP_PER_LINE) * TILEX;
+ *y = (graphic / SP_PER_LINE) * TILEY;
+ }
+ else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
+ {
+ graphic -= GFX_START_ROCKSDC;
+ *bitmap = pix[PIX_DC];
+ *x = (graphic % DC_PER_LINE) * TILEX;
+ *y = (graphic / DC_PER_LINE) * TILEY;
+ }
+ else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
+ {
+ graphic -= GFX_START_ROCKSMORE;
+ *bitmap = pix[PIX_MORE];
+ *x = (graphic % MORE_PER_LINE) * TILEX;
+ *y = (graphic / MORE_PER_LINE) * TILEY;
+ }
+ else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
+ {
+ graphic -= GFX_START_ROCKSFONT;
+ *bitmap = pix[PIX_FONT_EM];
+ *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
+ *y = (graphic / FONT_CHARS_PER_LINE) * TILEY;
+ }
+ else
+ {
+ *bitmap = pix[PIX_SP];
+ *x = 0;
+ *y = 0;
+ }
+}
+#endif
+
+#if 0
+void DrawGraphic(int x, int y, int graphic)
+{
+#if DEBUG
+ if (!IN_SCR_FIELD(x, y))
+ {
+ printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
+ printf("DrawGraphic(): This should never happen!\n");
+ return;
+ }
+#endif
+
+ DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic);
+ MarkTileDirty(x, y);
+}
+#endif
+
+void DrawNewGraphic(int x, int y, int graphic, int frame)
+{
+#if DEBUG
+ if (!IN_SCR_FIELD(x, y))
+ {
+ printf("DrawNewGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
+ printf("DrawNewGraphic(): This should never happen!\n");
+ return;
+ }
+#endif
+
+ DrawNewGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
+ graphic, frame);
+ MarkTileDirty(x, y);
+}
+
+void DrawOldGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic)
+{
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+
+ getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
+}
+
+void DrawNewGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
+ int frame)
+{
+ Bitmap *src_bitmap = new_graphic_info[graphic].bitmap;
+ int src_x = new_graphic_info[graphic].src_x;
+ int src_y = new_graphic_info[graphic].src_y;
+ int offset_x = new_graphic_info[graphic].offset_x;
+ int offset_y = new_graphic_info[graphic].offset_y;
+
+ src_x += frame * offset_x;
+ src_y += frame * offset_y;
+
+ BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
+}
+
+void DrawGraphicThruMask(int x, int y, int graphic)
+{
+#if DEBUG
+ if (!IN_SCR_FIELD(x, y))