XNA cuttable sprite


This matter is like a paradigm of cutting sprites. On the gaming world of XNA every one wants to cut sprites and in my game too.

When you start looking appears texels, triangles and else. I thought a simple way, just make the sprite from 4 rectangles and rotate them according to the slash and then scroll them.

The idea is easy but I had to create relative textures, relative rectangles, relative distances, and calculate the angle of a slice. But well it’s done. So here you have the code. If you have time and you want to increment the rectangles to have more details you are free to go and share.

 

public class CuttableEnemy
    {
        public IGame gamePage; // Game Page with spriteBatch
        public Texture2D SpriteTexture; // Texture that will be cut in 4
        public Rectangle[] SourceRectangles; // Actually these are the 4 textures
        public Vector2[] Origins; // The origins for the rotations (this was hard to acompplish)
        private Vector2 Center = new Vector2(240, 390); // The center of the screen game
        public Vector2 PixelPosition; // Simply The Offset from the Center
        
        private float Opacity = 1.0f; //Original Texture Opacity, when IsCut it decreases

        public bool IsCut { get { return iscut; } } // The property to increase score when cutted
        private bool iscut = false; // A Field that starts the cut
        
        private float distance = 0; // The distance from the middle when IsCut.
        private Vector2? InputPoint; //The first point
        private Vector2? OutputPoint; //The end point
        private float atan; //The angle between first and end

        private Int32 HalfWidth { get { return this.SpriteTexture.Width / 2; } } //Just to write less
        private Int32 HalfHeight { get { return this.SpriteTexture.Height / 2; } } //Just to write less

        private Vector2[] DistanceMatrix; //The distance vectors when IsCut

        public Rectangle BoundingBox
        {
            get
            {
                Rectangle rect = new Rectangle(
                 (int)(PixelPosition.X + Center.X - HalfWidth),
                 (int)(PixelPosition.Y + Center.Y - HalfHeight),
                 (int)(SpriteTexture.Width + HalfWidth),
                 (int)(SpriteTexture.Height + HalfHeight));
                //Increase the touch target a bit
                rect.Inflate(10, 10);
                return rect;
            }
        }

        public void Create(IGame currentgame)
        {
            this.gamePage = currentgame;
        }

        public void LoadContent()
        {
            if (SpriteTexture == null)
            {
                SpriteTexture = (App.Current as App).Content.Load<Texture2D>(@"Images\Sprites\spark");
                Origins = new Vector2[4];
                Origins[0] = new Vector2(HalfWidth, HalfHeight);
                Origins[1] = new Vector2(0, HalfHeight);
                Origins[2] = new Vector2(HalfWidth, 0);
                Origins[3] = new Vector2(0, 0);

                SourceRectangles = new Rectangle[4];
                SourceRectangles[0] = new Rectangle(0, 0, HalfWidth, HalfHeight);
                SourceRectangles[1] = new Rectangle(HalfWidth, 0, HalfWidth, HalfHeight);
                SourceRectangles[2] = new Rectangle(0, HalfHeight, HalfWidth, HalfHeight);
                SourceRectangles[3] = new Rectangle(HalfWidth, HalfHeight, HalfWidth, HalfHeight);

                DistanceMatrix = new Vector2[4];
                DistanceMatrix[0] = new Vector2(1,-1);
                DistanceMatrix[1] = new Vector2(1, -1);
                DistanceMatrix[2] = new Vector2(-1, 1);
                DistanceMatrix[3] = new Vector2(-1, 1);
            }
        }

        public void Update(TouchLocation TouchPoint)
        {
            if (!iscut && BoundingBox.Contains(TouchPoint.Position) && (TouchPoint.State == TouchLocationState.Moved || TouchPoint.State == TouchLocationState.Pressed))
            {
                InputPoint = TouchPoint.Position;
                iscut = true;
            }

            if (OutputPoint == null &&  iscut && !BoundingBox.Contains(TouchPoint.Position) && TouchPoint.State == TouchLocationState.Moved)
            {
                OutputPoint = TouchPoint.Position;
                double maxy = Math.Max(InputPoint.Value.Y, OutputPoint.Value.Y);
                double miny = Math.Min(InputPoint.Value.Y, OutputPoint.Value.Y);

                double maxx = Math.Max(InputPoint.Value.X, OutputPoint.Value.X);
                double minx = Math.Min(InputPoint.Value.X, OutputPoint.Value.X);

                atan = (float)Math.Atan2(OutputPoint.Value.Y - InputPoint.Value.Y, OutputPoint.Value.X - InputPoint.Value.X);
            }

            if (iscut)
            {
                //Increase the distance to show how it's cut.
                Opacity -= 0.05f;
                distance+= 0.5f + 1 * Opacity;
                if (Opacity < 0)
                {
                    iscut = false;
                    Opacity = 1.0f;
                    distance = 0;
                    InputPoint = null;
                    OutputPoint = null;
                }
            }
        }

        Int32 idx=0;
        public void Draw()
        {
            gamePage.spriteBatch.Begin();
            for (idx = 0; idx < 4; idx++)
            {
                gamePage.spriteBatch.Draw(SpriteTexture, PixelPosition + Center + GetOffset(idx),
                    SourceRectangles[idx], Color.White * Opacity, atan, Origins[idx], 1.0f, SpriteEffects.None, 0f);
            }
            gamePage.spriteBatch.End();
        }

        private float ywidth, xwidth;
        private Vector2 GetOffset(Int32 idx)
        {
            ywidth = distance * (float)Math.Cos(atan);
            xwidth = distance * (float)Math.Sin(atan);

            return new Vector2(xwidth, ywidth) * DistanceMatrix[idx];
        }
    }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s