+ else
+ graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
+
+ frame = getGraphicAnimationFrame(graphic, player->Frame);
+
+ if (player->GfxPos)
+ {
+ if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
+ sxx = player->GfxPos;
+ else
+ syy = player->GfxPos;
+ }
+
+ if (!setup.soft_scrolling && ScreenMovPos)
+ sxx = syy = 0;
+
+ DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+
+ if (SHIELD_ON(player))
+ {
+ int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+ IMG_SHIELD_NORMAL_ACTIVE);
+ int frame = getGraphicAnimationFrame(graphic, -1);
+
+ DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+ }
+
+ /* ----------------------------------------------------------------------- */
+ /* draw things the player is pushing, if needed */
+ /* ----------------------------------------------------------------------- */
+
+#if 0
+ printf("::: %d, %d [%d, %d] [%d]\n",
+ player->is_pushing, player_is_moving, player->GfxAction,
+ player->is_moving, player_is_moving);
+#endif
+
+#if 1
+ if (player->is_pushing && player->is_moving)
+#else
+ if (player->is_pushing && player_is_moving)
+#endif
+ {
+ int px = SCREENX(next_jx), py = SCREENY(next_jy);
+
+ if (Back[next_jx][next_jy])
+ DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+
+ if ((sxx || syy) && element == EL_SOKOBAN_OBJECT)
+ DrawGraphicShiftedThruMask(px, py, sxx, syy, IMG_SOKOBAN_OBJECT, 0,
+ NO_CUTTING);
+ else
+ {
+ int element = MovingOrBlocked2Element(next_jx, next_jy);
+ int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+#if 1
+ int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
+#else
+ int frame = getGraphicAnimationFrame(graphic, player->Frame);
+#endif
+
+ DrawGraphicShifted(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);
+ frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
+
+ if (game.emulation == EMU_SUPAPLEX)
+ DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
+ else
+ DrawGraphicThruMask(sx, sy, graphic, frame);
+ }
+
+ if (player_is_moving && last_element == EL_EXPLOSION)
+ {
+ int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
+ int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
+ int phase = ExplodePhase[last_jx][last_jy] - 1;
+ int frame = getGraphicAnimationFrame(graphic, phase - delay);
+
+ if (phase >= delay)
+ DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
+ }
+
+ /* ----------------------------------------------------------------------- */
+ /* draw elements the player is just walking/passing through/under */
+ /* ----------------------------------------------------------------------- */
+
+ /* handle the field the player is leaving ... */
+ if (player_is_moving && IS_ACCESSIBLE_INSIDE(last_element))
+ DrawLevelField(last_jx, last_jy);
+ else if (player_is_moving && IS_ACCESSIBLE_UNDER(last_element))
+ DrawLevelFieldThruMask(last_jx, last_jy);
+
+ /* ... and the field the player is entering */
+ if (IS_ACCESSIBLE_INSIDE(element))
+ DrawLevelField(jx, jy);
+ else if (IS_ACCESSIBLE_UNDER(element))
+ DrawLevelFieldThruMask(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);
+}
+
+void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
+{
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ *bitmap = g->bitmap;
+
+ if (g->offset_y == 0) /* frames are ordered horizontally */
+ {
+ int max_width = g->anim_frames_per_line * g->width;
+
+ *x = (g->src_x + frame * g->offset_x) % max_width;
+ *y = g->src_y + (g->src_x + frame * g->offset_x) / max_width * g->height;
+ }
+ else if (g->offset_x == 0) /* frames are ordered vertically */
+ {
+ int max_height = g->anim_frames_per_line * g->height;
+
+ *x = g->src_x + (g->src_y + frame * g->offset_y) / max_height * g->width;
+ *y = (g->src_y + frame * g->offset_y) % max_height;
+ }
+ else /* frames are ordered diagonally */
+ {
+ *x = g->src_x + frame * g->offset_x;
+ *y = g->src_y + frame * g->offset_y;
+ }
+}
+
+void DrawGraphic(int x, int y, int graphic, int frame)
+{
+#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, frame);
+ MarkTileDirty(x, y);
+}
+
+void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
+ int frame)
+{
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+
+ getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);