From 88c9b68c44a16e7df62557b63cc7e86731e028c9 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 7 Feb 2006 01:30:12 +0100 Subject: [PATCH] rnd-20060207-1-src * improved screen redraw for EMC graphics engine (faster and smoother) * when not scrolling, do not redraw the whole playfield if not needed * added multi-player mode for EMC game engine (with up to four players) --- ChangeLog | 7 ++ src/conftime.h | 2 +- src/files.c | 128 +++++++++++++++++++++++++++++++++++-- src/game.c | 87 ++++++++++++++++++++++++- src/game_em/cave.c | 35 +++++++--- src/game_em/convert.c | 111 +++++++++++++++++++++----------- src/game_em/game_em.h | 2 +- src/game_em/global.h | 2 +- src/game_em/graphics.c | 80 ++++++++++++++++++++--- src/game_em/input.c | 39 ++++------- src/game_em/level.h | 87 +------------------------ src/game_em/main_em.h | 3 +- src/game_em/synchro_1.c | 66 ++++++++++++++++++- src/game_em/synchro_2.c | 55 +++++++++++++++- src/game_em/tab_generate.c | 6 +- src/main.c | 107 ++++++++++++++++--------------- src/screens.c | 6 +- src/tools.c | 126 +++++++++++++++++++++++++++++++++++- 18 files changed, 708 insertions(+), 241 deletions(-) diff --git a/ChangeLog b/ChangeLog index 253e6ec8..66f05732 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-02-06 + * improved screen redraw for EMC graphics engine (faster and smoother) + * when not scrolling, do not redraw the whole playfield if not needed + +2006-02-03 + * added multi-player mode for EMC game engine (with up to four players) + 2006-01-28 * added android (can clone elements) from EMC engine to R'n'D engine diff --git a/src/conftime.h b/src/conftime.h index 9b40c697..3a96329a 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2006-02-03 19:01]" +#define COMPILE_DATE_STRING "[2006-02-07 01:20]" diff --git a/src/files.c b/src/files.c index 6b395bf0..4ff5c649 100644 --- a/src/files.c +++ b/src/files.c @@ -2389,10 +2389,17 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) }; struct LevelInfo_EM *level_em = level->native_em_level; struct LEVEL *lev = level_em->lev; - struct PLAYER *ply1 = level_em->ply1; - struct PLAYER *ply2 = level_em->ply2; + struct PLAYER **ply = level_em->ply; int i, j, x, y; +#if 0 + printf("::: A\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + lev->width = MIN(level->fieldx, EM_MAX_CAVE_WIDTH); lev->height = MIN(level->fieldy, EM_MAX_CAVE_HEIGHT); @@ -2445,6 +2452,13 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) map_element_RND_to_EM(level-> ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#if 0 + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + map_android_clone_elements_RND_to_EM(level); #if 0 @@ -2468,15 +2482,42 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) level_em->cave[x + 1][y + 1] = new_element; } +#if 1 + + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i]->x_initial = 0; + ply[i]->y_initial = 0; + } + +#else + ply1->x_initial = 0; ply1->y_initial = 0; ply2->x_initial = 0; ply2->y_initial = 0; +#endif + /* initialize player positions and delete players from the playfield */ for (y = 0; y < lev->height; y++) for (x = 0; x < lev->width; x++) { + +#if 1 + + if (ELEM_IS_PLAYER(level->field[x][y])) + { + int player_nr = GET_PLAYER_NR(level->field[x][y]); + + ply[player_nr]->x_initial = x + 1; + ply[player_nr]->y_initial = y + 1; + + level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_EMPTY); + } + +#else + #if 1 /* !!! CURRENTLY ONLY SUPPORT FOR ONE PLAYER !!! */ if (ELEM_IS_PLAYER(level->field[x][y])) @@ -2500,6 +2541,9 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) level_em->cave[x + 1][y + 1] = map_element_RND_to_EM(EL_EMPTY); } #endif + +#endif + } } @@ -2518,8 +2562,7 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) }; struct LevelInfo_EM *level_em = level->native_em_level; struct LEVEL *lev = level_em->lev; - struct PLAYER *ply1 = level_em->ply1; - struct PLAYER *ply2 = level_em->ply2; + struct PLAYER **ply = level_em->ply; int i, j, x, y; level->fieldx = MIN(lev->width, MAX_LEV_FIELDX); @@ -2570,11 +2613,27 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->wind_direction_initial = map_direction_EM_to_RND(lev->wind_direction_initial); +#if 0 + printf("::: foo\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (j = 0; j < 8; j++) level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]] = map_element_EM_to_RND(lev->ball_array[i][j]); +#if 0 + printf("::: bar\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + map_android_clone_elements_EM_to_RND(level); #if 0 @@ -2593,13 +2652,50 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->field[x][y] = new_element; } +#if 0 + printf("::: bar 0\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif + +#if 1 + + for (i = 0; i < MAX_PLAYERS; i++) + { + /* in case of all players set to the same field, use the first player */ + int nr = MAX_PLAYERS - i - 1; + int jx = ply[nr]->x_initial - 1; + int jy = ply[nr]->y_initial - 1; + +#if 0 + printf("::: player %d: %d, %d\n", nr, jx, jy); +#endif + + if (jx != -1 && jy != -1) + level->field[jx][jy] = EL_PLAYER_1 + nr; + } + +#else + /* in case of both players set to the same field, use the first player */ level->field[ply2->x_initial - 1][ply2->y_initial - 1] = EL_PLAYER_2; level->field[ply1->x_initial - 1][ply1->y_initial - 1] = EL_PLAYER_1; +#endif + #if 0 printf("::: native Emerald Mine file version: %d\n", level_em->file_version); #endif + +#if 0 + printf("::: bar 2\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); +#endif } static void LoadLevelFromFileInfo_EM(struct LevelInfo *level, @@ -2617,6 +2713,30 @@ void CopyNativeLevel_RND_to_Native(struct LevelInfo *level) void CopyNativeLevel_Native_to_RND(struct LevelInfo *level) { + +#if 0 + { + static int ball_xy[8][2] = + { + { 0, 0 }, + { 1, 0 }, + { 2, 0 }, + { 0, 1 }, + { 2, 1 }, + { 0, 2 }, + { 1, 2 }, + { 2, 2 }, + }; + int i, j; + + printf("::: A6\n"); + for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (j = 0; j < 8; j++) + printf("::: ball %d, %d: %d\n", i, j, + level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); + } +#endif + if (level->game_engine_type == GAME_ENGINE_TYPE_EM) CopyNativeLevel_EM_to_RND(level); } diff --git a/src/game.c b/src/game.c index 5d3e9844..a18c80bd 100644 --- a/src/game.c +++ b/src/game.c @@ -293,6 +293,8 @@ static void TestIfElementSmashesCustomElement(int, int, int); #endif static void HandleElementChange(int, int, int); +static void ExecuteCustomElementAction(int, int, int, int); +static boolean ChangeElement(int, int, int, int); static boolean CheckTriggeredElementChangeExt(int, int, int, int, int,int,int); #define CheckTriggeredElementChange(x, y, e, ev) \ @@ -2814,14 +2816,33 @@ static void ResetRandomAnimationValue(int x, int y) static void ResetGfxAnimation(int x, int y) { +#if 0 + int element, graphic; +#endif + GfxFrame[x][y] = 0; GfxAction[x][y] = ACTION_DEFAULT; GfxDir[x][y] = MovDir[x][y]; + +#if 0 + element = Feld[x][y]; + graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); + + if (graphic_info[graphic].anim_global_sync) + GfxFrame[x][y] = FrameCounter; + else if (ANIM_MODE(graphic) == ANIM_CE_VALUE) + GfxFrame[x][y] = CustomValue[x][y]; + else if (ANIM_MODE(graphic) == ANIM_CE_SCORE) + GfxFrame[x][y] = element_info[element].collect_score; +#endif } void InitMovingField(int x, int y, int direction) { int element = Feld[x][y]; +#if 0 + int graphic; +#endif int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0); int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); int newx = x + dx; @@ -2835,6 +2856,17 @@ void InitMovingField(int x, int y, int direction) GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ? ACTION_FALLING : ACTION_MOVING); +#if 0 + graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); + + if (graphic_info[graphic].anim_global_sync) + GfxFrame[x][y] = FrameCounter; + else if (ANIM_MODE(graphic) == ANIM_CE_VALUE) + GfxFrame[x][y] = CustomValue[x][y]; + else if (ANIM_MODE(graphic) == ANIM_CE_SCORE) + GfxFrame[x][y] = element_info[element].collect_score; +#endif + /* this is needed for CEs with property "can move" / "not moving" */ if (getElementMoveStepsize(x, y) != 0) /* moving or being moved */ @@ -5262,6 +5294,9 @@ inline static void TurnRoundExt(int x, int y) static void TurnRound(int x, int y) { int direction = MovDir[x][y]; +#if 1 + int element, graphic; +#endif TurnRoundExt(x, y); @@ -5272,6 +5307,18 @@ static void TurnRound(int x, int y) if (MovDelay[x][y]) GfxAction[x][y] = ACTION_TURNING_FROM_LEFT + MV_DIR_TO_BIT(direction); + +#if 1 + element = Feld[x][y]; + graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); + + if (graphic_info[graphic].anim_global_sync) + GfxFrame[x][y] = FrameCounter; + else if (ANIM_MODE(graphic) == ANIM_CE_VALUE) + GfxFrame[x][y] = CustomValue[x][y]; + else if (ANIM_MODE(graphic) == ANIM_CE_SCORE) + GfxFrame[x][y] = element_info[element].collect_score; +#endif } static boolean JustBeingPushed(int x, int y) @@ -6449,6 +6496,28 @@ void ContinueMoving(int x, int y) TestIfElementTouchesCustomElement(x, y); /* empty or new element */ +#if 0 + if (ChangePage[newx][newy] != -1) /* delayed change */ + { + int page = ChangePage[newx][newy]; + struct ElementChangeInfo *change = &ei->change_page[page]; + + ChangePage[newx][newy] = -1; + + if (change->can_change) + { + if (ChangeElement(newx, newy, element, page)) + { + if (change->post_change_function) + change->post_change_function(newx, newy); + } + } + + if (change->has_action) + ExecuteCustomElementAction(newx, newy, element, page); + } +#endif + TestIfElementHitsCustomElement(newx, newy, direction); TestIfPlayerTouchesCustomElement(newx, newy); TestIfElementTouchesCustomElement(newx, newy); @@ -7790,6 +7859,10 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_GETS_ZERO); CheckTriggeredElementChange(x, y, element, CE_VALUE_GETS_ZERO_OF_X); + +#if 0 + printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]); +#endif } #endif @@ -8339,8 +8412,20 @@ static boolean CheckElementChangeExt(int x, int y, element = Feld[x][y]; } - if (Feld[x][y] != element) /* check if element has already changed */ +#if 0 + /* check if element has already changed */ + if (Feld[x][y] != element) return FALSE; +#else + /* check if element has already changed or is about to change after moving */ + if ((game.engine_version < VERSION_IDENT(3,2,0,7) && + Feld[x][y] != element) || + + (game.engine_version >= VERSION_IDENT(3,2,0,7) && + (ChangeCount[x][y] >= game.max_num_changes_per_frame || + ChangePage[x][y] != -1))) + return FALSE; +#endif for (p = 0; p < element_info[element].num_change_pages; p++) { diff --git a/src/game_em/cave.c b/src/game_em/cave.c index 08c28ec2..47f7315e 100644 --- a/src/game_em/cave.c +++ b/src/game_em/cave.c @@ -17,17 +17,17 @@ void setLevelInfoToDefaults_EM(void) native_em_level.file_version = FILE_VERSION_EM_ACTUAL; native_em_level.lev = &lev; - native_em_level.ply1 = &ply1; - native_em_level.ply2 = &ply2; + for (i = 0; i < MAX_PLAYERS; i++) + native_em_level.ply[i] = &ply[i]; lev.width = 64; lev.height = 32; - ply1.x_initial = 0; - ply1.y_initial = 0; - - ply2.x_initial = 0; - ply2.y_initial = 0; + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i].x_initial = 0; + ply[i].y_initial = 0; + } lev.lenses_cnt_initial = 0; lev.magnify_cnt_initial = 0; @@ -47,10 +47,25 @@ void setLevelInfoToDefaults_EM(void) for (i = 0; i < TILE_MAX; i++) lev.android_array[i] = Xblank; - lev.home_initial = 2; /* initial number of players in this level */ +#if 1 + /* initial number of players in this level */ + lev.home_initial = 0; + + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i].exists = 0; + ply[i].alive_initial = FALSE; + } +#else + /* initial number of players in this level */ + lev.home_initial = (setup.team_mode ? 2 : 1); - ply1.alive_initial = (lev.home_initial >= 1); - ply2.alive_initial = (lev.home_initial >= 2); + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i].exists = 0; + ply[i].alive_initial = (lev.home_initial > i ? TRUE : FALSE); + } +#endif } diff --git a/src/game_em/convert.c b/src/game_em/convert.c index 3c714c6e..7b3b036a 100644 --- a/src/game_em/convert.c +++ b/src/game_em/convert.c @@ -563,12 +563,12 @@ void convert_em_level(unsigned char *src, int file_version) lev.required_initial = src[0x82F]; - temp = src[0x830] << 8 | src[0x831]; - ply1.x_initial = (temp & 63) + 1; - ply1.y_initial = (temp >> 6 & 31) + 1; - temp = src[0x832] << 8 | src[0x833]; - ply2.x_initial = (temp & 63) + 1; - ply2.y_initial = (temp >> 6 & 31) + 1; + for (i = 0; i < 2; i++) + { + temp = src[0x830 + i * 2] << 8 | src[0x831 + i * 2]; + ply[i].x_initial = (temp & 63) + 1; + ply[i].y_initial = (temp >> 6 & 31) + 1; + } temp = (src[0x834] << 8 | src[0x835]) * 28; if (temp > 9999) @@ -886,17 +886,23 @@ void convert_em_level(unsigned char *src, int file_version) native_em_level.cave[x + 1][y + 1] = remap_emerald[src[temp++]]; /* at last, set the two players at their positions in the playfield */ - if (ply1.alive_initial) - native_em_level.cave[ply1.x_initial][ply1.y_initial] = Zplayer; - if (ply2.alive_initial) - native_em_level.cave[ply2.x_initial][ply2.y_initial] = Zplayer; + /* (native EM[C] levels always have exactly two players in a level) */ +#if 1 + for (i = 0; i < 2; i++) + native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer; +#else + for (i = 0; i < 2; i++) + if (ply[i].alive_initial) + native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Zplayer; +#endif native_em_level.file_version = file_version; } void prepare_em_level(void) { - unsigned int x, y; + unsigned int i, x, y; + int players_left; /* reset all runtime variables to their initial values */ @@ -945,33 +951,64 @@ void prepare_em_level(void) lev.wonderwall_state = lev.wonderwall_state_initial; lev.wonderwall_time = lev.wonderwall_time_initial; + lev.killed_out_of_time = FALSE; + + /* determine number of players in this level */ + lev.home_initial = 0; + + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i].exists = 0; + ply[i].alive_initial = FALSE; + + if (ply[i].x_initial > 0 && ply[i].y_initial > 0) + { + ply[i].exists = 1; + + lev.home_initial++; + } + } + + if (!setup.team_mode) + lev.home_initial = MIN(lev.home_initial, 1); + lev.home = lev.home_initial; + players_left = lev.home_initial; - lev.killed_out_of_time = FALSE; + for (i = 0; i < MAX_PLAYERS; i++) + { + if (ply[i].exists) + { + if (players_left) + { + ply[i].alive_initial = TRUE; + players_left--; + } + else + { + native_em_level.cave[ply[i].x_initial][ply[i].y_initial] = Xblank; + } + } + } + + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i].num = i; + ply[i].alive = ply[i].alive_initial; + ply[i].dynamite = 0; + ply[i].dynamite_cnt = 0; + ply[i].keys = 0; + ply[i].anim = 0; + ply[i].oldx = ply[i].x = ply[i].x_initial; + ply[i].oldy = ply[i].y = ply[i].y_initial; + ply[i].last_move_dir = MV_NONE; + ply[i].joy_n = ply[i].joy_e = ply[i].joy_s = ply[i].joy_w = 0; + ply[i].joy_snap = ply[i].joy_drop = 0; + ply[i].joy_stick = ply[i].joy_spin = 0; - ply1.num = 0; - ply1.alive = ply1.alive_initial; - ply1.dynamite = 0; - ply1.dynamite_cnt = 0; - ply1.keys = 0; - ply1.anim = 0; - ply1.oldx = ply1.x = ply1.x_initial; - ply1.oldy = ply1.y = ply1.y_initial; - ply1.last_move_dir = MV_NONE; - ply1.joy_n = ply1.joy_e = ply1.joy_s = ply1.joy_w = 0; - ply1.joy_snap = ply1.joy_drop = 0; - ply1.joy_stick = ply1.joy_spin = 0; - - ply2.num = 1; - ply2.alive = ply2.alive_initial; - ply2.dynamite = 0; - ply2.dynamite_cnt = 0; - ply2.keys = 0; - ply2.anim = 0; - ply2.oldx = ply2.x = ply2.x_initial; - ply2.oldy = ply2.y = ply2.y_initial; - ply2.last_move_dir = MV_NONE; - ply2.joy_n = ply2.joy_e = ply2.joy_s = ply2.joy_w = 0; - ply2.joy_snap = ply1.joy_drop = 0; - ply2.joy_stick = ply2.joy_spin = 0; +#if 0 + printf("player %d: x/y == %d/%d, alive == %d\n", + i, ply[i].x_initial, ply[i].y_initial, ply[i].alive); +#endif + } } diff --git a/src/game_em/game_em.h b/src/game_em/game_em.h index 2ca711b4..d6a962c1 100644 --- a/src/game_em/game_em.h +++ b/src/game_em/game_em.h @@ -26,7 +26,7 @@ extern struct GlobalInfo_EM global_em_info; extern struct LevelInfo_EM native_em_level; extern struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8]; -extern struct GraphicInfo_EM graphic_info_em_player[2][SPR_MAX][8]; +extern struct GraphicInfo_EM graphic_info_em_player[MAX_PLAYERS][SPR_MAX][8]; extern void em_open_all(); extern void em_close_all(); diff --git a/src/game_em/global.h b/src/game_em/global.h index 1a6e77ad..e60f9629 100644 --- a/src/game_em/global.h +++ b/src/game_em/global.h @@ -25,7 +25,7 @@ int open_all(void); void close_all(void); #if 1 -void readjoy(byte, int); +void readjoy(byte, struct PLAYER *); #else void readjoy(byte); #endif diff --git a/src/game_em/graphics.c b/src/game_em/graphics.c index 06f974a2..cc746c0c 100644 --- a/src/game_em/graphics.c +++ b/src/game_em/graphics.c @@ -16,6 +16,8 @@ unsigned int screen_y; static unsigned int screentiles[MAX_BUF_YSIZE][MAX_BUF_XSIZE]; static unsigned int crumbled_state[MAX_BUF_YSIZE][MAX_BUF_XSIZE]; +static boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; + /* copy the entire screen to the window at the scroll position * @@ -69,7 +71,54 @@ void BlitScreenToBitmap_EM(Bitmap *target_bitmap) void blitscreen(void) { +#if 1 + + static boolean scrolling_last = FALSE; + unsigned int left = screen_x / TILEX; + unsigned int top = screen_y / TILEY; + boolean scrolling = (screen_x % TILEX != 0 || screen_y % TILEY != 0); + int x, y; + + SyncDisplay(); + + if (redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last) + { + /* blit all (up to four) parts of the scroll buffer to the backbuffer */ + BlitScreenToBitmap_EM(backbuffer); + + /* blit the completely updated backbuffer to the window (in one blit) */ + BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY); + } + else + { + for (x = 0; x < SCR_FIELDX; x++) + { + for (y = 0; y < SCR_FIELDY; y++) + { + int xx = (left + x) % MAX_BUF_XSIZE; + int yy = (top + y) % MAX_BUF_YSIZE; + + if (redraw[xx][yy]) + BlitBitmap(screenBitmap, window, + xx * TILEX, yy * TILEY, TILEX, TILEY, + SX + x * TILEX, SY + y * TILEY); + } + } + } + + for (x = 0; x < MAX_BUF_XSIZE; x++) + for (y = 0; y < MAX_BUF_YSIZE; y++) + redraw[x][y] = FALSE; + redraw_tiles = 0; + + scrolling_last = scrolling; + +#else + + /* blit all (up to four) parts of the scroll buffer to the window */ BlitScreenToBitmap_EM(window); + +#endif } static void DrawLevelField_EM(int x, int y, int sx, int sy, @@ -225,7 +274,7 @@ static void animscreen(void) { unsigned int x, y, i; unsigned int left = screen_x / TILEX; - unsigned int top = screen_y / TILEY; + unsigned int top = screen_y / TILEY; static int xy[4][2] = { { 0, -1 }, @@ -273,6 +322,9 @@ static void animscreen(void) screentiles[sy][sx] = obj; crumbled_state[sy][sx] = crm; + + redraw[sx][sy] = TRUE; + redraw_tiles++; } } } @@ -365,6 +417,8 @@ static void blitplayer(struct PLAYER *ply) void game_initscreen(void) { unsigned int x,y; + int dynamite_state = ply[0].dynamite; /* !!! ONLY PLAYER 1 !!! */ + int all_keys_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys; frame = 6; screen_x = 0; @@ -380,8 +434,8 @@ void game_initscreen(void) } #if 1 - DrawAllGameValues(lev.required, ply1.dynamite, lev.score, - lev.time, ply1.keys | ply2.keys); + DrawAllGameValues(lev.required, dynamite_state, lev.score, + lev.time, all_keys_state); #else DrawAllGameValues(lev.required, ply1.dynamite, lev.score, DISPLAY_TIME(lev.time + 4), ply1.keys | ply2.keys); @@ -390,11 +444,12 @@ void game_initscreen(void) void RedrawPlayfield_EM() { - unsigned int x,y; + unsigned int i, x, y; - x = (frame * ply1.oldx + (8 - frame) * ply1.x) * TILEX / 8 + /* !!! FIX THIS (CENTERED TO PLAYER 1) !!! */ + x = (frame * ply[0].oldx + (8 - frame) * ply[0].x) * TILEX / 8 + ((SCR_FIELDX - 1) * TILEX) / 2; - y = (frame * ply1.oldy + (8 - frame) * ply1.y) * TILEY / 8 + y = (frame * ply[0].oldy + (8 - frame) * ply[0].y) * TILEY / 8 + ((SCR_FIELDY - 1) * TILEY) / 2; if (x > lev.width * TILEX) @@ -411,8 +466,10 @@ void RedrawPlayfield_EM() screen_y = y - (SCR_FIELDY - 1) * TILEY; animscreen(); - blitplayer(&ply1); - blitplayer(&ply2); + + for (i = 0; i < MAX_PLAYERS; i++) + blitplayer(&ply[i]); + blitscreen(); FlushDisplay(); @@ -425,9 +482,12 @@ void game_animscreen(void) void DrawGameDoorValues_EM() { + int dynamite_state = ply[0].dynamite; /* !!! ONLY PLAYER 1 !!! */ + int all_keys_state = ply[0].keys | ply[1].keys | ply[2].keys | ply[3].keys; + #if 1 - DrawAllGameValues(lev.required, ply1.dynamite, lev.score, - lev.time, ply1.keys | ply2.keys); + DrawAllGameValues(lev.required, dynamite_state, lev.score, + lev.time, all_keys_state); #else DrawAllGameValues(lev.required, ply1.dynamite, lev.score, DISPLAY_TIME(lev.time), ply1.keys | ply2.keys); diff --git a/src/game_em/input.c b/src/game_em/input.c index b2a644c7..ae3e1d55 100644 --- a/src/game_em/input.c +++ b/src/game_em/input.c @@ -10,9 +10,8 @@ unsigned long RandomEM; -struct PLAYER ply1; -struct PLAYER ply2; struct LEVEL lev; +struct PLAYER ply[MAX_PLAYERS]; unsigned short **Boom; unsigned short **Cave; @@ -92,8 +91,8 @@ void GameActions_EM(byte action[MAX_PLAYERS]) frame = (frame - 1) & 7; - for (i = 0; i < 2; i++) - readjoy(action[i], i); + for (i = 0; i < MAX_PLAYERS; i++) + readjoy(action[i], &ply[i]); UpdateEngineValues(screen_x / TILEX, screen_y / TILEY); @@ -190,7 +189,7 @@ void GameActions_EM(byte action) #if 1 -void readjoy(byte action, int player_nr) +void readjoy(byte action, struct PLAYER *ply) { unsigned int north = 0, east = 0, south = 0, west = 0; unsigned int snap = 0, drop = 0; @@ -213,29 +212,15 @@ void readjoy(byte action, int player_nr) if (action & JOY_BUTTON_2) drop = 1; - if (player_nr == 0) - { - ply1.joy_snap = snap; - ply1.joy_drop = drop; - if (ply1.joy_stick || (north | east | south | west)) - { - ply1.joy_n = north; - ply1.joy_e = east; - ply1.joy_s = south; - ply1.joy_w = west; - } - } - else + ply->joy_snap = snap; + ply->joy_drop = drop; + + if (ply->joy_stick || (north | east | south | west)) { - ply2.joy_snap = snap; - ply2.joy_drop = drop; - if (ply2.joy_stick || (north | east | south | west)) - { - ply2.joy_n = north; - ply2.joy_e = east; - ply2.joy_s = south; - ply2.joy_w = west; - } + ply->joy_n = north; + ply->joy_e = east; + ply->joy_s = south; + ply->joy_w = west; } } diff --git a/src/game_em/level.h b/src/game_em/level.h index 46ba9e40..9fb51dd9 100644 --- a/src/game_em/level.h +++ b/src/game_em/level.h @@ -7,97 +7,14 @@ #define WIDTH EM_MAX_CAVE_WIDTH #define HEIGHT EM_MAX_CAVE_HEIGHT -#if 0 - -struct LEVEL -{ - unsigned int home; /* number of players that have to go home */ - /* 0 == all players home */ - - unsigned int width; /* world width */ - unsigned int height; /* world height */ - unsigned int time; /* time remaining */ - unsigned int required; /* emeralds needed */ - unsigned int score; /* score */ - - /* fill in all below /every/ time you read a level */ - unsigned int alien_score; /* alien popped by stone/spring score */ - unsigned int amoeba_time; /* amoeba speed */ - unsigned int android_move_cnt; /* android move time counter */ - unsigned int android_move_time; /* android move reset time */ - unsigned int android_clone_cnt; /* android clone time counter */ - unsigned int android_clone_time; /* android clone reset time */ - unsigned int ball_cnt; /* ball time counter */ - unsigned int ball_pos; /* ball array pos counter */ - unsigned int ball_random; /* ball is random flag */ - unsigned int ball_state; /* ball currently on flag */ - unsigned int ball_time; /* ball reset time */ - unsigned int bug_score; /* bug popped by stone/spring score */ - unsigned int diamond_score; /* diamond collect score */ - unsigned int dynamite_score; /* dynamite collect scoer*/ - unsigned int eater_pos; /* eater array pos */ - unsigned int eater_score; /* eater popped by stone/spring score */ - unsigned int emerald_score; /* emerald collect score */ - unsigned int exit_score; /* exit score */ - unsigned int key_score; /* key collect score */ - unsigned int lenses_cnt; /* lenses time counter */ - unsigned int lenses_score; /* lenses collect score */ - unsigned int lenses_time; /* lenses reset time */ - unsigned int magnify_cnt; /* magnify time counter */ - unsigned int magnify_score; /* magnify collect score */ - unsigned int magnify_time; /* magnify reset time */ - unsigned int nut_score; /* nut crack score */ - unsigned int shine_cnt; /* shine counter for emerald/diamond */ - unsigned int slurp_score; /* slurp alien score */ - unsigned int tank_score; /* tank popped by stone/spring */ - unsigned int wheel_cnt; /* wheel time counter */ - unsigned int wheel_x; /* wheel x pos */ - unsigned int wheel_y; /* wheel y pos */ - unsigned int wheel_time; /* wheel reset time */ - unsigned int wind_cnt; /* wind time counter */ - unsigned int wind_direction; /* wind direction */ - unsigned int wind_time; /* wind reset time */ - unsigned int wonderwall_state; /* wonderwall currently on flag */ - unsigned int wonderwall_time; /* wonderwall time */ - unsigned short eater_array[8][9]; /* eater data */ - unsigned short ball_array[8][8]; /* ball data */ - unsigned short android_array[TILE_MAX]; /* android clone table */ -}; - -struct PLAYER -{ - unsigned int num; - unsigned int alive; - unsigned int dynamite; - unsigned int dynamite_cnt; - unsigned int keys; - unsigned int anim; - unsigned int x; - unsigned int y; - unsigned int oldx; - unsigned int oldy; - - unsigned joy_n:1; - unsigned joy_e:1; - unsigned joy_s:1; - unsigned joy_w:1; - unsigned joy_snap:1; - unsigned joy_drop:1; - unsigned joy_stick:1; - unsigned joy_spin:1; -}; - -#endif - extern unsigned long RandomEM; -extern struct PLAYER ply1; -extern struct PLAYER ply2; extern struct LEVEL lev; +extern struct PLAYER ply[MAX_PLAYERS]; extern struct LevelInfo_EM native_em_level; extern struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8]; -extern struct GraphicInfo_EM graphic_info_em_player[2][SPR_MAX][8]; +extern struct GraphicInfo_EM graphic_info_em_player[MAX_PLAYERS][SPR_MAX][8]; extern unsigned short **Boom; extern unsigned short **Cave; diff --git a/src/game_em/main_em.h b/src/game_em/main_em.h index 5da62d3b..88f673f9 100644 --- a/src/game_em/main_em.h +++ b/src/game_em/main_em.h @@ -599,6 +599,7 @@ struct LEVEL struct PLAYER { unsigned int num; + unsigned int exists; unsigned int alive_initial; unsigned int alive; @@ -651,7 +652,7 @@ struct LevelInfo_EM unsigned short cave[EM_MAX_CAVE_WIDTH][EM_MAX_CAVE_HEIGHT]; struct LEVEL *lev; - struct PLAYER *ply1, *ply2; + struct PLAYER *ply[MAX_PLAYERS]; }; struct GraphicInfo_EM diff --git a/src/game_em/synchro_1.c b/src/game_em/synchro_1.c index 124751d0..0b3710e1 100644 --- a/src/game_em/synchro_1.c +++ b/src/game_em/synchro_1.c @@ -18,7 +18,24 @@ static boolean player_killed(struct PLAYER *); void synchro_1(void) { - /* must test for death and actually kill separately */ +#if 1 + + int start_check_nr; + int i; + + /* must test for death and actually kill separately */ + + for (i = 0; i < MAX_PLAYERS; i++) + { + boolean ply_kill = player_killed(&ply[i]); + + if (ply[i].alive && ply_kill) + kill_player(&ply[i]); + } + +#else + + /* must test for death and actually kill separately */ boolean ply1_kill = player_killed(&ply1); boolean ply2_kill = player_killed(&ply2); @@ -27,10 +44,51 @@ void synchro_1(void) if (ply2.alive && ply2_kill) kill_player(&ply2); +#endif + #if 0 ply1.alive = 1; /* debugging */ #endif +#if 1 + + for (i = 0; i < MAX_PLAYERS; i++) + { + ply[i].oldx = ply[i].x; + ply[i].oldy = ply[i].y; + ply[i].anim = SPR_still; + } + + start_check_nr = (RandomEM & 128 ? 0 : 1) * 2 + (RandomEM & 256 ? 0 : 1); + + for (i = 0; i < MAX_PLAYERS; i++) + { + int check_nr = (start_check_nr + i) % MAX_PLAYERS; + + if (ply[check_nr].alive) + check_player(&ply[check_nr]); + } + + for (i = 0; i < MAX_PLAYERS; i++) + { + if (!ply[i].alive) + continue; + + if (Cave[ply[i].oldy][ply[i].oldx] == Zplayer) + { + Cave[ply[i].oldy][ply[i].oldx] = Xblank; + Next[ply[i].oldy][ply[i].oldx] = Xblank; + } + + if (Cave[ply[i].y][ply[i].x] == Xblank) + { + Cave[ply[i].y][ply[i].x] = Zplayer; + Next[ply[i].y][ply[i].x] = Zplayer; + } + } + +#else + ply1.oldx = ply1.x; ply1.oldy = ply1.y; ply1.anim = SPR_still; @@ -78,6 +136,8 @@ void synchro_1(void) Next[ply2.y][ply2.x] = Zplayer; } } + +#endif } static boolean player_killed(struct PLAYER *ply) @@ -85,6 +145,10 @@ static boolean player_killed(struct PLAYER *ply) register unsigned int x = ply->x; register unsigned int y = ply->y; +#if 0 + printf("::: %d: %d, %d\n", ply->num, x, y); +#endif + if (!ply->alive) return FALSE; diff --git a/src/game_em/synchro_2.c b/src/game_em/synchro_2.c index 119d86a5..5079b7c2 100644 --- a/src/game_em/synchro_2.c +++ b/src/game_em/synchro_2.c @@ -16,6 +16,32 @@ #define RANDOM (random = random << 31 | random >> 1) +static void set_nearest_player_xy(int x, int y, int *dx, int *dy) +{ + int distance, distance_shortest = EM_MAX_CAVE_WIDTH + EM_MAX_CAVE_HEIGHT; + int i; + + /* default values if no players are alive anymore */ + *dx = 0; + *dy = 0; + + for (i = 0; i < MAX_PLAYERS; i++) + { + if (!ply[i].alive) + continue; + + distance = ABS(ply[i].x - x) + ABS(ply[i].y - y); + + if (distance < distance_shortest) + { + *dx = ply[i].x; + *dy = ply[i].y; + + distance_shortest = distance; + } + } +} + void synchro_2(void) { register unsigned int x = 0; @@ -1879,6 +1905,12 @@ void synchro_2(void) Cave[y+1][x+1] == Zplayer) goto android_still; +#if 1 + + set_nearest_player_xy(x, y, &dx, &dy); + +#else + if (ply1.alive && ply2.alive) { if ((ply1.x > x ? ply1.x - x : x - ply1.x) + @@ -1911,6 +1943,8 @@ void synchro_2(void) dy = 0; } +#endif + Next[y][x] = Xblank; /* assume we will move */ temp = ((x < dx) + 1 - (x > dx)) + ((y < dy) + 1 - (y > dy)) * 3; @@ -3205,6 +3239,21 @@ void synchro_2(void) /* --------------------------------------------------------------------- */ case Xalien: + +#if 1 + + if (lev.wheel_cnt) + { + dx = lev.wheel_x; + dy = lev.wheel_y; + } + else + { + set_nearest_player_xy(x, y, &dx, &dy); + } + +#else + if (lev.wheel_cnt) { dx = lev.wheel_x; @@ -3242,6 +3291,8 @@ void synchro_2(void) dy = 0; } +#endif + if (RANDOM & 1) { if (y > dy) @@ -4888,8 +4939,8 @@ void synchro_2(void) done: - if (ply1.alive || ply2.alive) - lev.score += score; /* only get a score if someone is alive */ + if (ply[0].alive || ply[1].alive || ply[2].alive || ply[3].alive) + lev.score += score; /* only add a score if someone is alive */ RandomEM = random; diff --git a/src/game_em/tab_generate.c b/src/game_em/tab_generate.c index 75c47b37..2828ecd3 100644 --- a/src/game_em/tab_generate.c +++ b/src/game_em/tab_generate.c @@ -4435,7 +4435,7 @@ unsigned short map_ttl[128]; struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8]; /* map player number, frames and action to graphic info */ -struct GraphicInfo_EM graphic_info_em_player[2][SPR_MAX][8]; +struct GraphicInfo_EM graphic_info_em_player[MAX_PLAYERS][SPR_MAX][8]; void create_tab(int *invert, unsigned char *array) { @@ -4641,14 +4641,14 @@ void create_spr_graphics_info_em() { int i, j, k; - for (i = 0; i < 2; i++) + for (i = 0; i < MAX_PLAYERS; i++) { for (j = 0; j < SPR_MAX; j++) { for (k = 0; k < 8; k++) { struct GraphicInfo_EM *g = &graphic_info_em_player[i][j][k]; - int spr = map_spr[i][k][j]; + int spr = map_spr[i % 2][k][j]; g->bitmap = sprBitmap; g->src_x = (spr / 8) * TILEX; diff --git a/src/main.c b/src/main.c index 591b96ab..bc9a1e8b 100644 --- a/src/main.c +++ b/src/main.c @@ -290,60 +290,63 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = { "key_1", "key", - "red key" + "key 1" }, { "key_2", "key", - "yellow key" + "key 2" }, { "key_3", "key", - "green key" + "key 3" }, { "key_4", "key", - "blue key" + "key 4" }, { "gate_1", "gate", - "red door" + "door 1" }, { "gate_2", "gate", - "yellow door" + "door 2" }, { "gate_3", "gate", - "green door" + "door 3" }, { "gate_4", "gate", - "blue door" + "door 4" }, { "gate_1_gray", "gate", - "gray door (opened by red key)" + "gray door (opened by key 1)" }, { "gate_2_gray", "gate", - "gray door (opened by yellow key)"}, + "gray door (opened by key 2)" + }, { "gate_3_gray", "gate", - "gray door (opened by green key)"}, + "gray door (opened by key 3)" + }, { "gate_4_gray", "gate", - "gray door (opened by blue key)"}, + "gray door (opened by key 4)" + }, { "dynamite", "dynamite", @@ -524,22 +527,22 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = { "player_1", "player", - "yellow player" + "player 1" }, { "player_2", "player", - "red player" + "player 2" }, { "player_3", "player", - "green player" + "player 3" }, { "player_4", "player", - "blue player" + "player 4" }, { "bug.right", @@ -1136,22 +1139,22 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = { "em_gate_1", "gate", - "red door (EM style)" + "door 1 (EM style)" }, { "em_gate_2", "gate", - "yellow door (EM style)" + "door 2 (EM style)" }, { "em_gate_3", "gate", - "green door (EM style)" + "door 3 (EM style)" }, { "em_gate_4", "gate", - "blue door (EM style)" + "door 4 (EM style)" }, { "em_key_2_file_obsolete", @@ -1371,22 +1374,22 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = { "em_gate_1_gray", "gate", - "gray door (EM style, red key)" + "gray door (EM style, key 1)" }, { "em_gate_2_gray", "gate", - "gray door (EM style, yellow key)" + "gray door (EM style, key 2)" }, { "em_gate_3_gray", "gate", - "gray door (EM style, green key)" + "gray door (EM style, key 3)" }, { "em_gate_4_gray", "gate", - "gray door (EM style, blue key)" + "gray door (EM style, key 4)" }, { "unused_254", @@ -1476,122 +1479,122 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = { "conveyor_belt_1_left", "conveyor_belt", - "red conveyor belt (left)" + "conveyor belt 1 (left)" }, { "conveyor_belt_1_middle", "conveyor_belt", - "red conveyor belt (middle)" + "conveyor belt 1 (middle)" }, { "conveyor_belt_1_right", "conveyor_belt", - "red conveyor belt (right)" + "conveyor belt 1 (right)" }, { "conveyor_belt_1_switch_left", "conveyor_belt_switch", - "switch for red conveyor belt (left)" + "switch for conveyor belt 1 (left)" }, { "conveyor_belt_1_switch_middle", "conveyor_belt_switch", - "switch for red conveyor belt (middle)" + "switch for conveyor belt 1 (middle)" }, { "conveyor_belt_1_switch_right", "conveyor_belt_switch", - "switch for red conveyor belt (right)" + "switch for conveyor belt 1 (right)" }, { "conveyor_belt_2_left", "conveyor_belt", - "yellow conveyor belt (left)" + "conveyor belt 2 (left)" }, { "conveyor_belt_2_middle", "conveyor_belt", - "yellow conveyor belt (middle)" + "conveyor belt 2 (middle)" }, { "conveyor_belt_2_right", "conveyor_belt", - "yellow conveyor belt (right)" + "conveyor belt 2 (right)" }, { "conveyor_belt_2_switch_left", "conveyor_belt_switch", - "switch for yellow conveyor belt (left)" + "switch for conveyor belt 2 (left)" }, { "conveyor_belt_2_switch_middle", "conveyor_belt_switch", - "switch for yellow conveyor belt (middle)" + "switch for conveyor belt 2 (middle)" }, { "conveyor_belt_2_switch_right", "conveyor_belt_switch", - "switch for yellow conveyor belt (right)" + "switch for conveyor belt 2 (right)" }, { "conveyor_belt_3_left", "conveyor_belt", - "green conveyor belt (left)" + "conveyor belt 3 (left)" }, { "conveyor_belt_3_middle", "conveyor_belt", - "green conveyor belt (middle)" + "conveyor belt 3 (middle)" }, { "conveyor_belt_3_right", "conveyor_belt", - "green conveyor belt (right)" + "conveyor belt 3 (right)" }, { "conveyor_belt_3_switch_left", "conveyor_belt_switch", - "switch for green conveyor belt (left)" + "switch for conveyor belt 3 (left)" }, { "conveyor_belt_3_switch_middle", "conveyor_belt_switch", - "switch for green conveyor belt (middle)" + "switch for conveyor belt 3 (middle)" }, { "conveyor_belt_3_switch_right", "conveyor_belt_switch", - "switch for green conveyor belt (right)" + "switch for conveyor belt 3 (right)" }, { "conveyor_belt_4_left", "conveyor_belt", - "blue conveyor belt (left)" + "conveyor belt 4 (left)" }, { "conveyor_belt_4_middle", "conveyor_belt", - "blue conveyor belt (middle)" + "conveyor belt 4 (middle)" }, { "conveyor_belt_4_right", "conveyor_belt", - "blue conveyor belt (right)" + "conveyor belt 4 (right)" }, { "conveyor_belt_4_switch_left", "conveyor_belt_switch", - "switch for blue conveyor belt (left)" + "switch for conveyor belt 4 (left)" }, { "conveyor_belt_4_switch_middle", "conveyor_belt_switch", - "switch for blue conveyor belt (middle)" + "switch for conveyor belt 4 (middle)" }, { "conveyor_belt_4_switch_right", "conveyor_belt_switch", - "switch for blue conveyor belt (right)" + "switch for conveyor belt 4 (right)" }, { "landmine", @@ -3201,22 +3204,22 @@ struct ElementNameInfo element_name_info[MAX_NUM_ELEMENTS + 1] = { "em_key_1", "key", - "red key (EM style)" + "key 1 (EM style)" }, { "em_key_2", "key", - "yellow key (EM style)" + "key 2 (EM style)" }, { "em_key_3", "key", - "green key (EM style)" + "key 3 (EM style)" }, { "em_key_4", "key", - "blue key (EM style)" + "key 4 (EM style)" }, { "envelope_1", diff --git a/src/screens.c b/src/screens.c index c7382d07..999e933e 100644 --- a/src/screens.c +++ b/src/screens.c @@ -3091,8 +3091,10 @@ void HandleGameActions() return; } - if (level.native_em_level->ply1->alive == 0 && - level.native_em_level->ply2->alive == 0) /* all dead */ + if (level.native_em_level->ply[0]->alive == 0 && + level.native_em_level->ply[1]->alive == 0 && + level.native_em_level->ply[2]->alive == 0 && + level.native_em_level->ply[3]->alive == 0) /* all dead */ AllPlayersGone = TRUE; if (AllPlayersGone && !TAPE_IS_STOPPED(tape)) diff --git a/src/tools.c b/src/tools.c index 90d10c55..4711961d 100644 --- a/src/tools.c +++ b/src/tools.c @@ -4737,6 +4737,110 @@ em_player_mapping_list[] = SPR_still, 1, EL_PLAYER_2, ACTION_DEFAULT, -1, }, + { + SPR_walk + 0, 2, + EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP, + }, + { + SPR_walk + 1, 2, + EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT, + }, + { + SPR_walk + 2, 2, + EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN, + }, + { + SPR_walk + 3, 2, + EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT, + }, + { + SPR_push + 0, 2, + EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP, + }, + { + SPR_push + 1, 2, + EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT, + }, + { + SPR_push + 2, 2, + EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN, + }, + { + SPR_push + 3, 2, + EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT, + }, + { + SPR_spray + 0, 2, + EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP, + }, + { + SPR_spray + 1, 2, + EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT, + }, + { + SPR_spray + 2, 2, + EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN, + }, + { + SPR_spray + 3, 2, + EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT, + }, + { + SPR_walk + 0, 3, + EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP, + }, + { + SPR_walk + 1, 3, + EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT, + }, + { + SPR_walk + 2, 3, + EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN, + }, + { + SPR_walk + 3, 3, + EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT, + }, + { + SPR_push + 0, 3, + EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP, + }, + { + SPR_push + 1, 3, + EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT, + }, + { + SPR_push + 2, 3, + EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN, + }, + { + SPR_push + 3, 3, + EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT, + }, + { + SPR_spray + 0, 3, + EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP, + }, + { + SPR_spray + 1, 3, + EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT, + }, + { + SPR_spray + 2, 3, + EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN, + }, + { + SPR_spray + 3, 3, + EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT, + }, + { + SPR_still, 2, + EL_PLAYER_3, ACTION_DEFAULT, -1, + }, + { + SPR_still, 3, + EL_PLAYER_4, ACTION_DEFAULT, -1, + }, { -1, -1, @@ -5655,7 +5759,7 @@ unsigned int InitRND(long seed) void InitGraphicInfo_EM(void) { struct Mapping_EM_to_RND_object object_mapping[TILE_MAX]; - struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX]; + struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX]; int i, j, p; #if DEBUG_EM_GFX @@ -5677,7 +5781,7 @@ void InitGraphicInfo_EM(void) } /* always start with reliable default values */ - for (p = 0; p < 2; p++) + for (p = 0; p < MAX_PLAYERS; p++) { for (i = 0; i < SPR_MAX; i++) { @@ -6021,6 +6125,15 @@ void InitGraphicInfo_EM(void) g_em->height = TILEY - cy * step; } +#if 1 + /* 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; +#else /* 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 @@ -6028,6 +6141,13 @@ void InitGraphicInfo_EM(void) bit 5 - 0 ( 6 bit): graphic height */ g_em->unique_identifier = (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height; +#endif + +#if 0 + if (effective_element == EL_ROCK) + printf("::: EL_ROCK(%d, %d): %d, %d => %d\n", + effective_action, j, graphic, frame, g_em->unique_identifier); +#endif #if DEBUG_EM_GFX @@ -6129,7 +6249,7 @@ void InitGraphicInfo_EM(void) } } - for (p = 0; p < 2; p++) + for (p = 0; p < MAX_PLAYERS; p++) { for (i = 0; i < SPR_MAX; i++) { -- 2.34.1