added achievements!
|
@ -8,6 +8,7 @@ using Android.Gms.Common;
|
|||
using Android.Gms.Common.Apis;
|
||||
using Android.Gms.Extensions;
|
||||
using Android.Gms.Games;
|
||||
using Android.Gms.Games.Achievement;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
|
@ -15,12 +16,40 @@ using Coroutine;
|
|||
using GameAnalyticsSDK;
|
||||
using GameAnalyticsSDK.Utilities;
|
||||
using TouchyTickets;
|
||||
using Achievement = TouchyTickets.Achievement;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
||||
namespace Android {
|
||||
public class AndroidPlatform : Platform {
|
||||
|
||||
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 LinearLayout adLayout;
|
||||
public GoogleApiClient GoogleApi { get; private set; }
|
||||
|
@ -59,6 +88,11 @@ namespace Android {
|
|||
})
|
||||
.Build();
|
||||
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) {
|
||||
|
@ -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")));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
4
Ideas.md
|
@ -8,10 +8,6 @@
|
|||
|
||||
# Achievements
|
||||
- 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
|
||||
- Upgrade that allows you to set park placement templates
|
||||
|
|
BIN
Media/Achievements/FullMap.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
Media/Achievements/Modifiers.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
Media/Achievements/OnlyNonTechnologyRides.png
Normal file
After Width: | Height: | Size: 3 KiB |
BIN
Media/Achievements/OnlyRelaxingRides.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
Media/Achievements/OnlySmallRides.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
Media/Achievements/OnlyWalkingRides.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
Media/Achievements/Star.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
Media/Achievements/Tickets.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
60
TouchyTickets/Achievement.cs
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ namespace TouchyTickets {
|
|||
public DateTime LastUpdate;
|
||||
public TimeSpan PlayTime;
|
||||
private double saveCounter;
|
||||
private double achievementCounter;
|
||||
|
||||
public GameImpl(Platform platform) {
|
||||
this.Platform = platform;
|
||||
|
@ -78,6 +79,15 @@ namespace TouchyTickets {
|
|||
if (this.Map != null) {
|
||||
// update the map
|
||||
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
|
||||
this.saveCounter += gameTime.ElapsedGameTime.TotalSeconds;
|
||||
if (this.saveCounter >= 3) {
|
||||
|
@ -122,7 +132,7 @@ namespace TouchyTickets {
|
|||
if (this.LastUpdate != default) {
|
||||
var lastTickets = this.Tickets;
|
||||
var lastTps = this.Map.TicketsPerSecond;
|
||||
|
||||
|
||||
var passed = now - this.LastUpdate;
|
||||
this.Map.Update(passed, passed.TotalSeconds >= 1);
|
||||
|
||||
|
|
|
@ -234,6 +234,11 @@ namespace TouchyTickets {
|
|||
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) {
|
||||
return pos.X >= 0 && pos.Y >= 0 && pos.X < this.Width && pos.Y < this.Height;
|
||||
}
|
||||
|
|
|
@ -11,5 +11,9 @@ namespace TouchyTickets {
|
|||
|
||||
public abstract void OpenRateLink();
|
||||
|
||||
public abstract void GainAchievement(Achievement achievement);
|
||||
|
||||
public abstract void ShowAchievements();
|
||||
|
||||
}
|
||||
}
|
|
@ -393,6 +393,10 @@ namespace TouchyTickets {
|
|||
}
|
||||
}));
|
||||
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) {
|
||||
PositionOffset = new Vector2(0, 10),
|
||||
|
@ -733,7 +737,7 @@ namespace TouchyTickets {
|
|||
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++) {
|
||||
if (number < ExpoNums[i])
|
||||
return number.ToString(Localization.NumberFormat[i]);
|
||||
|
|
|
@ -20,5 +20,13 @@ namespace iOS {
|
|||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void GainAchievement(Achievement achievement) {
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void ShowAchievements() {
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|