using System; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MLEM.Extended.Tiled; using MLEM.Extensions; using MLEM.Startup; using MLEM.Textures; using MonoGame.Extended.Tiled; using RectangleF = MonoGame.Extended.RectangleF; namespace GreatSpringGameJam { public class Entity { public static readonly UniformTextureAtlas StuffTexture = new(MlemGame.LoadContent("Textures/Stuff"), 8, 8); protected static readonly Random Random = new(); public readonly Map Map; public Vector2 Position; public Entity(Map map, Vector2 position) { this.Map = map; this.Position = position; } public virtual void Update(GameTime time) { } public virtual void Draw(GameTime time, SpriteBatch batch) { } protected void Collide(Func getArea, ref Vector2 velocity, ref bool onGround) { // if we're not on the ground, we should prioritize x collisions to be pushed out of walls first var penetrations = this.Map.Collisions.GetPenetrations(getArea, prioritizeX: !onGround); onGround = false; foreach (var (normal, penetration) in penetrations) { this.Position -= normal * penetration; if (normal.Y > 0) { onGround = true; var below = this.GetTileBelow(); if (below != null && below.Properties.GetBool("JumpPad") && velocity.Y > 0) { velocity.Y = -velocity.Y; continue; } } velocity *= new Vector2(Math.Abs(normal.Y), Math.Abs(normal.X)); } // disallow exiting the map's sides var area = getArea(); if (area.Left < 0) this.Position.X += -area.Left; if (area.Right >= this.Map.Size.X) this.Position.X += this.Map.Size.X - area.Right; } protected TiledMapTilesetTile GetTileBelow(Vector2? offset = null, string layer = null) { var (x, y) = this.Position + (offset ?? new Vector2(0, 0.5F)); var tile = this.Map.GetTile(layer ?? "Ground", (x + 0.5F).Floor(), (y + 0.5F).Floor()); return !tile.IsBlank ? this.Map.GetTilesetTile(tile) : null; } } }