| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using Tutorial020.Managers;
- using Tutorial020.Models;
- namespace Tutorial020.Sprites
- {
- public class Sprite : Component, ICloneable
- {
- protected Dictionary<string, Animation> _animations;
- protected AnimationManager _animationManager;
- protected float _layer { get; set; }
- protected Vector2 _origin { get; set; }
- protected Vector2 _position { get; set; }
- protected float _rotation { get; set; }
- protected float _scale { get; set; }
- protected Texture2D _texture;
- public List<Sprite> Children { get; set; }
- public Color Colour { get; set; }
- public bool IsRemoved { get; set; }
- public float Layer
- {
- get { return _layer; }
- set
- {
- _layer = value;
- if (_animationManager != null)
- _animationManager.Layer = _layer;
- }
- }
- public Vector2 Origin
- {
- get { return _origin; }
- set
- {
- _origin = value;
- if (_animationManager != null)
- _animationManager.Origin = _origin;
- }
- }
- public Vector2 Position
- {
- get
- {
- return _position;
- }
- set
- {
- _position = value;
- if (_animationManager != null)
- _animationManager.Position = _position;
- }
- }
- public Rectangle Rectangle
- {
- get
- {
- if (_texture != null)
- {
- return new Rectangle((int)Position.X - (int)Origin.X, (int)Position.Y - (int)Origin.Y, _texture.Width, _texture.Height);
- }
- if (_animationManager != null)
- {
- var animation = _animations.FirstOrDefault().Value;
- return new Rectangle((int)Position.X - (int)Origin.X, (int)Position.Y - (int)Origin.Y, animation.FrameWidth, animation.FrameHeight);
- }
- throw new Exception("Unknown sprite");
- }
- }
- public float Rotation
- {
- get { return _rotation; }
- set
- {
- _rotation = value;
- if (_animationManager != null)
- _animationManager.Rotation = value;
- }
- }
- public readonly Color[] TextureData;
- public Matrix Transform
- {
- get
- {
- return Matrix.CreateTranslation(new Vector3(-Origin, 0)) *
- Matrix.CreateRotationZ(_rotation) *
- Matrix.CreateTranslation(new Vector3(Position, 0));
- }
- }
- public Sprite Parent;
- /// <summary>
- /// The area of the sprite that could "potentially" be collided with
- /// </summary>
- public Rectangle CollisionArea
- {
- get
- {
- return new Rectangle(Rectangle.X, Rectangle.Y, MathHelper.Max(Rectangle.Width, Rectangle.Height), MathHelper.Max(Rectangle.Width, Rectangle.Height));
- }
- }
- public Sprite(Texture2D texture)
- {
- _texture = texture;
- Children = new List<Sprite>();
- Origin = new Vector2(_texture.Width / 2, _texture.Height / 2);
- Colour = Color.White;
- TextureData = new Color[_texture.Width * _texture.Height];
- _texture.GetData(TextureData);
- }
- public Sprite(Dictionary<string, Animation> animations)
- {
- _texture = null;
- Children = new List<Sprite>();
- Colour = Color.White;
- TextureData = null;
- _animations = animations;
- var animation = _animations.FirstOrDefault().Value;
- _animationManager = new AnimationManager(animation);
- Origin = new Vector2(animation.FrameWidth / 2, animation.FrameHeight / 2);
- }
- public override void Update(GameTime gameTime)
- {
- }
- public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
- {
- if (_texture != null)
- spriteBatch.Draw(_texture, Position, null, Colour, _rotation, Origin, 1f, SpriteEffects.None, Layer);
- else if (_animationManager != null)
- _animationManager.Draw(spriteBatch);
- }
- public bool Intersects(Sprite sprite)
- {
- if (this.TextureData == null)
- return false;
- if (sprite.TextureData == null)
- return false;
- // Calculate a matrix which transforms from A's local space into
- // world space and then into B's local space
- var transformAToB = this.Transform * Matrix.Invert(sprite.Transform);
- // When a point moves in A's local space, it moves in B's local space with a
- // fixed direction and distance proportional to the movement in A.
- // This algorithm steps through A one pixel at a time along A's X and Y axes
- // Calculate the analogous steps in B:
- var stepX = Vector2.TransformNormal(Vector2.UnitX, transformAToB);
- var stepY = Vector2.TransformNormal(Vector2.UnitY, transformAToB);
- // Calculate the top left corner of A in B's local space
- // This variable will be reused to keep track of the start of each row
- var yPosInB = Vector2.Transform(Vector2.Zero, transformAToB);
- for (int yA = 0; yA < this.Rectangle.Height; yA++)
- {
- // Start at the beginning of the row
- var posInB = yPosInB;
- for (int xA = 0; xA < this.Rectangle.Width; xA++)
- {
- // Round to the nearest pixel
- var xB = (int)Math.Round(posInB.X);
- var yB = (int)Math.Round(posInB.Y);
- if (0 <= xB && xB < sprite.Rectangle.Width &&
- 0 <= yB && yB < sprite.Rectangle.Height)
- {
- // Get the colors of the overlapping pixels
- var colourA = this.TextureData[xA + yA * this.Rectangle.Width];
- var colourB = sprite.TextureData[xB + yB * sprite.Rectangle.Width];
- // If both pixel are not completely transparent
- if (colourA.A != 0 && colourB.A != 0)
- {
- return true;
- }
- }
- // Move to the next pixel in the row
- posInB += stepX;
- }
- // Move to the next row
- yPosInB += stepY;
- }
- // No intersection found
- return false;
- }
- //public virtual void OnCollide(Sprite sprite)
- //{
- //}
- public object Clone()
- {
- var sprite = this.MemberwiseClone() as Sprite;
- if (_animations != null)
- {
- sprite._animations = this._animations.ToDictionary(c => c.Key, v => v.Value.Clone() as Animation);
- sprite._animationManager = sprite._animationManager.Clone() as AnimationManager;
- }
- return sprite;
- }
- }
- }
|