a bunch of stuff! yay!

This commit is contained in:
Ellpeck 2020-06-01 01:21:54 +02:00
parent f485f10c9f
commit 7c51c923b9
8 changed files with 147 additions and 46 deletions

View file

@ -14,12 +14,12 @@ namespace ThemeParkClicker.Attractions {
static Attraction() { static Attraction() {
Attractions.Add("Carousel", () => new Attraction(new[,] {{true}}, Texture[0, 0, 1, 1], 0.5F, 50)); Attractions.Add("Carousel", () => new Attraction(new[,] {{true}}, Texture[0, 0, 1, 1], 0.5F, 50));
Attractions.Add("FoodCourt", () => new Attraction(new[,] {{true, true}}, Texture[1, 0, 2, 1], 0.7F, 300)); Attractions.Add("FoodCourt", () => new Attraction(new[,] {{true, true}}, Texture[1, 0, 2, 1], 1.1F, 300));
} }
private readonly bool[,] area; private readonly bool[,] area;
public int Width => this.area.GetLength(0); public int Width => this.area.GetLength(1);
public int Height => this.area.GetLength(1); public int Height => this.area.GetLength(0);
public readonly TextureRegion TextureRegion; public readonly TextureRegion TextureRegion;
public readonly float GenerationPerSecond; public readonly float GenerationPerSecond;
public readonly long InitialPrice; public readonly long InitialPrice;
@ -32,8 +32,13 @@ namespace ThemeParkClicker.Attractions {
this.InitialPrice = initialPrice; this.InitialPrice = initialPrice;
} }
public bool HasTileAt(int x, int y) { public IEnumerable<Point> GetCoveredTiles() {
return this.area[y, x]; for (var x = 0; x < this.Width; x++) {
for (var y = 0; y < this.Height; y++) {
if (this.area[y, x])
yield return new Point(x, y);
}
}
} }
public delegate Attraction Constructor(); public delegate Attraction Constructor();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -11,12 +11,25 @@ namespace ThemeParkClicker {
public class GameImpl : MlemGame { public class GameImpl : MlemGame {
public static GameImpl Instance { get; private set; } public static GameImpl Instance { get; private set; }
public BigInteger Tickets = 200; private BigInteger tickets;
public BigInteger Tickets {
get => this.tickets;
set {
var diff = value - this.tickets;
if (diff > 0)
this.ticketsPerSecondCounter += (long) diff;
this.tickets = value;
}
}
public ParkMap Map { get; private set; } public ParkMap Map { 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 float TicketsPerSecond { get; private set; }
private long ticketsPerSecondCounter;
private double secondCounter;
public GameImpl() { public GameImpl() {
Instance = this; Instance = this;
} }
@ -26,17 +39,20 @@ namespace ThemeParkClicker {
this.Ui = new Ui(this.UiSystem); this.Ui = new Ui(this.UiSystem);
this.Map = new ParkMap(10, 10); this.Map = new ParkMap(10, 10);
this.Camera = new Camera(this.GraphicsDevice) { this.Camera = new Camera(this.GraphicsDevice) {
Scale = 16, Scale = 5,
AutoScaleWithScreen = true, AutoScaleWithScreen = true,
AutoScaleReferenceSize = new Point(720, 1280), AutoScaleReferenceSize = new Point(720, 1280),
MaxScale = 24, MaxScale = 24,
MinScale = 4 MinScale = 3
}; };
#if DEBUG
this.Tickets = 1000;
this.Map.Place(Point.Zero, Attraction.Attractions["Carousel"]()); this.Map.Place(Point.Zero, Attraction.Attractions["Carousel"]());
this.Map.Place(new Point(1, 0), Attraction.Attractions["Carousel"]()); this.Map.Place(new Point(1, 0), Attraction.Attractions["Carousel"]());
this.Map.Place(new Point(3, 0), Attraction.Attractions["Carousel"]()); this.Map.Place(new Point(3, 0), Attraction.Attractions["Carousel"]());
this.Map.Place(new Point(1, 2), Attraction.Attractions["FoodCourt"]()); this.Map.Place(new Point(1, 2), Attraction.Attractions["FoodCourt"]());
#endif
} }
public string DisplayTicketCount() { public string DisplayTicketCount() {
@ -47,13 +63,21 @@ namespace ThemeParkClicker {
base.DoUpdate(gameTime); base.DoUpdate(gameTime);
this.Map.Update(gameTime); this.Map.Update(gameTime);
this.Ui.Update(gameTime); this.Ui.Update(gameTime);
// we average tickets per second over two seconds
this.secondCounter += gameTime.ElapsedGameTime.TotalSeconds;
if (this.secondCounter >= 2) {
this.secondCounter -= 2;
this.TicketsPerSecond = this.ticketsPerSecondCounter / 2F;
this.ticketsPerSecondCounter = 0;
}
} }
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) {
this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: this.Camera.ViewMatrix); this.SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointClamp, transformMatrix: this.Camera.ViewMatrix);
this.Map.Draw(gameTime, this.SpriteBatch, Vector2.Zero, 1); this.Map.Draw(gameTime, this.SpriteBatch, Vector2.Zero, 1, 1);
this.SpriteBatch.End(); this.SpriteBatch.End();
} }
base.DoDraw(gameTime); base.DoDraw(gameTime);

View file

@ -19,6 +19,10 @@ namespace ThemeParkClicker {
private readonly Attraction[,] grid; private readonly Attraction[,] grid;
private readonly Dictionary<Point, Attraction> attractions = new Dictionary<Point, Attraction>(); private readonly Dictionary<Point, Attraction> attractions = new Dictionary<Point, Attraction>();
public Attraction PlacingAttraction;
public Point PlacingPosition;
private bool draggingAttraction;
public ParkMap(int width, int height) { public ParkMap(int width, int height) {
this.Width = width; this.Width = width;
this.Height = height; this.Height = height;
@ -43,35 +47,55 @@ namespace ThemeParkClicker {
camera.Zoom(-pinch.Delta.Length() / camera.Scale); camera.Zoom(-pinch.Delta.Length() / camera.Scale);
} }
} else if (MlemGame.Input.GetGesture(GestureType.FreeDrag, out var drag)) { } else if (MlemGame.Input.GetGesture(GestureType.FreeDrag, out var drag)) {
camera.Position -= drag.Delta / camera.Scale; if (this.draggingAttraction) {
// move the current placing position
var nextPos = (camera.ToWorldPos(drag.Position + drag.Delta) / Attraction.TileSize).ToPoint();
if (nextPos.X >= 0 && nextPos.Y >= 0 && nextPos.X < this.Width && nextPos.Y < this.Height)
this.PlacingPosition = nextPos;
} else {
// move the camera
camera.Position -= drag.Delta / camera.Scale;
}
} else if (this.PlacingAttraction != null) {
foreach (var touch in MlemGame.Input.TouchState) {
if (touch.State != TouchLocationState.Pressed)
continue;
// when first pressing down, go into attraction drag mode if we're touching the place location
var offset = (camera.ToWorldPos(touch.Position) / Attraction.TileSize).ToPoint();
this.draggingAttraction = this.PlacingAttraction.GetCoveredTiles()
.Any(p => this.PlacingPosition + p == offset);
}
} }
} }
} }
public void Draw(GameTime time, SpriteBatch batch, Vector2 position, float scale) { public void Draw(GameTime time, SpriteBatch batch, Vector2 position, float scale, float alpha) {
var tileSize = Attraction.TileSize * scale; var tileSize = Attraction.TileSize * scale;
// draw ground // draw ground
batch.Draw(batch.GetBlankTexture(), new RectangleF(position, new Vector2(this.Width, this.Height) * tileSize), ColorExtensions.FromHex(0xff53a662)); batch.Draw(batch.GetBlankTexture(), new RectangleF(position, new Vector2(this.Width, this.Height) * tileSize), ColorExtensions.FromHex(0xff53a662) * alpha);
// draw attractions // draw attractions
foreach (var kv in this.attractions) foreach (var kv in this.attractions)
batch.Draw(kv.Value.TextureRegion, position + kv.Key.ToVector2() * tileSize, Color.White); batch.Draw(kv.Value.TextureRegion, position + kv.Key.ToVector2() * tileSize, Color.White * alpha, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
// placing attraction
if (this.PlacingAttraction != null) {
var placingPos = position + this.PlacingPosition.ToVector2() * tileSize;
foreach (var pos in this.PlacingAttraction.GetCoveredTiles())
batch.Draw(batch.GetBlankTexture(), new RectangleF(placingPos + pos.ToVector2() * tileSize, tileSize), Color.Black * 0.15F * alpha);
batch.Draw(this.PlacingAttraction.TextureRegion, placingPos, Color.White * alpha * 0.5F, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
}
} }
public bool CanPlace(Point position, Attraction attraction) { public bool CanPlace(Point position, Attraction attraction) {
for (var x = 0; x < attraction.Width; x++) { foreach (var (x, y) in attraction.GetCoveredTiles()) {
for (var y = 0; y < attraction.Height; y++) { if (this.grid[position.X + x, position.Y + y] != null)
if (this.grid[position.X + x, position.Y + y] != null) return false;
return false;
}
} }
return true; return true;
} }
public void Place(Point position, Attraction attraction) { public void Place(Point position, Attraction attraction) {
for (var x = 0; x < attraction.Width; x++) { foreach (var (x, y) in attraction.GetCoveredTiles())
for (var y = 0; y < attraction.Height; y++) this.grid[position.X + x, position.Y + y] = attraction;
this.grid[position.X + x, position.Y + y] = attraction;
}
this.attractions[position] = attraction; this.attractions[position] = attraction;
} }

View file

@ -26,9 +26,9 @@ namespace ThemeParkClicker {
return this.position.Y >= 1.15F; return this.position.Y >= 1.15F;
} }
public void Draw(SpriteBatch batch, Vector2 viewport, float scale) { public void Draw(SpriteBatch batch, Vector2 viewport, float scale, Color color) {
var tex = Ui.Texture[2, 0]; var tex = Ui.Texture[2, 0];
batch.Draw(tex, this.position * viewport, Color.White, this.rotation, tex.Size.ToVector2() / 2, scale, SpriteEffects.None, 0); batch.Draw(tex, this.position * viewport, color, this.rotation, tex.Size.ToVector2() / 2, scale, SpriteEffects.None, 0);
} }
} }

View file

@ -5,6 +5,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Coroutine" Version="1.0.4" />
<PackageReference Include="MLEM.Startup" Version="3.3.3-189" /> <PackageReference Include="MLEM.Startup" Version="3.3.3-189" />
<PackageReference Include="MonoGame.Framework.Portable" Version="3.7.1.189"> <PackageReference Include="MonoGame.Framework.Portable" Version="3.7.1.189">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>

View file

@ -28,7 +28,7 @@ namespace ThemeParkClicker {
private bool finishingSwipe; private bool finishingSwipe;
public Ui(UiSystem uiSystem) { public Ui(UiSystem uiSystem) {
InputHandler.EnableGestures(GestureType.HorizontalDrag, GestureType.FreeDrag, GestureType.Pinch); InputHandler.EnableGestures(GestureType.HorizontalDrag, GestureType.FreeDrag, GestureType.Pinch, GestureType.Tap);
this.uiSystem = uiSystem; this.uiSystem = uiSystem;
this.uiSystem.GlobalScale = 4; this.uiSystem.GlobalScale = 4;
this.uiSystem.AutoScaleWithScreen = true; this.uiSystem.AutoScaleWithScreen = true;
@ -45,19 +45,22 @@ namespace ThemeParkClicker {
if (rainingTickets[i].Update()) if (rainingTickets[i].Update())
rainingTickets.RemoveAt(i); rainingTickets.RemoveAt(i);
} }
while (rainingTickets.Count < BigInteger.Min(GameImpl.Instance.Tickets / 100, 500)) while (rainingTickets.Count < Math.Min(GameImpl.Instance.TicketsPerSecond / 10, 500))
rainingTickets.Add(new RainingTicket()); rainingTickets.Add(new RainingTicket());
}, },
OnDrawn = (e, time, batch, alpha) => { OnDrawn = (e, time, batch, alpha) => {
batch.Draw(batch.GetBlankTexture(), e.DisplayArea, ColorExtensions.FromHex(0xff86cfcb)); batch.Draw(batch.GetBlankTexture(), e.DisplayArea, ColorExtensions.FromHex(0xff86cfcb) * alpha);
foreach (var ticket in rainingTickets) foreach (var ticket in rainingTickets)
ticket.Draw(batch, e.DisplayArea.Size, e.Scale); ticket.Draw(batch, e.DisplayArea.Size, e.Scale, Color.White * alpha);
} }
}; };
var ticketGroup = main.AddChild(new Group(Anchor.AutoCenter, new Vector2(1, 0.15F), false)); 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, 1, p => GameImpl.Instance.DisplayTicketCount(), true) {
TextScale = 0.3F TextScale = 0.3F
}); });
ticketGroup.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => GameImpl.Instance.TicketsPerSecond.ToString("0.##") + "<i ticket>/s", true) {
PositionOffset = new Vector2(0, -8)
});
BigInteger lastTickets = 0; BigInteger lastTickets = 0;
var storeGroup = main.AddChild(new CustomDrawGroup(Anchor.AutoCenter, new Vector2(1, 0.5F), null, null, false) { var storeGroup = main.AddChild(new CustomDrawGroup(Anchor.AutoCenter, new Vector2(1, 0.5F), null, null, false) {
OnUpdated = (e, time) => { OnUpdated = (e, time) => {
@ -80,9 +83,21 @@ namespace ThemeParkClicker {
var (scaleX, scaleY) = e.DisplayArea.Size / mapSize; var (scaleX, scaleY) = e.DisplayArea.Size / mapSize;
var scale = Math.Min(scaleX, scaleY); var scale = Math.Min(scaleX, scaleY);
var pos = e.DisplayArea.Location + (e.DisplayArea.Size - mapSize * scale) / 2; var pos = e.DisplayArea.Location + (e.DisplayArea.Size - mapSize * scale) / 2;
map.Draw(time, batch, pos, scale); map.Draw(time, batch, pos, scale, alpha);
}, },
OnPressed = e => CoroutineHandler.Start(this.SwipeUi(true)) 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))
});
// we want this to render below the main ui while it fades away
this.uiSystem.Add("MapViewBack", backUi).Priority = -100;
this.FadeUi(true);
}
}); });
this.currentUi = main; this.currentUi = main;
this.uiSystem.Add("Main", main); this.uiSystem.Add("Main", main);
@ -96,12 +111,36 @@ namespace ThemeParkClicker {
var instance = attraction.Value(); var instance = attraction.Value();
var button = buyUi.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 40)) { var button = buyUi.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 40)) {
ChildPadding = new Vector2(4), ChildPadding = new Vector2(4),
Padding = new Padding(0, 0, 0, 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();
map.PlacingPosition = pos.ToPoint();
var yesNoUi = new Group(Anchor.BottomLeft, new Vector2(1));
yesNoUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(0.5F, 40), "Back") {
OnPressed = e2 => this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name))
});
yesNoUi.AddChild(new Button(Anchor.AutoInlineIgnoreOverflow, new Vector2(0.5F, 40), "Place") {
OnPressed = e2 => {
GameImpl.Instance.Tickets -= map.PlacingAttraction.GetPrice();
map.Place(map.PlacingPosition, map.PlacingAttraction);
this.FadeUi(false, () => this.uiSystem.Remove(e2.Root.Name));
},
OnUpdated = (e2, time) => ((Button) e2).IsDisabled = !map.CanPlace(map.PlacingPosition, map.PlacingAttraction)
});
// we want this to render below the main ui while it fades away
this.uiSystem.Add("PlacingYesNo", yesNoUi).Priority = -100;
this.FadeUi(true);
}
}); });
button.OnUpdated += (e, time) => { button.OnUpdated += (e, time) => {
button.IsDisabled = GameImpl.Instance.Tickets < instance.GetPrice(); button.IsDisabled = GameImpl.Instance.Tickets < instance.GetPrice();
}; };
var center = button.AddChild(new Group(Anchor.Center, new Vector2(0.8F, 1), false)); var center = button.AddChild(new Group(Anchor.Center, new Vector2(0.8F, 1), false) {CanBeMoused = false});
center.AddChild(new Paragraph(Anchor.AutoCenter, 1, attraction.Key, true)); center.AddChild(new Paragraph(Anchor.AutoCenter, 1, attraction.Key, true));
center.AddChild(new Paragraph(Anchor.AutoCenter, 1, instance.GenerationPerSecond + "<i ticket>/s", true) {TextScale = 0.08F}); center.AddChild(new Paragraph(Anchor.AutoCenter, 1, instance.GenerationPerSecond + "<i ticket>/s", true) {TextScale = 0.08F});
var image = button.AddChild(new Image(Anchor.CenterLeft, new Vector2(1), instance.TextureRegion) { var image = button.AddChild(new Image(Anchor.CenterLeft, new Vector2(1), instance.TextureRegion) {
@ -167,21 +206,29 @@ namespace ThemeParkClicker {
} }
} }
private IEnumerator<IWait> SwipeUi(bool swipeOut) { private void FadeUi(bool fadeOut, Action after = null) {
GameImpl.Instance.DrawMap = true; IEnumerator<IWait> Impl() {
this.currentUi.IsHidden = false; // disable input handling during fade
var offset = 0F; this.uiSystem.Controls.HandleTouch = false;
while (offset < 1) { GameImpl.Instance.DrawMap = true;
offset += 0.025F; this.currentUi.IsHidden = false;
var trans = (!swipeOut ? 1 - offset : offset) * this.currentUi.DisplayArea.Height; var alpha = 1F;
this.currentUi.Root.Transform = Matrix.CreateTranslation(0, trans, 0); while (alpha > 0) {
yield return new WaitEvent(CoroutineEvents.Update); alpha -= 0.03F;
this.currentUi.DrawAlpha = !fadeOut ? 1 - alpha : alpha;
yield return new WaitEvent(CoroutineEvents.Update);
}
this.uiSystem.Controls.HandleTouch = true;
GameImpl.Instance.DrawMap = fadeOut;
this.currentUi.IsHidden = fadeOut;
// disable horizontal and vertical drag on map view to allow free drag to take priority
InputHandler.SetGesturesEnabled(!fadeOut, GestureType.HorizontalDrag, GestureType.VerticalDrag);
if (!fadeOut)
GameImpl.Instance.Map.PlacingAttraction = null;
after?.Invoke();
} }
this.currentUi.Root.Transform = Matrix.Identity;
GameImpl.Instance.DrawMap = swipeOut; CoroutineHandler.Start(Impl());
this.currentUi.IsHidden = swipeOut;
// disable horizontal and vertical drag on map view to allow free drag to take priority
InputHandler.SetGesturesEnabled(!swipeOut, GestureType.HorizontalDrag, GestureType.VerticalDrag);
} }
private static IEnumerator<IWait> WobbleElement(CustomDrawGroup element, float intensity = 0.02F) { private static IEnumerator<IWait> WobbleElement(CustomDrawGroup element, float intensity = 0.02F) {