X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=530345f5f5462971a895a01fdc4df939519f2b7f;hb=c1d1d669f782d9af7dfa71159962d5a89c62f03b;hp=c1691e61cb63635b48a9a71af671672b8ee2c6e5;hpb=f941ccddee3065d7531298e37ad4dcfcd892c1f8;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index c1691e61..530345f5 100644 --- a/src/game.c +++ b/src/game.c @@ -102,6 +102,8 @@ #define NUM_GAME_BUTTONS 6 /* forward declaration for internal use */ +static void CheckGravityMovement(struct PlayerInfo *); + static void MapGameButtons(); static void HandleGameButtons(struct GadgetInfo *); @@ -312,6 +314,19 @@ static void InitField(int x, int y, boolean init_game) Feld[x][y] = EL_LEERRAUM; break; + case EL_EM_KEY_1_FILE: + Feld[x][y] = EL_EM_KEY_1; + break; + case EL_EM_KEY_2_FILE: + Feld[x][y] = EL_EM_KEY_2; + break; + case EL_EM_KEY_3_FILE: + Feld[x][y] = EL_EM_KEY_3; + break; + case EL_EM_KEY_4_FILE: + Feld[x][y] = EL_EM_KEY_4; + break; + default: break; } @@ -339,6 +354,7 @@ void InitGame() player->action = 0; player->effective_action = 0; + player->programmed_action = 0; player->score = 0; player->gems_still_needed = level.edelsteine; @@ -371,6 +387,7 @@ void InitGame() player->move_delay = 0; player->last_move_dir = MV_NO_MOVING; + player->move_speed = (level.double_speed ? 4 : 8); player->snapped = FALSE; player->gone = FALSE; @@ -405,16 +422,12 @@ void InitGame() ScreenMovPos = 0; ScreenGfxPos = 0; - if (level.high_speed) - { - MoveSpeed = 4; - ScrollStepSize = TILEX/4; - } - else - { - MoveSpeed = 8; - ScrollStepSize = TILEX/8; - } + /* + MoveSpeed = (level.double_speed ? 4 : 8); + ScrollStepSize = TILEX / MoveSpeed; + */ + + ScrollStepSize = 0; AllPlayersGone = FALSE; SiebAktiv = FALSE; @@ -568,10 +581,10 @@ void InitGame() SBY_Lower = lev_fieldy - SCR_FIELDY + 1; } - if (lev_fieldx < SCR_FIELDX) + if (lev_fieldx + (SBX_Left == -1 ? 2 : 0) <= SCR_FIELDX) SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2; - if (lev_fieldy < SCR_FIELDY) + if (lev_fieldy + (SBY_Upper == -1 ? 2 : 0) <= SCR_FIELDY) SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2; scroll_x = SBX_Left; @@ -625,6 +638,7 @@ void InitGame() game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops; game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple; MapGameButtons(); + MapTapeButtons(); #endif XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc, @@ -975,6 +989,29 @@ int MovingOrBlocked2Element(int x, int y) return element; } +static int MovingOrBlocked2ElementIfNotLeaving(int x, int y) +{ + /* like MovingOrBlocked2Element(), but if element is moving + and (x,y) is the field the moving element is just leaving, + return EL_BLOCKED instead of the element value */ + int element = Feld[x][y]; + + if (IS_MOVING(x, y)) + { + if (element == EL_BLOCKED) + { + int oldx, oldy; + + Blocked2Moving(x, y, &oldx, &oldy); + return Feld[oldx][oldy]; + } + else + return EL_BLOCKED; + } + else + return element; +} + static void RemoveField(int x, int y) { Feld[x][y] = EL_LEERRAUM; @@ -1083,6 +1120,7 @@ void Explode(int ex, int ey, int phase, int mode) int num_phase = 9, delay = 2; int last_phase = num_phase * delay; int half_phase = (num_phase / 2) * delay; + int first_phase_after_start = EX_PHASE_START + 1; if (phase == EX_PHASE_START) /* initialize 'Store[][]' field */ { @@ -1197,9 +1235,20 @@ void Explode(int ex, int ey, int phase, int mode) x = ex; y = ey; - Frame[x][y] = (phaseframe_reset_delay > MoveSpeed) player->Frame = 0; + */ + + if (++player->frame_reset_delay > player->move_speed) + player->Frame = 0; } if (tape.recording && num_stored_actions >= MAX_PLAYERS && save_tape_entry) @@ -3509,6 +3569,26 @@ void GameActions() { int actual_player_action = stored_player[i].effective_action; + if (stored_player[i].programmed_action) + { +#if 0 + /* this is very bad and need to be fixed!!! */ + unsigned long move_delay = stored_player[i].move_delay; + + /* + if (FrameReached(&move_delay, MoveSpeed)) + */ + + if (FrameReached(&move_delay, stored_player[i].move_speed)) + { + actual_player_action = stored_player[i].programmed_action; + stored_player[i].programmed_action = 0; + } +#else + actual_player_action = stored_player[i].programmed_action; +#endif + } + if (recorded_player_action) actual_player_action = recorded_player_action[i]; @@ -3795,6 +3875,32 @@ void ScrollLevel(int dx, int dy) redraw_mask |= REDRAW_FIELD; } +static void CheckGravityMovement(struct PlayerInfo *player) +{ + if (level.gravity && !player->programmed_action) + { + int move_dir_vertical = player->action & (MV_UP | MV_DOWN); + int move_dir_horizontal = player->action & (MV_LEFT | MV_RIGHT); + int move_dir = + (player->last_move_dir & (MV_LEFT | MV_RIGHT) ? + (move_dir_vertical ? move_dir_vertical : move_dir_horizontal) : + (move_dir_horizontal ? move_dir_horizontal : move_dir_vertical)); + int jx = player->jx, jy = player->jy; + 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 new_jx = jx + dx, new_jy = jy + dy; + boolean field_under_player_is_free = + (IN_LEV_FIELD(jx, jy + 1) && IS_FREE(jx, jy + 1)); + boolean player_is_moving_to_valid_field = + (IN_LEV_FIELD(new_jx, new_jy) && + (Feld[new_jx][new_jy] == EL_SP_BASE || + Feld[new_jx][new_jy] == EL_ERDREICH)); + + if (field_under_player_is_free && !player_is_moving_to_valid_field) + player->programmed_action = MV_DOWN; + } +} + boolean MoveFigureOneStep(struct PlayerInfo *player, int dx, int dy, int real_dx, int real_dy) { @@ -3817,7 +3923,11 @@ boolean MoveFigureOneStep(struct PlayerInfo *player, if (!options.network && !AllPlayersInSight(player, new_jx, new_jy)) return MF_NO_ACTION; +#if 0 element = MovingOrBlocked2Element(new_jx, new_jy); +#else + element = MovingOrBlocked2ElementIfNotLeaving(new_jx, new_jy); +#endif if (DONT_GO_TO(element)) { @@ -3847,7 +3957,12 @@ boolean MoveFigureOneStep(struct PlayerInfo *player, jy = player->jy = new_jy; StorePlayer[jx][jy] = player->element_nr; + /* player->MovPos = (dx > 0 || dy > 0 ? -1 : 1) * (TILEX - TILEX / MoveSpeed); + */ + + player->MovPos = + (dx > 0 || dy > 0 ? -1 : 1) * (TILEX - TILEX / player->move_speed); ScrollFigure(player, SCROLL_INIT); @@ -3863,22 +3978,39 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) if (player->gone || (!dx && !dy)) return FALSE; + /* if (!FrameReached(&player->move_delay, MoveSpeed) && !tape.playing) return FALSE; + */ + + if (!FrameReached(&player->move_delay, player->move_speed) && !tape.playing) + return FALSE; + + /* remove the last programmed player action */ + player->programmed_action = 0; if (player->MovPos) { /* should only happen if pre-1.2 tape recordings are played */ /* this is only for backward compatibility */ + /* int old_move_speed = MoveSpeed; + */ + + int old_move_speed = player->move_speed; #if DEBUG printf("THIS SHOULD ONLY HAPPEN WITH PRE-1.2 LEVEL TAPES.\n"); #endif /* scroll remaining steps with finest movement resolution */ + + /* MoveSpeed = 8; + */ + + player->move_speed = 8; while (player->MovPos) { @@ -3889,7 +4021,12 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) BackToFront(); } + /* MoveSpeed = old_move_speed; + */ + + player->move_speed = old_move_speed; + } if (player->last_move_dir & (MV_LEFT | MV_RIGHT)) @@ -3992,7 +4129,11 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) player->last_move_dir = player->MovDir; } else + { + CheckGravityMovement(player); + player->last_move_dir = MV_NO_MOVING; + } TestIfHeroHitsBadThing(jx, jy); @@ -4006,6 +4147,7 @@ void ScrollFigure(struct PlayerInfo *player, int mode) { int jx = player->jx, jy = player->jy; int last_jx = player->last_jx, last_jy = player->last_jy; + int move_stepsize = TILEX / player->move_speed; if (!player->active || player->gone || !player->MovPos) return; @@ -4013,7 +4155,7 @@ void ScrollFigure(struct PlayerInfo *player, int mode) if (mode == SCROLL_INIT) { player->actual_frame_counter = FrameCounter; - player->GfxPos = ScrollStepSize * (player->MovPos / ScrollStepSize); + player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); if (Feld[last_jx][last_jy] == EL_LEERRAUM) Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING; @@ -4024,16 +4166,52 @@ void ScrollFigure(struct PlayerInfo *player, int mode) else if (!FrameReached(&player->actual_frame_counter, 1)) return; - player->MovPos += (player->MovPos > 0 ? -1 : 1) * TILEX / MoveSpeed; - player->GfxPos = ScrollStepSize * (player->MovPos / ScrollStepSize); + player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; + player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); if (Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) Feld[last_jx][last_jy] = EL_LEERRAUM; + +#if 0 + if (!player->MovPos && level.gravity) + { + if (player->action == MV_NO_MOVING) + player->programmed_action = MV_DOWN; + else if (player->action == MV_UP) + { + } + else if (player->action & (MV_LEFT | MV_RIGHT)) + { + } + } +#else + if (!player->MovPos) + CheckGravityMovement(player); +#endif + + DrawPlayer(player); if (!player->MovPos) { + if (IS_QUICK_GATE(Feld[last_jx][last_jy])) + { + /* continue with normal speed after moving through port */ + /* FIX THIS: what about player already having eaten a speed pill? */ + + /* + MoveSpeed = 8; + ScrollStepSize = TILEX / MoveSpeed; + */ + + player->move_speed = 8; + + /* don't wait for the next move -- the whole move delay stuff + is worse at the moment; FIX THIS! ;-) */ + player->move_delay = 0; + } + player->last_jx = jx; player->last_jy = jy; @@ -4053,6 +4231,9 @@ void ScrollScreen(struct PlayerInfo *player, int mode) if (mode == SCROLL_INIT) { + /* set scrolling step size according to actual player's moving speed */ + ScrollStepSize = TILEX / player->move_speed; + screen_frame_counter = FrameCounter; ScreenMovDir = player->MovDir; ScreenMovPos = player->MovPos; @@ -4064,7 +4245,7 @@ void ScrollScreen(struct PlayerInfo *player, int mode) if (ScreenMovPos) { - ScreenMovPos += (ScreenMovPos > 0 ? -1 : 1) * TILEX / MoveSpeed; + ScreenMovPos += (ScreenMovPos > 0 ? -1 : 1) * ScrollStepSize; ScreenGfxPos = ScrollStepSize * (ScreenMovPos / ScrollStepSize); redraw_mask |= REDRAW_FIELD; } @@ -4099,7 +4280,11 @@ void TestIfGoodThingHitsBadThing(int goodx, int goody) if (!IN_LEV_FIELD(x, y)) continue; +#if 0 element = Feld[x][y]; +#else + element = MovingOrBlocked2ElementIfNotLeaving(x, y); +#endif if (DONT_TOUCH(element)) { @@ -4282,6 +4467,10 @@ int DigField(struct PlayerInfo *player, { int jx = player->jx, jy = player->jy; int dx = x - jx, dy = y - jy; + int move_direction = (dx == -1 ? MV_LEFT : + dx == +1 ? MV_RIGHT : + dy == -1 ? MV_UP : + dy == +1 ? MV_DOWN : MV_NO_MOVING); int element; if (!player->MovPos) @@ -4338,8 +4527,14 @@ int DigField(struct PlayerInfo *player, case EL_SPEED_PILL: RemoveField(x, y); + + player->move_speed = 4; + + /* MoveSpeed = 4; - ScrollStepSize = TILEX/4; + ScrollStepSize = TILEX / MoveSpeed; + */ + PlaySoundLevel(x, y, SND_PONG); break; @@ -4384,7 +4579,27 @@ int DigField(struct PlayerInfo *player, case EL_SCHLUESSEL3: case EL_SCHLUESSEL4: { - int key_nr = element-EL_SCHLUESSEL1; + int key_nr = element - EL_SCHLUESSEL1; + + RemoveField(x, y); + player->key[key_nr] = TRUE; + RaiseScoreElement(EL_SCHLUESSEL); + DrawMiniGraphicExt(drawto, gc, + DX_KEYS+key_nr*MINI_TILEX, DY_KEYS, + GFX_SCHLUESSEL1+key_nr); + DrawMiniGraphicExt(window, gc, + DX_KEYS+key_nr*MINI_TILEX, DY_KEYS, + GFX_SCHLUESSEL1+key_nr); + PlaySoundLevel(x, y, SND_PONG); + break; + } + + case EL_EM_KEY_1: + case EL_EM_KEY_2: + case EL_EM_KEY_3: + case EL_EM_KEY_4: + { + int key_nr = element - EL_EM_KEY_1; RemoveField(x, y); player->key[key_nr] = TRUE; @@ -4480,7 +4695,7 @@ int DigField(struct PlayerInfo *player, case EL_PFORTE2: case EL_PFORTE3: case EL_PFORTE4: - if (!player->key[element-EL_PFORTE1]) + if (!player->key[element - EL_PFORTE1]) return MF_NO_ACTION; break; @@ -4488,10 +4703,42 @@ int DigField(struct PlayerInfo *player, case EL_PFORTE2X: case EL_PFORTE3X: case EL_PFORTE4X: - if (!player->key[element-EL_PFORTE1X]) + if (!player->key[element - EL_PFORTE1X]) return MF_NO_ACTION; break; + case EL_EM_GATE_1: + case EL_EM_GATE_2: + case EL_EM_GATE_3: + case EL_EM_GATE_4: + if (!player->key[element - EL_EM_GATE_1]) + return MF_NO_ACTION; + + if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) + return MF_NO_ACTION; + + /* automatically move to the next field with double speed */ + player->programmed_action = move_direction; + player->move_speed = 4; + + break; + + case EL_EM_GATE_1X: + case EL_EM_GATE_2X: + case EL_EM_GATE_3X: + case EL_EM_GATE_4X: + if (!player->key[element - EL_EM_GATE_1X]) + return MF_NO_ACTION; + + if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) + return MF_NO_ACTION; + + /* automatically move to the next field with double speed */ + player->programmed_action = move_direction; + player->move_speed = 4; + + break; + case EL_SP_PORT1_LEFT: case EL_SP_PORT2_LEFT: case EL_SP_PORT1_RIGHT: @@ -4526,6 +4773,16 @@ int DigField(struct PlayerInfo *player, !IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) return MF_NO_ACTION; + + /* automatically move to the next field with double speed */ + player->programmed_action = move_direction; + player->move_speed = 4; + + /* + MoveSpeed = 4; + ScrollStepSize = TILEX / MoveSpeed; + */ + break; case EL_AUSGANG_ZU: @@ -4985,7 +5242,8 @@ static void HandleGameButtons(struct GadgetInfo *gi) break; } - if (Request("Do you really want to quit the game ?", + if (level_editor_test_game || + Request("Do you really want to quit the game ?", REQ_ASK | REQ_STAY_CLOSED)) { #ifndef MSDOS