using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using System.Resources; namespace SpriteLibrary { /// /// The SpriteInfo only recognizes a few ways to create a sprite. Here are the different ways. /// public enum AnimationType { /// /// A Sprite definition knows an image, an X and Y, a size, and a few other items. /// SpriteDefinition =0, /// /// A rotated sprite is based off a pre-existing animation, but it is rotated by some degrees. /// Rotation =1, /// /// A mirrored sprite is based off a pre-existing animation, but is mirrored vertically or horizontally. /// Mirror =2 } /// /// An AnimationInfo class is used by the SpriteInfo class to /// contain the instructions for creating a sprite through the dictionary. Most people will not want /// to manually use these. It is simplest to use the /// SpriteDatabase.OpenEditWindow function and use the built-in sprite editor. That editor will create a file /// that can be used in the database without your needing to know about the AnimationInfo. /// Again, you do not want to use these within /// your program. Let the SpriteDatabase use this. The reason these are visible to the program is because /// This code uses "XML Serialization" to load and save. XML Serialization requires the items you are /// serializing to be "public", which makes them visible. /// public class AnimationInfo { /// /// The FieldsToUse tracks which of the values in AnimationInfo are important /// public AnimationType FieldsToUse = AnimationType.SpriteDefinition; /// /// If the sprite is either a mirror sprite, or a rotated sprite, it must be based off of /// a pre-existing animation. This value states which animation we copy. /// public int AnimationToUse = 0; /// /// If the sprite is a rotated copy of a pre-existing sprite, this value tells how many degrees to /// rotate the sprite. /// public int RotationDegrees=0; /// /// If the sprite is a mirrored copy of a pre-existing sprite, this value states whether or not /// the sprite is mirrored Horizontally. /// public bool MirrorHorizontally = false; /// /// If the sprite is a mirrored copy of a pre-existing sprite, this value states whether or not /// the sprite is mirrored Vertically. /// public bool MirrorVertically = false; /// /// If the sprite is based off of an image, this value is the starting point of the top-left corner /// of the sprite on the image. You will also want to include a Width and Height. /// public Point StartPoint = new Point(-1, -1); /// /// This is the image name which contains the sprite. This image should be in the Properties.Resources /// of your project. The name you want to give is case-sensitive, and should be the exact name as /// listed in Properties.Resources. For example, if your image name were Properties.Resources.Runner /// you would want to use the string "Runner" Note the caps are identical, and we have removed the /// "Properties.Resources. from the front. /// public string ImageName = ""; /// /// The width of the sprite to pull from the specified image. /// public int Width = -1; /// /// The height of the sprite to pull from the specified image. /// public int Height = -1; /// /// The number of frames to pull, one following the other, from the specified image. /// public int NumFrames = 1; /// /// The delay in milliseconds in-between frames of the sprite. This number is not exact, but is pretty /// close to what happens. Never use a number less than 20. /// public int AnimSpeed = 200; /// /// A generic cloning method that works when everything is public /// /// A clone of the specified AnimationInfo public AnimationInfo Clone() { return SpriteDatabase.CloneByXMLSerializing(this); } } /// /// A class which is used by the SpriteDatabase to build /// Sprites. You should not need to use this in your programming. It is simplest to use the Load/Save features /// of the SpriteDatabase, which will load and save the SpriteInfo. /// Again, you do not want to use these within /// your program. Let the SpriteDatabase use this. The reason these are visible to the program is because /// This code uses "XML Serialization" to load and save. XML Serialization requires the items you are /// serializing to be "public", which makes them visible. /// public class SpriteInfo { /// /// The name of the sprite. It should be unique within your application /// public string SpriteName = ""; /// /// The percentage size when the sprite is normally displayed. For example: If the image you drew your /// sprite on has your sprite drawn on a 200x200 grid, but you want your sprite to normally be 100x100, /// you would tell it to be 50 (50 percent of the original size). /// public int ViewPercent = 100; //The percent size of the sprite. 100 is full. 50 is half-size /// /// This is the list of animations that make up the sprite. Again, you do not want to use these within /// your program. Let the SpriteDatabase use this. The reason these are visible to the program is because /// This code uses "XML Serialization" to load and save. XML Serialization requires the items you are /// serializing to be "public", which makes them visible. /// public List Animations = new List(); /// /// A generic cloning method that works when everything is public /// /// A duplicate of the sprite info. public SpriteInfo Clone() { return SpriteDatabase.CloneByXMLSerializing(this); } /// /// Update the current SpriteInfo class such that it is identical to the class you are copying from. /// /// A spriteInfo class public void CopyFrom(SpriteInfo toCopyFrom) { if (toCopyFrom == null) return; SpriteName = toCopyFrom.SpriteName; ViewPercent = toCopyFrom.ViewPercent; Animations.Clear(); foreach(AnimationInfo AI in toCopyFrom.Animations) { Animations.Add(AI.Clone()); } } /// /// Create a sprite using the database sprite information. This does not do any checking to make sure /// the named sprite already exists. Usually, what you want to do is to create your SpriteController and /// register your SpriteDatabase with the controller. Then, when you ask the SpriteController for a sprite, /// if that sprite does not exist yet, it will create it from the database. /// /// The sprite controller that will end up controlling the sprite /// The database /// internal Sprite CreateSprite(SpriteController ControllerToUse, SpriteDatabase TheDatabaseToUse) { Sprite DestSprite = null; if (ControllerToUse == null) return null; for (int index = 0; index < Animations.Count; index++) { AnimationInfo CurrentAnimation = Animations[index]; Image myImage = TheDatabaseToUse.GetImageFromName(CurrentAnimation.ImageName, true); if (myImage == null) return null; //break out if we do not have the image defined for this AnimationType AT = CurrentAnimation.FieldsToUse; if (index == 0) AT = AnimationType.SpriteDefinition; //the first one MUST be this. switch(AT) { case AnimationType.SpriteDefinition: if(DestSprite == null)//Creating the sprite from scratch { DestSprite = new Sprite(CurrentAnimation.StartPoint, ControllerToUse, myImage, CurrentAnimation.Width, CurrentAnimation.Height, CurrentAnimation.AnimSpeed, CurrentAnimation.NumFrames); } else { DestSprite.AddAnimation(CurrentAnimation.StartPoint, myImage, CurrentAnimation.Width, CurrentAnimation.Height, CurrentAnimation.AnimSpeed, CurrentAnimation.NumFrames); } break; case AnimationType.Rotation: DestSprite.AddAnimation(CurrentAnimation.AnimationToUse, CurrentAnimation.RotationDegrees); break; case AnimationType.Mirror: DestSprite.AddAnimation(CurrentAnimation.AnimationToUse, CurrentAnimation.MirrorHorizontally,CurrentAnimation.MirrorVertically); break; } } int sizepercent = ViewPercent; if (sizepercent < 5) sizepercent = 100; if (sizepercent > 300) sizepercent = 100; double delta = (double)sizepercent / 100.0; //turn it into a double, and into something we can multiply. DestSprite.SetSize(new Size((int)(DestSprite.GetSize.Width * delta), (int)(DestSprite.GetSize.Height * delta))); DestSprite.SetName(SpriteName); //We have created a new sprite. Now, return a duplicate of that sprite. return DestSprite; } } }