added achievements!

This commit is contained in:
Ellpeck 2020-07-21 21:51:30 +02:00
parent 459ab78bee
commit 338810c623
16 changed files with 139 additions and 6 deletions

View file

@ -8,6 +8,7 @@ using Android.Gms.Common;
using Android.Gms.Common.Apis; using Android.Gms.Common.Apis;
using Android.Gms.Extensions; using Android.Gms.Extensions;
using Android.Gms.Games; using Android.Gms.Games;
using Android.Gms.Games.Achievement;
using Android.Runtime; using Android.Runtime;
using Android.Views; using Android.Views;
using Android.Widget; using Android.Widget;
@ -15,12 +16,40 @@ using Coroutine;
using GameAnalyticsSDK; using GameAnalyticsSDK;
using GameAnalyticsSDK.Utilities; using GameAnalyticsSDK.Utilities;
using TouchyTickets; using TouchyTickets;
using Achievement = TouchyTickets.Achievement;
using Uri = Android.Net.Uri; using Uri = Android.Net.Uri;
namespace Android { namespace Android {
public class AndroidPlatform : Platform { public class AndroidPlatform : Platform {
public const int GooglePlayLoginRequest = 9001; public const int GooglePlayLoginRequest = 9001;
public const int ShowAchievementsRequest = 9002;
private static readonly Dictionary<string, string> AchievementIds = new Dictionary<string, string> {
{"1Stars", "CgkI_Lyp7PcEEAIQAw"},
{"10Stars", "CgkI_Lyp7PcEEAIQBA"},
{"100Stars", "CgkI_Lyp7PcEEAIQBQ"},
{"FullMap", "CgkI_Lyp7PcEEAIQBg"},
{"OnlySmallRides", "CgkI_Lyp7PcEEAIQBw"},
{"OnlyRelaxedRides", "CgkI_Lyp7PcEEAIQCA"},
{"OnlyWalkingRides", "CgkI_Lyp7PcEEAIQCQ"},
{"OnlyNonTechnologyRides", "CgkI_Lyp7PcEEAIQCg"},
{"100Modifiers", "CgkI_Lyp7PcEEAIQCw"},
{"500Modifiers", "CgkI_Lyp7PcEEAIQDA"},
{"1000Modifiers", "CgkI_Lyp7PcEEAIQDQ"},
{"5000Modifiers", "CgkI_Lyp7PcEEAIQDg"},
{"1.00MTickets", "CgkI_Lyp7PcEEAIQDw"},
{"1.00BTickets", "CgkI_Lyp7PcEEAIQEA"},
{"1.00TTickets", "CgkI_Lyp7PcEEAIQEQ"},
{"1.00QTickets", "CgkI_Lyp7PcEEAIQEg"},
{"1.00QiTickets", "CgkI_Lyp7PcEEAIQEw"},
{"1.00STickets", "CgkI_Lyp7PcEEAIQFA"},
{"1.00SpTickets", "CgkI_Lyp7PcEEAIQFQ"},
{"1.00OTickets", "CgkI_Lyp7PcEEAIQFg"},
{"1.00NTickets", "CgkI_Lyp7PcEEAIQFw"},
{"1.00DTickets", "CgkI_Lyp7PcEEAIQGA"}
};
private readonly Activity activity; private readonly Activity activity;
private readonly LinearLayout adLayout; private readonly LinearLayout adLayout;
public GoogleApiClient GoogleApi { get; private set; } public GoogleApiClient GoogleApi { get; private set; }
@ -59,6 +88,11 @@ namespace Android {
}) })
.Build(); .Build();
this.GoogleApi.Connect(); this.GoogleApi.Connect();
// Sanity check to ensure that all achievements are mapped
foreach (var achievement in Achievement.Achievements.Values) {
var _ = AchievementIds[achievement.Name];
}
} }
public override void AddResourceEvent(bool sink, string currency, float amount, string itemType, string itemId) { public override void AddResourceEvent(bool sink, string currency, float amount, string itemType, string itemId) {
@ -77,5 +111,17 @@ namespace Android {
this.activity.StartActivity(new Intent(Intent.ActionView, Uri.Parse("https://play.google.com/store/apps/details?id=de.ellpeck.touchytickets"))); this.activity.StartActivity(new Intent(Intent.ActionView, Uri.Parse("https://play.google.com/store/apps/details?id=de.ellpeck.touchytickets")));
} }
public override void GainAchievement(Achievement achievement) {
if (this.GoogleApi != null)
GamesClass.Achievements.Unlock(this.GoogleApi, AchievementIds[achievement.Name]);
}
public override void ShowAchievements() {
if (this.GoogleApi == null)
return;
var intent = GamesClass.Achievements.GetAchievementsIntent(this.GoogleApi);
this.activity.StartActivityForResult(intent, ShowAchievementsRequest);
}
} }
} }

View file

@ -8,10 +8,6 @@
# Achievements # Achievements
- Each award has a "gotten for the first time" achievement - Each award has a "gotten for the first time" achievement
- Getting the first star
- Filling each space on the map
- Only attractions of a certain type
- High amount of modifiers on each ride
# More star upgrades # More star upgrades
- Upgrade that allows you to set park placement templates - Upgrade that allows you to set park placement templates

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
Media/Achievements/Star.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Microsoft.Xna.Framework;
using TouchyTickets.Attractions;
namespace TouchyTickets {
public class Achievement {
public static readonly Dictionary<string, Achievement> Achievements = new Dictionary<string, Achievement>();
static Achievement() {
foreach (var amount in new[] {1, 10, 100})
Register(new Achievement($"{amount}Stars", g => g.Stars >= amount));
Register(new Achievement("FullMap", g => {
for (var x = 0; x < g.Map.Width; x++) {
for (var y = 0; y < g.Map.Height; y++) {
if (g.Map.GetAttractionAt(new Point(x, y)) == null)
return false;
}
}
return true;
}));
foreach (var flag in new[] {AttractionFlags.Small, AttractionFlags.Relaxed, AttractionFlags.Walking, AttractionFlags.NonTechnology})
Register(new Achievement($"Only{flag}Rides", g => g.Map.GetAttractionAmount(null) >= 100 && g.Map.GetAttractions().All(a => a.Item2.Type.Flags.HasFlag(flag))));
foreach (var amount in new[] {100, 500, 1000, 5000})
Register(new Achievement($"{amount}Modifiers", g => g.Map.GetAttractions().All(a => a.Item2.GetModifierAmount(null) >= amount)));
for (var i = 1; i <= 10; i++) {
var amount = BigInteger.Pow(1000, i + 1);
Register(new Achievement($"{Ui.PrettyPrintNumber(amount).Replace(" ", "")}Tickets", g => g.Tickets >= amount));
}
}
public readonly string Name;
private readonly Func<GameImpl, bool> condition;
// this value doesn't save between game runs, since achievements
// are only displayed inside of the respective stores anyway
private bool unlocked;
public Achievement(string name, Func<GameImpl, bool> condition) {
this.Name = name;
this.condition = condition;
}
public void Update() {
if (this.unlocked)
return;
if (!this.condition.Invoke(GameImpl.Instance))
return;
GameImpl.Instance.Platform.GainAchievement(this);
this.unlocked = true;
}
public static void Register(Achievement achievement) {
Achievements.Add(achievement.Name, achievement);
}
}
}

View file

@ -25,6 +25,7 @@ namespace TouchyTickets {
public DateTime LastUpdate; public DateTime LastUpdate;
public TimeSpan PlayTime; public TimeSpan PlayTime;
private double saveCounter; private double saveCounter;
private double achievementCounter;
public GameImpl(Platform platform) { public GameImpl(Platform platform) {
this.Platform = platform; this.Platform = platform;
@ -78,6 +79,15 @@ namespace TouchyTickets {
if (this.Map != null) { if (this.Map != null) {
// update the map // update the map
this.UpdateMapOnce(); this.UpdateMapOnce();
// achievements
this.achievementCounter += gameTime.ElapsedGameTime.TotalSeconds;
if (this.achievementCounter >= 5) {
this.achievementCounter = 0;
foreach (var achievement in Achievement.Achievements.Values)
achievement.Update();
}
// save every 3 seconds // save every 3 seconds
this.saveCounter += gameTime.ElapsedGameTime.TotalSeconds; this.saveCounter += gameTime.ElapsedGameTime.TotalSeconds;
if (this.saveCounter >= 3) { if (this.saveCounter >= 3) {

View file

@ -234,6 +234,11 @@ namespace TouchyTickets {
return this.attractions.Any(a => modifier.IsAffected(a.Item2)); return this.attractions.Any(a => modifier.IsAffected(a.Item2));
} }
public IEnumerable<(Point, Attraction)> GetAttractions() {
foreach (var attraction in this.attractions)
yield return attraction;
}
public bool IsInBounds(Point pos) { public bool IsInBounds(Point pos) {
return pos.X >= 0 && pos.Y >= 0 && pos.X < this.Width && pos.Y < this.Height; return pos.X >= 0 && pos.Y >= 0 && pos.X < this.Width && pos.Y < this.Height;
} }

View file

@ -11,5 +11,9 @@ namespace TouchyTickets {
public abstract void OpenRateLink(); public abstract void OpenRateLink();
public abstract void GainAchievement(Achievement achievement);
public abstract void ShowAchievements();
} }
} }

View file

@ -393,6 +393,10 @@ namespace TouchyTickets {
} }
})); }));
num.PositionOffset = new Vector2(0, 1); num.PositionOffset = new Vector2(0, 1);
optionList.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 30), Localization.Get("Achievements")) {
PositionOffset = new Vector2(0, 1),
OnPressed = e => GameImpl.Instance.Platform.ShowAchievements()
});
optionList.AddChild(new Paragraph(Anchor.AutoCenter, 1, Localization.Get("OtherOptions"), true) { optionList.AddChild(new Paragraph(Anchor.AutoCenter, 1, Localization.Get("OtherOptions"), true) {
PositionOffset = new Vector2(0, 10), PositionOffset = new Vector2(0, 10),
@ -733,7 +737,7 @@ namespace TouchyTickets {
element.Transform = Matrix.Identity; element.Transform = Matrix.Identity;
} }
private static string PrettyPrintNumber(BigInteger number) { public static string PrettyPrintNumber(BigInteger number) {
for (var i = 0; i < Localization.NumberFormat.Count; i++) { for (var i = 0; i < Localization.NumberFormat.Count; i++) {
if (number < ExpoNums[i]) if (number < ExpoNums[i])
return number.ToString(Localization.NumberFormat[i]); return number.ToString(Localization.NumberFormat[i]);

View file

@ -20,5 +20,13 @@ namespace iOS {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public override void GainAchievement(Achievement achievement) {
throw new System.NotImplementedException();
}
public override void ShowAchievements() {
throw new System.NotImplementedException();
}
} }
} }