void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
{
- if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
+ if (game_status == GAME_MODE_PLAYING &&
+ level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ {
+ BlitScreenToBitmap_EM(backbuffer);
+ }
+ else if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
{
if (force_redraw)
{
}
#endif
- getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+ if (width > 0 && height > 0)
+ {
+ getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
- src_x += cx;
- src_y += cy;
+ src_x += cx;
+ src_y += cy;
- dst_x = FX + x * TILEX + dx;
- dst_y = FY + y * TILEY + dy;
+ dst_x = FX + x * TILEX + dx;
+ dst_y = FY + y * TILEY + dy;
- if (mask_mode == USE_MASKING)
- {
- SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
- dst_x - src_x, dst_y - src_y);
- BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
- dst_x, dst_y);
- }
- else
- BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
- dst_x, dst_y);
+ if (mask_mode == USE_MASKING)
+ {
+ SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+ dst_x - src_x, dst_y - src_y);
+ BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
+ dst_x, dst_y);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
+ dst_x, dst_y);
- MarkTileDirty(x, y);
+ MarkTileDirty(x, y);
+ }
}
inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
MarkTileDirty(x2, y2);
}
+
+#if 0
+ printf("::: DONE DrawGraphicShiftedDouble");
+ BackToFront();
+ Delay(1000);
+#endif
}
static void DrawGraphicShifted(int x, int y, int dx, int dy,
if (player->is_pushing && player_is_moving)
#endif
{
+#if 1
+ int px = SCREENX(jx), py = SCREENY(jy);
+ int pxx = (TILEX - ABS(sxx)) * dx;
+ int pyy = (TILEY - ABS(syy)) * dy;
+#else
int px = SCREENX(next_jx), py = SCREENY(next_jy);
+ int pxx = sxx;
+ int pyy = syy;
+#endif
+
+#if 1
+ int graphic;
+ int frame;
+
+ if (!IS_MOVING(jx, jy)) /* push movement already finished */
+ element = Feld[next_jx][next_jy];
+
+ graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+ frame = getGraphicAnimationFrame(graphic, player->StepFrame);
+ /* draw background element under pushed element (like the Sokoban field) */
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,
+ /* masked drawing is needed for EMC style (double) movement graphics */
+ DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
+
+#else
+ if (Back[next_jx][next_jy])
+ DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+
+ if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
+ DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
NO_CUTTING);
else
{
int frame = getGraphicAnimationFrame(graphic, player->Frame);
#endif
- DrawGraphicShifted(px, py, sxx, syy, graphic, frame,
+#if 1
+ /* masked drawing is needed for EMC style (double) movement graphics */
+ DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
+ NO_CUTTING);
+#else
+ DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
NO_CUTTING, NO_MASKING);
+#endif
}
+#endif
}
/* ----------------------------------------------------------------------- */
}
}
+#if 1
+ if (game_status == GAME_MODE_PLAYING &&
+ level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ BlitScreenToBitmap_EM(backbuffer);
+#endif
+
#if 1
/* disable deactivated drawing when quick-loading level tape recording */
if (tape.playing && tape.deactivate_display)
#if 1
-static struct
+static struct Mapping_EM_to_RND_object
{
int element_em;
boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
int action;
int direction;
}
-mapping_EM_to_RND_list[] =
+em_object_mapping_list[] =
{
{
Xblank, TRUE, FALSE,
EL_EMPTY, -1, -1
},
{
- Yacid_splash_eB, FALSE, TRUE,
+ Yacid_splash_eB, FALSE, FALSE,
EL_ACID_SPLASH_RIGHT, -1, -1
},
{
- Yacid_splash_wB, FALSE, TRUE,
+ Yacid_splash_wB, FALSE, FALSE,
EL_ACID_SPLASH_LEFT, -1, -1
},
EL_EMC_GRASS, -1, -1
},
{
- Ygrass_nB, FALSE, TRUE,
+ Ygrass_nB, FALSE, FALSE,
EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
},
{
- Ygrass_eB, FALSE, TRUE,
+ Ygrass_eB, FALSE, FALSE,
EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
},
{
- Ygrass_sB, FALSE, TRUE,
+ Ygrass_sB, FALSE, FALSE,
EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
},
{
- Ygrass_wB, FALSE, TRUE,
+ Ygrass_wB, FALSE, FALSE,
EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
},
{
EL_SAND, -1, -1
},
{
- Ydirt_nB, FALSE, TRUE,
+ Ydirt_nB, FALSE, FALSE,
EL_SAND, ACTION_DIGGING, MV_BIT_UP
},
{
- Ydirt_eB, FALSE, TRUE,
+ Ydirt_eB, FALSE, FALSE,
EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
},
{
- Ydirt_sB, FALSE, TRUE,
+ Ydirt_sB, FALSE, FALSE,
EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
},
{
- Ydirt_wB, FALSE, TRUE,
+ Ydirt_wB, FALSE, FALSE,
EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
},
{
EL_EMC_MAGIC_BALL, -1, -1
},
{
- Xball_1B, FALSE, TRUE,
+ Xball_1B, FALSE, FALSE,
EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
},
{
EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
},
{
- Xball_2B, FALSE, TRUE,
+ Xball_2B, FALSE, FALSE,
EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
},
{
Yball_eat, FALSE, FALSE,
EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
},
+ {
+ Ykey_1_eat, FALSE, FALSE,
+ EL_EM_KEY_1, ACTION_COLLECTING, -1
+ },
+ {
+ Ykey_2_eat, FALSE, FALSE,
+ EL_EM_KEY_2, ACTION_COLLECTING, -1
+ },
+ {
+ Ykey_3_eat, FALSE, FALSE,
+ EL_EM_KEY_3, ACTION_COLLECTING, -1
+ },
+ {
+ Ykey_4_eat, FALSE, FALSE,
+ EL_EM_KEY_4, ACTION_COLLECTING, -1
+ },
+ {
+ Ykey_5_eat, FALSE, FALSE,
+ EL_EM_KEY_5, ACTION_COLLECTING, -1
+ },
+ {
+ Ykey_6_eat, FALSE, FALSE,
+ EL_EM_KEY_6, ACTION_COLLECTING, -1
+ },
+ {
+ Ykey_7_eat, FALSE, FALSE,
+ EL_EM_KEY_7, ACTION_COLLECTING, -1
+ },
+ {
+ Ykey_8_eat, FALSE, FALSE,
+ EL_EM_KEY_8, ACTION_COLLECTING, -1
+ },
+ {
+ Ylenses_eat, FALSE, FALSE,
+ EL_EMC_LENSES, ACTION_COLLECTING, -1
+ },
+ {
+ Ymagnify_eat, FALSE, FALSE,
+ EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
+ },
+ {
+ Ygrass_eat, FALSE, FALSE,
+ EL_EMC_GRASS, ACTION_SNAPPING, -1
+ },
+ {
+ Ydirt_eat, FALSE, FALSE,
+ EL_SAND, ACTION_SNAPPING, -1
+ },
{
Xgrow_ns, TRUE, FALSE,
EL_EXPANDABLE_WALL_VERTICAL, -1, -1
EL_AMOEBA_DRY, ACTION_OTHER, -1
},
{
- Xamoeba_5, FALSE, FALSE,
+ Xamoeba_5, TRUE, FALSE,
EL_AMOEBA_WET, ACTION_OTHER, -1
},
{
Xfake_door_8, TRUE, FALSE,
EL_EM_GATE_8_GRAY, -1, -1
},
+ {
+ Xfake_acid_1, TRUE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_2, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_3, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_4, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_5, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_6, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_7, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_8, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
{
Xsteel_1, TRUE, FALSE,
EL_STEELWALL, -1, -1
}
};
+static struct Mapping_EM_to_RND_player
+{
+ int action_em;
+ int player_nr;
+
+ int element_rnd;
+ int action;
+ int direction;
+}
+em_player_mapping_list[] =
+{
+ {
+ SPR_walk + 0, 0,
+ EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
+ },
+ {
+ SPR_walk + 1, 0,
+ EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
+ },
+ {
+ SPR_walk + 2, 0,
+ EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
+ },
+ {
+ SPR_walk + 3, 0,
+ EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
+ },
+ {
+ SPR_push + 0, 0,
+ EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
+ },
+ {
+ SPR_push + 1, 0,
+ EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
+ },
+ {
+ SPR_push + 2, 0,
+ EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
+ },
+ {
+ SPR_push + 3, 0,
+ EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
+ },
+ {
+ SPR_spray + 0, 0,
+ EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
+ },
+ {
+ SPR_spray + 1, 0,
+ EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
+ },
+ {
+ SPR_spray + 2, 0,
+ EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
+ },
+ {
+ SPR_spray + 3, 0,
+ EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
+ },
+ {
+ SPR_walk + 0, 1,
+ EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
+ },
+ {
+ SPR_walk + 1, 1,
+ EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
+ },
+ {
+ SPR_walk + 2, 1,
+ EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
+ },
+ {
+ SPR_walk + 3, 1,
+ EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
+ },
+ {
+ SPR_push + 0, 1,
+ EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
+ },
+ {
+ SPR_push + 1, 1,
+ EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
+ },
+ {
+ SPR_push + 2, 1,
+ EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
+ },
+ {
+ SPR_push + 3, 1,
+ EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
+ },
+ {
+ SPR_spray + 0, 1,
+ EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
+ },
+ {
+ SPR_spray + 1, 1,
+ EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
+ },
+ {
+ SPR_spray + 2, 1,
+ EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
+ },
+ {
+ SPR_spray + 3, 1,
+ EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
+ },
+ {
+ SPR_still, 0,
+ EL_PLAYER_1, ACTION_DEFAULT, -1,
+ },
+ {
+ SPR_still, 1,
+ EL_PLAYER_2, ACTION_DEFAULT, -1,
+ },
+
+ {
+ -1, -1,
+ -1, -1, -1
+ }
+};
+
int map_element_RND_to_EM(int element_rnd)
{
static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
for (i = 0; i < NUM_FILE_ELEMENTS; i++)
mapping_RND_to_EM[i] = Xalpha_quest;
- for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
- if (mapping_EM_to_RND_list[i].is_rnd_to_em_mapping)
- mapping_RND_to_EM[mapping_EM_to_RND_list[i].element_rnd] =
- mapping_EM_to_RND_list[i].element_em;
+ for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+ if (em_object_mapping_list[i].is_rnd_to_em_mapping)
+ mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
+ em_object_mapping_list[i].element_em;
mapping_initialized = TRUE;
}
for (i = 0; i < TILE_MAX; i++)
mapping_EM_to_RND[i] = EL_UNKNOWN;
- for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
- mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
- mapping_EM_to_RND_list[i].element_rnd;
+ for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+ mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
+ em_object_mapping_list[i].element_rnd;
mapping_initialized = TRUE;
}
int element_em;
int element_rnd;
}
- mapping_EM_to_RND_list[] =
+ em_object_mapping_list[] =
{
{ Xblank, EL_EMPTY },
{ Yacid_splash_eB, EL_EMPTY },
for (i = 0; i < TILE_MAX; i++)
mapping_EM_to_RND[i] = EL_UNKNOWN;
- for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
- mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
- mapping_EM_to_RND_list[i].element_rnd;
+ for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+ mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
+ em_object_mapping_list[i].element_rnd;
mapping_initialized = TRUE;
}
}
}
+#if 0
+int el_act_dir2img(int element, int action, int direction)
+{
+ element = GFX_ELEMENT(element);
+
+ if (direction == MV_NO_MOVING)
+ return element_info[element].graphic[action];
+
+ direction = MV_DIR_BIT(direction);
+
+ return element_info[element].direction_graphic[action][direction];
+}
+#else
int el_act_dir2img(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
+ /* direction_graphic[][] == graphic[] for undefined direction graphics */
return element_info[element].direction_graphic[action][direction];
}
+#endif
+
+#if 0
+static int el_act_dir2crm(int element, int action, int direction)
+{
+ element = GFX_ELEMENT(element);
+ if (direction == MV_NO_MOVING)
+ return element_info[element].crumbled[action];
+
+ direction = MV_DIR_BIT(direction);
+
+ return element_info[element].direction_crumbled[action][direction];
+}
+#else
static int el_act_dir2crm(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
direction = MV_DIR_BIT(direction); /* default: MV_NO_MOVING => MV_DOWN */
+ /* direction_graphic[][] == graphic[] for undefined direction graphics */
return element_info[element].direction_crumbled[action][direction];
}
+#endif
int el_act2img(int element, int action)
{
int getGameFrameDelay_EM(int native_em_game_frame_delay)
{
- return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
- GameFrameDelay);
+ int game_frame_delay_value;
+
+ game_frame_delay_value =
+ (tape.playing && tape.fast_forward ? FfwdFrameDelay :
+ GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
+ GameFrameDelay);
+
+ if (tape.playing && tape.warp_forward && !tape.pausing)
+ game_frame_delay_value = 0;
+
+ return game_frame_delay_value;
}
unsigned int InitRND(long seed)
return InitEngineRND(seed);
}
+#define DEBUG_EM_GFX 0
+
void InitGraphicInfo_EM(void)
{
- int mapping_EM_to_RND_element[TILE_MAX];
- int mapping_EM_to_RND_action[TILE_MAX];
- int mapping_EM_to_RND_direction[TILE_MAX];
- boolean mapping_EM_to_RND_backside[TILE_MAX];
- int i, j;
+ struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
+ struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
+ int i, j, p;
+
+#if DEBUG_EM_GFX
+ if (graphic_info_em_object[0][0].bitmap == NULL)
+ {
+ /* EM graphics not yet initialized in em_open_all() */
- /* return "EL_UNKNOWN" for all undefined elements in mapping array */
+ return;
+ }
+#endif
+
+ /* always start with reliable default values */
for (i = 0; i < TILE_MAX; i++)
{
- mapping_EM_to_RND_element[i] = EL_UNKNOWN;
- mapping_EM_to_RND_backside[i] = FALSE;
- mapping_EM_to_RND_action[i] = ACTION_DEFAULT;
- mapping_EM_to_RND_direction[i] = MV_NO_MOVING;
+ object_mapping[i].element_rnd = EL_UNKNOWN;
+ object_mapping[i].is_backside = FALSE;
+ object_mapping[i].action = ACTION_DEFAULT;
+ object_mapping[i].direction = MV_NO_MOVING;
+ }
+
+ /* always start with reliable default values */
+ for (p = 0; p < 2; 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_NO_MOVING;
+ }
+ }
+
+ 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 = (1 << em_object_mapping_list[i].direction);
}
- for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
+ for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
{
- int e = mapping_EM_to_RND_list[i].element_em;
+ int a = em_player_mapping_list[i].action_em;
+ int p = em_player_mapping_list[i].player_nr;
- mapping_EM_to_RND_element[e] = mapping_EM_to_RND_list[i].element_rnd;
- mapping_EM_to_RND_backside[e] = mapping_EM_to_RND_list[i].is_backside;
+ player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
- if (mapping_EM_to_RND_list[i].action != -1)
- mapping_EM_to_RND_action[e] = mapping_EM_to_RND_list[i].action;
+ if (em_player_mapping_list[i].action != -1)
+ player_mapping[p][a].action = em_player_mapping_list[i].action;
- if (mapping_EM_to_RND_list[i].direction != -1)
- mapping_EM_to_RND_direction[e] = 1<< mapping_EM_to_RND_list[i].direction;
+ if (em_player_mapping_list[i].direction != -1)
+ player_mapping[p][a].direction =
+ (1 << em_player_mapping_list[i].direction);
}
for (i = 0; i < TILE_MAX; i++)
{
- int element = mapping_EM_to_RND_element[i];
- int action = mapping_EM_to_RND_action[i];
- int direction = mapping_EM_to_RND_direction[i];
- int backside = mapping_EM_to_RND_backside[i];
+ 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;
boolean action_removing = (action == ACTION_DIGGING ||
action == ACTION_SNAPPING ||
action == ACTION_COLLECTING);
for (j = 0; j < 8; j++)
{
- int effective_element = (j < 7 ? element :
- i == Ynut_sB ? element :
+ 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 == 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 == Yspring_kill_e ? EL_SPRING :
i == Yspring_kill_w ? EL_SPRING :
i == Yemerald_stone ? EL_EMERALD :
i == Ydiamond_stone ? EL_ROCK :
- backside ? EL_EMPTY :
+ i == Xsand_stonein_4 ? EL_EMPTY :
+ i == Xsand_stoneout_2 ? EL_ROCK :
+ is_backside ? EL_EMPTY :
action_removing ? EL_EMPTY :
element);
int effective_action = (j < 7 ? action :
- i == Ynut_sB ? action :
i == Xdrip_stretch ? action :
i == Xdrip_stretchB ? action :
i == Ydrip_s1 ? 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 :
action_active ? action :
action_other ? action :
ACTION_DEFAULT);
- int graphic = (direction == MV_NO_MOVING ?
- el_act2img(effective_element, effective_action) :
- el_act_dir2img(effective_element, effective_action,
+ 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_crumbled_graphics = (base_crumbled != base_graphic);
struct GraphicInfo *g = &graphic_info[graphic];
- struct GraphicInfo_EM *g_em = &graphic_info_em[i][7 - j];
+ 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);
int 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 ? 1 :
- i == Xacid_3 ? 2 :
- i == Xacid_4 ? 3 :
- i == Xacid_5 ? 4 :
- i == Xacid_6 ? 5 :
- i == Xacid_7 ? 6 :
- i == Xacid_8 ? 7 :
+ 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 == Xexit_2 ? j + 8 :
i == Xexit_3 ? j + 16 :
i == Xdynamite_1 ? 0 :
- i == Xdynamite_2 ? 2 :
- i == Xdynamite_3 ? 4 :
- i == Xdynamite_4 ? 6 :
+ i == Xdynamite_2 ? 20 :
+ i == Xdynamite_3 ? 40 :
+ i == Xdynamite_4 ? 60 :
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 ? 1 :
- i == Xsand_stoneout_1 && j == 1 ? 1 :
- i == Xsand_stoneout_1 && j == 2 ? 2 :
- i == Xsand_stoneout_1 && j == 3 ? 4 :
- i == Xsand_stoneout_1 && j == 4 ? 4 :
- i == Xsand_stoneout_1 && j == 5 ? 6 :
- i == Xsand_stoneout_1 && j == 6 ? 8 :
- i == Xsand_stoneout_1 && j == 7 ? 8 :
- i == Xsand_stoneout_2 && j == 0 ? 10 :
- i == Xsand_stoneout_2 && j == 1 ? 12 :
- i == Xsand_stoneout_2 && j == 2 ? 14 :
- i == Xsand_stoneout_2 && j == 3 ? 16 :
- i == Xsand_stoneout_2 && j == 4 ? 18 :
- i == Xsand_stoneout_2 && j == 5 ? 22 :
- i == Xsand_stoneout_2 && j == 6 ? 26 :
- i == Xsand_stoneout_2 && j == 7 ? 30 :
- i == Xboom_bug && j == 2 ? 1 :
- i == Xboom_bug && j == 3 ? 2 :
- i == Xboom_bug && j == 4 ? 2 :
- i == Xboom_bug && j == 5 ? 1 :
- i == Xboom_bug && j == 6 ? 1 :
+ 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 == 2 ? 1 :
- i == Xboom_bomb && j == 3 ? 2 :
- i == Xboom_bomb && j == 4 ? 2 :
- i == Xboom_bomb && j == 5 ? 1 :
- i == Xboom_bomb && j == 6 ? 1 :
+ 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 ? 3 :
- i == Xboom_1 && j == 2 ? 1 :
- i == Xboom_1 && j == 3 ? 2 :
- i == Xboom_1 && j == 4 ? 2 :
- i == Xboom_1 && j == 5 ? 3 :
- i == Xboom_1 && j == 6 ? 3 :
- i == Xboom_1 && j == 7 ? 4 :
- i == Xboom_2 && j == 0 ? 4 :
- i == Xboom_2 && j == 1 ? 4 :
- i == Xboom_2 && j == 2 ? 5 :
- i == Xboom_2 && j == 3 ? 5 :
- i == Xboom_2 && j == 4 ? 5 :
- i == Xboom_2 && j == 5 ? 6 :
+ 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);
-#if 0
+
+#if DEBUG_EM_GFX
Bitmap *debug_bitmap = g_em->bitmap;
int debug_src_x = g_em->src_x;
int debug_src_y = g_em->src_y;
sync_frame);
getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
- g->double_movement && backside);
+ g->double_movement && is_backside);
#if 1
g_em->bitmap = src_bitmap;
g_em->dst_offset_y = 0;
g_em->width = TILEX;
g_em->height = TILEY;
+
+ 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;
+#endif
+
+#if 0
+ if (effective_element == EL_EMC_GRASS &&
+ effective_action == ACTION_DIGGING)
+ printf("::: %d\n", crumbled);
+#endif
+
+#if 0
+ if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
+ printf("::: empty crumbled: %d [%s], %d, %d\n",
+ effective_element, element_info[effective_element].token_name,
+ effective_action, direction);
#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
+ 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);
+
+ 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 1
if (!g->double_movement && (effective_action == ACTION_FALLING ||
effective_action == ACTION_MOVING ||
(effective_action == ACTION_FALLING ? 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 cx = ABS(dx) * TILEX / 8;
- int cy = ABS(dy) * TILEY / 8;
-
- if (backside) /* tile where movement starts */
+ int num_steps = (i == Ydrip_s1 ||
+ i == Ydrip_s1B ||
+ i == Ydrip_s2 ||
+ i == Ydrip_s2B ? 16 : 8);
+ int cx = ABS(dx) * (TILEX / num_steps);
+ int cy = ABS(dy) * (TILEY / num_steps);
+ int step_frame = (i == Ydrip_s2 ||
+ i == Ydrip_s2B ? 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 * (j + 1);
- g_em->src_offset_y = cy * (j + 1);
+ g_em->src_offset_x = cx * step;
+ g_em->src_offset_y = cy * step;
}
else
{
- g_em->dst_offset_x = cx * (j + 1);
- g_em->dst_offset_y = cy * (j + 1);
+ g_em->dst_offset_x = cx * step;
+ g_em->dst_offset_y = cy * step;
}
-
- g_em->width = TILEX - cx * (j + 1);
- g_em->height = TILEY - cy * (j + 1);
}
else /* tile where movement ends */
{
if (dx < 0 || dy < 0)
{
- g_em->dst_offset_x = cx * (7 - j);
- g_em->dst_offset_y = cy * (7 - j);
+ g_em->dst_offset_x = cx * step;
+ g_em->dst_offset_y = cy * step;
}
else
{
- g_em->src_offset_x = cx * (7 - j);
- g_em->src_offset_y = cy * (7 - j);
+ g_em->src_offset_x = cx * step;
+ g_em->src_offset_y = cy * step;
}
+ }
- g_em->width = TILEX - cx * (7 - j);
- g_em->height = TILEY - cy * (7 - j);
+ g_em->width = TILEX - cx * step;
+ g_em->height = TILEY - cy * step;
+ }
+
+#if 0
+ if (effective_action == ACTION_SMASHED_BY_ROCK &&
+ element_info[effective_element].graphic[effective_action] ==
+ element_info[effective_element].graphic[ACTION_DEFAULT])
+ {
+ int move_dir = MV_DOWN;
+ 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 = 8;
+ int cx = ABS(dx) * (TILEX / num_steps);
+ int cy = ABS(dy) * (TILEY / num_steps);
+ int step_frame = j + 1;
+ int step = (is_backside ? step_frame : num_steps - step_frame);
+
+ graphic = (el_act_dir2img(EL_ROCK, ACTION_FALLING, MV_DOWN));
+ g = &graphic_info[graphic];
+ sync_frame = j;
+ 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,
+ g->double_movement && is_backside);
+
+ g_em->bitmap = src_bitmap;
+ g_em->src_x = src_x;
+ g_em->src_y = src_y;
+ g_em->src_offset_x = 0;
+ g_em->src_offset_y = 0;
+ g_em->dst_offset_x = 0;
+ g_em->dst_offset_y = 0;
+
+ 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;
+
+#if 0
+ printf("::: -> '%s'\n", element_info[effective_element].token_name);
+#endif
}
#endif
-#if 0
+#endif
+
+ /* create unique graphic identifier to decide if tile must be redrawn */
+ /* bit 31 - 16 (16 bit): EM style element
+ 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 =
+ (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
+
+#if DEBUG_EM_GFX
if (g_em->bitmap != debug_bitmap ||
g_em->src_x != debug_src_x ||
g_em->src_y != debug_src_y ||
if (i != last_i)
{
printf("\n");
-
last_i = i;
}
- printf("::: EMC GFX ERROR for element %d -> %d ('%s')",
- i, element, element_info[element].token_name);
+ printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
+ i, element, element_info[element].token_name,
+ element_action_info[effective_action].suffix, direction);
if (element != effective_element)
printf(" [%d ('%s')]",
- effective_element,element_info[effective_element].token_name);
+ effective_element,
+ element_info[effective_element].token_name);
printf("\n");
if (g_em->bitmap != debug_bitmap)
- printf(" %d(%d): different bitmap!\n",
- j, backside);
+ printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
+ j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
if (g_em->src_x != debug_src_x ||
g_em->src_y != debug_src_y)
printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
- j, (backside ? 'B' : 'F'),
+ j, (is_backside ? 'B' : 'F'),
g_em->src_x, g_em->src_y,
g_em->src_x / 32, g_em->src_y / 32,
debug_src_x, debug_src_y,
g_em->src_offset_y != 0 ||
g_em->dst_offset_x != 0 ||
g_em->dst_offset_y != 0)
- printf(" %d(%d): offsets %d,%d and %d,%d should be all 0\n",
- j, backside,
+ printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
+ j, is_backside,
g_em->src_offset_x, g_em->src_offset_y,
g_em->dst_offset_x, g_em->dst_offset_y);
if (g_em->width != TILEX ||
g_em->height != TILEY)
- printf(" %d(%d): size %d,%d should be %d,%d\n",
- j, backside,
+ printf(" %d (%d): size %d,%d should be %d,%d\n",
+ j, is_backside,
g_em->width, g_em->height, TILEX, TILEY);
}
#endif
}
}
-#if 0
+#if 1
+ for (i = 0; i < TILE_MAX; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+ int element = object_mapping[i].element_rnd;
+ int action = object_mapping[i].action;
+
+ if (action == ACTION_SMASHED_BY_ROCK &&
+ element_info[element].graphic[action] ==
+ element_info[element].graphic[ACTION_DEFAULT])
+ {
+ /* no separate animation for "smashed by rock" -- use rock instead */
+ struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
+ struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
+
+ g_em->bitmap = g_xx->bitmap;
+ g_em->src_x = g_xx->src_x;
+ g_em->src_y = g_xx->src_y;
+ g_em->src_offset_x = g_xx->src_offset_x;
+ g_em->src_offset_y = g_xx->src_offset_y;
+ g_em->dst_offset_x = g_xx->dst_offset_x;
+ g_em->dst_offset_y = g_xx->dst_offset_y;
+ g_em->width = g_xx->width;
+ g_em->height = g_xx->height;
+
+ g_em->preserve_background = TRUE;
+ }
+ }
+ }
+#endif
+
+ for (p = 0; p < 2; p++)
+ {
+ for (i = 0; i < SPR_MAX; i++)
+ {
+ int element = player_mapping[p][i].element_rnd;
+ int action = player_mapping[p][i].action;
+ int direction = player_mapping[p][i].direction;
+
+ for (j = 0; j < 8; j++)
+ {
+ int effective_element = element;
+ int effective_action = action;
+ int graphic = (direction == MV_NO_MOVING ?
+ el_act2img(effective_element, effective_action) :
+ el_act_dir2img(effective_element, effective_action,
+ direction));
+ struct GraphicInfo *g = &graphic_info[graphic];
+ struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int sync_frame = j;
+
+#if DEBUG_EM_GFX
+ Bitmap *debug_bitmap = g_em->bitmap;
+ int debug_src_x = g_em->src_x;
+ int debug_src_y = g_em->src_y;
+#endif
+
+ 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);
+
+#if 1
+ g_em->bitmap = src_bitmap;
+ g_em->src_x = src_x;
+ g_em->src_y = src_y;
+ 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;
+#endif
+
+#if DEBUG_EM_GFX
+ if (g_em->bitmap != debug_bitmap ||
+ g_em->src_x != debug_src_x ||
+ g_em->src_y != debug_src_y)
+ {
+ static int last_i = -1;
+
+ if (i != last_i)
+ {
+ printf("\n");
+ last_i = i;
+ }
+
+ printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
+ p, i, element, element_info[element].token_name,
+ element_action_info[effective_action].suffix, direction);
+
+ if (element != effective_element)
+ printf(" [%d ('%s')]",
+ effective_element,
+ element_info[effective_element].token_name);
+
+ printf("\n");
+
+ if (g_em->bitmap != debug_bitmap)
+ printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
+ j, (int)(g_em->bitmap), (int)(debug_bitmap));
+
+ if (g_em->src_x != debug_src_x ||
+ g_em->src_y != debug_src_y)
+ printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
+ j,
+ g_em->src_x, g_em->src_y,
+ g_em->src_x / 32, g_em->src_y / 32,
+ debug_src_x, debug_src_y,
+ debug_src_x / 32, debug_src_y / 32);
+ }
+#endif
+
+ }
+ }
+ }
+
+#if DEBUG_EM_GFX
exit(0);
#endif
}