adamkdean

software engineering

Import content using MonoGame & XNA

By Adam K Dean on

So I knew this was coming. I knew there would be issues with the content pipeline, long lost roots reaching back down into the abyss of XNA and unmaintained Microsoft projects. Game development is all about challenges. It's the reason I love it. Everything pushes you to the limit; mentally, physically, emotionally.

My first challenge is to get a MonoGame project up and running with the XNA pipeline. Luckily, the folks over at MonoGame have put a lot of effort into this already, and so it's quite straight forward. Then again, everything is once you've figured it out. Working against me is a fragmented web of outdated tutorials and insufficient documentation.

I am using Visual Studio 2012. I have Windows Phone SDK installed, which allowed me to install XNA Game Studio 4.0. I have also installed the Visual Studio 2012 XNA refresh extension, allowing me to do everything in VS2012. Finally, I have MonoGame installed.

I have created a project named Alpha, first of it's kind. In there I have added two new projects: a MonoGame Content Project, and a MonoGame Windows Project. The content project will create two projects. One will be called %name% and is an XNA content project, the other will be called %name%Content and is a MonoGame content project. I used the name Alpha, which gave me Alpha and AlphaContent. The MonoGame Windows Project will simply create a single project. I called it AlphaGame.

So now I have three projects: Alpha (XNA content), AlphaContent (MonoGame content), and AlphaGame (MonoGame windows).

The reason we need so much is because we rely on XNA to convert our content into XNA/MonoGame ready content. Once you're setup, you won't even need to worry about the particulars though. It's all very, very neat.

I've created two files; blue.png and green.png. I have a separate directory called assets which isn't part of the Visual Studio solution. I'll keep all my content here, and copy it when it's ready to the solution. To import them into the solution, I simply drag them into the Solution Explorer. We want them to belong to the AlphaContent project (the MonoGame content one).

Now when the project builds, they will be converted to XNA content. But we want to be able to access them in our AlphaGame.

Open up AlphaGame.csproj in a text editor. I use Sublime. At the bottom, we want to add in an AfterBuild script.

<Target Name="AfterBuild">
    <ItemGroup>
        <ContentSource Include="..\Alpha\Alpha\bin\PSM\Content\**\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(ContentSource)" DestinationFolder="$(TargetDir)\Content\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>

You may need to change some paths to suit your project.

When we now rebuild our entire solution, we will get the following:

1>AfterBuild:
1>  Copying file from "..\Alpha\Alpha\bin\PSM\Content\Artwork\blue.xnb" to "C:\Users\Adam\Desktop\AlphaGame\src\AlphaGame\bin\Windows\Debug\\Content\Artwork\blue.xnb".
1>  Copying file from "..\Alpha\Alpha\bin\PSM\Content\Artwork\green.xnb" to "C:\Users\Adam\Desktop\AlphaGame\src\AlphaGame\bin\Windows\Debug\\Content\Artwork\green.xnb".

Now we can easily load the content like so:

protected override void LoadContent()
{
    this.Content.Load<Texture2D>("Artwork/blue");
}

This post may not be as easy to read as some of my others. Most of the time I ponder of what I'm writing, making sure to produce easy to read content. But my head is in game development, so I'm just doing a braindump. I'm going to start tagging these posts as braindumps.

P.S, make sure you set the game project to rely on the content project by right clicking the solution and going to build order, and setting the game project to depending on the content project.

Proper sorting with JavaScript

By Adam K Dean on

If we're trying to sort an array, we're going to have a bad time. JavaScript doesn't do a good job of sorting out of the tin, so we're going to have to implement our own sorting algorithm. It's not really advanced enough to use the term algorithm, but let's get to it.

First, let's take an array. We can either have numbers, numbers in strings, or strings. Regardless of whether we have numbers in strings or actual numbers, the sorting will still be back to front by default. For example, [1, 8, 10, 12] will still become [1, 10, 12, 8] when we run sort().

So let's get that array.

var list = ['10', '12', '14', '16', '18', '20', '8'];

So now we have an array. It isn't sorted how you'd expect it to be. If we run sort(), we'll end up with a peculiar result. 10 will come before 8, as will 20, all the way up to 7...

// what we'll see
["10", "12", "14" "16", "18", "20", "8"]

// what we want to see
["8", "10", "12", "14", "16", "18", "20"]

To sort this, we're going to have to write our own sorting algorithm. We need to account for strings, numbers inside strings, numbers. The good thing about JavaScript sort() is that you can pass your own predicate. A predicate is an expression which returns either true or false. Is a greater than b?

A simple way to perform a numerical sort is:

list.sort(function (a, b) {
    return a - b;
});

But this isn't going to work properly for strings. A more advanced way of sorting it, which will account for strings as well, will check whether numbers are involved, and if so, convert the strings to numbers before comparing.

list.sort(function (a, b) {
    var ai = parseFloat(a), bi = parseFloat(b);
    return (isNaN(ai) || isNaN(bi)) 
        ? a > b ? 1 : a < b ? -1 : 0
        : ai > bi ? 1 : ai < bi ? -1 : 0;
});

Using either of these predicates with numbers/numbers-in-strings will output what you'd expect:

["8", "10", "12", "14", "16", "18", "20"]

But if we're using letters, such as a list of bra cup sizes, the advanced predicate will come out on top. Let's take a look at another example. In this, we're going to use said list of bra cup sizes and sort them. We'll see how the numerical predicate falls on it's face, and how the combined predicate doesn't.

var list = ['FF', 'GG', 'F', 'DD', 'K', 'E', 'G', 'D', 'JJ', 'J', 'HH', 'KK', 'H'];

list.sort(function(a, b) { return a - b; });
// outputs: 
// ["FF", "H", "F", "DD", "K", "E", "GG", "D", "JJ", "J", "HH", "KK", "G"]

list.sort(function (a, b) {
    var ai = parseFloat(a), bi = parseFloat(b);
    return (isNaN(ai) || isNaN(bi)) 
        ? a > b ? 1 : a < b ? -1 : 0
        : ai > bi ? 1 : ai < bi ? -1 : 0;
});
// outputs: 
// ["D", "DD", "E", "F", "FF", "G", "GG", "H", "HH", "J", "JJ", "K", "KK"]

It would be interesting to know why sort() doesn't use something like this by default. Maybe this will be the subject of a further blog post.

Check if type exists in MSSQL

By Adam K Dean on

Snippet time. Check if a type exists in MSSQL with the following simple query:

IF TYPE_ID(N'[dbo].[udt_SomeCustomType]') IS NOT NULL
BEGIN
    -- type exists, do something here
END

And of course, the other way round:

IF TYPE_ID(N'[dbo].[udt_SomeCustomType]') IS NULL
BEGIN
    -- type does not exist, do something here
END

More SQL snippets to come.

Ordering and filtering objects with ng-repeat

By Adam K Dean on

AngularJS allows you to iterate over collections using the ng-repeat directive. You have the ability to order and filter the collection, but this only works for arrays, not for objects. You'd think that you'd retain the functionality of arrays, considering the object is treated like one, but you don't.

The solution to this is to push the contents of the object into an array using a filter. By keeping the references intact, we are still able to bind to the objects, as they are essentially the same object.

.filter('objectAsArray', function() {
    return function(object) {
        var array = []; 
        for (item in object) {
            array.push(object[item]);
        }
        return array;
    }
});

Let's look at what we'd need if we wanted to order and/or filter an array:

<p ng-repeat="item in itemArray | orderBy: 'order' | filter: {visible: true}">
    {{item}}
</p>

But what if that was an object? Well, we just pop the objectAsArray filter in:

<p ng-repeat="item in itemObj | objectAsArray | orderBy: 'order' | filter: {visible: true}">
    {{item}}
</p>

This is indeed a very useful little filter.

View the live plunkr example here.

Giving the Squirt.io bookmarklet a favicon

By Adam K Dean on

Today I learnt about squirt.io, an open-source Spritz-like bookmarklet which helps you speed read the internet. From 250 words per minute all the way upto 950 words per minute. A bookmarklet is a javascript snippet which sits inside a bookmark on your "favourites bar", and allows you to execute that script on whichever website you're currently on.

I use Chrome mainly, and the only bug bear I have with bookmarklets is that they don't have favicons. As somebody who has a 1920 pixels of favicons stretching across the top of my browser, I can't stand to see that default white icon polluting the line of beautifully crafted icons.

There is a way to set the icon though!

Make sure you have the bookmarklet saved to your bookmarks bar. Then, go to squirt.io and bookmark it. Right click that bookmark, go to Bookmark manager. In the top left hand corner you'll see a menu Organise. Click it, and export your bookmarks to a HTML file.

Now open it up in your favourite text editor. I'm using Sublime. Search for squirt.io and you should find a line near the bottom of the file. It'll have a HREF pointing to squirt.io, an ADD_DATE, and more importantly, an ICON attribute.

<DT><A HREF="http://www.squirt.io/" ADD_DATE="1394700500" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABRElEQVQ4jZXSPUtcURAG4MeY+BVi0EJsBD8gRZogsk0Eu8XKRiSQwgj5CbYRLGyTKk0gTZoUsfCjEMFS/4EgRME2WwXUoEHN7qa4czfXu3dZM3A458y8874z5wzF1hH7BzzP+dpaCiyjjvW4P/gfgl4coRokC/clSQErkXiFW5yiX5s20uAozoMgu9ZyuJbqnyOhgi/YilYuMNaKJHU8w298x3gmPhekn3JiTeofA/imQGkT1xjJxtLEGgbwKs4/IjaMoTgf4xFe5wk6w1HOgF8GUR+6I16KpPnA1NLSHsa+KnmsJclP9GTKfxK+97jE43zvIkDy6rN4ireYwSSmsI1f+JPJazzUi6igEv3CLpYxIZmNM3zL5d25fJX8QhU7OMEB9v0bqFJB9Q2SQexpnsJ6lL5YpJ63LrzDIW7wExuYLlL+C3jqSJn7EH8tAAAAAElFTkSuQmCC">Squirt</A>

Above this bookmark, you should see your bookmarklet, where the HREF starts with javascript:. Notice how it doesn't have an ICON attribute set? Well, let's set that. Extract the ICON attribute from the squirt.io bookmark and inject it into the bookmarklet, like so:

<DT><A HREF="javascript:(function(){if(window.sq){window.sq.closed&&window.document.dispatchEvent(new Event('squirt.again'));}else{window.sq={};window.sq.userId='63c3f43e-7a2e-4652-ae1b-c8b309fbad5f';s=document.createElement('script');s.src='http://www.squirt.io/bm/squirt.js';s.s=window.location.search;s.idx=s.s.indexOf('sq-dev');if(s.idx!=-1){s.ampIdx=s.s.indexOf('&');s.host=s.s.substring(s.idx+7,s.ampIdx==-1?s.s.length:s.ampIdx);s.src='http://'+(s.host?s.host:'localhost')+':4000/bm/squirt.js';}document.body.appendChild(s);}})();" ADD_DATE="1394699165" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABRElEQVQ4jZXSPUtcURAG4MeY+BVi0EJsBD8gRZogsk0Eu8XKRiSQwgj5CbYRLGyTKk0gTZoUsfCjEMFS/4EgRME2WwXUoEHN7qa4czfXu3dZM3A458y8874z5wzF1hH7BzzP+dpaCiyjjvW4P/gfgl4coRokC/clSQErkXiFW5yiX5s20uAozoMgu9ZyuJbqnyOhgi/YilYuMNaKJHU8w298x3gmPhekn3JiTeofA/imQGkT1xjJxtLEGgbwKs4/IjaMoTgf4xFe5wk6w1HOgF8GUR+6I16KpPnA1NLSHsa+KnmsJclP9GTKfxK+97jE43zvIkDy6rN4ireYwSSmsI1f+JPJazzUi6igEv3CLpYxIZmNM3zL5d25fJX8QhU7OMEB9v0bqFJB9Q2SQexpnsJ6lL5YpJ63LrzDIW7wExuYLlL+C3jqSJn7EH8tAAAAAElFTkSuQmCC">Squirt</A>

Now save that file, go back to your Bookmark manager in Chrome, and import the file. Your bookmarklet will now be beautiful and all will be well with the world. Thanks again to Cameron Boehmer for this amazing bookmarklet, and to Readability and Spritz Inc too for their contributions!