the start of upgrades!
This commit is contained in:
parent
6f2eff29cc
commit
3feb5f86da
9 changed files with 177 additions and 37 deletions
|
@ -38,7 +38,7 @@ namespace TouchyTickets.Attractions {
|
|||
}
|
||||
|
||||
private static void Register(AttractionType type) {
|
||||
Attractions[type.Name] = type;
|
||||
Attractions.Add(type.Name, type);
|
||||
}
|
||||
|
||||
public delegate Attraction Constructor(AttractionType type);
|
||||
|
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 2 KiB |
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
@ -7,12 +8,16 @@ using MLEM.Extensions;
|
|||
using MLEM.Font;
|
||||
using MLEM.Startup;
|
||||
using TouchyTickets.Attractions;
|
||||
using TouchyTickets.Upgrades;
|
||||
|
||||
namespace TouchyTickets {
|
||||
public class GameImpl : MlemGame {
|
||||
|
||||
public static GameImpl Instance { get; private set; }
|
||||
public readonly ISet<Upgrade> AppliedUpgrades = new HashSet<Upgrade>();
|
||||
public BigInteger Tickets;
|
||||
public int TimesRestarted;
|
||||
public int Stars;
|
||||
public ParkMap Map;
|
||||
public Camera Camera { get; private set; }
|
||||
public Ui Ui { get; private set; }
|
||||
|
@ -28,7 +33,7 @@ namespace TouchyTickets {
|
|||
base.LoadContent();
|
||||
|
||||
if (!SaveHandler.Load(this))
|
||||
this.Map = new ParkMap(10, 10);
|
||||
this.Map = new ParkMap(12, 12);
|
||||
|
||||
this.Ui = new Ui(this.UiSystem);
|
||||
this.Camera = new Camera(this.GraphicsDevice) {
|
||||
|
@ -36,7 +41,7 @@ namespace TouchyTickets {
|
|||
AutoScaleWithScreen = true,
|
||||
AutoScaleReferenceSize = new Point(720, 1280),
|
||||
MaxScale = 24,
|
||||
MinScale = 3
|
||||
MinScale = 2
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -73,22 +78,8 @@ namespace TouchyTickets {
|
|||
base.DoDraw(gameTime);
|
||||
}
|
||||
|
||||
public string DisplayTicketCount() {
|
||||
if (this.Tickets < 1000)
|
||||
return this.Tickets.ToString();
|
||||
// thousands
|
||||
if (this.Tickets < 1000000)
|
||||
return this.Tickets.ToString("0,.##K");
|
||||
// millions
|
||||
if (this.Tickets < 1000000000)
|
||||
return this.Tickets.ToString("0,,.##M");
|
||||
// billions
|
||||
if (this.Tickets < 1000000000000)
|
||||
return this.Tickets.ToString("0,,,.##B");
|
||||
// trillions
|
||||
if (this.Tickets < 1000000000000000)
|
||||
return this.Tickets.ToString("0,,,,.##T");
|
||||
return this.Tickets.ToString("0,,,,,.##Q");
|
||||
public BigInteger GetStarPrice() {
|
||||
return BigInteger.Pow(1000000, this.TimesRestarted / 2 + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace TouchyTickets {
|
|||
public class ParkMap {
|
||||
|
||||
private static readonly UniformTextureAtlas TilesTexture = new UniformTextureAtlas(MlemGame.LoadContent<Texture2D>("Textures/Tiles"), 16, 16);
|
||||
private const int AdditionalRadius = 10;
|
||||
private const int AdditionalRadius = 15;
|
||||
[DataMember]
|
||||
public readonly int Width;
|
||||
[DataMember]
|
||||
|
@ -37,12 +37,15 @@ namespace TouchyTickets {
|
|||
|
||||
// set up trees
|
||||
var random = new Random();
|
||||
for (var i = 0; i < 100; i++) {
|
||||
var type = random.Next(3);
|
||||
var x = random.Next(-AdditionalRadius, this.Width + AdditionalRadius);
|
||||
var y = random.Next(-AdditionalRadius, this.Height + AdditionalRadius);
|
||||
if (x < 0 || y < 0 || x >= this.Width || y >= this.Width)
|
||||
for (var x = -AdditionalRadius; x < this.Width + AdditionalRadius; x++) {
|
||||
for (var y = -AdditionalRadius; y < this.Height + AdditionalRadius; y++) {
|
||||
if (x >= 0 && y >= 0 && x < this.Width && y < this.Height)
|
||||
continue;
|
||||
if (random.Next(15) != 0)
|
||||
continue;
|
||||
var type = random.Next(3);
|
||||
this.treePositions[new Point(x, y)] = type;
|
||||
}
|
||||
}
|
||||
|
||||
// set up fences
|
||||
|
@ -163,5 +166,10 @@ namespace TouchyTickets {
|
|||
return this.attractions.Count(a => a.Item2.Type == type);
|
||||
}
|
||||
|
||||
public void CopyAttractionsFrom(ParkMap other) {
|
||||
foreach (var (pos, attraction) in other.attractions)
|
||||
this.Place(pos, attraction);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Newtonsoft.Json;
|
||||
using TouchyTickets.Upgrades;
|
||||
|
||||
namespace TouchyTickets {
|
||||
public static class SaveHandler {
|
||||
|
@ -20,7 +23,10 @@ namespace TouchyTickets {
|
|||
SaveVersion = SaveVersion,
|
||||
Tickets = game.Tickets,
|
||||
LastUpdate = game.LastUpdate,
|
||||
Map = game.Map
|
||||
Map = game.Map,
|
||||
Stars = game.Stars,
|
||||
TimesRestarted = game.TimesRestarted,
|
||||
Upgrades = game.AppliedUpgrades.Select(u => u.Name).ToList()
|
||||
};
|
||||
Serializer.Serialize(stream, data);
|
||||
}
|
||||
|
@ -35,6 +41,11 @@ namespace TouchyTickets {
|
|||
game.Tickets = data.Tickets;
|
||||
game.LastUpdate = data.LastUpdate;
|
||||
game.Map = data.Map;
|
||||
game.Stars = data.Stars;
|
||||
game.TimesRestarted = data.TimesRestarted;
|
||||
game.AppliedUpgrades.Clear();
|
||||
foreach (var name in data.Upgrades)
|
||||
game.AppliedUpgrades.Add(Upgrade.Upgrades[name]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -59,6 +70,9 @@ namespace TouchyTickets {
|
|||
public BigInteger Tickets;
|
||||
public DateTime LastUpdate;
|
||||
public ParkMap Map;
|
||||
public int Stars;
|
||||
public int TimesRestarted;
|
||||
public List<string> Upgrades;
|
||||
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Coroutine" Version="1.0.4" />
|
||||
<PackageReference Include="MLEM.Startup" Version="3.3.3-190" />
|
||||
<PackageReference Include="MLEM.Startup" Version="3.3.3-191" />
|
||||
<PackageReference Include="MonoGame.Framework.Portable" Version="3.7.1.189">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
|
|
|
@ -16,6 +16,7 @@ using MLEM.Textures;
|
|||
using MLEM.Ui;
|
||||
using MLEM.Ui.Elements;
|
||||
using TouchyTickets.Attractions;
|
||||
using TouchyTickets.Upgrades;
|
||||
|
||||
namespace TouchyTickets {
|
||||
public class Ui {
|
||||
|
@ -36,6 +37,7 @@ namespace TouchyTickets {
|
|||
this.uiSystem.Style.Font = new GenericSpriteFont(MlemGame.LoadContent<SpriteFont>("Fonts/Regular"));
|
||||
this.uiSystem.Style.TextScale = 0.1F;
|
||||
this.uiSystem.TextFormatter.AddImage("ticket", Texture[2, 0]);
|
||||
this.uiSystem.TextFormatter.AddImage("star", Texture[3, 0]);
|
||||
|
||||
// main ticket store ui
|
||||
var rainingTickets = new List<RainingTicket>();
|
||||
|
@ -55,7 +57,7 @@ namespace TouchyTickets {
|
|||
}
|
||||
};
|
||||
var ticketGroup = main.AddChild(new Group(Anchor.AutoCenter, new Vector2(1, 0.15F), false));
|
||||
ticketGroup.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => GameImpl.Instance.DisplayTicketCount(), true) {
|
||||
ticketGroup.AddChild(new Paragraph(Anchor.AutoCenter, 10000, p => PrettyPrintNumber(GameImpl.Instance.Tickets) + "<i ticket>", true) {
|
||||
TextScale = 0.3F
|
||||
});
|
||||
ticketGroup.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => GameImpl.Instance.Map.TicketsPerSecond.ToString("0.##") + "<i ticket>/s", true) {
|
||||
|
@ -71,7 +73,13 @@ namespace TouchyTickets {
|
|||
}
|
||||
});
|
||||
storeGroup.AddChild(new Image(Anchor.TopLeft, Vector2.One, Texture[0, 0, 2, 3]) {
|
||||
OnPressed = e => GameImpl.Instance.Tickets++,
|
||||
OnPressed = e => {
|
||||
#if DEBUG
|
||||
GameImpl.Instance.Tickets += 500000;
|
||||
#else
|
||||
GameImpl.Instance.Tickets++;
|
||||
#endif
|
||||
},
|
||||
CanBeSelected = true,
|
||||
CanBeMoused = true
|
||||
});
|
||||
|
@ -86,9 +94,6 @@ namespace TouchyTickets {
|
|||
map.Draw(time, batch, pos, scale, alpha, false, new RectangleF(Vector2.Zero, mapSize * scale));
|
||||
},
|
||||
OnPressed = e => {
|
||||
var map = GameImpl.Instance.Map;
|
||||
GameImpl.Instance.Camera.LookingPosition = new Vector2(map.Width, map.Height) / 2 * Attraction.TileSize;
|
||||
|
||||
var backUi = new Group(Anchor.BottomLeft, new Vector2(1));
|
||||
backUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(1, 40), "Back") {
|
||||
OnPressed = e2 => this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name))
|
||||
|
@ -111,13 +116,12 @@ namespace TouchyTickets {
|
|||
BigInteger price = 0;
|
||||
var button = buyUi.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 40)) {
|
||||
ChildPadding = new Vector2(4),
|
||||
Padding = new Padding(0, 0, 0, 4),
|
||||
OnPressed = e => {
|
||||
var map = GameImpl.Instance.Map;
|
||||
var pos = new Vector2(map.Width, map.Height) / 2;
|
||||
GameImpl.Instance.Camera.LookingPosition = (pos + new Vector2(0.5F)) * Attraction.TileSize;
|
||||
map.PlacingAttraction = attraction.Value.Create();
|
||||
map.PlacingPosition = pos.ToPoint();
|
||||
// set placing position to center of camera's view
|
||||
var (posX, posY) = (GameImpl.Instance.Camera.LookingPosition / Attraction.TileSize).ToPoint();
|
||||
map.PlacingPosition = new Point(MathHelper.Clamp(posX, 0, map.Width), MathHelper.Clamp(posY, 0, map.Height));
|
||||
|
||||
var yesNoUi = new Group(Anchor.BottomLeft, new Vector2(1));
|
||||
yesNoUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(0.5F, 40), "Back") {
|
||||
|
@ -157,7 +161,56 @@ namespace TouchyTickets {
|
|||
}
|
||||
this.uiSystem.Add("Buy", buyUi);
|
||||
|
||||
this.swipeRelations = new Element[] {main, buyUi};
|
||||
// upgrade ui
|
||||
var upgradeUi = new Group(Anchor.TopLeft, Vector2.One, false) {
|
||||
IsHidden = true,
|
||||
OnDrawn = (e, time, batch, alpha) => batch.Draw(batch.GetBlankTexture(), e.DisplayArea, ColorExtensions.FromHex(0xff86bccf) * alpha)
|
||||
};
|
||||
var upgradeHeader = upgradeUi.AddChild(new Group(Anchor.AutoLeft, new Vector2(1, 0.25F), false));
|
||||
upgradeHeader.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => GameImpl.Instance.Stars + "<i star>", true) {TextScale = 0.3F});
|
||||
upgradeHeader.AddChild(new Button(Anchor.AutoCenter, new Vector2(0.8F, 20), "Earn <i star>") {
|
||||
PositionOffset = new Vector2(0, 4),
|
||||
OnUpdated = (e, time) => ((Button) e).IsDisabled = GameImpl.Instance.Tickets < GameImpl.Instance.GetStarPrice(),
|
||||
OnPressed = e => {
|
||||
var game = GameImpl.Instance;
|
||||
game.TimesRestarted++;
|
||||
game.Stars++;
|
||||
game.Map = new ParkMap(game.Map.Width, game.Map.Height);
|
||||
game.Tickets = 0;
|
||||
}
|
||||
});
|
||||
upgradeHeader.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => $"Requires {PrettyPrintNumber(GameImpl.Instance.GetStarPrice())}<i ticket>", true) {
|
||||
PositionOffset = new Vector2(0, 2)
|
||||
});
|
||||
var upgradeList = upgradeUi.AddChild(new Panel(Anchor.AutoLeft, new Vector2(1, 0.75F), Vector2.Zero, false, true, new Point(10, 30), false) {
|
||||
ChildPadding = new Padding(5, 15, 5, 5)
|
||||
});
|
||||
foreach (var upgrade in Upgrade.Upgrades.Values) {
|
||||
var button = upgradeList.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 40)) {
|
||||
ChildPadding = new Vector2(4),
|
||||
OnPressed = e => {
|
||||
GameImpl.Instance.Stars--;
|
||||
GameImpl.Instance.AppliedUpgrades.Add(upgrade);
|
||||
upgrade.OnApplied();
|
||||
}
|
||||
});
|
||||
button.OnUpdated += (e, time) => {
|
||||
// we want to hide if we're active, or if we still need a dependency to be active
|
||||
button.IsHidden = Upgrade.IsActive(upgrade) || upgrade.Dependencies.Any(u => !Upgrade.IsActive(u));
|
||||
button.IsDisabled = GameImpl.Instance.Stars < upgrade.Price;
|
||||
};
|
||||
var center = button.AddChild(new Group(Anchor.Center, new Vector2(0.8F, 1), false) {CanBeMoused = false});
|
||||
center.AddChild(new Paragraph(Anchor.AutoCenter, 1, upgrade.Name, true));
|
||||
//center.AddChild(new Paragraph(Anchor.AutoCenter, 1, upgrade.Description, true) {TextScale = 0.08F});
|
||||
var image = button.AddChild(new Image(Anchor.CenterLeft, new Vector2(1), upgrade.Texture) {
|
||||
Padding = new Vector2(4)
|
||||
});
|
||||
button.OnAreaUpdated += e => image.Size = new Vector2(e.DisplayArea.Height / e.Scale);
|
||||
button.AddChild(new Paragraph(Anchor.CenterRight, 1, p => upgrade.Price + "<i star>", true));
|
||||
}
|
||||
this.uiSystem.Add("Upgrade", upgradeUi);
|
||||
|
||||
this.swipeRelations = new Element[] {upgradeUi, main, buyUi};
|
||||
}
|
||||
|
||||
public void Update(GameTime time) {
|
||||
|
@ -247,5 +300,23 @@ namespace TouchyTickets {
|
|||
element.Transform = Matrix.Identity;
|
||||
}
|
||||
|
||||
private static string PrettyPrintNumber(BigInteger number) {
|
||||
if (number < 1000)
|
||||
return number.ToString();
|
||||
// thousands
|
||||
if (number < 1000000)
|
||||
return number.ToString("0,.##K");
|
||||
// millions
|
||||
if (number < 1000000000)
|
||||
return number.ToString("0,,.##M");
|
||||
// billions
|
||||
if (number < 1000000000000)
|
||||
return number.ToString("0,,,.##B");
|
||||
// trillions
|
||||
if (number < 1000000000000000)
|
||||
return number.ToString("0,,,,.##T");
|
||||
return number.ToString("0,,,,,.##Q");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
56
TouchyTickets/Upgrade.cs
Normal file
56
TouchyTickets/Upgrade.cs
Normal file
|
@ -0,0 +1,56 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MLEM.Extensions;
|
||||
using MLEM.Textures;
|
||||
|
||||
namespace TouchyTickets.Upgrades {
|
||||
public class Upgrade {
|
||||
|
||||
public static readonly Dictionary<string, Upgrade> Upgrades = new Dictionary<string, Upgrade>();
|
||||
public static readonly Upgrade[] MapSize = RegisterTiers("MapSize", 10, 1, 0.5F, Ui.Texture[0, 3]);
|
||||
|
||||
public readonly string Name;
|
||||
public readonly int Price;
|
||||
public readonly TextureRegion Texture;
|
||||
public readonly Upgrade[] Dependencies;
|
||||
|
||||
public Upgrade(string name, int price, TextureRegion texture, params Upgrade[] dependencies) {
|
||||
this.Name = name;
|
||||
this.Price = price;
|
||||
this.Texture = texture;
|
||||
this.Dependencies = dependencies;
|
||||
}
|
||||
|
||||
private static Upgrade[] RegisterTiers(string name, int amount, int startPrice, float priceIncrease, TextureRegion texture) {
|
||||
var ret = new Upgrade[amount];
|
||||
for (var i = 0; i < amount; i++) {
|
||||
// every tier except first depends on last tier
|
||||
var deps = i == 0 ? Array.Empty<Upgrade>() : new[] {ret[i - 1]};
|
||||
var price = (startPrice * (1 + i * priceIncrease)).Floor();
|
||||
Register(ret[i] = new Upgrade(name + (i + 1), price, texture, deps));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void OnApplied() {
|
||||
// map size upgrades
|
||||
if (MapSize.Contains(this)) {
|
||||
var oldMap = GameImpl.Instance.Map;
|
||||
var newMap = new ParkMap(oldMap.Width + 5, oldMap.Height + 5);
|
||||
newMap.CopyAttractionsFrom(oldMap);
|
||||
GameImpl.Instance.Map = newMap;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Register(Upgrade upgrade) {
|
||||
Upgrades.Add(upgrade.Name, upgrade);
|
||||
}
|
||||
|
||||
public static bool IsActive(Upgrade upgrade) {
|
||||
return GameImpl.Instance.AppliedUpgrades.Contains(upgrade);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue