Add project files.
This commit is contained in:
120
FreedomFighter/Sprites.cs
Normal file
120
FreedomFighter/Sprites.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace FreedomFighter;
|
||||
|
||||
/// <summary>
|
||||
/// Port of the Omega TSprite base class. Position is the pattern's top-left;
|
||||
/// CenterX/CenterY only affect the rotation pivot. Width/Height define the
|
||||
/// logical collision box, independent of the drawn pattern size.
|
||||
/// </summary>
|
||||
public abstract class Sprite
|
||||
{
|
||||
public string Name = "";
|
||||
public float X, Y;
|
||||
public int Width, Height;
|
||||
public float Rotation; // degrees
|
||||
public float CenterX, CenterY; // 0..1 fraction of pattern
|
||||
public float ScaleX = 1, ScaleY = 1;
|
||||
public int Red = 255, Green = 255, Blue = 255, Alpha = 255;
|
||||
public OmegaImage? Image;
|
||||
public int ImageIndex;
|
||||
public bool DoCollision;
|
||||
public bool DoPixelCheck;
|
||||
public bool IsDead;
|
||||
|
||||
protected Sprite(SpriteManager manager) => manager.Add(this);
|
||||
|
||||
public void SetGreen(int v) => Green = Math.Clamp(v, 0, 255);
|
||||
public void SetBlue(int v) => Blue = Math.Clamp(v, 0, 255);
|
||||
|
||||
/// <summary>Marks the sprite for removal (Omega's Dead).</summary>
|
||||
public void Kill() => IsDead = true;
|
||||
|
||||
public virtual void Move(float moveCount) { }
|
||||
|
||||
public virtual void Draw(SpriteBatch sb)
|
||||
{
|
||||
Image?.Draw(sb, (int)Math.Round(X), (int)Math.Round(Y), Rotation,
|
||||
CenterX, CenterY, ScaleX, ScaleY, Red, Green, Blue, Alpha, ImageIndex);
|
||||
}
|
||||
|
||||
public virtual void OnCollision(Sprite sprite, int colX, int colY) { }
|
||||
|
||||
public Rectangle Bounds => new((int)X, (int)Y, Width, Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Port of TOmegaSprite: owns all sprites, runs movement, collision
|
||||
/// (bounding box + optional pixel check), removal, and drawing.
|
||||
/// </summary>
|
||||
public class SpriteManager
|
||||
{
|
||||
public readonly List<Sprite> Items = new();
|
||||
|
||||
public int Count => Items.Count;
|
||||
|
||||
public void Add(Sprite s) => Items.Add(s);
|
||||
|
||||
public void KillAll()
|
||||
{
|
||||
foreach (var s in Items) s.Kill();
|
||||
}
|
||||
|
||||
public void Move(float moveCount)
|
||||
{
|
||||
// like the Pascal for-loop, sprites spawned during iteration are not moved this frame
|
||||
int n = Items.Count;
|
||||
for (int i = 0; i < n; i++)
|
||||
Items[i].Move(moveCount);
|
||||
}
|
||||
|
||||
public void Collision()
|
||||
{
|
||||
int n = Items.Count;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
var a = Items[i];
|
||||
if (!a.DoCollision || a.IsDead) continue;
|
||||
for (int j = i + 1; j < n; j++)
|
||||
{
|
||||
var b = Items[j];
|
||||
if (!b.DoCollision || b.IsDead) continue;
|
||||
|
||||
var overlap = Rectangle.Intersect(a.Bounds, b.Bounds);
|
||||
if (overlap.IsEmpty) continue;
|
||||
|
||||
if ((a.DoPixelCheck || b.DoPixelCheck) && !PixelOverlap(a, b, overlap)) continue;
|
||||
|
||||
a.OnCollision(b, overlap.X, overlap.Y);
|
||||
b.OnCollision(a, overlap.X, overlap.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Pixel test on the unrotated pattern masks (rotation ignored, like a cheap approximation).</summary>
|
||||
static bool PixelOverlap(Sprite a, Sprite b, Rectangle overlap)
|
||||
{
|
||||
if (a.Image == null || b.Image == null) return true;
|
||||
for (int y = overlap.Top; y < overlap.Bottom; y++)
|
||||
for (int x = overlap.Left; x < overlap.Right; x++)
|
||||
{
|
||||
bool pa = a.Image.IsOpaque(a.ImageIndex, x - (int)a.X, y - (int)a.Y);
|
||||
bool pb = b.Image.IsOpaque(b.ImageIndex, x - (int)b.X, y - (int)b.Y);
|
||||
if (pa && pb) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void RemoveDead() => Items.RemoveAll(s => s.IsDead);
|
||||
|
||||
public void Draw(SpriteBatch sb)
|
||||
{
|
||||
int n = Items.Count;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (!Items[i].IsDead)
|
||||
Items[i].Draw(sb);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user