drawto_field = fieldbuffer;
}
- else /* DRAW_DIRECT, DRAW_BACKBUFFER */
+ else /* DRAW_BACKBUFFER */
{
FX = SX;
FY = SY;
redraw_x1 = 0;
redraw_y1 = 0;
- drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
+ drawto_field = backbuffer;
}
}
height = gfx.sysize + 2 * TILEY;
}
- if (force_redraw || setup.direct_draw)
+ if (force_redraw)
{
int xx, yy;
int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
- if (setup.direct_draw)
- SetDrawtoField(DRAW_BACKBUFFER);
-
for (xx = BX1; xx <= BX2; xx++)
for (yy = BY1; yy <= BY2; yy++)
if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
DrawScreenField(xx, yy);
DrawAllPlayers();
-
- if (setup.direct_draw)
- SetDrawtoField(DRAW_DIRECT);
}
if (setup.soft_scrolling)
void DrawMaskedBorder_FIELD()
{
- if (game_status >= GAME_MODE_TITLE &&
- game_status <= GAME_MODE_PLAYING &&
- border.draw_masked[game_status])
+ if (global.border_status >= GAME_MODE_TITLE &&
+ global.border_status <= GAME_MODE_PLAYING &&
+ border.draw_masked[global.border_status])
DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
}
void DrawMaskedBorder_DOOR_1()
{
if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
- (game_status != GAME_MODE_EDITOR ||
+ (global.border_status != GAME_MODE_EDITOR ||
border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
}
void DrawMaskedBorder_DOOR_2()
{
if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
- game_status != GAME_MODE_EDITOR)
+ global.border_status != GAME_MODE_EDITOR)
DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
}
void DrawMaskedBorder(int redraw_mask)
{
- /* do not draw masked screen borders when displaying title screens */
- if (effectiveGameStatus() == GAME_MODE_TITLE ||
- effectiveGameStatus() == GAME_MODE_MESSAGE)
+ /* never draw masked screen borders on borderless screens */
+ if (effectiveGameStatus() == GAME_MODE_LOADING ||
+ effectiveGameStatus() == GAME_MODE_TITLE)
return;
if (redraw_mask & REDRAW_ALL)
void BackToFront()
{
- int x,y;
+ int x, y;
DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
- if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
- redraw_mask &= ~REDRAW_MAIN;
+#if 0
+ printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
+ for (x = 0; x < SCR_FIELDX; x++)
+ for (y = 0 ; y < SCR_FIELDY; y++)
+ if (redraw[redraw_x1 + x][redraw_y1 + y])
+ printf("::: - %d, %d [%s]\n",
+ LEVELX(x), LEVELY(y),
+ EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
+#endif
if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
redraw_mask |= REDRAW_FIELD;
if (!global.fps_slowdown)
info1[0] = '\0';
- sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
+ sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
+#if 1
+ DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
+#else
DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
+#endif
}
FlushDisplay();
redraw_mask = REDRAW_NONE;
}
-void FadeToFront()
+static void FadeCrossSaveBackbuffer()
{
-#if 0
- long fading_delay = 300;
+ BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+}
+
+static void FadeExt(int fade_mask, int fade_mode, int fade_type)
+{
+ static int fade_type_skip = FADE_TYPE_NONE;
+ void (*draw_border_function)(void) = NULL;
+ Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
+ int x, y, width, height;
+ int fade_delay, post_delay;
- if (setup.fading && (redraw_mask & REDRAW_FIELD))
+ if (fade_type == FADE_TYPE_FADE_OUT)
{
+ if (fade_type_skip != FADE_TYPE_NONE)
+ {
+#if 0
+ printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
#endif
-#if 0
- int x,y;
+ /* skip all fade operations until specified fade operation */
+ if (fade_type & fade_type_skip)
+ fade_type_skip = FADE_TYPE_NONE;
- ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
- FlushDisplay();
+ return;
+ }
- for (i = 0; i < 2 * FULL_SYSIZE; i++)
+ if (fading.fade_mode & FADE_TYPE_TRANSFORM)
{
- for (y = 0; y < FULL_SYSIZE; y++)
- {
- BlitBitmap(backbuffer, window,
- REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
- }
- FlushDisplay();
- Delay(10);
+ FadeCrossSaveBackbuffer();
+
+ return;
}
+ }
+
+ redraw_mask |= fade_mask;
+
+ if (fade_type == FADE_TYPE_SKIP)
+ {
+#if 0
+ printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
#endif
+ fade_type_skip = fade_mode;
+
+ return;
+ }
+
#if 0
- for (i = 1; i < FULL_SYSIZE; i+=2)
- BlitBitmap(backbuffer, window,
- REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
- FlushDisplay();
- Delay(fading_delay);
+ printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
+ fade_type_skip);
#endif
+#if 1
+ fade_delay = fading.fade_delay;
+ post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
+#endif
+
+ if (fade_type_skip != FADE_TYPE_NONE)
+ {
#if 0
- SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
- BlitBitmapMasked(backbuffer, window,
- REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
- REAL_SX,REAL_SY);
- FlushDisplay();
- Delay(fading_delay);
-
- SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
- BlitBitmapMasked(backbuffer, window,
- REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
- REAL_SX,REAL_SY);
- FlushDisplay();
- Delay(fading_delay);
-
- SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
- BlitBitmapMasked(backbuffer, window,
- REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
- REAL_SX,REAL_SY);
- FlushDisplay();
- Delay(fading_delay);
-
- SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
- BlitBitmapMasked(backbuffer, window,
- REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
- REAL_SX,REAL_SY);
- FlushDisplay();
- Delay(fading_delay);
+ printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
+#endif
- redraw_mask &= ~REDRAW_MAIN;
+ /* skip all fade operations until specified fade operation */
+ if (fade_type & fade_type_skip)
+ fade_type_skip = FADE_TYPE_NONE;
+
+#if 1
+ fade_delay = 0;
+#else
+ return;
+#endif
+ }
+
+#if 1
+ if (global.autoplay_leveldir)
+ {
+ // fading.fade_mode = FADE_MODE_NONE;
+
+ return;
}
#endif
- BackToFront();
-}
+#if 0
+ if (fading.fade_mode == FADE_MODE_NONE)
+ {
+ BackToFront();
-void FadeExt(int fade_mask, int fade_mode)
-{
- void (*draw_border_function)(void) = NULL;
- Bitmap *bitmap = (fade_mode == FADE_MODE_CROSSFADE ? bitmap_db_cross : NULL);
- int x, y, width, height;
- int fade_delay, post_delay;
+ return;
+ }
+#endif
+
+ /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
+
+#if 0
+ printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
+#endif
+
+#if 0
+ if (fade_mask == REDRAW_NONE)
+ fade_mask = REDRAW_FIELD;
+#endif
- if (fade_mask & REDRAW_FIELD)
+ // if (fade_mask & REDRAW_FIELD)
+ if (fade_mask == REDRAW_FIELD)
{
x = REAL_SX;
y = REAL_SY;
width = FULL_SXSIZE;
height = FULL_SYSIZE;
- fade_delay = menu.fade_delay;
- post_delay = (fade_mode == FADE_MODE_FADE_OUT ? menu.post_delay : 0);
+#if 0
+ fade_delay = fading.fade_delay;
+ post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
+#endif
- draw_border_function = DrawMaskedBorder_FIELD;
+ if (border.draw_masked_when_fading)
+ draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
+ else
+ DrawMaskedBorder_FIELD(); /* draw once */
}
else /* REDRAW_ALL */
{
width = WIN_XSIZE;
height = WIN_YSIZE;
- fade_delay = title.fade_delay_final;
- post_delay = (fade_mode == FADE_MODE_FADE_OUT ? title.post_delay_final : 0);
+#if 0
+ fade_delay = fading.fade_delay;
+ post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
+#endif
}
- redraw_mask |= fade_mask;
-
+#if 1
+ if (!setup.fade_screens ||
+ fade_delay == 0 ||
+ fading.fade_mode == FADE_MODE_NONE)
+#else
if (!setup.fade_screens || fade_delay == 0)
+#endif
{
if (fade_mode == FADE_MODE_FADE_OUT)
+ return;
+
+#if 0
+ if (fade_mode == FADE_MODE_FADE_OUT &&
+ fading.fade_mode != FADE_MODE_NONE)
ClearRectangle(backbuffer, x, y, width, height);
+#endif
+#if 1
+ BlitBitmap(backbuffer, window, x, y, width, height, x, y);
+ redraw_mask = REDRAW_NONE;
+#else
BackToFront();
+#endif
return;
}
void FadeIn(int fade_mask)
{
- FadeExt(fade_mask, FADE_MODE_FADE_IN);
+ if (fading.fade_mode & FADE_TYPE_TRANSFORM)
+ FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
+ else
+ FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
}
void FadeOut(int fade_mask)
{
- FadeExt(fade_mask, FADE_MODE_FADE_OUT);
+ if (fading.fade_mode & FADE_TYPE_TRANSFORM)
+ FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
+ else
+ FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
+
+ global.border_status = game_status;
}
-void FadeCross(int fade_mask)
+static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
{
- FadeExt(fade_mask, FADE_MODE_CROSSFADE);
+ static struct TitleFadingInfo fading_leave_stored;
+
+ if (set)
+ fading_leave_stored = fading_leave;
+ else
+ fading = fading_leave_stored;
}
-void FadeCrossSaveBackbuffer()
+void FadeSetEnterMenu()
{
- BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ fading = menu.enter_menu;
+
+#if 0
+ printf("::: storing enter_menu\n");
+#endif
+
+ FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+}
+
+void FadeSetLeaveMenu()
+{
+ fading = menu.leave_menu;
+
+#if 0
+ printf("::: storing leave_menu\n");
+#endif
+
+ FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+}
+
+void FadeSetEnterScreen()
+{
+ fading = menu.enter_screen[game_status];
+
+#if 0
+ printf("::: storing leave_screen[%d]\n", game_status);
+#endif
+
+ FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
+}
+
+void FadeSetNextScreen()
+{
+ fading = menu.next_screen;
+
+#if 0
+ printf("::: storing next_screen\n");
+#endif
+
+ // (do not overwrite fade mode set by FadeSetEnterScreen)
+ // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+}
+
+void FadeSetLeaveScreen()
+{
+#if 0
+ printf("::: recalling last stored value\n");
+#endif
+
+ FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
+}
+
+void FadeSetFromType(int type)
+{
+ if (type & TYPE_ENTER_SCREEN)
+ FadeSetEnterScreen();
+ else if (type & TYPE_ENTER)
+ FadeSetEnterMenu();
+ else if (type & TYPE_LEAVE)
+ FadeSetLeaveMenu();
+}
+
+void FadeSetDisabled()
+{
+ static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
+
+ fading = fading_none;
+}
+
+void FadeSkipNextFadeIn()
+{
+ FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
+}
+
+void FadeSkipNextFadeOut()
+{
+ FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
}
void SetWindowBackgroundImageIfDefined(int graphic)
DrawBackground(x, y, width, height);
}
-void ClearWindow()
+void ClearField()
{
/* !!! "drawto" might still point to playfield buffer here (see above) !!! */
/* (when entering hall of fame after playing) */
}
else
SetDrawtoField(DRAW_BACKBUFFER);
-
- if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
- {
- ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
- SetDrawtoField(DRAW_DIRECT);
- }
}
void MarkTileDirty(int x, int y)
sync_frame);
}
+void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
+ Bitmap **bitmap, int *x, int *y)
+{
+ struct
+ {
+ int width_mult, width_div;
+ int height_mult, height_div;
+ }
+ offset_calc[6] =
+ {
+ { 15, 16, 2, 3 }, /* 1 x 1 */
+ { 7, 8, 2, 3 }, /* 2 x 2 */
+ { 3, 4, 2, 3 }, /* 4 x 4 */
+ { 1, 2, 2, 3 }, /* 8 x 8 */
+ { 0, 1, 2, 3 }, /* 16 x 16 */
+ { 0, 1, 0, 1 }, /* 32 x 32 */
+ };
+ struct GraphicInfo *g = &graphic_info[graphic];
+ Bitmap *src_bitmap = g->bitmap;
+ int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
+ int offset_calc_pos = log_2(tilesize);
+ int width_mult = offset_calc[offset_calc_pos].width_mult;
+ int width_div = offset_calc[offset_calc_pos].width_div;
+ int height_mult = offset_calc[offset_calc_pos].height_mult;
+ int height_div = offset_calc[offset_calc_pos].height_div;
+ int startx = src_bitmap->width * width_mult / width_div;
+ int starty = src_bitmap->height * height_mult / height_div;
+ int src_x = g->src_x * tilesize / TILESIZE;
+ int src_y = g->src_y * tilesize / TILESIZE;
+ int width = g->width * tilesize / TILESIZE;
+ int height = g->height * tilesize / TILESIZE;
+ int offset_x = g->offset_x * tilesize / TILESIZE;
+ int offset_y = g->offset_y * tilesize / TILESIZE;
+
+ if (g->offset_y == 0) /* frames are ordered horizontally */
+ {
+ int max_width = g->anim_frames_per_line * width;
+ int pos = (src_y / height) * max_width + src_x + frame * offset_x;
+
+ src_x = pos % max_width;
+ src_y = src_y % height + pos / max_width * height;
+ }
+ else if (g->offset_x == 0) /* frames are ordered vertically */
+ {
+ int max_height = g->anim_frames_per_line * height;
+ int pos = (src_x / width) * max_height + src_y + frame * offset_y;
+
+ src_x = src_x % width + pos / max_height * width;
+ src_y = pos % max_height;
+ }
+ else /* frames are ordered diagonally */
+ {
+ src_x = src_x + frame * offset_x;
+ src_y = src_y + frame * offset_y;
+ }
+
+ *bitmap = src_bitmap;
+ *x = startx + src_x;
+ *y = starty + src_y;
+}
+
+void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+{
+#if 1
+ getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
+#else
+ struct GraphicInfo *g = &graphic_info[graphic];
+ int mini_startx = 0;
+ int mini_starty = g->bitmap->height * 2 / 3;
+
+ *bitmap = g->bitmap;
+ *x = mini_startx + g->src_x / 2;
+ *y = mini_starty + g->src_y / 2;
+#endif
+}
+
inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
int *x, int *y, boolean get_backside)
{
BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
}
-void DrawMiniGraphic(int x, int y, int graphic)
+void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
{
- DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
- MarkTileDirty(x / 2, y / 2);
+ DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
+ frame, tilesize);
+ MarkTileDirty(x / tilesize, y / tilesize);
}
-void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
+void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
+ int tilesize)
{
- struct GraphicInfo *g = &graphic_info[graphic];
- int mini_startx = 0;
- int mini_starty = g->bitmap->height * 2 / 3;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
- *bitmap = g->bitmap;
- *x = mini_startx + g->src_x / 2;
- *y = mini_starty + g->src_y / 2;
+ getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
+}
+
+void DrawMiniGraphic(int x, int y, int graphic)
+{
+ DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
+ MarkTileDirty(x / 2, y / 2);
}
void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
}
+/* !!! implementation of quicksand is totally broken !!! */
+#define IS_CRUMBLED_TILE(x, y, e) \
+ (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
+ !IS_MOVING(x, y) || \
+ (e) == EL_QUICKSAND_EMPTYING || \
+ (e) == EL_QUICKSAND_FAST_EMPTYING))
+
static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
{
Bitmap *src_bitmap;
element = TILE_GFX_ELEMENT(x, y);
/* crumble field itself */
+#if 1
+ if (IS_CRUMBLED_TILE(x, y, element))
+#else
if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
+#endif
{
if (!IN_SCR_FIELD(sx, sy))
return;
BorderElement);
/* check if neighbour field is of same type */
+#if 1
+ if (IS_CRUMBLED_TILE(xx, yy, element))
+ continue;
+#else
if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
continue;
+#endif
if (i == 1 || i == 2)
{
int sxx = sx + xy[i][0];
int syy = sy + xy[i][1];
+#if 1
+ if (!IN_LEV_FIELD(xx, yy) ||
+ !IN_SCR_FIELD(sxx, syy))
+ continue;
+#else
if (!IN_LEV_FIELD(xx, yy) ||
!IN_SCR_FIELD(sxx, syy) ||
IS_MOVING(xx, yy))
continue;
+#endif
if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
continue;
element = TILE_GFX_ELEMENT(xx, yy);
+#if 1
+ if (!IS_CRUMBLED_TILE(xx, yy, element))
+ continue;
+#else
if (!GFX_CRUMBLED(element))
continue;
+#endif
graphic = el_act2crm(element, ACTION_DEFAULT);
crumbled_border_size = graphic_info[graphic].border_size;
element = getBorderElement(lx, ly);
DrawScreenElement(x, y, element);
+
return;
}
element == EL_DC_MAGIC_WALL_FILLING)
cut_mode = CUT_BELOW;
+#if 0
+ if (lx == 9 && ly == 1)
+ printf("::: %s [%d] [%d, %d] [%d]\n",
+ EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
+ el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
+ element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
+ element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
+ GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
+#endif
+
if (cut_mode == CUT_ABOVE)
+#if 1
+ DrawScreenElement(x, y, element);
+#else
DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
+#endif
else
DrawScreenElement(x, y, EL_EMPTY);
else if (cut_mode == NO_CUTTING)
DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
else
+ {
DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
+#if 1
+ if (cut_mode == CUT_BELOW &&
+ IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
+ DrawLevelElement(lx, ly + 1, element);
+#endif
+ }
+
if (content == EL_ACID)
{
int dir = MovDir[lx][ly];
BackToFront();
}
-void getPreviewGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y,
- int tilesize)
-{
- struct
- {
- int width_mult, width_div;
- int height_mult, height_div;
- } offset_calc[4] =
- {
- { 0, 1, 0, 1 },
- { 0, 1, 2, 3 },
- { 1, 2, 2, 3 },
- { 3, 4, 2, 3 },
- };
- int offset_calc_pos = (tilesize < MICRO_TILESIZE || tilesize > TILESIZE ? 3 :
- 5 - log_2(tilesize));
- Bitmap *src_bitmap = graphic_info[graphic].bitmap;
- int width_mult = offset_calc[offset_calc_pos].width_mult;
- int width_div = offset_calc[offset_calc_pos].width_div;
- int height_mult = offset_calc[offset_calc_pos].height_mult;
- int height_div = offset_calc[offset_calc_pos].height_div;
- int mini_startx = src_bitmap->width * width_mult / width_div;
- int mini_starty = src_bitmap->height * height_mult / height_div;
- int src_x = mini_startx + graphic_info[graphic].src_x * tilesize / TILESIZE;
- int src_y = mini_starty + graphic_info[graphic].src_y * tilesize / TILESIZE;
-
- *bitmap = src_bitmap;
- *x = src_x;
- *y = src_y;
-}
-
void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
{
Bitmap *src_bitmap;
int src_x, src_y;
int graphic = el2preimg(element);
- getPreviewGraphicSource(graphic, &src_bitmap, &src_x, &src_y, tilesize);
+ getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
}
{
int x,y;
+#if 1
+ SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
+ SetDrawBackgroundMask(REDRAW_FIELD);
+#else
SetDrawBackgroundMask(REDRAW_NONE);
- ClearWindow();
+#endif
+
+ ClearField();
for (x = BX1; x <= BX2; x++)
for (y = BY1; y <= BY2; y++)
int real_preview_xsize = MIN(level_xsize, preview.xsize);
int real_preview_ysize = MIN(level_ysize, preview.ysize);
int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
- int dst_y = SY + preview.y;
+ int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
int x, y;
DrawBackground(dst_x, dst_y, preview_width, preview_height);
struct TextPosInfo *pos = &menu.main.text.level_info_2;
char label_text[MAX_OUTPUT_LINESIZE + 1];
int max_len_label_text;
- int font_nr = FONT_TEXT_2;
+#if 1
+ int font_nr = pos->font;
int i;
if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
mode == MICROLABEL_IMPORTED_FROM_HEAD ||
mode == MICROLABEL_IMPORTED_BY_HEAD)
- font_nr = FONT_TEXT_3;
-
-#if 1
+ font_nr = pos->font_alt;
+#else
+ int font_nr = FONT_TEXT_2;
+ int i;
+
+ if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
+ mode == MICROLABEL_IMPORTED_FROM_HEAD ||
+ mode == MICROLABEL_IMPORTED_BY_HEAD)
+ font_nr = FONT_TEXT_3;
+#endif
+
+#if 1
max_len_label_text = getMaxTextLength(pos, font_nr);
#else
max_len_label_text = SXSIZE / getFontWidth(font_nr);
#endif
#if 1
- if (pos->chars != -1)
- max_len_label_text = pos->chars;
+ if (pos->size != -1)
+ max_len_label_text = pos->size;
#endif
for (i = 0; i < max_len_label_text; i++)
int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
int last_game_status = game_status; /* save current game status */
+#if 0
/* force PREVIEW font on preview level */
game_status = GAME_MODE_PSEUDO_PREVIEW;
+#endif
if (restart)
{
{
struct TextPosInfo *pos = &menu.main.text.level_info_1;
char label_text[MAX_OUTPUT_LINESIZE + 1];
+#if 1
+ int font_nr = pos->font;
+#else
int font_nr = FONT_TEXT_1;
+#endif
#if 1
int max_len_label_text = getMaxTextLength(pos, font_nr);
#else
#endif
#if 1
- if (pos->chars != -1)
- max_len_label_text = pos->chars;
+ if (pos->size != -1)
+ max_len_label_text = pos->size;
#endif
strncpy(label_text, leveldir_current->name, max_len_label_text);
if (!IN_SCR_FIELD(sx, sy))
return;
- if (setup.direct_draw)
- SetDrawtoField(DRAW_BUFFERED);
-
/* ----------------------------------------------------------------------- */
/* draw things behind the player, if needed */
/* ----------------------------------------------------------------------- */
DrawLevelFieldThruMask(jx, jy);
}
- if (setup.direct_draw)
- {
- int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
- int dst_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,
- dst_x, dst_y, x_size, y_size, dst_x, dst_y);
- SetDrawtoField(DRAW_DIRECT);
- }
-
MarkTileDirty(sx, sy);
}
/* clear door drawing field */
DrawBackground(DX, DY, DXSIZE, DYSIZE);
- /* force DOOR font on preview level */
+ /* force DOOR font inside door area */
game_status = GAME_MODE_PSEUDO_DOOR;
/* write text for request */
case EVENT_KEYPRESS:
switch (GetEventKey((KeyEvent *)&event, TRUE))
{
+ case KSYM_space:
+ if (req_state & REQ_CONFIRM)
+ result = 1;
+ break;
+
case KSYM_Return:
result = 1;
break;
default:
break;
}
+
if (req_state & REQ_PLAYER)
result = 0;
break;
if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
{
HandleGameActions();
- BackToFront();
}
else
{
Delay(10);
}
+ BackToFront();
+
#else
DoAnimation();
if (setup.quick_doors)
{
- stepsize = 20; /* must be choosen to always draw last frame */
+ stepsize = 20; /* must be chosen to always draw last frame */
door_delay_value = 0;
}
door_state &= ~DOOR_CLOSE_ALL;
}
+#if 1
+ if (game_status == GAME_MODE_EDITOR)
+ door_state |= DOOR_NO_DELAY;
+#endif
+
if (door_state & DOOR_ACTION)
{
boolean handle_door_1 = (door_state & DOOR_ACTION_1);
Xsand_stonein_4, FALSE, TRUE,
EL_ROCK, ACTION_FILLING, -1
},
+#if 1
+ {
+ Xsand_stonesand_1, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
+ },
+ {
+ Xsand_stonesand_2, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
+ },
+ {
+ Xsand_stonesand_3, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
+ },
+ {
+ Xsand_stonesand_4, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
+ },
+ {
+ Xsand_stonesand_quickout_1, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
+ },
+ {
+ Xsand_stonesand_quickout_2, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
+ },
+#else
{
Xsand_stonesand_1, FALSE, FALSE,
EL_QUICKSAND_FULL, -1, -1
Xsand_stonesand_4, FALSE, FALSE,
EL_QUICKSAND_FULL, -1, -1
},
+#endif
{
Xsand_stoneout_1, FALSE, FALSE,
EL_ROCK, ACTION_EMPTYING, -1
Xsand_stoneout_2, FALSE, FALSE,
EL_ROCK, ACTION_EMPTYING, -1
},
+#if 1
+ {
+ Xsand_sandstone_1, FALSE, FALSE,
+ EL_QUICKSAND_FILLING, -1, -1
+ },
+ {
+ Xsand_sandstone_2, FALSE, FALSE,
+ EL_QUICKSAND_FILLING, -1, -1
+ },
+ {
+ Xsand_sandstone_3, FALSE, FALSE,
+ EL_QUICKSAND_FILLING, -1, -1
+ },
+ {
+ Xsand_sandstone_4, FALSE, FALSE,
+ EL_QUICKSAND_FILLING, -1, -1
+ },
+#else
{
Xsand_sandstone_1, FALSE, FALSE,
EL_QUICKSAND_FULL, -1, -1
Xsand_sandstone_4, FALSE, FALSE,
EL_QUICKSAND_FULL, -1, -1
},
+#endif
{
Xplant, TRUE, FALSE,
EL_EMC_PLANT, -1, -1
return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
}
+int el2panelimg(int element)
+{
+ element = GFX_ELEMENT(element);
+
+ return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
+}
+
int font2baseimg(int font_nr)
{
return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
return belt_move_dir[belt_dir_nr];
}
-int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
+int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
{
static int belt_base_element[4] =
{
EL_CONVEYOR_BELT_3_LEFT,
EL_CONVEYOR_BELT_4_LEFT
};
- int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
return belt_base_element[belt_nr] + belt_dir_nr;
}
-int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
+int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
+{
+ int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
+
+ return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
+}
+
+int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
{
static int belt_base_element[4] =
{
EL_CONVEYOR_BELT_3_SWITCH_LEFT,
EL_CONVEYOR_BELT_4_SWITCH_LEFT
};
- int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
return belt_base_element[belt_nr] + belt_dir_nr;
}
+int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
+{
+ int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
+
+ return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
+}
+
int getNumActivePlayers_EM()
{
int num_players = 0;
static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
#endif
+inline static int get_effective_element_EM(int tile, int frame_em)
+{
+ int element = object_mapping[tile].element_rnd;
+ int action = object_mapping[tile].action;
+ boolean is_backside = object_mapping[tile].is_backside;
+ boolean action_removing = (action == ACTION_DIGGING ||
+ action == ACTION_SNAPPING ||
+ action == ACTION_COLLECTING);
+
+ if (frame_em < 7)
+ {
+ switch (tile)
+ {
+ case Yacid_splash_eB:
+ case Yacid_splash_wB:
+ return (frame_em > 5 ? EL_EMPTY : element);
+
+ default:
+ return element;
+ }
+ }
+ else /* frame_em == 7 */
+ {
+ switch (tile)
+ {
+ case Yacid_splash_eB:
+ case Yacid_splash_wB:
+ return EL_EMPTY;
+
+ case Yemerald_stone:
+ return EL_EMERALD;
+
+ case Ydiamond_stone:
+ return EL_ROCK;
+
+ case Xdrip_stretch:
+ case Xdrip_stretchB:
+ case Ydrip_s1:
+ case Ydrip_s1B:
+ case Xball_1B:
+ case Xball_2:
+ case Xball_2B:
+ case Yball_eat:
+ case Ykey_1_eat:
+ case Ykey_2_eat:
+ case Ykey_3_eat:
+ case Ykey_4_eat:
+ case Ykey_5_eat:
+ case Ykey_6_eat:
+ case Ykey_7_eat:
+ case Ykey_8_eat:
+ case Ylenses_eat:
+ case Ymagnify_eat:
+ case Ygrass_eat:
+ case Ydirt_eat:
+ case Xsand_stonein_1:
+ case Xsand_stonein_2:
+ case Xsand_stonein_3:
+ case Xsand_stonein_4:
+ return element;
+
+ default:
+ return (is_backside || action_removing ? EL_EMPTY : element);
+ }
+ }
+}
+
+inline static boolean check_linear_animation_EM(int tile)
+{
+ switch (tile)
+ {
+ case Xsand_stonesand_1:
+ case Xsand_stonesand_quickout_1:
+ case Xsand_sandstone_1:
+ case Xsand_stonein_1:
+ case Xsand_stoneout_1:
+ case Xboom_1:
+ case Xdynamite_1:
+ case Ybug_w_n:
+ case Ybug_n_e:
+ case Ybug_e_s:
+ case Ybug_s_w:
+ case Ybug_e_n:
+ case Ybug_s_e:
+ case Ybug_w_s:
+ case Ybug_n_w:
+ case Ytank_w_n:
+ case Ytank_n_e:
+ case Ytank_e_s:
+ case Ytank_s_w:
+ case Ytank_e_n:
+ case Ytank_s_e:
+ case Ytank_w_s:
+ case Ytank_n_w:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
+ boolean has_crumbled_graphics,
+ int crumbled, int sync_frame)
+{
+ /* if element can be crumbled, but certain action graphics are just empty
+ space (like instantly snapping sand to empty space in 1 frame), do not
+ treat these empty space graphics as crumbled graphics in EMC engine */
+ if (crumbled == IMG_EMPTY_SPACE)
+ has_crumbled_graphics = FALSE;
+
+ if (has_crumbled_graphics)
+ {
+ struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
+ int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
+ g_crumbled->anim_delay,
+ g_crumbled->anim_mode,
+ g_crumbled->anim_start_frame,
+ sync_frame);
+
+ getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
+ &g_em->crumbled_src_x, &g_em->crumbled_src_y);
+
+ g_em->crumbled_border_size = graphic_info[crumbled].border_size;
+
+ g_em->has_crumbled_graphics = TRUE;
+ }
+ else
+ {
+ g_em->crumbled_bitmap = NULL;
+ g_em->crumbled_src_x = 0;
+ g_em->crumbled_src_y = 0;
+ g_em->crumbled_border_size = 0;
+
+ g_em->has_crumbled_graphics = FALSE;
+ }
+}
+
void ResetGfxAnimation_EM(int x, int y, int tile)
{
GfxFrame[x][y] = 0;
}
-void getGraphicSourceObjectExt_EM(int tile, int frame_em,
- Bitmap **src_bitmap, int *src_x, int *src_y)
+void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
+ int tile, int frame_em, int x, int y)
{
- int element = object_mapping[tile].element_rnd;
- int action = object_mapping[tile].action;
- int direction = object_mapping[tile].direction;
- boolean is_backside = object_mapping[tile].is_backside;
- boolean action_removing = (action == ACTION_DIGGING ||
- action == ACTION_SNAPPING ||
- action == ACTION_COLLECTING);
- int effective_element = (frame_em > 0 ? element :
- is_backside ? EL_EMPTY :
- action_removing ? EL_EMPTY :
- element);
+ int action = object_mapping[tile].action;
+#if 1
+ int direction = object_mapping[tile].direction;
+ int effective_element = get_effective_element_EM(tile, frame_em);
int graphic = (direction == MV_NONE ?
el_act2img(effective_element, action) :
el_act_dir2img(effective_element, action, direction));
struct GraphicInfo *g = &graphic_info[graphic];
int sync_frame;
+#endif
+ boolean action_removing = (action == ACTION_DIGGING ||
+ action == ACTION_SNAPPING ||
+ action == ACTION_COLLECTING);
+ boolean action_moving = (action == ACTION_FALLING ||
+ action == ACTION_MOVING ||
+ action == ACTION_PUSHING ||
+ action == ACTION_EATING ||
+ action == ACTION_FILLING ||
+ action == ACTION_EMPTYING);
+ boolean action_falling = (action == ACTION_FALLING ||
+ action == ACTION_FILLING ||
+ action == ACTION_EMPTYING);
+
+ /* special case: graphic uses "2nd movement tile" and has defined
+ 7 frames for movement animation (or less) => use default graphic
+ for last (8th) frame which ends the movement animation */
+ if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
+ {
+ action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
+ graphic = (direction == MV_NONE ?
+ el_act2img(effective_element, action) :
+ el_act_dir2img(effective_element, action, direction));
+
+ g = &graphic_info[graphic];
+ }
- if (graphic_info[graphic].anim_global_sync)
- sync_frame = FrameCounter;
- else
- sync_frame = 7 - frame_em;
+#if 0
+ if (tile == Xsand_stonesand_1 ||
+ tile == Xsand_stonesand_2 ||
+ tile == Xsand_stonesand_3 ||
+ tile == Xsand_stonesand_4)
+ printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
+#endif
- int frame = getAnimationFrame(g->anim_frames,
- g->anim_delay,
- g->anim_mode,
- g->anim_start_frame,
- sync_frame);
+#if 1
+ if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
+ {
+ GfxFrame[x][y] = 0;
- getGraphicSourceExt(graphic, frame, src_bitmap, src_x, src_y, FALSE);
-}
+ // printf("::: resetting... [%d]\n", tile);
+ }
+#else
+ if (action_removing || check_linear_animation_EM(tile))
+ {
+ GfxFrame[x][y] = frame_em;
-void getGraphicSourcePlayerExt_EM(int player_nr, int anim, int frame_em,
- Bitmap **src_bitmap, int *src_x, int *src_y)
-{
- int element = player_mapping[player_nr][anim].element_rnd;
- int action = player_mapping[player_nr][anim].action;
- int direction = player_mapping[player_nr][anim].direction;
- int graphic = (direction == MV_NONE ?
- el_act2img(element, action) :
- el_act_dir2img(element, action, direction));
- struct GraphicInfo *g = &graphic_info[graphic];
- int sync_frame;
+ // printf("::: resetting... [%d]\n", tile);
+ }
+#endif
+ else if (action_moving)
+ {
+ boolean is_backside = object_mapping[tile].is_backside;
- InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
+ if (is_backside)
+ {
+ int direction = object_mapping[tile].direction;
+ int move_dir = (action_falling ? MV_DOWN : direction);
- stored_player[player_nr].StepFrame = 7 - frame_em;
+ GfxFrame[x][y]++;
- sync_frame = stored_player[player_nr].Frame;
+#if 1
+ /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
+ if (g->double_movement && frame_em == 0)
+ {
+ GfxFrame[x][y] = 0;
+
+ // printf("::: resetting... [%d]\n", tile);
+ }
+#endif
+
+ if (move_dir == MV_LEFT)
+ GfxFrame[x - 1][y] = GfxFrame[x][y];
+ else if (move_dir == MV_RIGHT)
+ GfxFrame[x + 1][y] = GfxFrame[x][y];
+ else if (move_dir == MV_UP)
+ GfxFrame[x][y - 1] = GfxFrame[x][y];
+ else if (move_dir == MV_DOWN)
+ GfxFrame[x][y + 1] = GfxFrame[x][y];
+ }
+ }
+ else
+ {
+ GfxFrame[x][y]++;
+
+ /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
+ if (tile == Xsand_stonesand_quickout_1 ||
+ tile == Xsand_stonesand_quickout_2)
+ GfxFrame[x][y]++;
+ }
#if 0
- printf("::: %d: %d, %d [%d]\n",
- player_nr,
- stored_player[player_nr].Frame,
- stored_player[player_nr].StepFrame,
- FrameCounter);
+ if (tile == Xsand_stonesand_1 ||
+ tile == Xsand_stonesand_2 ||
+ tile == Xsand_stonesand_3 ||
+ tile == Xsand_stonesand_4)
+ printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
#endif
+#if 1
+ if (graphic_info[graphic].anim_global_sync)
+ sync_frame = FrameCounter;
+ else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
+ sync_frame = GfxFrame[x][y];
+ else
+ sync_frame = 0; /* playfield border (pseudo steel) */
+
+ SetRandomAnimationValue(x, y);
+
int frame = getAnimationFrame(g->anim_frames,
g->anim_delay,
g->anim_mode,
g->anim_start_frame,
sync_frame);
- getGraphicSourceExt(graphic, frame, src_bitmap, src_x, src_y, FALSE);
+ g_em->unique_identifier =
+ (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
+#endif
}
-void InitGraphicInfo_EM(void)
+void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
+ int tile, int frame_em, int x, int y)
{
+ int action = object_mapping[tile].action;
+ int direction = object_mapping[tile].direction;
+ boolean is_backside = object_mapping[tile].is_backside;
+ int effective_element = get_effective_element_EM(tile, frame_em);
+#if 1
+ int effective_action = action;
+#else
+ int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
+#endif
+ int graphic = (direction == MV_NONE ?
+ el_act2img(effective_element, effective_action) :
+ el_act_dir2img(effective_element, effective_action,
+ direction));
+ int crumbled = (direction == MV_NONE ?
+ el_act2crm(effective_element, effective_action) :
+ el_act_dir2crm(effective_element, effective_action,
+ direction));
+ int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
+ int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
+ boolean has_crumbled_graphics = (base_crumbled != base_graphic);
+ struct GraphicInfo *g = &graphic_info[graphic];
#if 0
- struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
- struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
+ struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
#endif
- int i, j, p;
-
-#if DEBUG_EM_GFX
- int num_em_gfx_errors = 0;
-
- if (graphic_info_em_object[0][0].bitmap == NULL)
- {
- /* EM graphics not yet initialized in em_open_all() */
+ int sync_frame;
- return;
+ /* special case: graphic uses "2nd movement tile" and has defined
+ 7 frames for movement animation (or less) => use default graphic
+ for last (8th) frame which ends the movement animation */
+ if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
+ {
+ effective_action = ACTION_DEFAULT;
+ graphic = (direction == MV_NONE ?
+ el_act2img(effective_element, effective_action) :
+ el_act_dir2img(effective_element, effective_action,
+ direction));
+ crumbled = (direction == MV_NONE ?
+ el_act2crm(effective_element, effective_action) :
+ el_act_dir2crm(effective_element, effective_action,
+ direction));
+
+ g = &graphic_info[graphic];
}
- printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
+#if 0
+ if (frame_em == 7)
+ return;
#endif
- /* always start with reliable default values */
- for (i = 0; i < TILE_MAX; i++)
- {
- object_mapping[i].element_rnd = EL_UNKNOWN;
- object_mapping[i].is_backside = FALSE;
- object_mapping[i].action = ACTION_DEFAULT;
- object_mapping[i].direction = MV_NONE;
- }
-
- /* always start with reliable default values */
- for (p = 0; p < MAX_PLAYERS; p++)
- {
- for (i = 0; i < SPR_MAX; i++)
- {
- player_mapping[p][i].element_rnd = EL_UNKNOWN;
- player_mapping[p][i].action = ACTION_DEFAULT;
- player_mapping[p][i].direction = MV_NONE;
- }
- }
- for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+#if 0
+ if (frame_em == 0) /* reset animation frame for certain elements */
{
- int e = em_object_mapping_list[i].element_em;
-
- object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
- object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
-
- if (em_object_mapping_list[i].action != -1)
- object_mapping[e].action = em_object_mapping_list[i].action;
-
- if (em_object_mapping_list[i].direction != -1)
- object_mapping[e].direction =
- MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
+ if (check_linear_animation_EM(tile))
+ GfxFrame[x][y] = 0;
}
+#endif
- for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
- {
- int a = em_player_mapping_list[i].action_em;
- int p = em_player_mapping_list[i].player_nr;
-
- player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
+ if (graphic_info[graphic].anim_global_sync)
+ sync_frame = FrameCounter;
+ else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
+ sync_frame = GfxFrame[x][y];
+ else
+ sync_frame = 0; /* playfield border (pseudo steel) */
- if (em_player_mapping_list[i].action != -1)
- player_mapping[p][a].action = em_player_mapping_list[i].action;
+ SetRandomAnimationValue(x, y);
- if (em_player_mapping_list[i].direction != -1)
- player_mapping[p][a].direction =
- MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
+#if 0
+ int i = tile;
+ int j = frame_em;
+ int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
+ i == Xdrip_stretchB ? 7 :
+ i == Ydrip_s2 ? j + 8 :
+ i == Ydrip_s2B ? j + 8 :
+ i == Xacid_1 ? 0 :
+ i == Xacid_2 ? 10 :
+ i == Xacid_3 ? 20 :
+ i == Xacid_4 ? 30 :
+ i == Xacid_5 ? 40 :
+ i == Xacid_6 ? 50 :
+ i == Xacid_7 ? 60 :
+ i == Xacid_8 ? 70 :
+ i == Xfake_acid_1 ? 0 :
+ i == Xfake_acid_2 ? 10 :
+ i == Xfake_acid_3 ? 20 :
+ i == Xfake_acid_4 ? 30 :
+ i == Xfake_acid_5 ? 40 :
+ i == Xfake_acid_6 ? 50 :
+ i == Xfake_acid_7 ? 60 :
+ i == Xfake_acid_8 ? 70 :
+ i == Xball_2 ? 7 :
+ i == Xball_2B ? j + 8 :
+ i == Yball_eat ? j + 1 :
+ i == Ykey_1_eat ? j + 1 :
+ i == Ykey_2_eat ? j + 1 :
+ i == Ykey_3_eat ? j + 1 :
+ i == Ykey_4_eat ? j + 1 :
+ i == Ykey_5_eat ? j + 1 :
+ i == Ykey_6_eat ? j + 1 :
+ i == Ykey_7_eat ? j + 1 :
+ i == Ykey_8_eat ? j + 1 :
+ i == Ylenses_eat ? j + 1 :
+ i == Ymagnify_eat ? j + 1 :
+ i == Ygrass_eat ? j + 1 :
+ i == Ydirt_eat ? j + 1 :
+ i == Xamoeba_1 ? 0 :
+ i == Xamoeba_2 ? 1 :
+ i == Xamoeba_3 ? 2 :
+ i == Xamoeba_4 ? 3 :
+ i == Xamoeba_5 ? 0 :
+ i == Xamoeba_6 ? 1 :
+ i == Xamoeba_7 ? 2 :
+ i == Xamoeba_8 ? 3 :
+ i == Xexit_2 ? j + 8 :
+ i == Xexit_3 ? j + 16 :
+ i == Xdynamite_1 ? 0 :
+ i == Xdynamite_2 ? 8 :
+ i == Xdynamite_3 ? 16 :
+ i == Xdynamite_4 ? 24 :
+ i == Xsand_stonein_1 ? j + 1 :
+ i == Xsand_stonein_2 ? j + 9 :
+ i == Xsand_stonein_3 ? j + 17 :
+ i == Xsand_stonein_4 ? j + 25 :
+ i == Xsand_stoneout_1 && j == 0 ? 0 :
+ i == Xsand_stoneout_1 && j == 1 ? 0 :
+ i == Xsand_stoneout_1 && j == 2 ? 1 :
+ i == Xsand_stoneout_1 && j == 3 ? 2 :
+ i == Xsand_stoneout_1 && j == 4 ? 2 :
+ i == Xsand_stoneout_1 && j == 5 ? 3 :
+ i == Xsand_stoneout_1 && j == 6 ? 4 :
+ i == Xsand_stoneout_1 && j == 7 ? 4 :
+ i == Xsand_stoneout_2 && j == 0 ? 5 :
+ i == Xsand_stoneout_2 && j == 1 ? 6 :
+ i == Xsand_stoneout_2 && j == 2 ? 7 :
+ i == Xsand_stoneout_2 && j == 3 ? 8 :
+ i == Xsand_stoneout_2 && j == 4 ? 9 :
+ i == Xsand_stoneout_2 && j == 5 ? 11 :
+ i == Xsand_stoneout_2 && j == 6 ? 13 :
+ i == Xsand_stoneout_2 && j == 7 ? 15 :
+ i == Xboom_bug && j == 1 ? 2 :
+ i == Xboom_bug && j == 2 ? 2 :
+ i == Xboom_bug && j == 3 ? 4 :
+ i == Xboom_bug && j == 4 ? 4 :
+ i == Xboom_bug && j == 5 ? 2 :
+ i == Xboom_bug && j == 6 ? 2 :
+ i == Xboom_bug && j == 7 ? 0 :
+ i == Xboom_bomb && j == 1 ? 2 :
+ i == Xboom_bomb && j == 2 ? 2 :
+ i == Xboom_bomb && j == 3 ? 4 :
+ i == Xboom_bomb && j == 4 ? 4 :
+ i == Xboom_bomb && j == 5 ? 2 :
+ i == Xboom_bomb && j == 6 ? 2 :
+ i == Xboom_bomb && j == 7 ? 0 :
+ i == Xboom_android && j == 7 ? 6 :
+ i == Xboom_1 && j == 1 ? 2 :
+ i == Xboom_1 && j == 2 ? 2 :
+ i == Xboom_1 && j == 3 ? 4 :
+ i == Xboom_1 && j == 4 ? 4 :
+ i == Xboom_1 && j == 5 ? 6 :
+ i == Xboom_1 && j == 6 ? 6 :
+ i == Xboom_1 && j == 7 ? 8 :
+ i == Xboom_2 && j == 0 ? 8 :
+ i == Xboom_2 && j == 1 ? 8 :
+ i == Xboom_2 && j == 2 ? 10 :
+ i == Xboom_2 && j == 3 ? 10 :
+ i == Xboom_2 && j == 4 ? 10 :
+ i == Xboom_2 && j == 5 ? 12 :
+ i == Xboom_2 && j == 6 ? 12 :
+ i == Xboom_2 && j == 7 ? 12 :
+#if 0
+ special_animation && j == 4 ? 3 :
+ effective_action != action ? 0 :
+#endif
+ j);
+#endif
+
+#if 0
+ int xxx_effective_action;
+ int xxx_has_action_graphics;
+
+ {
+ int element = object_mapping[i].element_rnd;
+ int action = object_mapping[i].action;
+ int direction = object_mapping[i].direction;
+ boolean is_backside = object_mapping[i].is_backside;
+#if 0
+ boolean action_removing = (action == ACTION_DIGGING ||
+ action == ACTION_SNAPPING ||
+ action == ACTION_COLLECTING);
+#endif
+ boolean action_exploding = ((action == ACTION_EXPLODING ||
+ action == ACTION_SMASHED_BY_ROCK ||
+ action == ACTION_SMASHED_BY_SPRING) &&
+ element != EL_DIAMOND);
+ boolean action_active = (action == ACTION_ACTIVE);
+ boolean action_other = (action == ACTION_OTHER);
+
+ {
+#if 1
+ int effective_element = get_effective_element_EM(i, j);
+#else
+ int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
+ j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
+ j < 7 ? element :
+ i == Xdrip_stretch ? element :
+ i == Xdrip_stretchB ? element :
+ i == Ydrip_s1 ? element :
+ i == Ydrip_s1B ? element :
+ i == Xball_1B ? element :
+ i == Xball_2 ? element :
+ i == Xball_2B ? element :
+ i == Yball_eat ? element :
+ i == Ykey_1_eat ? element :
+ i == Ykey_2_eat ? element :
+ i == Ykey_3_eat ? element :
+ i == Ykey_4_eat ? element :
+ i == Ykey_5_eat ? element :
+ i == Ykey_6_eat ? element :
+ i == Ykey_7_eat ? element :
+ i == Ykey_8_eat ? element :
+ i == Ylenses_eat ? element :
+ i == Ymagnify_eat ? element :
+ i == Ygrass_eat ? element :
+ i == Ydirt_eat ? element :
+ i == Yemerald_stone ? EL_EMERALD :
+ i == Ydiamond_stone ? EL_ROCK :
+ i == Xsand_stonein_1 ? element :
+ i == Xsand_stonein_2 ? element :
+ i == Xsand_stonein_3 ? element :
+ i == Xsand_stonein_4 ? element :
+ is_backside ? EL_EMPTY :
+ action_removing ? EL_EMPTY :
+ element);
+#endif
+ int effective_action = (j < 7 ? action :
+ i == Xdrip_stretch ? action :
+ i == Xdrip_stretchB ? action :
+ i == Ydrip_s1 ? action :
+ i == Ydrip_s1B ? action :
+ i == Xball_1B ? action :
+ i == Xball_2 ? action :
+ i == Xball_2B ? action :
+ i == Yball_eat ? action :
+ i == Ykey_1_eat ? action :
+ i == Ykey_2_eat ? action :
+ i == Ykey_3_eat ? action :
+ i == Ykey_4_eat ? action :
+ i == Ykey_5_eat ? action :
+ i == Ykey_6_eat ? action :
+ i == Ykey_7_eat ? action :
+ i == Ykey_8_eat ? action :
+ i == Ylenses_eat ? action :
+ i == Ymagnify_eat ? action :
+ i == Ygrass_eat ? action :
+ i == Ydirt_eat ? action :
+ i == Xsand_stonein_1 ? action :
+ i == Xsand_stonein_2 ? action :
+ i == Xsand_stonein_3 ? action :
+ i == Xsand_stonein_4 ? action :
+ i == Xsand_stoneout_1 ? action :
+ i == Xsand_stoneout_2 ? action :
+ i == Xboom_android ? ACTION_EXPLODING :
+ action_exploding ? ACTION_EXPLODING :
+ action_active ? action :
+ action_other ? action :
+ ACTION_DEFAULT);
+ int graphic = (el_act_dir2img(effective_element, effective_action,
+ direction));
+ int crumbled = (el_act_dir2crm(effective_element, effective_action,
+ direction));
+ int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
+ int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
+ boolean has_action_graphics = (graphic != base_graphic);
+ boolean has_crumbled_graphics = (base_crumbled != base_graphic);
+ struct GraphicInfo *g = &graphic_info[graphic];
+#if 0
+ struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
+#endif
+ struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
+ boolean special_animation = (action != ACTION_DEFAULT &&
+ g->anim_frames == 3 &&
+ g->anim_delay == 2 &&
+ g->anim_mode & ANIM_LINEAR);
+ xxx_sync_frame = (i == Xdrip_stretch ? 7 :
+ i == Xdrip_stretchB ? 7 :
+ i == Ydrip_s2 ? j + 8 :
+ i == Ydrip_s2B ? j + 8 :
+ i == Xacid_1 ? 0 :
+ i == Xacid_2 ? 10 :
+ i == Xacid_3 ? 20 :
+ i == Xacid_4 ? 30 :
+ i == Xacid_5 ? 40 :
+ i == Xacid_6 ? 50 :
+ i == Xacid_7 ? 60 :
+ i == Xacid_8 ? 70 :
+ i == Xfake_acid_1 ? 0 :
+ i == Xfake_acid_2 ? 10 :
+ i == Xfake_acid_3 ? 20 :
+ i == Xfake_acid_4 ? 30 :
+ i == Xfake_acid_5 ? 40 :
+ i == Xfake_acid_6 ? 50 :
+ i == Xfake_acid_7 ? 60 :
+ i == Xfake_acid_8 ? 70 :
+ i == Xball_2 ? 7 :
+ i == Xball_2B ? j + 8 :
+ i == Yball_eat ? j + 1 :
+ i == Ykey_1_eat ? j + 1 :
+ i == Ykey_2_eat ? j + 1 :
+ i == Ykey_3_eat ? j + 1 :
+ i == Ykey_4_eat ? j + 1 :
+ i == Ykey_5_eat ? j + 1 :
+ i == Ykey_6_eat ? j + 1 :
+ i == Ykey_7_eat ? j + 1 :
+ i == Ykey_8_eat ? j + 1 :
+ i == Ylenses_eat ? j + 1 :
+ i == Ymagnify_eat ? j + 1 :
+ i == Ygrass_eat ? j + 1 :
+ i == Ydirt_eat ? j + 1 :
+ i == Xamoeba_1 ? 0 :
+ i == Xamoeba_2 ? 1 :
+ i == Xamoeba_3 ? 2 :
+ i == Xamoeba_4 ? 3 :
+ i == Xamoeba_5 ? 0 :
+ i == Xamoeba_6 ? 1 :
+ i == Xamoeba_7 ? 2 :
+ i == Xamoeba_8 ? 3 :
+ i == Xexit_2 ? j + 8 :
+ i == Xexit_3 ? j + 16 :
+ i == Xdynamite_1 ? 0 :
+ i == Xdynamite_2 ? 8 :
+ i == Xdynamite_3 ? 16 :
+ i == Xdynamite_4 ? 24 :
+ i == Xsand_stonein_1 ? j + 1 :
+ i == Xsand_stonein_2 ? j + 9 :
+ i == Xsand_stonein_3 ? j + 17 :
+ i == Xsand_stonein_4 ? j + 25 :
+ i == Xsand_stoneout_1 && j == 0 ? 0 :
+ i == Xsand_stoneout_1 && j == 1 ? 0 :
+ i == Xsand_stoneout_1 && j == 2 ? 1 :
+ i == Xsand_stoneout_1 && j == 3 ? 2 :
+ i == Xsand_stoneout_1 && j == 4 ? 2 :
+ i == Xsand_stoneout_1 && j == 5 ? 3 :
+ i == Xsand_stoneout_1 && j == 6 ? 4 :
+ i == Xsand_stoneout_1 && j == 7 ? 4 :
+ i == Xsand_stoneout_2 && j == 0 ? 5 :
+ i == Xsand_stoneout_2 && j == 1 ? 6 :
+ i == Xsand_stoneout_2 && j == 2 ? 7 :
+ i == Xsand_stoneout_2 && j == 3 ? 8 :
+ i == Xsand_stoneout_2 && j == 4 ? 9 :
+ i == Xsand_stoneout_2 && j == 5 ? 11 :
+ i == Xsand_stoneout_2 && j == 6 ? 13 :
+ i == Xsand_stoneout_2 && j == 7 ? 15 :
+ i == Xboom_bug && j == 1 ? 2 :
+ i == Xboom_bug && j == 2 ? 2 :
+ i == Xboom_bug && j == 3 ? 4 :
+ i == Xboom_bug && j == 4 ? 4 :
+ i == Xboom_bug && j == 5 ? 2 :
+ i == Xboom_bug && j == 6 ? 2 :
+ i == Xboom_bug && j == 7 ? 0 :
+ i == Xboom_bomb && j == 1 ? 2 :
+ i == Xboom_bomb && j == 2 ? 2 :
+ i == Xboom_bomb && j == 3 ? 4 :
+ i == Xboom_bomb && j == 4 ? 4 :
+ i == Xboom_bomb && j == 5 ? 2 :
+ i == Xboom_bomb && j == 6 ? 2 :
+ i == Xboom_bomb && j == 7 ? 0 :
+ i == Xboom_android && j == 7 ? 6 :
+ i == Xboom_1 && j == 1 ? 2 :
+ i == Xboom_1 && j == 2 ? 2 :
+ i == Xboom_1 && j == 3 ? 4 :
+ i == Xboom_1 && j == 4 ? 4 :
+ i == Xboom_1 && j == 5 ? 6 :
+ i == Xboom_1 && j == 6 ? 6 :
+ i == Xboom_1 && j == 7 ? 8 :
+ i == Xboom_2 && j == 0 ? 8 :
+ i == Xboom_2 && j == 1 ? 8 :
+ i == Xboom_2 && j == 2 ? 10 :
+ i == Xboom_2 && j == 3 ? 10 :
+ i == Xboom_2 && j == 4 ? 10 :
+ i == Xboom_2 && j == 5 ? 12 :
+ i == Xboom_2 && j == 6 ? 12 :
+ i == Xboom_2 && j == 7 ? 12 :
+ special_animation && j == 4 ? 3 :
+ effective_action != action ? 0 :
+ j);
+
+ xxx_effective_action = effective_action;
+ xxx_has_action_graphics = has_action_graphics;
+ }
+ }
+#endif
+
+ int frame = getAnimationFrame(g->anim_frames,
+ g->anim_delay,
+ g->anim_mode,
+ g->anim_start_frame,
+ sync_frame);
+
+
+#if 0
+ return;
+#endif
+
+#if 0
+ if (frame_em == 7)
+ return;
+#endif
+
+#if 0
+ int old_src_x = g_em->src_x;
+ int old_src_y = g_em->src_y;
+#endif
+
+#if 1
+ getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
+ g->double_movement && is_backside);
+#else
+ getGraphicSourceExt(graphic, frame, &g_em->bitmap,
+ &g_em->src_x, &g_em->src_y, FALSE);
+#endif
+
+
+#if 0
+ return;
+#endif
+
+#if 0
+ if (frame_em == 7)
+ {
+ if (graphic == IMG_BUG_MOVING_RIGHT)
+ printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
+ g->double_movement, is_backside,
+ old_src_x, old_src_y, g_em->src_x, g_em->src_y);
+
+ return;
+ }
+#endif
+
+
+#if 0
+ g_em->src_offset_x = 0;
+ g_em->src_offset_y = 0;
+ g_em->dst_offset_x = 0;
+ g_em->dst_offset_y = 0;
+ g_em->width = TILEX;
+ g_em->height = TILEY;
+
+ g_em->preserve_background = FALSE;
+#endif
+
+ /* (updating the "crumbled" graphic definitions is probably not really needed,
+ as animations for crumbled graphics can't be longer than one EMC cycle) */
+#if 1
+ set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
+ sync_frame);
+
+#else
+
+ g_em->crumbled_bitmap = NULL;
+ g_em->crumbled_src_x = 0;
+ g_em->crumbled_src_y = 0;
+
+ g_em->has_crumbled_graphics = FALSE;
+
+ if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
+ {
+ int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
+ g_crumbled->anim_delay,
+ g_crumbled->anim_mode,
+ g_crumbled->anim_start_frame,
+ sync_frame);
+
+ getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
+ &g_em->crumbled_src_x, &g_em->crumbled_src_y);
+
+ g_em->has_crumbled_graphics = TRUE;
+ }
+#endif
+
+#if 0
+ {
+ int effective_action = xxx_effective_action;
+ int has_action_graphics = xxx_has_action_graphics;
+
+ if ((!g->double_movement && (effective_action == ACTION_FALLING ||
+ effective_action == ACTION_MOVING ||
+ effective_action == ACTION_PUSHING ||
+ effective_action == ACTION_EATING)) ||
+ (!has_action_graphics && (effective_action == ACTION_FILLING ||
+ effective_action == ACTION_EMPTYING)))
+ {
+ int move_dir =
+ (effective_action == ACTION_FALLING ||
+ effective_action == ACTION_FILLING ||
+ effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
+ int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
+ int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
+ int num_steps = (i == Ydrip_s1 ? 16 :
+ i == Ydrip_s1B ? 16 :
+ i == Ydrip_s2 ? 16 :
+ i == Ydrip_s2B ? 16 :
+ i == Xsand_stonein_1 ? 32 :
+ i == Xsand_stonein_2 ? 32 :
+ i == Xsand_stonein_3 ? 32 :
+ i == Xsand_stonein_4 ? 32 :
+ i == Xsand_stoneout_1 ? 16 :
+ i == Xsand_stoneout_2 ? 16 : 8);
+ int cx = ABS(dx) * (TILEX / num_steps);
+ int cy = ABS(dy) * (TILEY / num_steps);
+ int step_frame = (i == Ydrip_s2 ? j + 8 :
+ i == Ydrip_s2B ? j + 8 :
+ i == Xsand_stonein_2 ? j + 8 :
+ i == Xsand_stonein_3 ? j + 16 :
+ i == Xsand_stonein_4 ? j + 24 :
+ i == Xsand_stoneout_2 ? j + 8 : j) + 1;
+ int step = (is_backside ? step_frame : num_steps - step_frame);
+
+ if (is_backside) /* tile where movement starts */
+ {
+ if (dx < 0 || dy < 0)
+ {
+ g_em->src_offset_x = cx * step;
+ g_em->src_offset_y = cy * step;
+ }
+ else
+ {
+ g_em->dst_offset_x = cx * step;
+ g_em->dst_offset_y = cy * step;
+ }
+ }
+ else /* tile where movement ends */
+ {
+ if (dx < 0 || dy < 0)
+ {
+ g_em->dst_offset_x = cx * step;
+ g_em->dst_offset_y = cy * step;
+ }
+ else
+ {
+ g_em->src_offset_x = cx * step;
+ g_em->src_offset_y = cy * step;
+ }
+ }
+
+ g_em->width = TILEX - cx * step;
+ g_em->height = TILEY - cy * step;
+ }
+
+ /* create unique graphic identifier to decide if tile must be redrawn */
+ /* bit 31 - 16 (16 bit): EM style graphic
+ bit 15 - 12 ( 4 bit): EM style frame
+ bit 11 - 6 ( 6 bit): graphic width
+ bit 5 - 0 ( 6 bit): graphic height */
+ g_em->unique_identifier =
+ (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
+ }
+#endif
+
+}
+
+void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
+ int player_nr, int anim, int frame_em)
+{
+ int element = player_mapping[player_nr][anim].element_rnd;
+ int action = player_mapping[player_nr][anim].action;
+ int direction = player_mapping[player_nr][anim].direction;
+ int graphic = (direction == MV_NONE ?
+ el_act2img(element, action) :
+ el_act_dir2img(element, action, direction));
+ struct GraphicInfo *g = &graphic_info[graphic];
+ int sync_frame;
+
+ InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
+
+ stored_player[player_nr].StepFrame = frame_em;
+
+ sync_frame = stored_player[player_nr].Frame;
+
+ int frame = getAnimationFrame(g->anim_frames,
+ g->anim_delay,
+ g->anim_mode,
+ g->anim_start_frame,
+ sync_frame);
+
+ getGraphicSourceExt(graphic, frame, &g_em->bitmap,
+ &g_em->src_x, &g_em->src_y, FALSE);
+
+#if 0
+ printf("::: %d: %d, %d [%d]\n",
+ player_nr,
+ stored_player[player_nr].Frame,
+ stored_player[player_nr].StepFrame,
+ FrameCounter);
+#endif
+}
+
+void InitGraphicInfo_EM(void)
+{
+#if 0
+ struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
+ struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
+#endif
+ int i, j, p;
+
+#if DEBUG_EM_GFX
+ int num_em_gfx_errors = 0;
+
+ if (graphic_info_em_object[0][0].bitmap == NULL)
+ {
+ /* EM graphics not yet initialized in em_open_all() */
+
+ return;
+ }
+
+ printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
+#endif
+
+ /* always start with reliable default values */
+ for (i = 0; i < TILE_MAX; i++)
+ {
+ object_mapping[i].element_rnd = EL_UNKNOWN;
+ object_mapping[i].is_backside = FALSE;
+ object_mapping[i].action = ACTION_DEFAULT;
+ object_mapping[i].direction = MV_NONE;
+ }
+
+ /* always start with reliable default values */
+ for (p = 0; p < MAX_PLAYERS; p++)
+ {
+ for (i = 0; i < SPR_MAX; i++)
+ {
+ player_mapping[p][i].element_rnd = EL_UNKNOWN;
+ player_mapping[p][i].action = ACTION_DEFAULT;
+ player_mapping[p][i].direction = MV_NONE;
+ }
+ }
+
+ for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+ {
+ int e = em_object_mapping_list[i].element_em;
+
+ object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
+ object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
+
+ if (em_object_mapping_list[i].action != -1)
+ object_mapping[e].action = em_object_mapping_list[i].action;
+
+ if (em_object_mapping_list[i].direction != -1)
+ object_mapping[e].direction =
+ MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
+ }
+
+ for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
+ {
+ int a = em_player_mapping_list[i].action_em;
+ int p = em_player_mapping_list[i].player_nr;
+
+ player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
+
+ if (em_player_mapping_list[i].action != -1)
+ player_mapping[p][a].action = em_player_mapping_list[i].action;
+
+ if (em_player_mapping_list[i].direction != -1)
+ player_mapping[p][a].direction =
+ MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
}
for (i = 0; i < TILE_MAX; i++)
int action = object_mapping[i].action;
int direction = object_mapping[i].direction;
boolean is_backside = object_mapping[i].is_backside;
+#if 0
boolean action_removing = (action == ACTION_DIGGING ||
action == ACTION_SNAPPING ||
action == ACTION_COLLECTING);
+#endif
boolean action_exploding = ((action == ACTION_EXPLODING ||
action == ACTION_SMASHED_BY_ROCK ||
action == ACTION_SMASHED_BY_SPRING) &&
for (j = 0; j < 8; j++)
{
+#if 1
+ int effective_element = get_effective_element_EM(i, j);
+#else
int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
j < 7 ? element :
is_backside ? EL_EMPTY :
action_removing ? EL_EMPTY :
element);
+#endif
int effective_action = (j < 7 ? action :
i == Xdrip_stretch ? action :
i == Xdrip_stretchB ? action :
boolean has_action_graphics = (graphic != base_graphic);
boolean has_crumbled_graphics = (base_crumbled != base_graphic);
struct GraphicInfo *g = &graphic_info[graphic];
+#if 0
+ struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
+#endif
struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
Bitmap *src_bitmap;
int src_x, src_y;
g_em->width = TILEX;
g_em->height = TILEY;
+ g_em->preserve_background = FALSE;
+
+#if 1
+ set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
+ sync_frame);
+
+#else
+
g_em->crumbled_bitmap = NULL;
g_em->crumbled_src_x = 0;
g_em->crumbled_src_y = 0;
g_em->crumbled_border_size = 0;
g_em->has_crumbled_graphics = FALSE;
- g_em->preserve_background = FALSE;
#if 0
if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
#endif
/* if element can be crumbled, but certain action graphics are just empty
- space (like snapping sand with the original R'n'D graphics), do not
+ space (like instantly snapping sand to empty space in 1 frame), do not
treat these empty space graphics as crumbled graphics in EMC engine */
if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
{
- getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
+ int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
+ g_crumbled->anim_delay,
+ g_crumbled->anim_mode,
+ g_crumbled->anim_start_frame,
+ sync_frame);
+
+ getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
g_em->has_crumbled_graphics = TRUE;
g_em->crumbled_bitmap = src_bitmap;
g_em->crumbled_src_x = src_x;
g_em->crumbled_src_y = src_y;
g_em->crumbled_border_size = graphic_info[crumbled].border_size;
+
+
+#if 0
+ if (g_em == &graphic_info_em_object[207][0])
+ printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
+ graphic_info_em_object[207][0].crumbled_src_x,
+ graphic_info_em_object[207][0].crumbled_src_y,
+
+ crumbled, frame, src_x, src_y,
+
+ g->anim_frames,
+ g->anim_delay,
+ g->anim_mode,
+ g->anim_start_frame,
+ sync_frame,
+ gfx.anim_random_frame,
+ frame);
+#endif
+
+#if 0
+ printf("::: EMC tile %d is crumbled\n", i);
+#endif
}
+#endif
#if 0
if (element == EL_ROCK &&
#endif
}
-void PlayMenuSound()
+void PlayMenuSoundExt(int sound)
{
- int sound = menu.sound[game_status];
-
if (sound == SND_UNDEFINED)
return;
PlaySound(sound);
}
+void PlayMenuSound()
+{
+ PlayMenuSoundExt(menu.sound[game_status]);
+}
+
void PlayMenuSoundStereo(int sound, int stereo_position)
{
if (sound == SND_UNDEFINED)
PlaySoundStereo(sound, stereo_position);
}
-void PlayMenuSoundIfLoop()
+void PlayMenuSoundIfLoopExt(int sound)
{
- int sound = menu.sound[game_status];
-
if (sound == SND_UNDEFINED)
return;
PlaySoundLoop(sound);
}
-void PlayMenuMusic()
+void PlayMenuSoundIfLoop()
{
- int music = menu.music[game_status];
+ PlayMenuSoundIfLoopExt(menu.sound[game_status]);
+}
+void PlayMenuMusicExt(int music)
+{
if (music == MUS_UNDEFINED)
return;
PlayMusic(music);
}
+void PlayMenuMusic()
+{
+ PlayMenuMusicExt(menu.music[game_status]);
+}
+
void PlaySoundActivating()
{
#if 0