<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dylan Black</title>
	<atom:link href="http://www.dylanblack.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dylanblack.com</link>
	<description></description>
	<lastBuildDate>Fri, 13 Mar 2015 22:27:04 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.6</generator>
	<item>
		<title>Displaying image thumbnails in the level editor</title>
		<link>http://www.dylanblack.com/2010/01/17/displaying-image-thumbnails-in-the-level-editor/</link>
		<comments>http://www.dylanblack.com/2010/01/17/displaying-image-thumbnails-in-the-level-editor/#comments</comments>
		<pubDate>Sat, 16 Jan 2010 22:35:59 +0000</pubDate>
		<dc:creator><![CDATA[dylan]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Game]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[WinForms]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://www.dylanblack.com/?p=47</guid>
		<description><![CDATA[To display the sprite thumbnails in my level editor application, I wrote a couple of simple custom controls. The first control extends from the .NET PictureBox control, and just has an additional property to track whether it’s been selected. Then, in the OnPaint method, if the SelectablePictureBox is selected, then I draw a border over [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>To display the sprite thumbnails in my level editor application, I wrote a couple of simple custom controls.</p>
<p>The first control extends from the .NET PictureBox control, and just has an additional property to track whether it’s been selected. Then, in the OnPaint method, if the SelectablePictureBox is selected, then I draw a border over the top of it.</p>
<p>The second control extends from the .NET FlowLayoutPanel control, and has an event that is raised when any child SelectablePictureBox is clicked, and then some code to handle Ctrl-clicking and Shift-clicking to select and deselect individual SelectablePictureBox child controls.</p>
<p>The source code for both controls is below. Feel free to use it if you want to, but note that it’s pretty simple and inflexible, so the SelectableImageFlowLayoutPanel will only work with the SelectablePictureBox.</p>
<p>Let me know if you have any questions about it.</p>
<pre><code class="cs">using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace Editor
{
    public class SelectablePictureBox : PictureBox
    {
        private bool _selected = false;

        public bool Selected
        {
            get { return _selected; }
            set
            {
                _selected = value;
            }
        }

        public SelectablePictureBox()
            : base()
        {
            this.SizeMode = PictureBoxSizeMode.Zoom;
            this.BorderStyle = BorderStyle.FixedSingle;
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            if (_selected)
            {
                this.BorderStyle = BorderStyle.None;
            }
            else
            {
                this.BorderStyle = BorderStyle.FixedSingle;
            }

            base.OnPaint(pe);

            if (_selected)
            {
                this.BorderStyle = BorderStyle.None;
                Pen pen = new Pen(System.Drawing.Color.CornflowerBlue, 6.0f);
                int penWidth = (int)pen.Width;
                Point[] points = new Point[5] { new Point(pe.ClipRectangle.Left, pe.ClipRectangle.Top),
                    new Point(pe.ClipRectangle.Right, pe.ClipRectangle.Top),
                    new Point(pe.ClipRectangle.Right, pe.ClipRectangle.Bottom),
                    new Point(pe.ClipRectangle.Left, pe.ClipRectangle.Bottom),
                    new Point(pe.ClipRectangle.Left, pe.ClipRectangle.Top )};
                pe.Graphics.DrawLines(pen, points);
            }
        }
    }
}</code></pre>
<pre><code class="cs">using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace Editor
{
    public class SelectableImageFlowLayoutPanel : FlowLayoutPanel
    {
        public delegate void OnSelectedIndexChanged();
        public event OnSelectedIndexChanged SelectedIndexChanged;

        public SelectableImageFlowLayoutPanel()
            : base()
        {
        }

        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);

            if (e.Control.GetType() == typeof(SelectablePictureBox))
            {
                e.Control.Click += new EventHandler(SelectablePictureBox_Click);
            }
        }

        public int SelectedIndex
        {
            get
            {
                int i = 0;
                bool found = false; ;
                foreach (Control c in Controls)
                {
                    if (((SelectablePictureBox)c).Selected)
                    {
                        found = true;
                        break;
                    }
                    i++;
                }

                if (found)
                {
                    return i;
                }
                else
                {
                    return -1;
                }
            }
            set
            {
                int i = 0;
                foreach (Control c in Controls)
                {
                    if (i == value)
                    {
                        // select controls
                        ((SelectablePictureBox)c).Selected = true;
                        // force a redraw
                        c.Invalidate();
                        break;
                    }
                    else
                    {
                        // deselect controls
                        ((SelectablePictureBox)c).Selected = false;
                        // force a redraw
                        c.Invalidate();
                    }
                    i++;
                }
            }
        }

        public List&lt;SelectablePictureBox&gt; SelectedItems
        {
            get
            {
                List&lt;SelectablePictureBox&gt; selectedItems = new List&lt;SelectablePictureBox&gt;();

                foreach (Control c in Controls)
                {
                    if (((SelectablePictureBox)c).Selected)
                    {
                        selectedItems.Add(((SelectablePictureBox)c));
                    }
                }
                return selectedItems;
            }
        }

        public List&lt;SelectablePictureBox&gt; Items
        {
            get
            {
                List&lt;SelectablePictureBox&gt; items = new List&lt;SelectablePictureBox&gt;();

                foreach (Control c in Controls)
                {
                    items.Add(((SelectablePictureBox)c));
                }
                return items;
            }
        }

        void SelectablePictureBox_Click(object sender, EventArgs e)
        {
            if (InputHelper.IsKeyDown(Keys.ControlKey))
            {
                ((SelectablePictureBox)sender).Selected = true;
                // force a redraw
                ((SelectablePictureBox)sender).Invalidate();
            }
            else if (InputHelper.IsKeyDown(Keys.ShiftKey))
            {
                int startIdx = 0, endIdx = 0;
                bool foundStart = false;

                endIdx = Controls.IndexOf(((SelectablePictureBox)sender));

                foreach (Control c in Controls)
                {
                    if (!foundStart &amp;&amp; ((SelectablePictureBox)c).Selected)
                    {
                        foundStart = true;
                        startIdx = Controls.IndexOf(c);
                    }
                    else
                    {
                        // deselect controls
                        ((SelectablePictureBox)c).Selected = false;
                        // force a redraw
                        c.Invalidate();
                    }
                }

                if (!foundStart)
                {
                    startIdx = endIdx;
                }

                for (int i = startIdx; i &lt;= endIdx; i++)
                {
                    // select the controls in range
                    ((SelectablePictureBox)Controls[i]).Selected = true;
                    // force a redraw
                    Controls[i].Invalidate();
                }
            }
            else
            {
                foreach (Control c in Controls)
                {
                    if (c == sender)
                    {
                        ((SelectablePictureBox)c).Selected = true;
                    }
                    else
                    {
                        ((SelectablePictureBox)c).Selected = false;
                    }
                    // force a redraw
                    c.Invalidate();
                }
            }

            if (SelectedIndexChanged != null)
            {
                SelectedIndexChanged();
            }
        }
    }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.dylanblack.com/2010/01/17/displaying-image-thumbnails-in-the-level-editor/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Jolicloud</title>
		<link>http://www.dylanblack.com/2009/07/26/jolicloud/</link>
		<comments>http://www.dylanblack.com/2009/07/26/jolicloud/#respond</comments>
		<pubDate>Sun, 26 Jul 2009 04:48:10 +0000</pubDate>
		<dc:creator><![CDATA[dylan]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.dylanblack.com/?p=33</guid>
		<description><![CDATA[I installed the Jolicloud OS on my EEE PC 701 this weekend, and so far it&#8217;s working beautifully. Installation was fast (around 15 minutes) and easy, and it picked up my home WiFi with no problems. It&#8217;s also easy to install new applications. There&#8217;s an application catalog in the OS, and it&#8217;s a one-click process [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I installed the <a title="Jolicloud" href="http://www.jolicloud.com/" target="_blank">Jolicloud</a> OS on my EEE PC 701 this weekend, and so far it&#8217;s working beautifully.</p>
<p>Installation was fast (around 15 minutes) and easy, and it picked up my home WiFi with no problems.</p>
<p>It&#8217;s also easy to install new applications. There&#8217;s an application catalog in the OS, and it&#8217;s a one-click process to install them, and you can queue up multiple installs.</p>
<p>I couldn&#8217;t find Comix in the catalog, so I ran apt-get, and it was downloaded quickly from a local repository, installed, and a shortcut was placed in the main screen (something I could never get the EEE OS to do properly).</p>
<p>So far I&#8217;m very impressed, and would recommend it over the default EEE OS without hesitation, alpha version or not.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dylanblack.com/2009/07/26/jolicloud/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing the level processor</title>
		<link>http://www.dylanblack.com/2008/07/04/writing-the-level-processor/</link>
		<comments>http://www.dylanblack.com/2008/07/04/writing-the-level-processor/#comments</comments>
		<pubDate>Fri, 04 Jul 2008 01:26:04 +0000</pubDate>
		<dc:creator><![CDATA[dylan]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Game]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://www.dylanblack.com/?p=29</guid>
		<description><![CDATA[I thought it might be useful to go over how I wrote the custom level processor, because after following the example in the documentation I still had some questions. The Level Classes I already had the classes that make up my level, because I was using them in the level editor. This is the class [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I thought it might be useful to go over how I wrote the custom level processor, because after following the example in the documentation I still had some questions.</p>
<h3>The Level Classes</h3>
<p>I already had the classes that make up my level, because I was using them in the level editor. This is the class diagram of the level objects:</p>
<p><a href="http://www.dylanblack.com/wp-content/uploads/2008/07/level-class-diagram.png" target="_blank"><img src="http://www.dylanblack.com/wp-content/uploads/2008/07/level-class-diagram-thumb.png" alt="Level Class Diagram" width="441" height="480" /></a></p>
<p>As you can see, it&#8217;s pretty straightforward.<br /> The classes on the left hold the Farseer collision entity data. I need to update these to add extra information, such as making the collision entities static or dynamic.<br /> The TextureInstance class represents a single texture drawn on the screen. Note that it doesn&#8217;t hold the actual texture, just the name of the texture. The textures themselves are stored in the Level class. This is so that I&#8217;m not duplicating textures in memory if I need to draw the same image in multiple places.<br /> The Level class just holds collections of the other classes, the Texture2D images, and the height and width of the level. <span id="more-29"></span> </p>
<h3>The Level XML File</h3>
<p>Next, I designed an XML file to represent the level structure:</p>
<pre><code class="xml">&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;Level height="768" width="1024"&gt;
    &lt;CollisionEntities&gt;
        &lt;PolygonCollisionEntity mass="0.5f"&gt;
            &lt;Vertex x="100" y="100"/&gt;
            &lt;Vertex x="150" y="100"/&gt;
            &lt;Vertex x="150" y="200"/&gt;
            &lt;Vertex x="100" y="200"/&gt;
        &lt;/PolygonCollisionEntity&gt;
        &lt;RectangleCollisionEntity x="100.0f" y="100.0f" height="100.0f" width="100.0f" mass="0.5f"/&gt;
    &lt;/CollisionEntities&gt;
    &lt;TextureInstances&gt;
        &lt;TextureInstance x="100.0f" y="100.0f" height="100.0f" width="100.0f" name="texture"/&gt;
    &lt;/TextureInstances&gt;
    &lt;Textures&gt;
        &lt;TextureResource name="texture" filename="C:\texture.jpg"/&gt;
    &lt;/Textures&gt;
&lt;/Level&gt;</code></pre>
<h3>The Input Data</h3>
<p>Following the &#8220;How To: Write a Custom Importer and Processor&#8221; article in the XNA Documentation, the first step is to write a class to hold the data that we are importing, which in the case of the level is the XML file.</p>
<pre><code class="cs">using System;
using System.Collections.Generic;
using System.Text;

namespace LevelProcessor
{
    public class LevelSourceCode
    {
        public LevelSourceCode(string sourceCode)
        {
            this._sourceCode = sourceCode;
        }

        private string _sourceCode;

        public string SourceCode { get { return _sourceCode; } }

    }
}</code></pre>
<p>This is basically the same as the example in the documentation, as we also only need to store the file text.</p>
<h3>The Content Importer</h3>
<p>The content importer is also virtually identical to the documentation, as it just needs to read the text from the XML file and store it in the LevelSourceCode object.</p>
<pre><code class="cs">using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content.Pipeline;

namespace LevelProcessor
{
    [ContentImporter(".lvl", DefaultProcessor = "XmlLevelProcessor", DisplayName = "XML Level Importer")]
    public class XmlLevelImporter : ContentImporter&lt;LevelSourceCode&gt;
    {
        public override LevelSourceCode Import(string filename, ContentImporterContext context)
        {
            string sourceCode = System.IO.File.ReadAllText(filename);
            return new LevelSourceCode(sourceCode);
        }

    }
}</code></pre>
<h3>The Content Processor</h3>
<p>Here is where we start to differ from the documentation. What we need to do is parse the XML that we read in the previous step, and store it in an instance of the Level object.</p>
<pre><code class="cs">using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework;
using PhysicsGameEngine;

namespace LevelProcessor
{
    [ContentProcessor(DisplayName = "XML Level Processor")]
    public class XmlLevelProcessor : ContentProcessor&lt;LevelSourceCode, Level&gt;
    {
        public override Level Process(LevelSourceCode input, ContentProcessorContext context)
        {
            Level level = new Level();

            try
            {
                // load the source xml into a memory stream
                byte[] byteArray = new byte[input.SourceCode.Length];
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                byteArray = encoding.GetBytes(input.SourceCode);

                MemoryStream memoryStream = new MemoryStream(byteArray);
                memoryStream.Seek(0, SeekOrigin.Begin);

                // create an xml reader to parse the xml
                XmlReader reader = XmlReader.Create(memoryStream);

                // loop through the xml and create elements for our level
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Element:
                            switch (reader.Name.ToUpper())
                            {
                                case "LEVEL":
                                    int levelHeight = int.Parse(reader.GetAttribute("height"));
                                    int levelWidth = int.Parse(reader.GetAttribute("width"));
                                    level.Height = levelHeight;
                                    level.Width = levelWidth;
                                    break;

                                case "POLYGONCOLLISIONENTITY":
                                    float mass = float.Parse(reader.GetAttribute("mass"));
                                    PolygonCollisionEntity poly = new PolygonCollisionEntity();
                                    poly.Mass = mass;

                                    // loop through the vertex list and get the vertices that make up the polygon
                                    List&lt;Vector2&gt; vertices = new List&lt;Vector2&gt;();

                                    while (reader.Read())
                                    {
                                        if (reader.NodeType == XmlNodeType.EndElement &amp;&amp; reader.Name.ToUpper() == "POLYGONCOLLISIONENTITY")
                                        {
			                    break;
                                        }

                                        float xPos = float.Parse(reader.GetAttribute("x"));
                                        float yPos = float.Parse(reader.GetAttribute("y"));

                                        vertices.Add(new Vector2(xPos, yPos));
                                    }

                                    // add the vertices to the poly collision
                                    poly.Vertices = vertices.ToArray();

                                    level.PolygonCollisionEntities.Add(poly);
                                    break;

                                case "RECTANGLECOLLISIONENTITY":
                                    float rectXPos = float.Parse(reader.GetAttribute("x"));
                                    float rectYPos = float.Parse(reader.GetAttribute("y"));
                                    float height = float.Parse(reader.GetAttribute("height"));
                                    float width = float.Parse(reader.GetAttribute("width"));
                                    float rectMass = float.Parse(reader.GetAttribute("mass"));

                                    RectangleCollisionEntity rect = new RectangleCollisionEntity();
                                    rect.Height = height;
                                    rect.Mass = rectMass;
                                    rect.Position = new Vector2(rectXPos, rectYPos);
                                    rect.Width = width;

                                    level.RectangleCollisionEntities.Add(rect);
                                    break;

                                case "TEXTUREINSTANCE":
                                    float textXPos = float.Parse(reader.GetAttribute("x"));
                                    float textYPos = float.Parse(reader.GetAttribute("y"));
                                    int textureHeight = int.Parse(reader.GetAttribute("height"));
                                    int textureWidth = int.Parse(reader.GetAttribute("width"));
                                    string name = reader.GetAttribute("name");

                                    TextureInstance instance = new TextureInstance();
                                    instance.Height = textureHeight;
                                    instance.Name = name;
                                    instance.Position = new Vector2(textXPos, textYPos);
                                    instance.Width = textureWidth;

                                    level.TextureInstances.Add(instance);
                                    break;

                                case "TEXTURERESOURCE":
                                    level.TextureResources.Add(reader.GetAttribute("name"));
                                    break;
                            }

                            break;
                        case XmlNodeType.EndElement:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException(ex.Message);
            }

            return level;
        }

    }
}</code></pre>
<h3>The Content Type Writer</h3>
<p>In this step, we are taking the Level object that we read in the previous step, and writing it out in a binary XNB file. The binary file is much smaller than the XML file, as it doesn&#8217;t have the overhead of storing all the XML tag names, so it&#8217;s much quicker for XNA to load when you run your level.</p>
<p>At this stage you need to think about how to represent your level in the binary format so that you can read it out again in the next step. For example, because we can&#8217;t just iterate over the collections (because they&#8217;re not stored as collections), you need to make sure you include the number of objects to read.</p>
<p>You can see the structure I came up with in comments towards the top of the file:</p>
<pre><code class="cs">using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content.Pipeline.Serialization.Compiler;
using PhysicsGameEngine;

namespace LevelProcessor
{
    [ContentTypeWriter]
    public class XmlLevelWriter : ContentTypeWriter
    {
        protected override void Write(ContentWriter output, Level value)
        {
            //LEVEL HEIGHT (INT)
            //LEVEL WIDTH (INT)
            //NUMBER OF POLY COLLISIONS (INT)
            //  POLY MASS (FLOAT)
            //  NUMBER OF POLY VERTICES (INT)
            //      X (FLOAT)
            //      Y (FLOAT)
            //NUMBER OF RECTANGLE COLLISIONS (INT)
            //  RECT MASS (FLOAT)
            //  X (FLOAT)
            //  Y (FLOAT)
            //  HEIGHT (FLOAT)
            //  WIDTH (FLOAT)
            //NUMBER OF TEXTURE INSTANCES (INT)
            //  NAME (STRING)
            //  X (FLOAT)
            //  Y (FLOAT)
            //  HEIGHT (INT)
            //  WIDTH (INT)

            output.Write(value.Height);
            output.Write(value.Width);

            output.Write(value.PolygonCollisionEntities.Count);
            foreach(PolygonCollisionEntity poly in value.PolygonCollisionEntities)
            {
                output.Write(poly.Mass);
                output.Write(poly.Vertices.Length);
                foreach (Vector2 vert in poly.Vertices)
                {
                    output.Write(vert.X);
                    output.Write(vert.Y);
                }
            }

            output.Write(value.RectangleCollisionEntities.Count);
            foreach (RectangleCollisionEntity rect in value.RectangleCollisionEntities)
            {
                output.Write(rect.Mass);
                output.Write(rect.Position.X);
                output.Write(rect.Position.Y);
                output.Write(rect.Height);
                output.Write(rect.Width);
            }

            output.Write(value.TextureInstances.Count);
            foreach (TextureInstance instance in value.TextureInstances)
            {
                output.Write(instance.Name);
                output.Write(instance.Position.X);
                output.Write(instance.Position.Y);
                output.Write(instance.Height);
                output.Write(instance.Width);
            }

            output.Write(value.TextureResources.Count);
            foreach (string textureName in value.TextureResources)
            {
                output.Write(textureName);
            }
        }
        public override string GetRuntimeType(TargetPlatform targetPlatform)
        {
            return typeof(Level).AssemblyQualifiedName;
        }
        public override string GetRuntimeReader(TargetPlatform targetPlatform)
        {
            return "PhysicsGameEngine.XmlLevelReader, PhysicsGameEngine, Version=1.0.0.0, Culture=neutral";
        }

    }
}</code></pre>
<h3>The Content Type Reader</h3>
<p>Now we need to write the reader, which simply reads the file that we created in the previous step.</p>
<p>As you can see, it&#8217;s almost identical to the writer, only we are reading, and we return the instantiated level at the end:</p>
<pre><code class="cs">using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace PhysicsGameEngine
{
    public class XmlLevelReader : ContentTypeReader
    {
        protected override Level Read(ContentReader input, Level existingInstance)
        {
            Level level = new Level();

            //LEVEL HEIGHT (INT)
            //LEVEL WIDTH (INT)
            //NUMBER OF POLY COLLISIONS (INT)
            //  POLY MASS (FLOAT)
            //  NUMBER OF POLY VERTICES (INT)
            //      X (FLOAT)
            //      Y (FLOAT)
            //NUMBER OF RECTANGLE COLLISIONS (INT)
            //  RECT MASS (FLOAT)
            //  X (FLOAT)
            //  Y (FLOAT)
            //  HEIGHT (FLOAT)
            //  WIDTH (FLOAT)
            //NUMBER OF TEXTURE INSTANCES (INT)
            //  NAME (STRING)
            //  X (FLOAT)
            //  Y (FLOAT)
            //  HEIGHT (INT)
            //  WIDTH (INT)
            //NUMBER OF TEXTURES (INT)
            //  NAME (STRING)

            level.Height = input.ReadInt32();
            level.Width = input.ReadInt32();            

            int numPolys = input.ReadInt32();
            for (int i = 0; i &lt; numPolys; i++)
            {
                PolygonCollisionEntity poly = new PolygonCollisionEntity();
                poly.Mass = input.ReadSingle();
                int numVertices = input.ReadInt32();
                List&lt;Vector2&gt; vertices = new List&lt;Vector2&gt;();
                for (int j = 0; j &lt; numVertices; j++)
                {
                    float xPos = input.ReadSingle();
                    float yPos = input.ReadSingle();
                    vertices.Add(new Vector2(xPos, yPos));

                }
                poly.Vertices = vertices.ToArray();
                level.PolygonCollisionEntities.Add(poly);
            }

            int numRects = input.ReadInt32();
            for (int i = 0; i &lt; numRects; i++)
            {
                RectangleCollisionEntity rect = new RectangleCollisionEntity();
                rect.Mass = input.ReadSingle();
                float xPos = input.ReadSingle();
                float yPos = input.ReadSingle();
                rect.Position = new Vector2(xPos, yPos);
                rect.Height = input.ReadSingle();
                rect.Width = input.ReadSingle();

                level.RectangleCollisionEntities.Add(rect);
            }

            int numTextureInstances = input.ReadInt32();
            for (int i = 0; i &lt; numTextureInstances; i++)
            {
                TextureInstance instance = new TextureInstance();
                instance.Name = input.ReadString();
                float xPos = input.ReadSingle();
                float yPos = input.ReadSingle();
                instance.Position = new Vector2(xPos, yPos);
                instance.Height = input.ReadInt32();
                instance.Width = input.ReadInt32();

                level.TextureInstances.Add(instance);
            }

            int numTextures = input.ReadInt32();
            for (int i = 0; i &lt; numTextures; i++)
            {
                level.TextureResources.Add(input.ReadString());
            }

            return level;
        }

    }
}</code></pre>
<h3>And we&#8217;re done!</h3>
<p>Now, after adding the content processor reference to the game, we can add level files to the Content project, and it should automatically identify our new level processor:</p>
<p><a href="http://www.dylanblack.com/wp-content/uploads/2008/07/level-content-processor2.png" target="_blank"><img src="http://www.dylanblack.com/wp-content/uploads/2008/07/level-content-processor-thumb2.png" alt="Level Content Processor" width="123" height="480" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dylanblack.com/2008/07/04/writing-the-level-processor/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Video of exported level in-game!</title>
		<link>http://www.dylanblack.com/2008/07/02/video-of-exported-level-in-game/</link>
		<comments>http://www.dylanblack.com/2008/07/02/video-of-exported-level-in-game/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 04:03:40 +0000</pubDate>
		<dc:creator><![CDATA[dylan]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Game]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://www.dylanblack.com/?p=24</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="350" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="http://www.youtube.com/v/24khjqDvnjg" /><embed type="application/x-shockwave-flash" width="425" height="350" src="http://www.youtube.com/v/24khjqDvnjg"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dylanblack.com/2008/07/02/video-of-exported-level-in-game/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>XNA Level Editor</title>
		<link>http://www.dylanblack.com/2008/07/02/xna-level-editor/</link>
		<comments>http://www.dylanblack.com/2008/07/02/xna-level-editor/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 02:25:07 +0000</pubDate>
		<dc:creator><![CDATA[dylan]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Game]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[WinForms]]></category>
		<category><![CDATA[XNA]]></category>

		<guid isPermaLink="false">http://www.dylanblack.com/?p=13</guid>
		<description><![CDATA[I&#8217;m working on a level editor for creating XNA games. At the moment, it only supports the 2D game engine I&#8217;m working on, but I&#8217;m planning to extend both the engine and editor to support 3D graphics (but keeping it to 2D logic for the time-being). This is what the editor looks like when it [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m working on a level editor for creating XNA games.</p>
<p>At the moment, it only supports the 2D game engine I&#8217;m working on, but I&#8217;m planning to extend both the engine and editor to support 3D graphics (but keeping it to 2D logic for the time-being).</p>
<p>This is what the editor looks like when it loads:    <br /><a href="http://www.dylanblack.com/wp-content/uploads/2008/07/level-editor1.png" target="_blank"><img alt="Level Editor" src="http://www.dylanblack.com/wp-content/uploads/2008/07/level-editor-thumb1.png" width="540" height="407" /></a>     <br />The grid can be turned on or off, and the grid size will be editable in the application settings.</p>
<p>From here, you can load your images, and place them in the level: <a href="http://www.dylanblack.com/wp-content/uploads/2008/07/level-editor-images1.png" target="_blank"><img alt="Level Editor Images" src="http://www.dylanblack.com/wp-content/uploads/2008/07/level-editor-images-thumb1.png" width="540" height="407" /></a> Note: game sprites are from <a title="Lost Garden" href="http://lostgarden.com" target="_blank">Lost Garden</a>.</p>
<div id='extendedEntryBreak' name='extendedEntryBreak'></div>
<p> The engine supports the <a title="Farseer Physics" href="http://www.codeplex.com/FarseerPhysics" target="_blank">Farseer Physics</a> engine for XNA, and the editor supports drawing polygon and rectangle collision objects (visible as magenta lines):   <br /><a href="http://www.dylanblack.com/wp-content/uploads/2008/07/level-editor-collisions1.png" target="_blank"><img alt="Level Editor Collisions" src="http://www.dylanblack.com/wp-content/uploads/2008/07/level-editor-collisions-thumb1.png" width="540" height="407" /></a>   </p>
<p>I wrote a custom processor to get the level into the game engine, so I only have to save the level in the editor and add it to the Content project in XNA Game Studio, along with the images that I&#8217;ve used:    <br /><a href="http://www.dylanblack.com/wp-content/uploads/2008/07/level-content-processor1.png" target="_blank"><img alt="Level Content Processor" src="http://www.dylanblack.com/wp-content/uploads/2008/07/level-content-processor-thumb1.png" width="123" height="480" /></a></p>
<p>Then I just need to add some code to the LoadContent method to load the images and create the collision objects in Farseer:</p>
<pre><code class="cs">foreach (PolygonCollisionEntity poly in level.PolygonCollisionEntities)
{
    Body polyBody = BodyFactory.Instance.CreatePolygonBody(new Vertices(poly.Vertices), poly.Mass);
    polyBody.IsStatic = true;
    Geom polyGeom = GeomFactory.Instance.CreatePolygonGeom(physicsSimulator, polyBody, new Vertices(poly.Vertices), 1.0f);
} 

foreach (RectangleCollisionEntity rect in level.RectangleCollisionEntities)
{
    Body rectBody = BodyFactory.Instance.CreateRectangleBody(rect.Width, rect.Height, rect.Mass);
    rectBody.IsStatic = true;
    rectBody.Position = rect.Position;
    Geom polyGeom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, rectBody, rect.Width, rect.Height);
} 

foreach (string textureName in level.TextureResources)
{
    Texture2D texture = Content.Load&lt;Texture2D&gt;(textureName);
    level.Textures.Add(textureName, texture);
}</code></pre>
<p>Then I can run the level:</p>
<p><a href="http://www.dylanblack.com/wp-content/uploads/2008/07/level-in-game1.png" target="_blank"><img alt="Level In Game" src="http://www.dylanblack.com/wp-content/uploads/2008/07/level-in-game-thumb1.png" width="501" height="480" /></a> </p>
<p>The collision objects are visible as dark green lines, and the green and white boxes form a chain, implemented in Farseer, interacting with the level.</p>
<p>Next up I plan on implementing the following features:</p>
<ul>
<li>Modify level content processor to load textures automatically, so that they don&#8217;t need to be added manually </li>
<li>Implement a camera system to be able to create larger levels and move around them </li>
<li>Add functionality to the level editor to be able to edit objects once they have been placed </li>
<li>Implement the Properties tab using the .NET Property Grid control to be able to edit the properties of selected objects </li>
</ul>
<p>Once that&#8217;s done, it&#8217;s on to the game itself!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dylanblack.com/2008/07/02/xna-level-editor/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
	</channel>
</rss>
