using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System; namespace AlienAttack.MonoGame.Things.Items; public abstract class Item : MoveableSprite { private Vector2 _anchor; // the "center" the item orbits around private float _t; // radians private float _radius = 6f; // pixels (small circle) private float _omega = 2.2f; // radians/sec (speed of orbit) private float _scale = 1f; protected string TextureName; public const int Width = 48; public const int Height = 29; protected abstract PickupKind Kind { get; } public Item(int x, int y) : base(x, y) { YVelocity = .5f; BoundBox = new Rectangle(0, 0, Width, Height); _anchor = new Vector2(x, y); } public override void Draw(SpriteDrawArgs args) { if (TextureName is null) return; Texture2D texture = args.Content.Load(TextureName); args.SpriteBatch.Draw(texture, Position, null, DrawColor, 0, new Vector2(0, 0), _scale, SpriteEffects.None, 1); } public override void Update(SpriteUpdateContext context) { // Move the anchor using your normal velocities (downward drift) _anchor.Y += YVelocity; _anchor.X += XVelocity; // Advance time smoothly (use dt; if you don't have it yet, see note below) float dt = (float)context.GameTime.ElapsedGameTime.TotalSeconds; _t += _omega * dt; // Apply circular offset around the anchor XPosition = _anchor.X + MathF.Cos(_t) * _radius; YPosition = _anchor.Y + MathF.Sin(_t) * _radius; if (YPosition > context.ViewTransform.ScreenHeight) { IsDead = true; return; } base.Update(context); } public override void OnCollision(SpriteCollisionContext context) { if (context.Sprite is Player) { IsDead = true; context.AudioManager.PlayPickup(Kind); } } }