public static void GhostEaten(GameState gameState, Ghost ghost, Game game, GameNotifications gameNotifications) { SendGhostHome(gameState, ghost); IncreaseScoreAfterEatingGhost(gameState, game); MakeGhostNotEdible(gameState, ghost); gameNotifications.Publish(GameNotification.EatGhost); }
public static void SetupGame(GameState gameState, DateTime now, GameNotifications gameNotifications) { gameState.RecordLastTick(now); MoveGhostsHome(gameState); gameState.ShowGhosts(); gameNotifications.Publish(GameNotification.Beginning); }
internal Actions(IGameSettings gameSettings, GameNotifications gameNotifications) { _gameSettings = gameSettings; _gameNotifications = gameNotifications; }
public GameStateMachine(IGameActions game, IGameSettings settings, GameNotifications gameNotifications) { InstanceState(x => x.Status); DuringAny( When(Tick) .Then(context => context.Instance.LastTick = context.Data.Now)); Initially( When(Tick) .Then(context => context.Instance.LastTick = context.Data.Now) .Then(context => game.MoveGhostsHome()) .Then(context => game.ShowGhosts(context.Instance)) .Then(context => gameNotifications.Publish(GameNotification.Beginning)) .TransitionTo(Scatter)); WhenEnter(Scatter, binder => binder .Then(context => context.Instance.TimeToChangeState = context.Instance.LastTick.AddSeconds(settings.InitialScatterTimeInSeconds)) .Then(context => game.ScatterGhosts())); During(Scatter, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .TransitionTo(GhostChase)); WhenEnter(GhostChase, binder => binder .Then(context => context.Instance.TimeToChangeState = context.Instance.LastTick.AddSeconds(settings.ChaseTimeInSeconds)) .Then(context => game.GhostToChase())); During(GhostChase, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .TransitionTo(Scatter)); During(Frightened, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .Then(x => game.MakeGhostsNotEdible()) .TransitionTo(Scatter)); During(Scatter, GhostChase, Frightened, When(Tick) .ThenAsync(async context => await game.MoveGhosts(context, this)) .Then(context => game.MovePacMan(context, this)), When(CoinEaten) .Then(context => context.Instance.Score += 10) .Then(context => gameNotifications.Publish(GameNotification.EatCoin)), When(PowerPillEaten) .Then(context => context.Instance.Score += 50) .Then(context => gameNotifications.Publish(GameNotification.EatPowerPill)) .Then(context => game.MakeGhostsEdible()) .Then(context => context.Instance.TimeToChangeState = context.Instance.LastTick.AddSeconds(7)) .TransitionTo(Frightened), When(GhostCollision) .IfElse(x => x.Data.Ghost.Edible, binder => binder.Then(x => game.SendGhostHome(x.Data.Ghost)), binder => binder.Then(context => context.Instance.Lives -= 1) .TransitionTo(Dying))); WhenEnter(Dying, binder => binder .Then(context => context.Instance.TimeToChangeState = context.Instance.LastTick.AddSeconds(4)) .Then(context => gameNotifications.Publish(GameNotification.Dying))); During(Dying, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .Then(context => game.HideGhosts(context.Instance)) .Then(context => context.Instance.TimeToChangeState = context.Data.Now.AddSeconds(4)) .IfElse(context => context.Instance.Lives > 0, binder => binder.TransitionTo(Respawning), binder => binder.TransitionTo(Dead))); WhenEnter(Respawning, binder => binder .Then(context => gameNotifications.Publish(GameNotification.Respawning))); During(Respawning, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .Then(context => context.Instance.TimeToChangeState = context.Data.Now.AddSeconds(4)) .Then(context => game.MoveGhostsHome()) .Then(context => game.MovePacManHome()) .Then(context => game.ShowGhosts(context.Instance)) .TransitionTo(GhostChase)); During(Dead, Ignore(Tick)); }
public GameStateMachine(IGameSettings settings, GameNotifications gameNotifications, Game game) { InstanceState(x => x.Status); DuringAny( When(Tick) .Then(context => Actions.Tick(context.Instance, context.Data.Now, gameNotifications))); Initially( When(Tick) .Then(context => Actions.SetupGame(context.Instance, context.Data.Now, gameNotifications)) .TransitionTo(Scatter)); WhenEnter(Scatter, binder => binder .Then(context => context.Instance.ChangeStateIn(settings.InitialScatterTimeInSeconds)) .Then(context => Actions.ScatterGhosts(context.Instance))); During(Scatter, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .TransitionTo(GhostChase)); During(ChangingLevel, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .TransitionTo(Scatter)); WhenLeave(ChangingLevel, binder => binder.Then(context => Actions.GetReadyForNextLevel(context.Instance, settings))); WhenEnter(GhostChase, binder => binder .Then(context => context.Instance.ChangeStateIn(settings.ChaseTimeInSeconds)) .Then(context => Actions.GhostToChase(context.Instance))); During(GhostChase, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .TransitionTo(Scatter)); During(Frightened, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .Then(context => Actions.MakeGhostsNotEdible(context.Instance)) .TransitionTo(Scatter)); During(Scatter, GhostChase, Frightened, When(PlayersWishesToChangeDirection) .Then(context => Actions.ChangeDirection(game, context.Instance, context.Data.NewDirection)), When(Tick) .ThenAsync(async context => await Actions.MoveGhosts(game, context.Instance, context, this)) .ThenAsync(async context => await Actions.MovePacMan(game, context.Instance, context, this, settings)), When(CoinCollision) .Then(context => Actions.CoinEaten(game, settings, context.Instance, context.Data.Location, gameNotifications)) .If(context => context.Instance.IsLevelComplete(), binder => binder.TransitionTo(ChangingLevel)), When(FruitCollision) .Then(context => Actions.FruitEaten(game, settings, context.Instance, context.Data.Location, gameNotifications)), When(PowerPillCollision) .Then(context => Actions.PowerPillEaten(settings, context.Instance, context.Data.Location, gameNotifications)) .IfElse(context => context.Instance.IsLevelComplete(), binder => binder.TransitionTo(ChangingLevel), binder => binder.Then(context => context.Instance.ChangeStateIn(settings.FrightenedTimeInSeconds)) .TransitionTo(Frightened)), When(GhostCollision) .IfElse(x => x.Data.Ghost.Edible, binder => binder.Then(context => Actions.GhostEaten(context.Instance, context.Data.Ghost, game, gameNotifications)), binder => binder.Then(context => Actions.EatenByGhost(context.Instance)) .TransitionTo(Dying))); WhenEnter(ChangingLevel, binder => binder .Then(context => context.Instance.HideGhosts()) .Then(context => context.Instance.ChangeStateIn(4))); WhenEnter(Dying, binder => binder .Then(context => Actions.BeginDying(context.Instance, gameNotifications)) .Then(context => context.Instance.ChangeStateIn(4))); During(Dying, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .IfElse(context => context.Instance.Lives > 0, binder => binder.TransitionTo(Respawning), binder => binder.TransitionTo(Dead))); WhenEnter(Respawning, binder => binder .Then(context => context.Instance.ChangeStateIn(4)) .Then(context => Actions.BeginRespawning(gameNotifications))); During(Respawning, When(Tick, context => context.Data.Now >= context.Instance.TimeToChangeState) .Then(context => Actions.CompleteRespawning(context.Instance, settings)) .TransitionTo(Scatter)); During(Dead, Ignore(Tick)); During(Dying, Respawning, Dead, ChangingLevel, Ignore(PlayersWishesToChangeDirection), Ignore(CoinCollision), Ignore(PowerPillCollision), Ignore(GhostCollision)); }
public static void PowerPillEaten(IGameSettings gameSettings, GameState gameState, CellLocation powerPillLocation, GameNotifications gameNotifications) { gameState.IncreaseScore(50); gameNotifications.Publish(GameNotification.EatPowerPill); MakeGhostsEdible(gameSettings, gameState); gameState.RemovePowerPill(powerPillLocation); }
public static void CoinEaten(Game game, IGameSettings settings, GameState gameState, CellLocation coinLocation, GameNotifications gameNotifications) { gameState.RemoveCoin(coinLocation); gameState.IncreaseScore(10); if (settings.FruitAppearsAfterCoinsEaten.Contains(game.StartingCoins.Count - game.Coins.Count)) { if (!FruitForLevel.TryGetValue(gameState.Level, out var fruitType)) { fruitType = FruitType.Key; } gameState.ShowFruit(settings.FruitVisibleForSeconds, fruitType); } gameNotifications.Publish(GameNotification.EatCoin); }
public static void BeginRespawning(GameNotifications gameNotifications) { gameNotifications.Publish(GameNotification.Respawning); }
public static void BeginDying(GameState gameState, GameNotifications gameNotifications) { gameState.HideGhosts(); gameNotifications.Publish(GameNotification.Dying); }
internal static void FruitEaten(Game game, IGameSettings settings, GameState gameState, CellLocation location, GameNotifications gameNotifications) { var scoreInc = gameState.FruitTypeToShow switch { FruitType.Cherry => 100, FruitType.Strawberry => 300, FruitType.Orange => 500, FruitType.Bell => 700, FruitType.Apple => 1000, FruitType.Grapes => 2000, FruitType.Arcadian => 3000, FruitType.Key => 5000, _ => throw new NotImplementedException() }; gameState.IncreaseScore(scoreInc); gameState.HideFruit(); gameNotifications.Publish(GameNotification.EatFruit); }
public static void Tick(GameState gameState, DateTime now, GameNotifications gameNotifications) { gameNotifications.Publish(GameNotification.PreTick); gameState.RecordLastTick(now); }