From d612a6230606f75c3b6b10d2ce150d26a6532e7d Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sun, 31 May 2020 00:44:15 +0200 Subject: [PATCH] attractions and swiping, that took long --- ThemeParkClicker/Attractions/Attraction.cs | 42 +++++++ ThemeParkClicker/Content/Content.mgcb | 5 + .../Content/Textures/Attractions.aseprite | Bin 0 -> 1089 bytes .../Content/Textures/Attractions.png | Bin 0 -> 1580 bytes ThemeParkClicker/GameImpl.cs | 5 + ThemeParkClicker/ThemeParkClicker.csproj | 6 +- ThemeParkClicker/Ui.cs | 115 ++++++++++++++++-- 7 files changed, 156 insertions(+), 17 deletions(-) create mode 100644 ThemeParkClicker/Attractions/Attraction.cs create mode 100644 ThemeParkClicker/Content/Textures/Attractions.aseprite create mode 100644 ThemeParkClicker/Content/Textures/Attractions.png diff --git a/ThemeParkClicker/Attractions/Attraction.cs b/ThemeParkClicker/Attractions/Attraction.cs new file mode 100644 index 0000000..748f884 --- /dev/null +++ b/ThemeParkClicker/Attractions/Attraction.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework.Graphics; +using MLEM.Startup; +using MLEM.Textures; + +namespace ThemeParkClicker.Attractions { + public class Attraction { + + public static readonly Dictionary Attractions = new Dictionary(); + public static readonly UniformTextureAtlas Texture = new UniformTextureAtlas(MlemGame.LoadContent("Textures/Attractions"), 16, 16); + + static Attraction() { + Attractions.Add("Carousel", () => new Attraction(new[,] {{true}}, Texture[0, 0, 1, 1], 0.25F, 50)); + Attractions.Add("FoodCourt", () => new Attraction(new[,] {{true, true}}, Texture[1, 0, 2, 1], 0.6F, 300)); + } + + private readonly bool[,] area; + public int Width => this.area.GetLength(0); + public int Height => this.area.GetLength(1); + public readonly TextureRegion TextureRegion; + public readonly float GenerationPerSecond; + public readonly long InitialPrice; + + public Attraction(bool[,] area, TextureRegion texture, float generationPerSecond, long initialPrice) { + this.area = area; + this.TextureRegion = texture; + this.GenerationPerSecond = generationPerSecond; + this.InitialPrice = initialPrice; + } + + public bool HasTileAt(int x, int y) { + return this.area[y, x]; + } + + public delegate Attraction Constructor(); + + public long GetPrice() { + return this.InitialPrice; + } + + } +} \ No newline at end of file diff --git a/ThemeParkClicker/Content/Content.mgcb b/ThemeParkClicker/Content/Content.mgcb index 9a4ab94..d6d7b88 100644 --- a/ThemeParkClicker/Content/Content.mgcb +++ b/ThemeParkClicker/Content/Content.mgcb @@ -30,3 +30,8 @@ /processor:FontDescriptionProcessor /build:Fonts/Regular.spritefont +#begin Textures/Attractions.png +/importer:TextureImporter +/processor:TextureProcessor +/build:Textures/Attractions.png + diff --git a/ThemeParkClicker/Content/Textures/Attractions.aseprite b/ThemeParkClicker/Content/Textures/Attractions.aseprite new file mode 100644 index 0000000000000000000000000000000000000000..d45f86001a62e9681df307e48be7601cd761f8f2 GIT binary patch literal 1089 zcmcJN@l%s^9LK*CIpi|%ti!88do=YV(;+h0gBu(uQj#H-4Dv!?C^7F?t|{VZTt-KT z!Fer+U<@?Wu7VS8O$N+p(I^~?A=nhzc4SsCI3_gP!1W$==hk&ndPLjM#+{WD=b z@@A>^60(kp0+TlJz$5fFusVGQXg#(Ov@{(7r}dwJ9%nRIcXuBs(nWwVib61@fDP_X zSr10?XfQrr3Pxm~1`ih6L1DcYJY@VC9JsvzdQpVbf2je>cKfM>)JUJ({p?z?vi4VJ(L(1$z3VGU*YLKddbgd+rD2Q_#>3P#ZJ zxp=*>fCBOnj%36l6M;xW6w8-H;ky4VD3Ad1Qcm$<3AK&8j1Ygy_a9&>^nce@eD;$K zYK3X@uCyl&_r%#WGcf1+%J5g@QO_!#KD#zYpBupmuM9u;QTy5-cBe(}dE&9d%~N?> zn59D_u2I1~C0(@g*yON7DVy$5$;RJihjiSYvn&1Hu^&Q@zlu_A_T{g9R`1oBw2M2C8lhRvs^|*?vk{ z`&!0*PTR(VlOi!~Qu2}-ZnkCd&0+MdFpm7{Pp;P0-{vja-)L3_b|-w+)h7+6*O(gl z*3My%^Ucktb=zAKzsu}zXsxiYiigWN7dxZ@Jk^2w6L;oUa4WA{vcA`j)SX*VQ*`1o zJF%Y`G&iIp!u3+YkGAlk`G-ems$G3-)7SUh`eDbLSHf7_s{D5>d;4OWC0-p#)d!)5)xAjw?} zoZzy?S~O#V9ob^Xb8pq@d5QUSvTDnRQ-3@oTXc*E^G(ZQFHXc&HBNuLQ{34$7XPX+ zwt&?tR3;c6#Mv3F2eX5#!fFSdI&<=9hN|z>n)a{UJV|R-xkq2F*4VD<^3A=@qjQf( Xi<-N>aZi@G3*_3FQcbGKYApE+fg`O; literal 0 HcmV?d00001 diff --git a/ThemeParkClicker/Content/Textures/Attractions.png b/ThemeParkClicker/Content/Textures/Attractions.png new file mode 100644 index 0000000000000000000000000000000000000000..876ed7221d06942db25bfff73529c997d348e4c8 GIT binary patch literal 1580 zcmd^<`BM@I6vrt|J2Yq3ZLO7ZSIIUjopB@YD@|j(I#e_vGz3lYZZi4OpI=`7m5>0_gWn$n005?t z%YN4YfIa$g4`9EMzQHp7K!4pbuLWEL(0M=!0I*LC@$(70SG78M6%(#FZoHm)x(>F2 zDYj2}kP!crotA56Yi}ryD=JdnI)8|3j071Dcg5v{(A{yd_A99D$wpW3PKz@>^5Y@S zcP}hEy)O&*BDv`3l9t2-zXZlZ=#B0-B;4Wc;fDKrQfZ+X891J5inxYVYI!=fV8I+S z-r6wUf`o2Bz@Dk`?matB@hI~1^niS1I4ZePsof6NhriIA0@kD3W27+{e#d;Gk zE%|A?6d%xkGU>pmN2ogj#NO(mmdrU60EuVJYi%H817Cr_XtNE0X`~LH3Jn(DUsHG2 z$%+}J78WF(P$hBS-kFJBju39gY&6HXLbr6DCf2s@E^tK)stUt z44THUa?B#YQeD?6h~tIug}k}X6#y72lU!(~^Xo0n$JHhp1{$TX<7%ne`*l%Z<$P2u z^{DO+XB4Ofsn$$si45>=nwkslf!9n3H%V-N4|$?T`1q;ig8GDK(|;?hH15r#6t;ga zs;Jj@*VVD?7JSH?qe|{*8kk;bc%0Ox!ZHbcb!eY>X*&5VP!&jCD42|=fDmQ4?TocU zoral|1#WrkmKm1|uyu8dKN1`oy2w=qEphzQTfY+9J=*F~5$k%Zv4ubb=wCt*c4zJZ z7BfWVHYlE7wF)Ii{pdj35t+l!r#vYWx6EK^z4}Hs%aak&l_oC|2&T#!E$wN= zzTUPdM1AVJs!?K%O?@>)UVv&JXNv$RBETKr8M{(Rx8 z%Adbq%*SmmOj^i4@hs)6&!o+c;_Wv(qbIR0f`TpV+(YBRd*d!e(l1-8viwmP~i$!}GNeGU@Jg znK41Th{v*@nKUzOu#&7~V}aY-W+Y3TcS#RylcLckg(-a<301u<36Vz3#?zHPguVwOH9!Sj0>>Nc5;C%u_MrtR?V>@&?twJ0#zv27k-R znCbE%C#RR6E?2xhR#jOMLf%p+BABTdjQbS4`W)@{2`7kP!XQl|wq?(mzs%ST*0{L1 zn19Gy>#01eg@tb|ZwVwJ(3{l+H-wcEKdlsLfz-^{cSH;ZJ=fCQ?1V(lOQh1K_we64 zCs=cIl`WzZMBct=| z)L#$rp~J^0t*sm7HNkD4C$1ix>l;9FlfnAlF1;EYT6H>? zc)A-IBUY~GUw6U(8y2VxL|vgg$0jq=+i&*ng~>{Cr@QdC l1-gk;3%vdZ{+~+gr8Cgg94)sV0a}0chFl8qqhE~q^*>4?*Ps9Z literal 0 HcmV?d00001 diff --git a/ThemeParkClicker/GameImpl.cs b/ThemeParkClicker/GameImpl.cs index 47d32e8..787ec9a 100644 --- a/ThemeParkClicker/GameImpl.cs +++ b/ThemeParkClicker/GameImpl.cs @@ -25,6 +25,11 @@ namespace ThemeParkClicker { return this.Tickets.ToString(); } + protected override void DoUpdate(GameTime gameTime) { + base.DoUpdate(gameTime); + this.Ui.Update(gameTime); + } + protected override void DoDraw(GameTime gameTime) { this.GraphicsDevice.Clear(ColorExtensions.FromHex(0x86cfcb)); base.DoDraw(gameTime); diff --git a/ThemeParkClicker/ThemeParkClicker.csproj b/ThemeParkClicker/ThemeParkClicker.csproj index 7dadf37..c026cfb 100644 --- a/ThemeParkClicker/ThemeParkClicker.csproj +++ b/ThemeParkClicker/ThemeParkClicker.csproj @@ -5,14 +5,10 @@ - + all - - - - \ No newline at end of file diff --git a/ThemeParkClicker/Ui.cs b/ThemeParkClicker/Ui.cs index 0f28cf6..2cfaa7f 100644 --- a/ThemeParkClicker/Ui.cs +++ b/ThemeParkClicker/Ui.cs @@ -1,30 +1,43 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; using Coroutine; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input.Touch; +using MLEM.Extensions; using MLEM.Font; +using MLEM.Formatting.Codes; +using MLEM.Misc; using MLEM.Startup; using MLEM.Textures; using MLEM.Ui; using MLEM.Ui.Elements; +using ThemeParkClicker.Attractions; namespace ThemeParkClicker { public class Ui { public static readonly UniformTextureAtlas Texture = new UniformTextureAtlas(MlemGame.LoadContent("Textures/Ui"), 16, 16); + private readonly UiSystem uiSystem; + private readonly Element[] swipeRelations; + private Element currentUi; + private float swipeProgress; + private bool finishingSwipe; public Ui(UiSystem uiSystem) { - uiSystem.GlobalScale = 4; - uiSystem.AutoScaleWithScreen = true; - uiSystem.AutoScaleReferenceSize = new Point(720, 1280); - uiSystem.Style.Font = new GenericSpriteFont(MlemGame.LoadContent("Fonts/Regular")); - uiSystem.Style.TextScale = 0.1F; + 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("Fonts/Regular")); + this.uiSystem.Style.TextScale = 0.1F; + this.uiSystem.TextFormatter.AddImage("ticket", Texture[2, 0]); - // ticket store ui + // main ticket store ui var rainingTickets = new List(); - Group ticketStoreUi = new Group(Anchor.TopLeft, Vector2.One, false) { + var main = new Group(Anchor.TopLeft, Vector2.One, false) { OnUpdated = (e, time) => { for (var i = rainingTickets.Count - 1; i >= 0; i--) { if (rainingTickets[i].Update()) @@ -38,10 +51,10 @@ namespace ThemeParkClicker { ticket.Draw(batch, e.DisplayArea.Size, e.Scale); } }; - ticketStoreUi.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => GameImpl.Instance.DisplayTicketCount(), true) { + main.AddChild(new Paragraph(Anchor.AutoCenter, 1, p => GameImpl.Instance.DisplayTicketCount(), true) { TextScale = 0.3F }); - var storeGroup = ticketStoreUi.AddChild(new CustomDrawGroup(Anchor.AutoLeft, Vector2.One)); + var storeGroup = main.AddChild(new CustomDrawGroup(Anchor.AutoLeft, Vector2.One)); storeGroup.AddChild(new Image(Anchor.TopLeft, Vector2.One, Texture[0, 0, 2, 3]) { OnPressed = e => { GameImpl.Instance.Tickets++; @@ -50,11 +63,89 @@ namespace ThemeParkClicker { CanBeSelected = true, CanBeMoused = true }); - ticketStoreUi.OnAreaUpdated += e => storeGroup.Size = new Vector2(e.DisplayArea.Width / e.Scale); - uiSystem.Add("TicketStore", ticketStoreUi); + main.OnAreaUpdated += e => storeGroup.Size = new Vector2(e.DisplayArea.Width / e.Scale); + this.currentUi = main; + this.uiSystem.Add("Main", main); + + // buy ui + var buyUi = new Panel(Anchor.TopLeft, Vector2.One, Vector2.Zero, false, true, new Point(10, 30), false) { + ChildPadding = new Padding(5, 15, 5, 5), + IsHidden = true + }; + foreach (var attraction in Attraction.Attractions) { + 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) + }); + 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)); + center.AddChild(new Paragraph(Anchor.AutoCenter, 1, attraction.Key, true)); + center.AddChild(new Paragraph(Anchor.AutoCenter, 1, instance.GenerationPerSecond + "/s", true) {TextScale = 0.08F}); + var image = button.AddChild(new Image(Anchor.CenterLeft, new Vector2(1), instance.TextureRegion) { + Padding = new Vector2(4) + }); + button.OnAreaUpdated += e => image.Size = new Vector2(e.DisplayArea.Height / e.Scale); + button.AddChild(new Paragraph(Anchor.CenterRight, 1, p => instance.GetPrice() + "", true)); + } + this.uiSystem.Add("Buy", buyUi); + + this.swipeRelations = new Element[] {main, buyUi}; } - private static IEnumerator WobbleElement(CustomDrawGroup element, float intensity = 0.01F) { + public void Update(GameTime time) { + // swiping between tabs + if (MlemGame.Input.GetGesture(GestureType.HorizontalDrag, out var gesture)) { + this.swipeProgress -= gesture.Delta.X / this.currentUi.DisplayArea.Width; + } else if (!this.finishingSwipe && this.swipeProgress != 0 && !MlemGame.Input.TouchState.Any()) { + // if we're not dragging or holding, we need to move back to our current ui + this.swipeProgress -= Math.Sign(this.swipeProgress) * 0.03F; + if (this.swipeProgress.Equals(0, 0.03F)) + this.ResetSwipe(); + } + + if (this.swipeProgress != 0) { + // actual swipe reaction logic + var curr = Array.IndexOf(this.swipeRelations, this.currentUi); + var next = curr + Math.Sign(this.swipeProgress); + if (next >= 0 && next < this.swipeRelations.Length) { + this.swipeRelations[next].IsHidden = false; + // if we've swiped a bit, we count this as a success and move to the next ui + this.finishingSwipe = Math.Abs(this.swipeProgress) >= 0.15F; + // if we're in the process of finishing a swipe, move without requiring input + if (this.finishingSwipe) { + if (!MlemGame.Input.TouchState.Any()) + this.swipeProgress += Math.Sign(this.swipeProgress) * 0.05F; + // we're done with the swipe, so switch the active ui + if (this.swipeProgress.Equals(Math.Sign(this.swipeProgress), 0.05F)) { + this.currentUi = this.swipeRelations[next]; + this.ResetSwipe(); + } + } + } else { + // when we're swiping into the void, we want to stop at the max + this.swipeProgress = MathHelper.Clamp(this.swipeProgress, -1, 1); + } + + // update element positions + this.currentUi.Root.Transform = Matrix.CreateTranslation(-this.swipeProgress * this.currentUi.DisplayArea.Width, 0, 0); + if (next >= 0 && next < this.swipeRelations.Length) + this.swipeRelations[next].Root.Transform = Matrix.CreateTranslation((Math.Sign(this.swipeProgress) - this.swipeProgress) * this.swipeRelations[next].DisplayArea.Width, 0, 0); + } + } + + private void ResetSwipe() { + this.finishingSwipe = false; + this.swipeProgress = 0; + foreach (var element in this.swipeRelations) { + element.IsHidden = element != this.currentUi; + element.Root.Transform = Matrix.Identity; + } + } + + private static IEnumerator WobbleElement(CustomDrawGroup element, float intensity = 0.02F) { var sin = 0F; while (sin < MathHelper.Pi) { element.ScaleOrigin(1 + (float) Math.Sin(sin) * intensity);