(s)==SND_TYGER || (s)==SND_VOYAGER || \
(s)==SND_TWILIGHT)
-/* score for elements */
-#define SC_EDELSTEIN 0
-#define SC_DIAMANT 1
-#define SC_KAEFER 2
-#define SC_FLIEGER 3
-#define SC_MAMPFER 4
-#define SC_ROBOT 5
-#define SC_PACMAN 6
-#define SC_KOKOSNUSS 7
-#define SC_DYNAMIT 8
-#define SC_SCHLUESSEL 9
-#define SC_ZEITBONUS 10
+/* values for player movement speed (which is in fact a delay value) */
+#define MOVE_DELAY_NORMAL_SPEED 8
+#define MOVE_DELAY_HIGH_SPEED 4
+#define DOUBLE_MOVE_DELAY(x) (x = (x <= MOVE_DELAY_HIGH_SPEED ? x * 2 : x))
+#define HALVE_MOVE_DELAY(x) (x = (x >= MOVE_DELAY_HIGH_SPEED ? x / 2 : x))
+#define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value))
+#define HALVE_PLAYER_SPEED(p) (DOUBLE_MOVE_DELAY((p)->move_delay_value))
+
+/* game button identifiers */
+#define GAME_CTRL_ID_STOP 0
+#define GAME_CTRL_ID_PAUSE 1
+#define GAME_CTRL_ID_PLAY 2
+#define SOUND_CTRL_ID_MUSIC 3
+#define SOUND_CTRL_ID_LOOPS 4
+#define SOUND_CTRL_ID_SIMPLE 5
+
+#define NUM_GAME_BUTTONS 6
+
+/* forward declaration for internal use */
+static void CheckGravityMovement(struct PlayerInfo *);
+
+static void MapGameButtons();
+static void HandleGameButtons(struct GadgetInfo *);
+
+static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
player->present = TRUE;
- /*
- if (!network_playing || player->connected)
- */
-
if (!options.network || player->connected)
{
player->active = TRUE;
+ player->gone = FALSE;
/* remove potentially duplicate players */
if (StorePlayer[jx][jy] == Feld[x][y])
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;
}
player->action = 0;
player->effective_action = 0;
+ player->programmed_action = 0;
player->score = 0;
player->gems_still_needed = level.edelsteine;
player->move_delay = 0;
player->last_move_dir = MV_NO_MOVING;
+ player->move_delay_value =
+ (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+
player->snapped = FALSE;
- player->gone = FALSE;
+ player->gone = TRUE;
player->last_jx = player->last_jy = 0;
player->jx = player->jy = 0;
ScreenMovPos = 0;
ScreenGfxPos = 0;
- if (level.high_speed)
- {
- MoveSpeed = 4;
- ScrollStepSize = TILEX/4;
- }
- else
- {
- MoveSpeed = 8;
- ScrollStepSize = TILEX/8;
- }
+ ScrollStepSize = 0; /* will be correctly initialized by ScrollScreen() */
AllPlayersGone = FALSE;
SiebAktiv = FALSE;
{
player->present = TRUE;
player->active = TRUE;
+ player->gone = FALSE;
some_player->present = FALSE;
StorePlayer[jx][jy] = player->element_nr;
int jx = player->jx, jy = player->jy;
player->active = FALSE;
+ player->gone = TRUE;
StorePlayer[jx][jy] = 0;
Feld[jx][jy] = EL_LEERRAUM;
}
int jx = player->jx, jy = player->jy;
player->active = FALSE;
+ player->gone = TRUE;
StorePlayer[jx][jy] = 0;
Feld[jx][jy] = EL_LEERRAUM;
}
emulate_sb ? EMU_SOKOBAN :
emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
- scroll_x = scroll_y = -1;
- if (local_player->jx >= MIDPOSX-1)
- scroll_x = (local_player->jx <= lev_fieldx-MIDPOSX ?
+ /* determine border element for this level */
+ SetBorderElement();
+
+ if (BorderElement == EL_LEERRAUM)
+ {
+ SBX_Left = 0;
+ SBX_Right = lev_fieldx - SCR_FIELDX;
+ SBY_Upper = 0;
+ SBY_Lower = lev_fieldy - SCR_FIELDY;
+ }
+ else
+ {
+ SBX_Left = -1;
+ SBX_Right = lev_fieldx - SCR_FIELDX + 1;
+ SBY_Upper = -1;
+ SBY_Lower = lev_fieldy - SCR_FIELDY + 1;
+ }
+
+ if (lev_fieldx + (SBX_Left == -1 ? 2 : 0) <= SCR_FIELDX)
+ SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2;
+
+ if (lev_fieldy + (SBY_Upper == -1 ? 2 : 0) <= SCR_FIELDY)
+ SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2;
+
+ scroll_x = SBX_Left;
+ scroll_y = SBY_Upper;
+ if (local_player->jx >= SBX_Left + MIDPOSX)
+ scroll_x = (local_player->jx <= SBX_Right + MIDPOSX ?
local_player->jx - MIDPOSX :
- lev_fieldx - SCR_FIELDX + 1);
- if (local_player->jy >= MIDPOSY-1)
- scroll_y = (local_player->jy <= lev_fieldy-MIDPOSY ?
+ SBX_Right);
+ if (local_player->jy >= SBY_Upper + MIDPOSY)
+ scroll_y = (local_player->jy <= SBY_Lower + MIDPOSY ?
local_player->jy - MIDPOSY :
- lev_fieldy - SCR_FIELDY + 1);
+ SBY_Lower);
CloseDoor(DOOR_CLOSE_1);
DrawAllPlayers();
FadeToFront();
- XCopyArea(display, pix[PIX_DOOR], pix[PIX_DB_DOOR], gc,
- DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
- DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
- DrawTextExt(pix[PIX_DB_DOOR], gc,
- DOOR_GFX_PAGEX1 + XX_LEVEL, DOOR_GFX_PAGEY1 + YY_LEVEL,
- int2str(level_nr, 2), FS_SMALL, FC_YELLOW);
- DrawTextExt(pix[PIX_DB_DOOR], gc,
- DOOR_GFX_PAGEX1 + XX_EMERALDS, DOOR_GFX_PAGEY1 + YY_EMERALDS,
- int2str(local_player->gems_still_needed,3), FS_SMALL, FC_YELLOW);
- DrawTextExt(pix[PIX_DB_DOOR], gc,
- DOOR_GFX_PAGEX1 + XX_DYNAMITE, DOOR_GFX_PAGEY1 + YY_DYNAMITE,
- int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW);
- DrawTextExt(pix[PIX_DB_DOOR], gc,
- DOOR_GFX_PAGEX1 + XX_SCORE, DOOR_GFX_PAGEY1 + YY_SCORE,
- int2str(local_player->score, 5), FS_SMALL, FC_YELLOW);
- DrawTextExt(pix[PIX_DB_DOOR], gc,
- DOOR_GFX_PAGEX1 + XX_TIME, DOOR_GFX_PAGEY1 + YY_TIME,
- int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
-
- DrawGameButton(BUTTON_GAME_STOP);
- DrawGameButton(BUTTON_GAME_PAUSE);
- DrawGameButton(BUTTON_GAME_PLAY);
- DrawSoundDisplay(BUTTON_SOUND_MUSIC | (setup.sound_music ? BUTTON_ON : 0));
- DrawSoundDisplay(BUTTON_SOUND_LOOPS | (setup.sound_loops ? BUTTON_ON : 0));
- DrawSoundDisplay(BUTTON_SOUND_SIMPLE | (setup.sound_simple ? BUTTON_ON : 0));
+ /* copy default game door content to main double buffer */
+ XCopyArea(display, pix[PIX_DOOR], drawto, gc,
+ DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+
+ DrawText(DX + XX_LEVEL, DY + YY_LEVEL,
+ int2str(level_nr, 2), FS_SMALL, FC_YELLOW);
+ DrawText(DX + XX_EMERALDS, DY + YY_EMERALDS,
+ int2str(local_player->gems_still_needed,3), FS_SMALL, FC_YELLOW);
+ DrawText(DX + XX_DYNAMITE, DY + YY_DYNAMITE,
+ int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW);
+ DrawText(DX + XX_SCORE, DY + YY_SCORE,
+ int2str(local_player->score, 5), FS_SMALL, FC_YELLOW);
+ DrawText(DX + XX_TIME, DY + YY_TIME,
+ int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+
+ UnmapGameButtons();
+ game_gadget[SOUND_CTRL_ID_MUSIC]->checked = setup.sound_music;
+ game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops;
+ game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple;
+ MapGameButtons();
+ MapTapeButtons();
+
+ /* copy actual game door content to door double buffer for OpenDoor() */
XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
- DX + GAME_CONTROL_XPOS, DY + GAME_CONTROL_YPOS,
- GAME_CONTROL_XSIZE, 2 * GAME_CONTROL_YSIZE,
- DOOR_GFX_PAGEX1 + GAME_CONTROL_XPOS,
- DOOR_GFX_PAGEY1 + GAME_CONTROL_YPOS);
+ DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
- OpenDoor(DOOR_OPEN_1);
+ OpenDoor(DOOR_OPEN_ALL);
if (setup.sound_music)
PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
if (options.verbose)
{
for (i=0; i<4; i++)
- printf("Spieler %d %saktiv.\n",
- i+1, (stored_player[i].active ? "" : "nicht "));
+ printf("Player %d %sactive.\n",
+ i + 1, (stored_player[i].active ? "" : "not "));
}
}
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;
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 */
{
RemoveMovingField(x, y);
}
- if (!IN_LEV_FIELD(x, y) || IS_MASSIV(element) || element == EL_BURNING)
+ if (!IN_LEV_FIELD(x, y) || IS_MASSIVE(element) || element == EL_BURNING)
continue;
if ((mode!=EX_NORMAL || center_element == EL_AMOEBA2DIAM) &&
x = ex;
y = ey;
- Frame[x][y] = (phase<last_phase ? phase+1 : 0);
+ Frame[x][y] = (phase < last_phase ? phase + 1 : 0);
- if (phase == half_phase)
+ if (phase == first_phase_after_start)
+ {
+ int element = Store2[x][y];
+
+ if (element == EL_BLACK_ORB)
+ {
+ Feld[x][y] = Store2[x][y];
+ Store2[x][y] = 0;
+ Bang(x, y);
+ }
+ }
+ else if (phase == half_phase)
{
int element = Store2[x][y];
int y = ey+j*xy[i%4][1];
int element;
- if (!IN_LEV_FIELD(x, y) || IS_MASSIV(Feld[x][y]))
+ if (!IN_LEV_FIELD(x, y) || IS_MASSIVE(Feld[x][y]))
break;
element = Feld[x][y];
case EL_SCHLUESSEL2:
case EL_SCHLUESSEL3:
case EL_SCHLUESSEL4:
+ case EL_EM_KEY_1:
+ case EL_EM_KEY_2:
+ case EL_EM_KEY_3:
+ case EL_EM_KEY_4:
sound = SND_KINK;
break;
case EL_ZEIT_VOLL:
player_action &= JOY_BUTTON;
stored_player_action[player->index_nr] = player_action;
-
-#if 0
- /* this allows cycled sequences of PlayerActions() */
- if (num_stored_actions >= MAX_PLAYERS)
- {
- TapeRecordAction(stored_player_action);
- num_stored_actions = 0;
- }
-#endif
-
}
else if (tape.playing && snapped)
SnapField(player, 0, 0); /* stop snapping */
}
else
{
+ /* no actions for this player (no input at player's configured device) */
+
DigField(player, 0, 0, 0, 0, DF_NO_PUSH);
SnapField(player, 0, 0);
- if (++player->frame_reset_delay > MoveSpeed)
+ CheckGravityMovement(player);
+
+ if (++player->frame_reset_delay > player->move_delay_value)
player->Frame = 0;
}
action_delay_value =
(tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay);
- /*
- if (tape.playing && tape.fast_forward)
- {
- char buf[100];
+ /* ---------- main game synchronization point ---------- */
- sprintf(buf, "FFWD: %ld ms", action_delay_value);
- print_debug(buf);
- }
- */
-
-
- /* main game synchronization point */
-
-
-
-
-#if 1
WaitUntilDelayReached(&action_delay, action_delay_value);
-#else
-
- while (!DelayReached(&action_delay, action_delay_value))
- {
- char buf[100];
-
- sprintf(buf, "%ld %ld %ld",
- Counter(), action_delay, action_delay_value);
- print_debug(buf);
- }
- print_debug("done");
-
-#endif
-
-
-
if (network_playing && !network_player_action_received)
{
}
}
-
- /*
- if (tape.pausing || (tape.playing && !TapePlayDelay()))
- return;
- else if (tape.recording)
- TapeRecordDelay();
- */
-
if (tape.pausing)
return;
{
int actual_player_action = stored_player[i].effective_action;
+ if (stored_player[i].programmed_action)
+ actual_player_action = stored_player[i].programmed_action;
+
if (recorded_player_action)
actual_player_action = recorded_player_action[i];
ScrollScreen(NULL, SCROLL_GO_ON);
- /*
- if (tape.pausing || (tape.playing && !TapePlayDelay()))
- return;
- else if (tape.recording)
- TapeRecordDelay();
- */
-
-
-
-
#ifdef DEBUG
- /*
+#if 0
if (TimeFrames == 0 && !local_player->gone)
{
extern unsigned int last_RND();
printf("DEBUG: %03d last RND was %d \t [state checksum is %d]\n",
- TimePlayed,
- last_RND(),
- getStateCheckSum(TimePlayed));
+ TimePlayed, last_RND(), getStateCheckSum(TimePlayed));
}
- */
#endif
-
-
+#endif
#ifdef DEBUG
- /*
+#if 0
if (GameFrameDelay >= 500)
printf("FrameCounter == %d\n", FrameCounter);
- */
#endif
-
-
+#endif
Blocked2Moving(x, y, &oldx, &oldy);
if (!IS_MOVING(oldx, oldy))
{
- printf("GameActions(): (BLOCKED=>MOVING) context corrupted!\n");
+ printf("GameActions(): (BLOCKED => MOVING) context corrupted!\n");
printf("GameActions(): BLOCKED: x = %d, y = %d\n", x, y);
printf("GameActions(): !MOVING: oldx = %d, oldy = %d\n", oldx, oldy);
printf("GameActions(): This should never happen!\n");
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)
{
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))
{
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_delay_value);
ScrollFigure(player, SCROLL_INIT);
if (player->gone || (!dx && !dy))
return FALSE;
- if (!FrameReached(&player->move_delay, MoveSpeed) && !tape.playing)
+ if (!FrameReached(&player->move_delay, player->move_delay_value) &&
+ !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 original_move_delay_value = player->move_delay_value;
#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_delay_value = MOVE_DELAY_NORMAL_SPEED;
while (player->MovPos)
{
BackToFront();
}
- MoveSpeed = old_move_speed;
+ player->move_delay_value = original_move_delay_value;
}
if (player->last_move_dir & (MV_LEFT | MV_RIGHT))
{
if (jx != old_jx) /* player has moved horizontally */
{
- if ((player->MovDir == MV_LEFT && scroll_x > jx-MIDPOSX+offset) ||
- (player->MovDir == MV_RIGHT && scroll_x < jx-MIDPOSX-offset))
+ if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
+ (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
scroll_x = jx-MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
/* don't scroll over playfield boundaries */
- if (scroll_x < -1 || scroll_x > lev_fieldx - SCR_FIELDX + 1)
- scroll_x = (scroll_x < -1 ? -1 : lev_fieldx - SCR_FIELDX + 1);
+ if (scroll_x < SBX_Left || scroll_x > SBX_Right)
+ scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
/* don't scroll more than one field at a time */
scroll_x = old_scroll_x + SIGN(scroll_x - old_scroll_x);
}
else /* player has moved vertically */
{
- if ((player->MovDir == MV_UP && scroll_y > jy-MIDPOSY+offset) ||
- (player->MovDir == MV_DOWN && scroll_y < jy-MIDPOSY-offset))
+ if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
+ (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
scroll_y = jy-MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
/* don't scroll over playfield boundaries */
- if (scroll_y < -1 || scroll_y > lev_fieldy - SCR_FIELDY + 1)
- scroll_y = (scroll_y < -1 ? -1 : lev_fieldy - SCR_FIELDY + 1);
+ if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
+ scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
/* don't scroll more than one field at a time */
scroll_y = old_scroll_y + SIGN(scroll_y - old_scroll_y);
player->last_move_dir = player->MovDir;
}
else
+ {
+ CheckGravityMovement(player);
+
player->last_move_dir = MV_NO_MOVING;
+ }
TestIfHeroHitsBadThing(jx, jy);
{
int jx = player->jx, jy = player->jy;
int last_jx = player->last_jx, last_jy = player->last_jy;
+ int move_stepsize = TILEX / player->move_delay_value;
if (!player->active || player->gone || !player->MovPos)
return;
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;
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;
+ /* before DrawPlayer() to draw correct player graphic for this case */
+ if (player->MovPos == 0)
+ CheckGravityMovement(player);
+
DrawPlayer(player);
- if (!player->MovPos)
+ if (player->MovPos == 0)
{
+ if (IS_QUICK_GATE(Feld[last_jx][last_jy]))
+ {
+ /* continue with normal speed after quickly moving through gate */
+ HALVE_PLAYER_SPEED(player);
+
+ /* be able to make the next move without delay */
+ player->move_delay = 0;
+ }
+
player->last_jx = jx;
player->last_jy = jy;
if (mode == SCROLL_INIT)
{
+ /* set scrolling step size according to actual player's moving speed */
+ ScrollStepSize = TILEX / player->move_delay_value;
+
screen_frame_counter = FrameCounter;
ScreenMovDir = player->MovDir;
ScreenMovPos = player->MovPos;
if (ScreenMovPos)
{
- ScreenMovPos += (ScreenMovPos > 0 ? -1 : 1) * TILEX / MoveSpeed;
+ ScreenMovPos += (ScreenMovPos > 0 ? -1 : 1) * ScrollStepSize;
ScreenGfxPos = ScrollStepSize * (ScreenMovPos / ScrollStepSize);
redraw_mask |= REDRAW_FIELD;
}
if (!IN_LEV_FIELD(x, y))
continue;
+#if 0
element = Feld[x][y];
+#else
+ element = MovingOrBlocked2ElementIfNotLeaving(x, y);
+#endif
if (DONT_TOUCH(element))
{
{
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)
case EL_SPEED_PILL:
RemoveField(x, y);
- MoveSpeed = 4;
- ScrollStepSize = TILEX/4;
+ player->move_delay_value = MOVE_DELAY_HIGH_SPEED;
PlaySoundLevel(x, y, SND_PONG);
break;
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;
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;
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;
+ DOUBLE_PLAYER_SPEED(player);
+
+ 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;
+ DOUBLE_PLAYER_SPEED(player);
+
+ break;
+
case EL_SP_PORT1_LEFT:
case EL_SP_PORT2_LEFT:
case EL_SP_PORT1_RIGHT:
!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;
+ DOUBLE_PLAYER_SPEED(player);
+
break;
case EL_AUSGANG_ZU:
PlaySoundLevel(x, y, SND_BUING);
- /*
- player->gone = TRUE;
- PlaySoundLevel(x, y, SND_BUING);
-
- if (!local_player->friends_still_needed)
- player->LevelSolved = player->GameOver = TRUE;
- */
-
break;
case EL_BIRNE_AUS:
volume = PSND_MAX_VOLUME;
#ifndef MSDOS
- stereo = (sx-SCR_FIELDX/2)*12;
+ stereo = (sx - SCR_FIELDX/2) * 12;
#else
- stereo = PSND_MIDDLE+(2*sx-(SCR_FIELDX-1))*5;
- if(stereo > PSND_MAX_RIGHT) stereo = PSND_MAX_RIGHT;
- if(stereo < PSND_MAX_LEFT) stereo = PSND_MAX_LEFT;
+ stereo = PSND_MIDDLE + (2 * sx - (SCR_FIELDX - 1)) * 5;
+ if (stereo > PSND_MAX_RIGHT)
+ stereo = PSND_MAX_RIGHT;
+ if (stereo < PSND_MAX_LEFT)
+ stereo = PSND_MAX_LEFT;
#endif
if (!IN_SCR_FIELD(sx, sy))
{
- int dx = ABS(sx-SCR_FIELDX/2)-SCR_FIELDX/2;
- int dy = ABS(sy-SCR_FIELDY/2)-SCR_FIELDY/2;
+ int dx = ABS(sx - SCR_FIELDX/2) - SCR_FIELDX/2;
+ int dy = ABS(sy - SCR_FIELDY/2) - SCR_FIELDY/2;
- volume -= volume*(dx > dy ? dx : dy)/silence_distance;
+ volume -= volume * (dx > dy ? dx : dy) / silence_distance;
}
PlaySoundExt(sound_nr, volume, stereo, PSND_NO_LOOP);
break;
}
}
+
+/* ---------- new game button stuff ---------------------------------------- */
+
+/* graphic position values for game buttons */
+#define GAME_BUTTON_XSIZE 30
+#define GAME_BUTTON_YSIZE 30
+#define GAME_BUTTON_XPOS 5
+#define GAME_BUTTON_YPOS 215
+#define SOUND_BUTTON_XPOS 5
+#define SOUND_BUTTON_YPOS (GAME_BUTTON_YPOS + GAME_BUTTON_YSIZE)
+
+#define GAME_BUTTON_STOP_XPOS (GAME_BUTTON_XPOS + 0 * GAME_BUTTON_XSIZE)
+#define GAME_BUTTON_PAUSE_XPOS (GAME_BUTTON_XPOS + 1 * GAME_BUTTON_XSIZE)
+#define GAME_BUTTON_PLAY_XPOS (GAME_BUTTON_XPOS + 2 * GAME_BUTTON_XSIZE)
+#define SOUND_BUTTON_MUSIC_XPOS (SOUND_BUTTON_XPOS + 0 * GAME_BUTTON_XSIZE)
+#define SOUND_BUTTON_LOOPS_XPOS (SOUND_BUTTON_XPOS + 1 * GAME_BUTTON_XSIZE)
+#define SOUND_BUTTON_SIMPLE_XPOS (SOUND_BUTTON_XPOS + 2 * GAME_BUTTON_XSIZE)
+
+static struct
+{
+ int x, y;
+ int gadget_id;
+ char *infotext;
+} gamebutton_info[NUM_GAME_BUTTONS] =
+{
+ {
+ GAME_BUTTON_STOP_XPOS, GAME_BUTTON_YPOS,
+ GAME_CTRL_ID_STOP,
+ "stop game"
+ },
+ {
+ GAME_BUTTON_PAUSE_XPOS, GAME_BUTTON_YPOS,
+ GAME_CTRL_ID_PAUSE,
+ "pause game"
+ },
+ {
+ GAME_BUTTON_PLAY_XPOS, GAME_BUTTON_YPOS,
+ GAME_CTRL_ID_PLAY,
+ "play game"
+ },
+ {
+ SOUND_BUTTON_MUSIC_XPOS, SOUND_BUTTON_YPOS,
+ SOUND_CTRL_ID_MUSIC,
+ "background music on/off"
+ },
+ {
+ SOUND_BUTTON_LOOPS_XPOS, SOUND_BUTTON_YPOS,
+ SOUND_CTRL_ID_LOOPS,
+ "sound loops on/off"
+ },
+ {
+ SOUND_BUTTON_SIMPLE_XPOS, SOUND_BUTTON_YPOS,
+ SOUND_CTRL_ID_SIMPLE,
+ "normal sounds on/off"
+ }
+};
+
+void CreateGameButtons()
+{
+ int i;
+
+ for (i=0; i<NUM_GAME_BUTTONS; i++)
+ {
+ Pixmap gd_pixmap = pix[PIX_DOOR];
+ struct GadgetInfo *gi;
+ int button_type;
+ boolean checked;
+ unsigned long event_mask;
+ int gd_xoffset, gd_yoffset;
+ int gd_x1, gd_x2, gd_y1, gd_y2;
+ int id = i;
+
+ gd_xoffset = gamebutton_info[i].x;
+ gd_yoffset = gamebutton_info[i].y;
+ gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
+ gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
+
+ if (id == GAME_CTRL_ID_STOP ||
+ id == GAME_CTRL_ID_PAUSE ||
+ id == GAME_CTRL_ID_PLAY)
+ {
+ button_type = GD_TYPE_NORMAL_BUTTON;
+ checked = FALSE;
+ event_mask = GD_EVENT_RELEASED;
+ gd_y1 = DOOR_GFX_PAGEY1 + gd_yoffset - GAME_BUTTON_YSIZE;
+ gd_y2 = DOOR_GFX_PAGEY1 + gd_yoffset - GAME_BUTTON_YSIZE;
+ }
+ else
+ {
+ button_type = GD_TYPE_CHECK_BUTTON;
+ checked =
+ ((id == SOUND_CTRL_ID_MUSIC && setup.sound_music) ||
+ (id == SOUND_CTRL_ID_LOOPS && setup.sound_loops) ||
+ (id == SOUND_CTRL_ID_SIMPLE && setup.sound_simple) ? TRUE : FALSE);
+ event_mask = GD_EVENT_PRESSED;
+ gd_y1 = DOOR_GFX_PAGEY1 + gd_yoffset;
+ gd_y2 = DOOR_GFX_PAGEY1 + gd_yoffset - GAME_BUTTON_YSIZE;
+ }
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_INFO_TEXT, gamebutton_info[i].infotext,
+ GDI_X, DX + gd_xoffset,
+ GDI_Y, DY + gd_yoffset,
+ GDI_WIDTH, GAME_BUTTON_XSIZE,
+ GDI_HEIGHT, GAME_BUTTON_YSIZE,
+ GDI_TYPE, button_type,
+ GDI_STATE, GD_BUTTON_UNPRESSED,
+ GDI_CHECKED, checked,
+ GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
+ GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
+ GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
+ GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_ACTION, HandleGameButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ game_gadget[id] = gi;
+ }
+}
+
+static void MapGameButtons()
+{
+ int i;
+
+ for (i=0; i<NUM_GAME_BUTTONS; i++)
+ MapGadget(game_gadget[i]);
+}
+
+void UnmapGameButtons()
+{
+ int i;
+
+ for (i=0; i<NUM_GAME_BUTTONS; i++)
+ UnmapGadget(game_gadget[i]);
+}
+
+static void HandleGameButtons(struct GadgetInfo *gi)
+{
+ int id = gi->custom_id;
+
+ if (game_status != PLAYING)
+ return;
+
+ switch (id)
+ {
+ case GAME_CTRL_ID_STOP:
+ if (AllPlayersGone)
+ {
+ CloseDoor(DOOR_CLOSE_1);
+ game_status = MAINMENU;
+ DrawMainMenu();
+ break;
+ }
+
+ if (level_editor_test_game ||
+ Request("Do you really want to quit the game ?",
+ REQ_ASK | REQ_STAY_CLOSED))
+ {
+#ifndef MSDOS
+ if (options.network)
+ SendToServer_StopPlaying();
+ else
+#endif
+ {
+ game_status = MAINMENU;
+ DrawMainMenu();
+ }
+ }
+ else
+ OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+ break;
+
+ case GAME_CTRL_ID_PAUSE:
+ if (options.network)
+ {
+#ifndef MSDOS
+ if (tape.pausing)
+ SendToServer_ContinuePlaying();
+ else
+ SendToServer_PausePlaying();
+#endif
+ }
+ else
+ TapeTogglePause();
+ break;
+
+ case GAME_CTRL_ID_PLAY:
+ if (tape.pausing)
+ {
+#ifndef MSDOS
+ if (options.network)
+ SendToServer_ContinuePlaying();
+ else
+#endif
+ {
+ tape.pausing = FALSE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+ }
+ }
+ break;
+
+ case SOUND_CTRL_ID_MUSIC:
+ if (setup.sound_music)
+ {
+ setup.sound_music = FALSE;
+ FadeSound(background_loop[level_nr % num_bg_loops]);
+ }
+ else if (sound_loops_allowed)
+ {
+ setup.sound = setup.sound_music = TRUE;
+ PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+ }
+ break;
+
+ case SOUND_CTRL_ID_LOOPS:
+ if (setup.sound_loops)
+ setup.sound_loops = FALSE;
+ else if (sound_loops_allowed)
+ setup.sound = setup.sound_loops = TRUE;
+ break;
+
+ case SOUND_CTRL_ID_SIMPLE:
+ if (setup.sound_simple)
+ setup.sound_simple = FALSE;
+ else if (sound_status==SOUND_AVAILABLE)
+ setup.sound = setup.sound_simple = TRUE;
+ break;
+
+ default:
+ break;
+ }
+}