diff --git a/TouchyTickets/Content/Localization/Localization.json b/TouchyTickets/Content/Localization/Localization.json index 18d6136..ef5fd56 100644 --- a/TouchyTickets/Content/Localization/Localization.json +++ b/TouchyTickets/Content/Localization/Localization.json @@ -4,7 +4,17 @@ "EarnStar": "Earn ", "ReallyEarnStar": "Are you sure that you want to earn a ? This will remove all placed attractions and reset your !", "Yes": "Yes", + "Okay": "Okay", "RequiresTickets": "Requires {0}", + "Tutorial1": "Hi! Welcome to Touchy Tickets. To start the game, simply tap the ticket booth to sell a . Start by racking up 50!", + "Tutorial2": "Great! Now, you can buy your first attraction. Access the menu on the right by swiping and purchase a carousel.", + "Tutorial3": "This is your park map. The area inside the fence is what belongs to you. Place the carousel by dragging it to the perfect location and then pressing the button below.", + "Tutorial4": "Now that you've placed your carousel, you can see that you're automatically starting to rack up on the main screen!", + "Tutorial5": "You'll still be able to sell manually by tapping, but the longer you play, the more you'll be able to accumulate automatically.", + "Tutorial6": "While the game is closed or in the background, you'll sell at half the regular speed.", + "Tutorial7": "Looks like you finally sold enough to exchange them for a ! Once you're ready, access the menu on the left by swiping and earn a .", + "Tutorial8": "Now that you have a , you also have to restart the game. But don't worry - give you the ability to purchase some great permanent upgrades for your attractions.", + "Tutorial9": "Now, you can rack up more even faster to earn more to rack up more ... you get the point. Have fun!", "Carousel": "Carousel", "FoodCourt": "Food Court", "FerrisWheel": "Ferris Wheel", diff --git a/TouchyTickets/GameImpl.cs b/TouchyTickets/GameImpl.cs index b197e83..170e819 100644 --- a/TouchyTickets/GameImpl.cs +++ b/TouchyTickets/GameImpl.cs @@ -15,6 +15,7 @@ namespace TouchyTickets { public static GameImpl Instance { get; private set; } public readonly ISet AppliedUpgrades = new HashSet(); + public readonly Tutorial Tutorial = new Tutorial(); public BigInteger Tickets; public int TimesRestarted; public int Stars; @@ -61,6 +62,7 @@ namespace TouchyTickets { this.LastUpdate = now; this.Ui.Update(gameTime); + this.Tutorial.Update(this); // save every 3 seconds this.saveCounter += gameTime.ElapsedGameTime.TotalSeconds; diff --git a/TouchyTickets/SaveHandler.cs b/TouchyTickets/SaveHandler.cs index 9a8e710..a67d809 100644 --- a/TouchyTickets/SaveHandler.cs +++ b/TouchyTickets/SaveHandler.cs @@ -25,7 +25,8 @@ namespace TouchyTickets { Map = game.Map, Stars = game.Stars, TimesRestarted = game.TimesRestarted, - Upgrades = game.AppliedUpgrades.Select(u => u.Name).ToList() + Upgrades = game.AppliedUpgrades.Select(u => u.Name).ToList(), + TutorialStep = game.Tutorial.CurrentStep }; Serializer.Serialize(stream, data); } @@ -45,6 +46,7 @@ namespace TouchyTickets { game.AppliedUpgrades.Clear(); foreach (var name in data.Upgrades) game.AppliedUpgrades.Add(Upgrade.Upgrades[name]); + game.Tutorial.CurrentStep = data.TutorialStep; } return true; } @@ -72,6 +74,7 @@ namespace TouchyTickets { public int Stars; public int TimesRestarted; public List Upgrades; + public int TutorialStep; } } \ No newline at end of file diff --git a/TouchyTickets/Tutorial.cs b/TouchyTickets/Tutorial.cs new file mode 100644 index 0000000..ff83559 --- /dev/null +++ b/TouchyTickets/Tutorial.cs @@ -0,0 +1,65 @@ +using Microsoft.Xna.Framework; +using MLEM.Extensions; +using MLEM.Ui; +using MLEM.Ui.Elements; +using TouchyTickets.Attractions; + +namespace TouchyTickets { + public class Tutorial { + + private static readonly Step[] Steps = { + new Step(g => true, "Tutorial1"), + new Step(g => g.Tickets >= AttractionType.Carousel.InitialPrice, "Tutorial2"), + new Step(g => g.DrawMap && g.Map.PlacingAttraction?.Type == AttractionType.Carousel, "Tutorial3"), + new Step(g => g.Map.GetAttractionAmount(AttractionType.Carousel) > 0, "Tutorial4", "Tutorial5", "Tutorial6"), + new Step(g => g.Tickets >= g.GetStarPrice(), "Tutorial7"), + new Step(g => g.Stars > 0, "Tutorial8", "Tutorial9") + }; + public int CurrentStep; + private int currentStepMessage; + + public void Update(GameImpl game) { + // stop if the tutorial is finished + if (this.CurrentStep >= Steps.Length) + return; + // don't do anything while a tutorial box is already displaying + if (game.UiSystem.Get("TutorialBox") != null) + return; + + var step = Steps[this.CurrentStep]; + if (step.ShouldContinue(game)) { + var infoBox = new Group(Anchor.TopLeft, Vector2.One, false) { + OnDrawn = (e2, time, batch, alpha) => batch.Draw(batch.GetBlankTexture(), e2.DisplayArea, Color.Black * 0.35F) + }; + var panel = infoBox.AddChild(new Panel(Anchor.Center, new Vector2(0.8F), Vector2.Zero, true)); + panel.AddChild(new Paragraph(Anchor.AutoLeft, 1, Localization.Get(step.Content[this.currentStepMessage]))); + panel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 30), Localization.Get("Okay")) { + OnPressed = e2 => { + game.UiSystem.Remove(e2.Root.Name); + this.currentStepMessage++; + if (this.currentStepMessage >= step.Content.Length) { + this.currentStepMessage = 0; + this.CurrentStep++; + } + } + }); + game.UiSystem.Add("TutorialBox", infoBox); + } + } + + private class Step { + + public readonly ContinueDelegate ShouldContinue; + public readonly string[] Content; + + public Step(ContinueDelegate shouldContinue, params string[] content) { + this.ShouldContinue = shouldContinue; + this.Content = content; + } + + public delegate bool ContinueDelegate(GameImpl game); + + } + + } +} \ No newline at end of file diff --git a/TouchyTickets/Ui.cs b/TouchyTickets/Ui.cs index 737368f..e505cf8 100644 --- a/TouchyTickets/Ui.cs +++ b/TouchyTickets/Ui.cs @@ -283,7 +283,7 @@ namespace TouchyTickets { var center = splash.AddChild(new Group(Anchor.Center, new Vector2(0.5F, 0.5F), false) {DrawAlpha = 0}); center.AddChild(new Image(Anchor.AutoCenter, new Vector2(1, -1), Texture[4, 0])); center.AddChild(new Paragraph(Anchor.AutoCenter, 10000, "A game by Ellpeck", true)); - this.uiSystem.Add("Splash", splash); + this.uiSystem.Add("Splash", splash).Priority = 100000; while (center.DrawAlpha < 1) { center.DrawAlpha += 0.01F; yield return new WaitEvent(CoroutineEvents.Update);