using System;␍␊ |
using System.Collections.Generic;␍␊ |
using System.Linq;␍␊ |
using System.Text;␍␊ |
using System.Xml;␍␊ |
using System.Xml.Serialization;␍␊ |
using Microsoft.Xna.Framework;␍␊ |
using Microsoft.Xna.Framework.Graphics;␍␊ |
using Microsoft.Xna.Framework.Content;␍␊ |
using System.IO;␍␊ |
using FarseerPhysics.Dynamics;␍␊ |
using FarseerPhysics.Common;␍␊ |
using FarseerPhysics.SamplesFramework;␍␊ |
using FarseerPhysics.Factories;␍␊ |
␍␊ |
namespace Axios.Engine.Glee2D␍␊ |
{␍␊ |
public partial class Level␍␊ |
{␍␊ |
private World _world;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The name of the level.␍␊ |
/// </summary>␍␊ |
[XmlAttribute()]␍␊ |
public String Name;␍␊ |
␍␊ |
[XmlAttribute()]␍␊ |
public bool Visible;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// A Level contains several Layers. Each Layer contains several Items.␍␊ |
/// </summary>␍␊ |
public List<Layer> Layers;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// A Dictionary containing any user-defined Properties.␍␊ |
/// </summary>␍␊ |
public SerializableDictionary CustomProperties;␍␊ |
␍␊ |
␍␊ |
public Level()␍␊ |
{␍␊ |
Visible = true;␍␊ |
Layers = new List<Layer>();␍␊ |
CustomProperties = new SerializableDictionary();␍␊ |
}␍␊ |
␍␊ |
public Level(World world)␍␊ |
{␍␊ |
Visible = true;␍␊ |
Layers = new List<Layer>();␍␊ |
CustomProperties = new SerializableDictionary();␍␊ |
_world = world;␍␊ |
}␍␊ |
␍␊ |
public static Level FromFile(string filename, ContentManager cm, World world)␍␊ |
{␍␊ |
FileStream stream = System.IO.File.Open(filename, FileMode.Open);␍␊ |
XmlSerializer serializer = new XmlSerializer(typeof(Level));␍␊ |
Level level = (Level)serializer.Deserialize(stream);␍␊ |
stream.Close();␍␊ |
␍␊ |
foreach (Layer layer in level.Layers)␍␊ |
{␍␊ |
foreach (Item item in layer.Items)␍␊ |
{␍␊ |
item.CustomProperties.RestoreItemAssociations(level);␍␊ |
item.load(cm, world);␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
return level;␍␊ |
}␍␊ |
␍␊ |
public Item getItemByName(string name)␍␊ |
{␍␊ |
foreach (Layer layer in Layers)␍␊ |
{␍␊ |
foreach (Item item in layer.Items)␍␊ |
{␍␊ |
if (item.Name == name) return item;␍␊ |
}␍␊ |
}␍␊ |
return null;␍␊ |
}␍␊ |
␍␊ |
public Layer getLayerByName(string name)␍␊ |
{␍␊ |
foreach (Layer layer in Layers)␍␊ |
{␍␊ |
if (layer.Name == name) return layer;␍␊ |
}␍␊ |
return null;␍␊ |
}␍␊ |
␍␊ |
public void draw(SpriteBatch sb)␍␊ |
{␍␊ |
foreach (Layer layer in Layers) layer.draw(sb);␍␊ |
}␍␊ |
␍␊ |
␍␊ |
}␍␊ |
␍␊ |
␍␊ |
public partial class Layer␍␊ |
{␍␊ |
/// <summary>␍␊ |
/// The name of the layer.␍␊ |
/// </summary>␍␊ |
[XmlAttribute()]␍␊ |
public String Name;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// Should this layer be visible?␍␊ |
/// </summary>␍␊ |
[XmlAttribute()]␍␊ |
public bool Visible;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The list of the items in this layer.␍␊ |
/// </summary>␍␊ |
public List<Item> Items;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The Scroll Speed relative to the main camera. The X and Y components are ␍␊ |
/// interpreted as factors, so (1;1) means the same scrolling speed as the main camera.␍␊ |
/// Enables parallax scrolling.␍␊ |
/// </summary>␍␊ |
public Vector2 ScrollSpeed;␍␊ |
␍␊ |
␍␊ |
public Layer()␍␊ |
{␍␊ |
Items = new List<Item>();␍␊ |
ScrollSpeed = Vector2.One;␍␊ |
}␍␊ |
␍␊ |
public void draw(SpriteBatch sb)␍␊ |
{␍␊ |
if (!Visible) return;␍␊ |
foreach (Item item in Items) item.draw(sb);␍␊ |
}␍␊ |
␍␊ |
}␍␊ |
␍␊ |
␍␊ |
[XmlInclude(typeof(TextureItem))]␍␊ |
[XmlInclude(typeof(RectangleItem))]␍␊ |
[XmlInclude(typeof(CircleItem))]␍␊ |
[XmlInclude(typeof(PathItem))]␍␊ |
public partial class Item␍␊ |
{␍␊ |
/// <summary>␍␊ |
/// The name of this item.␍␊ |
/// </summary>␍␊ |
[XmlAttribute()]␍␊ |
public String Name;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// Should this item be visible?␍␊ |
/// </summary>␍␊ |
[XmlAttribute()]␍␊ |
public bool Visible;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The item's position in world space.␍␊ |
/// </summary>␍␊ |
public Vector2 Position;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// A Dictionary containing any user-defined Properties.␍␊ |
/// </summary>␍␊ |
public SerializableDictionary CustomProperties;␍␊ |
␍␊ |
␍␊ |
public Item()␍␊ |
{␍␊ |
CustomProperties = new SerializableDictionary();␍␊ |
}␍␊ |
␍␊ |
/// <summary>␍␊ |
/// Called by Level.FromFile(filename) on each Item after the deserialization process.␍␊ |
/// Should be overriden and can be used to load anything needed by the Item (e.g. a texture).␍␊ |
/// </summary>␍␊ |
public virtual void load(ContentManager cm, World world)␍␊ |
{␍␊ |
}␍␊ |
␍␊ |
public virtual void draw(SpriteBatch sb)␍␊ |
{␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
␍␊ |
public partial class TextureItem : Item␍␊ |
{␍␊ |
/// <summary>␍␊ |
/// The item's rotation in radians.␍␊ |
/// </summary>␍␊ |
public float Rotation;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The item's scale factor.␍␊ |
/// </summary>␍␊ |
public float Scale;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The color to tint the item's texture with (use white for no tint).␍␊ |
/// </summary>␍␊ |
public Color TintColor;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// If true, the texture is flipped horizontally when drawn.␍␊ |
/// </summary>␍␊ |
public bool FlipHorizontally;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// If true, the texture is flipped vertically when drawn.␍␊ |
/// </summary>␍␊ |
public bool FlipVertically;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The path to the texture's filename (including the extension) relative to ContentRootFolder.␍␊ |
/// </summary>␍␊ |
public String texture_filename;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The texture_filename without extension. For using in Content.Load<Texture2D>().␍␊ |
/// </summary>␍␊ |
public String asset_name;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The XNA texture to be drawn. Can be loaded either from file (using "texture_filename") ␍␊ |
/// or via the Content Pipeline (using "asset_name") - then you must ensure that the texture␍␊ |
/// exists as an asset in your project.␍␊ |
/// Loading is done in the Item's load() method.␍␊ |
/// </summary>␍␊ |
Texture2D texture;␍␊ |
␍␊ |
/// <summary>␍␊ |
/// The item's origin relative to the upper left corner of the texture. Usually the middle of the texture.␍␊ |
/// Used for placing and rotating the texture when drawn.␍␊ |
/// </summary>␍␊ |
public Vector2 Origin;␍␊ |
␍␊ |
␍␊ |
public TextureItem()␍␊ |
{␍␊ |
}␍␊ |
␍␊ |
/// <summary>␍␊ |
/// Called by Level.FromFile(filename) on each Item after the deserialization process.␍␊ |
/// Loads all assets needed by the TextureItem, especially the Texture2D.␍␊ |
/// You must provide your own implementation. However, you can rely on all public fields being␍␊ |
/// filled by the level deserialization process.␍␊ |
/// </summary>␍␊ |
public override void load(ContentManager cm, World world)␍␊ |
{␍␊ |
//throw new NotImplementedException();␍␊ |
␍␊ |
//TODO: provide your own implementation of how a TextureItem loads its assets␍␊ |
//for example:␍␊ |
//this.texture = Texture2D.FromFile(<GraphicsDevice>, texture_filename);␍␊ |
//or by using the Content Pipeline:␍␊ |
this.texture = cm.Load<Texture2D>(asset_name);␍␊ |
␍␊ |
}␍␊ |
␍␊ |
public override void draw(SpriteBatch sb)␍␊ |
{␍␊ |
if (!Visible) return;␍␊ |
SpriteEffects effects = SpriteEffects.None;␍␊ |
if (FlipHorizontally) effects |= SpriteEffects.FlipHorizontally;␍␊ |
if (FlipVertically) effects |= SpriteEffects.FlipVertically;␍␊ |
sb.Draw(texture, Position, null, TintColor, Rotation, Origin, Scale, effects, 0);␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
␍␊ |
public partial class RectangleItem : Item␍␊ |
{␍␊ |
public float Width;␍␊ |
public float Height;␍␊ |
public Color FillColor;␍␊ |
␍␊ |
Body _body;␍␊ |
␍␊ |
public RectangleItem()␍␊ |
{␍␊ |
}␍␊ |
␍␊ |
public override void load(ContentManager cm, World world)␍␊ |
{␍␊ |
base.load(cm, world);␍␊ |
␍␊ |
_body = BodyFactory.CreateRectangle(world, Width, Height, 1f);␍␊ |
_body.Position = Position;␍␊ |
_body.UserData = this;␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
␍␊ |
public partial class CircleItem : Item␍␊ |
{␍␊ |
public float Radius;␍␊ |
public Color FillColor;␍␊ |
␍␊ |
Body _body;␍␊ |
␍␊ |
public CircleItem()␍␊ |
{␍␊ |
}␍␊ |
␍␊ |
public override void load(ContentManager cm, World world)␍␊ |
{␍␊ |
base.load(cm, world);␍␊ |
␍␊ |
_body = BodyFactory.CreateCircle(world, Radius, 1f);␍␊ |
_body.Position = Position;␍␊ |
_body.UserData = this;␍␊ |
}␍␊ |
␍␊ |
}␍␊ |
␍␊ |
␍␊ |
public partial class PathItem : Item␍␊ |
{␍␊ |
public Vector2[] LocalPoints;␍␊ |
public Vector2[] WorldPoints;␍␊ |
public bool IsPolygon;␍␊ |
public int LineWidth;␍␊ |
public Color LineColor;␍␊ |
␍␊ |
Body _body;␍␊ |
␍␊ |
public PathItem()␍␊ |
{␍␊ |
}␍␊ |
␍␊ |
public override void load(ContentManager cm, World world)␍␊ |
{␍␊ |
base.load(cm, world);␍␊ |
␍␊ |
Vertices v = new Vertices(WorldPoints.Length);␍␊ |
foreach (Vector2 vec in WorldPoints)␍␊ |
v.Add(new Vector2(ConvertUnits.ToSimUnits(vec.X), ConvertUnits.ToSimUnits(vec.Y)));␍␊ |
␍␊ |
_body = BodyFactory.CreateLoopShape(world, v);␍␊ |
_body.Position = this.Position;␍␊ |
_body.UserData = this;␍␊ |
}␍␊ |
␍␊ |
}␍␊ |
␍␊ |
␍␊ |
///////////////////////////////////////////////////////////////////////////////////////////␍␊ |
///////////////////////////////////////////////////////////////////////////////////////////␍␊ |
//␍␊ |
// NEEDED FOR SERIALIZATION. YOU SHOULDN'T CHANGE ANYTHING BELOW!␍␊ |
//␍␊ |
///////////////////////////////////////////////////////////////////////////////////////////␍␊ |
///////////////////////////////////////////////////////////////////////////////////////////␍␊ |
␍␊ |
␍␊ |
public class CustomProperty␍␊ |
{␍␊ |
public string name;␍␊ |
public object value;␍␊ |
public Type type;␍␊ |
public string description;␍␊ |
␍␊ |
public CustomProperty()␍␊ |
{␍␊ |
}␍␊ |
␍␊ |
public CustomProperty(string n, object v, Type t, string d)␍␊ |
{␍␊ |
name = n;␍␊ |
value = v;␍␊ |
type = t;␍␊ |
description = d;␍␊ |
}␍␊ |
␍␊ |
public CustomProperty clone()␍␊ |
{␍␊ |
CustomProperty result = new CustomProperty(name, value, type, description);␍␊ |
return result;␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
␍␊ |
public class SerializableDictionary : Dictionary<String, CustomProperty>, IXmlSerializable␍␊ |
{␍␊ |
␍␊ |
public SerializableDictionary()␍␊ |
: base()␍␊ |
{␍␊ |
␍␊ |
}␍␊ |
␍␊ |
public SerializableDictionary(SerializableDictionary copyfrom)␍␊ |
: base(copyfrom)␍␊ |
{␍␊ |
string[] keyscopy = new string[Keys.Count];␍␊ |
Keys.CopyTo(keyscopy, 0);␍␊ |
foreach (string key in keyscopy)␍␊ |
{␍␊ |
this[key] = this[key].clone();␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
public System.Xml.Schema.XmlSchema GetSchema()␍␊ |
{␍␊ |
return null;␍␊ |
}␍␊ |
␍␊ |
public void ReadXml(System.Xml.XmlReader reader)␍␊ |
{␍␊ |
␍␊ |
bool wasEmpty = reader.IsEmptyElement;␍␊ |
reader.Read();␍␊ |
␍␊ |
if (wasEmpty) return;␍␊ |
␍␊ |
while (reader.NodeType != System.Xml.XmlNodeType.EndElement)␍␊ |
{␍␊ |
CustomProperty cp = new CustomProperty();␍␊ |
cp.name = reader.GetAttribute("Name");␍␊ |
cp.description = reader.GetAttribute("Description");␍␊ |
␍␊ |
string type = reader.GetAttribute("Type");␍␊ |
if (type == "string") cp.type = typeof(string);␍␊ |
if (type == "bool") cp.type = typeof(bool);␍␊ |
if (type == "Vector2") cp.type = typeof(Vector2);␍␊ |
if (type == "Color") cp.type = typeof(Color);␍␊ |
if (type == "Item") cp.type = typeof(Item);␍␊ |
␍␊ |
if (cp.type == typeof(Item))␍␊ |
{␍␊ |
cp.value = reader.ReadInnerXml();␍␊ |
this.Add(cp.name, cp);␍␊ |
}␍␊ |
else␍␊ |
{␍␊ |
reader.ReadStartElement("Property");␍␊ |
XmlSerializer valueSerializer = new XmlSerializer(cp.type);␍␊ |
object obj = valueSerializer.Deserialize(reader);␍␊ |
#if WINDOWS␍␊ |
cp.value = Convert.ChangeType(obj, cp.type);␍␊ |
#elif WINDOWS_PHONE || XBOX360␍␊ |
cp.value = Convert.ChangeType(obj, cp.type, null);␍␊ |
#endif␍␊ |
this.Add(cp.name, cp);␍␊ |
reader.ReadEndElement();␍␊ |
}␍␊ |
␍␊ |
reader.MoveToContent();␍␊ |
}␍␊ |
reader.ReadEndElement();␍␊ |
}␍␊ |
␍␊ |
public void WriteXml(System.Xml.XmlWriter writer)␍␊ |
{␍␊ |
foreach (String key in this.Keys)␍␊ |
{␍␊ |
writer.WriteStartElement("Property");␍␊ |
writer.WriteAttributeString("Name", this[key].name);␍␊ |
if (this[key].type == typeof(string)) writer.WriteAttributeString("Type", "string");␍␊ |
if (this[key].type == typeof(bool)) writer.WriteAttributeString("Type", "bool");␍␊ |
if (this[key].type == typeof(Vector2)) writer.WriteAttributeString("Type", "Vector2");␍␊ |
if (this[key].type == typeof(Color)) writer.WriteAttributeString("Type", "Color");␍␊ |
if (this[key].type == typeof(Item)) writer.WriteAttributeString("Type", "Item");␍␊ |
writer.WriteAttributeString("Description", this[key].description);␍␊ |
␍␊ |
if (this[key].type == typeof(Item))␍␊ |
{␍␊ |
Item item = (Item)this[key].value;␍␊ |
if (item != null) writer.WriteString(item.Name);␍␊ |
else writer.WriteString("$null$");␍␊ |
}␍␊ |
else␍␊ |
{␍␊ |
XmlSerializer valueSerializer = new XmlSerializer(this[key].type);␍␊ |
valueSerializer.Serialize(writer, this[key].value);␍␊ |
}␍␊ |
writer.WriteEndElement();␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
/// <summary>␍␊ |
/// Must be called after all Items have been deserialized. ␍␊ |
/// Restores the Item references in CustomProperties of type Item.␍␊ |
/// </summary>␍␊ |
public void RestoreItemAssociations(Level level)␍␊ |
{␍␊ |
foreach (CustomProperty cp in Values)␍␊ |
{␍␊ |
if (cp.type == typeof(Item)) cp.value = level.getItemByName((string)cp.value);␍␊ |
}␍␊ |
}␍␊ |
␍␊ |
␍␊ |
}␍␊ |
}␍␊ |