using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using MLEM.Animations; using MLEM.Extended.Extensions; using MLEM.Extended.Tiled; using MLEM.Extensions; using MLEM.Startup; using MLEM.Textures; using MonoGame.Extended; using MonoGame.Extended.Tiled; using RectangleF = MLEM.Misc.RectangleF; namespace GreatSpringGameJam { public class Player : Entity { private static readonly UniformTextureAtlas Atlas = new(MlemGame.LoadContent("Textures/Player"), 4, 1); private readonly SpriteAnimationGroup animations; public RectangleF Bounds => new(this.Position + new Vector2(4 / 16F, 0), new Vector2(9 / 16F, 1)); private bool walking; private bool onGround; private Vector2 velocity; private TimeSpan jumpTime; private bool facingRight; public Player(Map map, Vector2 position) : base(map, position) { this.animations = new SpriteAnimationGroup(); this.animations.Add(new SpriteAnimation(0.15F, Atlas[1], Atlas[2], Atlas[3], Atlas[0]), () => this.walking); this.animations.Add(new SpriteAnimation(1, Atlas[0]), () => !this.walking); } public override void Update(GameTime time) { base.Update(time); // input var lastVel = this.velocity; if (MlemGame.Input.IsAnyDown(Keys.A, Keys.Left, Buttons.DPadLeft, Buttons.LeftThumbstickLeft)) { this.velocity.X -= 0.04F; this.facingRight = false; } if (MlemGame.Input.IsAnyDown(Keys.D, Keys.Right, Buttons.DPadRight, Buttons.LeftThumbstickRight)) { this.velocity.X += 0.04F; this.facingRight = true; } this.walking = this.velocity != lastVel; if (MlemGame.Input.IsAnyDown(Keys.Up, Buttons.B, Keys.Space)) { // only start jumping if we just started pressing the buttons if (this.onGround && MlemGame.Input.IsAnyPressed(Keys.Up, Buttons.B, Keys.Space)) this.jumpTime = TimeSpan.FromSeconds(0.3F); this.jumpTime -= time.ElapsedGameTime; if (this.jumpTime > TimeSpan.Zero) this.velocity.Y = -0.15F; } else { this.jumpTime = TimeSpan.Zero; } // movement and collisions this.onGround = false; this.Position += this.velocity; foreach (var (normal, penetration) in this.Map.Collisions.GetPenetrations(() => this.Bounds.ToExtended())) { this.Position -= normal * penetration; this.velocity *= new Vector2(Math.Abs(normal.Y), Math.Abs(normal.X)); if (normal.Y > 0) this.onGround = true; } this.velocity *= new Vector2(this.onGround ? 0.5F : 0.6F, 0.9F); this.velocity.Y += 0.02F; this.animations.Update(time); } public override void Draw(GameTime time, SpriteBatch batch) { base.Draw(time, batch); var effects = this.facingRight ? SpriteEffects.FlipHorizontally : SpriteEffects.None; batch.Draw(this.animations.CurrentRegion, this.Position * this.Map.TileSize, Color.White, 0, Vector2.Zero, 1, effects, 0); } } }