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() {
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;
public int Width => this.area.GetLength(0);
public int Height => this.area.GetLength(1);
public int Width => this.area.GetLength(1);
public int Height => this.area.GetLength(0);
public readonly TextureRegion TextureRegion;
public readonly float GenerationPerSecond;
public readonly long InitialPrice;
@ -32,8 +32,13 @@ namespace ThemeParkClicker.Attractions {
this.InitialPrice = initialPrice;
}
public bool HasTileAt(int x, int y) {
return this.area[y, x];
public IEnumerable<Point> GetCoveredTiles() {
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();

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 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 Camera Camera { get; private set; }
public Ui Ui { get; private set; }
public bool DrawMap;
public float TicketsPerSecond { get; private set; }
private long ticketsPerSecondCounter;
private double secondCounter;
public GameImpl() {
Instance = this;
}
@ -26,17 +39,20 @@ namespace ThemeParkClicker {
this.Ui = new Ui(this.UiSystem);
this.Map = new ParkMap(10, 10);
this.Camera = new Camera(this.GraphicsDevice) {
Scale = 16,
Scale = 5,
AutoScaleWithScreen = true,
AutoScaleReferenceSize = new Point(720, 1280),
MaxScale = 24,
MinScale = 4
MinScale = 3
};
#if DEBUG
this.Tickets = 1000;
this.Map.Place(Point.Zero, 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(1, 2), Attraction.Attractions["FoodCourt"]());
#endif
}
public string DisplayTicketCount() {
@ -47,13 +63,21 @@ namespace ThemeParkClicker {
base.DoUpdate(gameTime);
this.Map.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) {
this.GraphicsDevice.Clear(Color.Black);
if (this.DrawMap) {
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();
}
base.DoDraw(gameTime);

View file

@ -19,6 +19,10 @@ namespace ThemeParkClicker {
private readonly Attraction[,] grid;
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) {
this.Width = width;
this.Height = height;
@ -43,35 +47,55 @@ namespace ThemeParkClicker {
camera.Zoom(-pinch.Delta.Length() / camera.Scale);
}
} else if (MlemGame.Input.GetGesture(GestureType.FreeDrag, out var drag)) {
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;
// 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
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) {
for (var x = 0; x < attraction.Width; x++) {
for (var y = 0; y < attraction.Height; y++) {
foreach (var (x, y) in attraction.GetCoveredTiles()) {
if (this.grid[position.X + x, position.Y + y] != null)
return false;
}
}
return true;
}
public void Place(Point position, Attraction attraction) {
for (var x = 0; x < attraction.Width; x++) {
for (var y = 0; y < attraction.Height; y++)
foreach (var (x, y) in attraction.GetCoveredTiles())
this.grid[position.X + x, position.Y + y] = attraction;
}
this.attractions[position] = attraction;
}

View file

@ -26,9 +26,9 @@ namespace ThemeParkClicker {
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];
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>
<ItemGroup>
<PackageReference Include="Coroutine" Version="1.0.4" />
<PackageReference Include="MLEM.Startup" Version="3.3.3-189" />
<PackageReference Include="MonoGame.Framework.Portable" Version="3.7.1.189">
<PrivateAssets>all</PrivateAssets>

View file

@ -28,7 +28,7 @@ namespace ThemeParkClicker {
private bool finishingSwipe;
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.GlobalScale = 4;
this.uiSystem.AutoScaleWithScreen = true;
@ -45,19 +45,22 @@ namespace ThemeParkClicker {
if (rainingTickets[i].Update())
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());
},
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)
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));
ticketGroup.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => GameImpl.Instance.DisplayTicketCount(), true) {
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;
var storeGroup = main.AddChild(new CustomDrawGroup(Anchor.AutoCenter, new Vector2(1, 0.5F), null, null, false) {
OnUpdated = (e, time) => {
@ -80,9 +83,21 @@ namespace ThemeParkClicker {
var (scaleX, scaleY) = e.DisplayArea.Size / mapSize;
var scale = Math.Min(scaleX, scaleY);
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.uiSystem.Add("Main", main);
@ -96,12 +111,36 @@ namespace ThemeParkClicker {
var instance = attraction.Value();
var button = buyUi.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 40)) {
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.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, instance.GenerationPerSecond + "<i ticket>/s", true) {TextScale = 0.08F});
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) {
IEnumerator<IWait> Impl() {
// disable input handling during fade
this.uiSystem.Controls.HandleTouch = false;
GameImpl.Instance.DrawMap = true;
this.currentUi.IsHidden = false;
var offset = 0F;
while (offset < 1) {
offset += 0.025F;
var trans = (!swipeOut ? 1 - offset : offset) * this.currentUi.DisplayArea.Height;
this.currentUi.Root.Transform = Matrix.CreateTranslation(0, trans, 0);
var alpha = 1F;
while (alpha > 0) {
alpha -= 0.03F;
this.currentUi.DrawAlpha = !fadeOut ? 1 - alpha : alpha;
yield return new WaitEvent(CoroutineEvents.Update);
}
this.currentUi.Root.Transform = Matrix.Identity;
GameImpl.Instance.DrawMap = swipeOut;
this.currentUi.IsHidden = swipeOut;
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(!swipeOut, GestureType.HorizontalDrag, GestureType.VerticalDrag);
InputHandler.SetGesturesEnabled(!fadeOut, GestureType.HorizontalDrag, GestureType.VerticalDrag);
if (!fadeOut)
GameImpl.Instance.Map.PlacingAttraction = null;
after?.Invoke();
}
CoroutineHandler.Start(Impl());
}
private static IEnumerator<IWait> WobbleElement(CustomDrawGroup element, float intensity = 0.02F) {