shuffle analytics and ad loading around after the gdpr message

This commit is contained in:
Ellpeck 2020-06-14 01:18:12 +02:00
parent c1438464cd
commit 6408be7646
11 changed files with 136 additions and 104 deletions

View file

@ -31,9 +31,13 @@ namespace Android {
protected override void OnCreate(Bundle bundle) { protected override void OnCreate(Bundle bundle) {
base.OnCreate(bundle); base.OnCreate(bundle);
// ad layout
var adLayout = new LinearLayout(this) {Orientation = Orientation.Vertical};
adLayout.SetGravity(GravityFlags.Bottom);
// set up the game // set up the game
TextInputWrapper.Current = new TextInputWrapper.Mobile(); TextInputWrapper.Current = new TextInputWrapper.Mobile();
this.game = new GameImpl(new AndroidAnalytics(this)); this.game = new GameImpl(new AndroidPlatform(this, adLayout));
this.game.GraphicsDeviceManager.ResetWidthAndHeight(this.game.Window); this.game.GraphicsDeviceManager.ResetWidthAndHeight(this.game.Window);
this.game.GraphicsDeviceManager.IsFullScreen = true; this.game.GraphicsDeviceManager.IsFullScreen = true;
this.game.OnLoadContent += game => { this.game.OnLoadContent += game => {
@ -53,18 +57,6 @@ namespace Android {
if (Build.VERSION.SdkInt >= BuildVersionCodes.P) if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges; this.Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
// ad layout
var adLayout = new LinearLayout(this) {Orientation = Orientation.Vertical};
adLayout.SetGravity(GravityFlags.Bottom);
var ad = new AdView(this) {
AdUnitId = "ca-app-pub-5754829579653773/7841535920",
AdSize = AdSize.SmartBanner
};
ad.LoadAd(new AdRequest.Builder()
.AddTestDevice("14B965C6457E17D2808061ADF7E34923")
.Build());
adLayout.AddView(ad);
// total layout that is displayed // total layout that is displayed
this.mainView = new LinearLayout(this) {Orientation = Orientation.Vertical}; this.mainView = new LinearLayout(this) {Orientation = Orientation.Vertical};
this.mainView.LayoutParameters = new LinearLayout.LayoutParams(MatchParent, MatchParent); this.mainView.LayoutParameters = new LinearLayout.LayoutParams(MatchParent, MatchParent);

View file

@ -54,7 +54,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Activity1.cs" /> <Compile Include="Activity1.cs" />
<Compile Include="AndroidAnalytics.cs" /> <Compile Include="AndroidPlatform.cs" />
<Compile Include="Resources\Resource.Designer.cs" /> <Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>

View file

@ -1,26 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using Android.App;
using GameAnalyticsSDK;
using GameAnalyticsSDK.Utilities;
using TouchyTickets;
namespace Android {
public class AndroidAnalytics : Analytics {
private readonly Activity activity;
public AndroidAnalytics(Activity activity) {
this.activity = activity;
}
public override void Setup(Dictionary<string, object> json) {
GameAnalytics.Initialize(this.activity, GA_MiniJSON.JsonEncode(new Hashtable(json)));
}
public override void AddResourceEvent(bool sink, string currency, float amount, string itemType, string itemId) {
GameAnalytics.NewResourceEvent(sink ? GAResourceFlowType.Sink : GAResourceFlowType.Source, currency, amount, itemType, itemId);
}
}
}

View file

@ -0,0 +1,41 @@
using System.Collections;
using System.Collections.Generic;
using Android.App;
using Android.Gms.Ads;
using Android.Widget;
using GameAnalyticsSDK;
using GameAnalyticsSDK.Utilities;
using TouchyTickets;
namespace Android {
public class AndroidPlatform : Platform {
private readonly Activity activity;
private readonly LinearLayout adLayout;
public AndroidPlatform(Activity activity, LinearLayout adLayout) {
this.activity = activity;
this.adLayout = adLayout;
}
public override void SetupAds() {
var ad = new AdView(this.activity) {
AdUnitId = "ca-app-pub-5754829579653773/7841535920",
AdSize = AdSize.SmartBanner
};
ad.LoadAd(new AdRequest.Builder()
.AddTestDevice("14B965C6457E17D2808061ADF7E34923")
.Build());
this.adLayout.AddView(ad);
}
public override void SetupAnalytics(Dictionary<string, object> json) {
GameAnalytics.Initialize(this.activity, GA_MiniJSON.JsonEncode(new Hashtable(json)));
}
public override void AddResourceEvent(bool sink, string currency, float amount, string itemType, string itemId) {
GameAnalytics.NewResourceEvent(sink ? GAResourceFlowType.Sink : GAResourceFlowType.Source, currency, amount, itemType, itemId);
}
}
}

View file

@ -12,23 +12,32 @@ namespace TouchyTickets {
public static GameImpl Instance { get; private set; } public static GameImpl Instance { get; private set; }
public readonly ISet<Upgrade> AppliedUpgrades = new HashSet<Upgrade>(); public readonly ISet<Upgrade> AppliedUpgrades = new HashSet<Upgrade>();
public readonly Tutorial Tutorial = new Tutorial(); public readonly Platform Platform;
public bool ReadAnalyticsInfo;
public readonly Analytics Analytics;
public BigInteger Tickets; public BigInteger Tickets;
public int TimesRestarted; public int TimesRestarted;
public int Stars; public int Stars;
public ParkMap Map; public ParkMap Map;
public Tutorial Tutorial { get; private set; }
public Camera Camera { get; private set; } public Camera Camera { get; private set; }
public Ui Ui { get; private set; } public Ui Ui { get; private set; }
public bool DrawMap; public bool DrawMap;
public DateTime LastUpdate; public DateTime LastUpdate;
private double saveCounter; private double saveCounter;
public GameImpl(Analytics analytics) { public GameImpl(Platform platform) {
this.Analytics = analytics; this.Platform = platform;
Instance = this; Instance = this;
}
protected override void LoadContent() {
base.LoadContent();
// start the load sequence
Ui.SetupUiSystem(this.UiSystem);
CoroutineHandler.Start(Ui.DisplaySplash(this.LoadGame));
}
private void LoadGame() {
// set up analytics // set up analytics
var settings = new Dictionary<string, object>(); var settings = new Dictionary<string, object>();
settings["InfoLog"] = true; settings["InfoLog"] = true;
@ -39,15 +48,15 @@ namespace TouchyTickets {
// ios comes first, then android. For now they're the same // ios comes first, then android. For now they're the same
settings["GameKey"] = new[] {"cc18de06eebbc5d5e987c384fcd28000", "cc18de06eebbc5d5e987c384fcd28000"}; settings["GameKey"] = new[] {"cc18de06eebbc5d5e987c384fcd28000", "cc18de06eebbc5d5e987c384fcd28000"};
settings["SecretKey"] = new[] {"82ca1a930ee38e2383ffb02db7631e16033b511d", "82ca1a930ee38e2383ffb02db7631e16033b511d"}; settings["SecretKey"] = new[] {"82ca1a930ee38e2383ffb02db7631e16033b511d", "82ca1a930ee38e2383ffb02db7631e16033b511d"};
this.Analytics.Setup(settings); this.Platform.SetupAnalytics(settings);
} this.Platform.SetupAds();
protected override void LoadContent() { this.Tutorial = new Tutorial();
base.LoadContent();
if (!SaveHandler.Load(this)) if (!SaveHandler.Load(this))
this.Map = new ParkMap(20, 20); this.Map = new ParkMap(20, 20);
// load other stuff
this.Ui = new Ui(this.UiSystem); this.Ui = new Ui(this.UiSystem);
this.Camera = new Camera(this.GraphicsDevice) { this.Camera = new Camera(this.GraphicsDevice) {
Scale = 4, Scale = 4,
@ -56,13 +65,12 @@ namespace TouchyTickets {
MaxScale = 24, MaxScale = 24,
MinScale = 2 MinScale = 2
}; };
CoroutineHandler.Start(this.Ui.DisplaySplash());
} }
protected override void DoUpdate(GameTime gameTime) { protected override void DoUpdate(GameTime gameTime) {
base.DoUpdate(gameTime); base.DoUpdate(gameTime);
if (this.Map != null) {
var now = DateTime.Now; var now = DateTime.Now;
if (this.LastUpdate != default) { if (this.LastUpdate != default) {
var passed = now - this.LastUpdate; var passed = now - this.LastUpdate;
@ -73,9 +81,6 @@ namespace TouchyTickets {
} }
this.LastUpdate = now; this.LastUpdate = now;
this.Ui.Update(gameTime);
this.Tutorial.Update(this);
// 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) {
@ -84,6 +89,10 @@ namespace TouchyTickets {
} }
} }
this.Ui?.Update(gameTime);
this.Tutorial?.Update(this);
}
protected override void DoDraw(GameTime gameTime) { protected override void DoDraw(GameTime gameTime) {
this.GraphicsDevice.Clear(Color.Black); this.GraphicsDevice.Clear(Color.Black);
if (this.DrawMap) { if (this.DrawMap) {

View file

@ -1,9 +1,11 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace TouchyTickets { namespace TouchyTickets {
public abstract class Analytics { public abstract class Platform {
public abstract void Setup(Dictionary<string, object> json); public abstract void SetupAds();
public abstract void SetupAnalytics(Dictionary<string, object> json);
public abstract void AddResourceEvent(bool sink, string currency, float amount, string itemType, string itemId); public abstract void AddResourceEvent(bool sink, string currency, float amount, string itemType, string itemId);

View file

@ -25,8 +25,7 @@ namespace TouchyTickets {
Stars = game.Stars, Stars = game.Stars,
TimesRestarted = game.TimesRestarted, TimesRestarted = game.TimesRestarted,
Upgrades = game.AppliedUpgrades.Select(u => u.Name).ToList(), Upgrades = game.AppliedUpgrades.Select(u => u.Name).ToList(),
TutorialStep = game.Tutorial.CurrentStep, TutorialStep = game.Tutorial.CurrentStep
ReadAnalyticsInfo = game.ReadAnalyticsInfo
}; };
Serializer.Serialize(stream, data); Serializer.Serialize(stream, data);
} }
@ -49,7 +48,6 @@ namespace TouchyTickets {
foreach (var name in data.Upgrades) foreach (var name in data.Upgrades)
game.AppliedUpgrades.Add(Upgrade.Upgrades[name]); game.AppliedUpgrades.Add(Upgrade.Upgrades[name]);
game.Tutorial.CurrentStep = data.TutorialStep; game.Tutorial.CurrentStep = data.TutorialStep;
game.ReadAnalyticsInfo = data.ReadAnalyticsInfo;
// version 1 had smaller maps // version 1 had smaller maps
if (data.SaveVersion <= 1) { if (data.SaveVersion <= 1) {

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using Coroutine; using Coroutine;
@ -28,19 +29,7 @@ namespace TouchyTickets {
private bool finishingSwipe; private bool finishingSwipe;
public Ui(UiSystem uiSystem) { public Ui(UiSystem uiSystem) {
InputHandler.EnableGestures(GestureType.HorizontalDrag, GestureType.FreeDrag, GestureType.Pinch, GestureType.Tap);
this.uiSystem = uiSystem; this.uiSystem = uiSystem;
this.uiSystem.GlobalScale = 4;
this.uiSystem.AutoScaleWithScreen = true;
this.uiSystem.AutoScaleReferenceSize = new Point(720, 1280);
this.uiSystem.Style.Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/Regular"));
this.uiSystem.Style.PanelTexture = this.uiSystem.Style.ScrollBarBackground = new NinePatch(Texture[2, 1], 4);
this.uiSystem.Style.ButtonTexture = this.uiSystem.Style.ScrollBarScrollerTexture = new NinePatch(Texture[3, 1], 4);
this.uiSystem.Style.TextScale = 0.1F;
this.uiSystem.TextFormatter.AddImage("ticket", Texture[2, 0]);
this.uiSystem.TextFormatter.AddImage("star", Texture[3, 0]);
foreach (var modifier in AttractionModifier.Modifiers.Values)
this.uiSystem.TextFormatter.AddImage(modifier.Name, modifier.Texture);
// main ticket store ui // main ticket store ui
var rainingTickets = new List<RainingTicket>(); var rainingTickets = new List<RainingTicket>();
@ -174,7 +163,7 @@ namespace TouchyTickets {
yesNoUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(0.5F, 30), Localization.Get("Place")) { yesNoUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(0.5F, 30), Localization.Get("Place")) {
OnPressed = e2 => { OnPressed = e2 => {
GameImpl.Instance.Tickets -= price; GameImpl.Instance.Tickets -= price;
GameImpl.Instance.Analytics.AddResourceEvent(true, "Tickets", price, "Attraction", attraction.Key); GameImpl.Instance.Platform.AddResourceEvent(true, "Tickets", price, "Attraction", attraction.Key);
map.Place(map.PlacingPosition, map.PlacingAttraction); map.Place(map.PlacingPosition, map.PlacingAttraction);
this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name)); this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name));
@ -241,7 +230,7 @@ namespace TouchyTickets {
var price = attraction.GetModifierPrice(map.PlacingModifier); var price = attraction.GetModifierPrice(map.PlacingModifier);
GameImpl.Instance.Tickets -= price; GameImpl.Instance.Tickets -= price;
GameImpl.Instance.Analytics.AddResourceEvent(true, "Tickets", price, "Modifier", modifier.Name); GameImpl.Instance.Platform.AddResourceEvent(true, "Tickets", price, "Modifier", modifier.Name);
attraction.ApplyModifier(map.PlacingModifier); attraction.ApplyModifier(map.PlacingModifier);
}, },
@ -305,8 +294,8 @@ namespace TouchyTickets {
this.uiSystem.Remove(e2.Root.Name); this.uiSystem.Remove(e2.Root.Name);
var game = GameImpl.Instance; var game = GameImpl.Instance;
game.Analytics.AddResourceEvent(true, "Tickets", (long) game.Tickets, "Restart", "Restart" + game.TimesRestarted); game.Platform.AddResourceEvent(true, "Tickets", (long) game.Tickets, "Restart", "Restart" + game.TimesRestarted);
game.Analytics.AddResourceEvent(false, "Stars", game.GetBuyableStars(), "Restart", "Restart" + game.TimesRestarted); game.Platform.AddResourceEvent(false, "Stars", game.GetBuyableStars(), "Restart", "Restart" + game.TimesRestarted);
game.Stars += game.GetBuyableStars(); game.Stars += game.GetBuyableStars();
game.TimesRestarted++; game.TimesRestarted++;
@ -381,41 +370,64 @@ namespace TouchyTickets {
} }
} }
public IEnumerator<IWait> DisplaySplash() { public static void SetupUiSystem(UiSystem uiSystem) {
InputHandler.EnableGestures(GestureType.HorizontalDrag, GestureType.FreeDrag, GestureType.Pinch, GestureType.Tap);
uiSystem.GlobalScale = 4;
uiSystem.AutoScaleWithScreen = true;
uiSystem.AutoScaleReferenceSize = new Point(720, 1280);
uiSystem.Style.Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/Regular"));
uiSystem.Style.PanelTexture = uiSystem.Style.ScrollBarBackground = new NinePatch(Texture[2, 1], 4);
uiSystem.Style.ButtonTexture = uiSystem.Style.ScrollBarScrollerTexture = new NinePatch(Texture[3, 1], 4);
uiSystem.Style.TextScale = 0.1F;
uiSystem.TextFormatter.AddImage("ticket", Texture[2, 0]);
uiSystem.TextFormatter.AddImage("star", Texture[3, 0]);
foreach (var modifier in AttractionModifier.Modifiers.Values)
uiSystem.TextFormatter.AddImage(modifier.Name, modifier.Texture);
}
public static IEnumerator<IWait> DisplaySplash(Action loadGame) {
var splash = new Group(Anchor.TopLeft, Vector2.One, false) { var splash = new Group(Anchor.TopLeft, Vector2.One, false) {
OnDrawn = (e, time, batch, alpha) => batch.Draw(batch.GetBlankTexture(), e.DisplayArea, Color.Black * alpha) OnDrawn = (e, time, batch, alpha) => batch.Draw(batch.GetBlankTexture(), e.DisplayArea, Color.Black * alpha)
}; };
var center = splash.AddChild(new Group(Anchor.Center, new Vector2(0.5F, 0.5F), false) {DrawAlpha = 0}); 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 Image(Anchor.AutoCenter, new Vector2(1, -1), Texture[4, 0]));
center.AddChild(new Paragraph(Anchor.AutoCenter, 10000, "A game by Ellpeck", true)); center.AddChild(new Paragraph(Anchor.AutoCenter, 10000, "A game by Ellpeck", true));
this.uiSystem.Add("Splash", splash).Priority = 100000; GameImpl.Instance.UiSystem.Add("Splash", splash).Priority = 100000;
while (center.DrawAlpha < 1) { while (center.DrawAlpha < 1) {
center.DrawAlpha += 0.015F; center.DrawAlpha += 0.015F;
yield return new WaitEvent(CoroutineEvents.Update); yield return new WaitEvent(CoroutineEvents.Update);
} }
yield return new WaitSeconds(1); yield return new WaitSeconds(0.5);
while (center.DrawAlpha > 0) {
center.DrawAlpha -= 0.015F; var analyticsFlag = new FileInfo(Path.Combine(SaveHandler.GetGameDirectory(true).FullName, "_ReadGdpr"));
yield return new WaitEvent(CoroutineEvents.Update); if (!analyticsFlag.Exists) {
}
if (!GameImpl.Instance.ReadAnalyticsInfo) {
var evt = new Event(); var evt = new Event();
var panel = splash.AddChild(new Panel(Anchor.Center, new Vector2(0.8F), Vector2.Zero, true)); var panel = splash.AddChild(new Panel(Anchor.Center, new Vector2(0.8F), Vector2.Zero, true));
panel.AddChild(new Paragraph(Anchor.AutoLeft, 1, Localization.Get("GDPRInfo"))); panel.AddChild(new Paragraph(Anchor.AutoLeft, 1, Localization.Get("GDPRInfo")));
panel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 30), Localization.Get("Okay")) { panel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 30), Localization.Get("Okay")) {
OnPressed = e2 => { OnPressed = e2 => {
GameImpl.Instance.ReadAnalyticsInfo = true; // create the (empty) flag file
using (analyticsFlag.Create()) {
}
splash.RemoveChild(panel); splash.RemoveChild(panel);
CoroutineHandler.RaiseEvent(evt); CoroutineHandler.RaiseEvent(evt);
} }
}); });
yield return new WaitEvent(evt); yield return new WaitEvent(evt);
} }
yield return new WaitSeconds(0.25);
loadGame();
yield return new WaitSeconds(0.25);
while (center.DrawAlpha > 0) {
center.DrawAlpha -= 0.015F;
yield return new WaitEvent(CoroutineEvents.Update);
}
while (splash.DrawAlpha > 0) { while (splash.DrawAlpha > 0) {
splash.DrawAlpha -= 0.015F; splash.DrawAlpha -= 0.015F;
yield return new WaitEvent(CoroutineEvents.Update); yield return new WaitEvent(CoroutineEvents.Update);
} }
this.uiSystem.Remove(splash.Root.Name); splash.System.Remove(splash.Root.Name);
} }
private void FadeUi(bool fadeOut, Action after = null) { private void FadeUi(bool fadeOut, Action after = null) {
@ -481,7 +493,7 @@ namespace TouchyTickets {
ChildPadding = new Vector2(4), ChildPadding = new Vector2(4),
OnPressed = e => { OnPressed = e => {
GameImpl.Instance.Stars -= upgrade.Price; GameImpl.Instance.Stars -= upgrade.Price;
GameImpl.Instance.Analytics.AddResourceEvent(true, "Stars", upgrade.Price, "Upgrade", upgrade.Name); GameImpl.Instance.Platform.AddResourceEvent(true, "Stars", upgrade.Price, "Upgrade", upgrade.Name);
GameImpl.Instance.AppliedUpgrades.Add(upgrade); GameImpl.Instance.AppliedUpgrades.Add(upgrade);
upgrade.OnApplied(); upgrade.OnApplied();

View file

@ -5,9 +5,13 @@ using GameAnalyticsSDK.Utilities;
using TouchyTickets; using TouchyTickets;
namespace iOS { namespace iOS {
public class IosAnalytics : Analytics { public class IosPlatform : Platform {
public override void Setup(Dictionary<string, object> json) { public override void SetupAds() {
throw new System.NotImplementedException();
}
public override void SetupAnalytics(Dictionary<string, object> json) {
GameAnalytics.Initialize(GA_MiniJSON.JsonEncode(new Hashtable(json))); GameAnalytics.Initialize(GA_MiniJSON.JsonEncode(new Hashtable(json)));
} }

View file

@ -11,7 +11,7 @@ namespace iOS {
private static void RunGame() { private static void RunGame() {
TextInputWrapper.Current = new TextInputWrapper.Mobile(); TextInputWrapper.Current = new TextInputWrapper.Mobile();
game = new GameImpl(new IosAnalytics()); game = new GameImpl(new IosPlatform());
game.Run(); game.Run();
} }

View file

@ -111,7 +111,7 @@
<Reference Include="Xamarin.iOS" /> <Reference Include="Xamarin.iOS" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="IosAnalytics.cs" /> <Compile Include="IosPlatform.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>