using System; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using MLEM.Extended.Tiled; using MLEM.Extensions; using MLEM.Misc; using MLEM.Startup; using MLEM.Textures; using MonoGame.Extended.Tiled; 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.GetPenetrations(getArea, !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.1F) { 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 (Point, TiledMapTilesetTile) GetTileBelow(Vector2? offset = null, string layer = null) { var (x, y) = this.Position + (offset ?? new Vector2(0, 0.5F)); var pos = new Point((x + 0.5F).Floor(), (y + 0.5F).Floor()); var tile = this.Map.GetTile(layer ?? "Ground", pos.X, pos.Y); return !tile.IsBlank ? (pos, this.Map.GetTilesetTile(tile, this.Map.GetTileset(tile))) : default; } } }