Pages

Saturday, 14 January 2012

XNA BulletML implementation

I have been working on my own implementation of BulletML in XNA. Currently, I'm using a Content Importer to parse the entire BulletML document and create a logical object structure representing the BulletML document. I used TiledLib by Nick Gravelyn as an example on how to work with the Content Pipeline.

With the parsing down I started working on creating the actual implementation of the BulletML patterns. To "shoot" the bullets we call the bulletML.Run() this could we seen as one run through the BulletML document. One run through means start at the TopAction and loop through every Task defined in that Action. Tasks are everything in BulletML that require something to happen, like firing a bullet is a FireTask, changing the speed is ChangeSpeedTask. All logics for these Tasks is of course handled inside itself. This way everyone can understand what's happening after a simple read through the code. We also need to run bulletML.Update() to update our bullets, nothing else.

After the script is done and shot all it's bullets the BulletML pattern can not simply be shot again. In order to be able to shoot the pattern again we need to call the bulletML.Reset() method. The reason for this is that some Tasks in BulletML take longer than some and actually need to work for a couple of frames. Borrowing the idea from Bandle I made the Run() methods from Tasks return a BulletMLRunStatus containing an enum wether to continue on or break from the loop (WaitTasks). Also when a tasks is done, their Done property will to set to true and their action will be skipped by the bulletML.Run() call.

I might change the need to call Run(), Update() and Reset() separately because if you want to shoot the pattern every X seconds you'll want to call the Reset() function every X seconds, which is a little strange.

But anyway, here is a screenshot of a very simple BulletML document containing a couple of <fire> tasks with each their <direction type="absolute"> to plus 10. This should of course we by a repeat and <direction type="sequence"> but I started with just supported an easy script to I can be sure my design was actually working.


The counter tells us it's running at 60 frames a second, which it was with simulating around 1300 bullets in it's memory. I did however notice a slight hiccup every so seconds and the counter is showing 59FPS just for a brief second. But it also might just be an optical illusion but I hope it won't be any problem further down the road.

Thursday, 12 January 2012

My implementation of BulletML

Today I decided I'm going to stop working out features of Bullet Revolution and really dive into Bandle Games's BulletML implementation and use it to implement my own. Which will better integrate in XNA and my own project.

My current experience in handling XML is limited. I know how to parse them and how to write them, but to actually transform BulletML into interactive bullet patterns seems a little daunting to me.

Writing BulletML is simple enough, it's the parsing that's a but daunting to me.


Monday, 9 January 2012

How XNA 4.0 Custom Content Pipeline works

By following the article Creating a Custom Importer and Processor I think I figured out how the Content Pipeline actually works with custom content. Turns out, I was quite right. Although very simplified, it works like this:

  • A Content Importer reads asset data into the memory
  • A Content Processor processes the data into actual instances. (Still a little unsure about this)
  • A Writer will finally compile the processed data into an .xnb file.
  • A Reader is used to read from those compiled .xnb files, and is automatically called when you call content.Load<ContentType>.
If you got your importer, processor, writer and reader into place. You can just go on onto normal business by loading you newly created content with content.Load<ContentType>.

As a bonus check out this post by Shawn Hargreaves What to extend in the content pipeline a simple cheat sheet which will tell you what to do in certain scenarios.

Starting on my game editor

As my previous post said. For me to create a nice way to store my game data including levels, enemies, bullets, patterns and pretty much everything that can vary. I need to parse/create them on runtime instead of compile time. In order to do that I'm going to use C#/XNA's way of serializing data.

Serialization will allow me to serialize class instances into XML documents, pretty much like the example found here, I think. With this solution however, we don't really pay attention to the human aspect of creating these XML files. To describe a simple levels containing just a couple of enemies using just a couple of patterns will result in dozens of XML files describing each enemy instance, each pattern instance seperately while then being referenced by the level XML.

While typing this I realise there is still a lot of research for me to do about this kind of serialization and using this data to create class instances on runtime. Some good resources I've found are Jamie McMahon's awesome tutorials explaining you how to write your own RPG, and not just a simple one. These tutorial include a game editor and a level editor, so it's definitely a resource to keep an eye on. The only downside of these series is that Jamie is using dozens of classes including Data, DataManager classes of pretty much everything, I don't know if this is the normal way to go but seems like a bit of an overkill to me. Another downside is that Jamie seem to have stopped writing new tutorial continuing his work according to this post. But definitely an amazing resource!

Role Playing Game Starter Kit
Another good resource is Microsoft's Role-Playing Game Start Kit which according to the description
"Additionally, all game data are exposed in XML files, making it easy to write your own quests, create your own towns, or even write your own storyline."
 And since this is a microsoft advertised solution of using XML we can expect is uses every last bit of what XNA has to offer. So let us open the RolePlayingGameWindows.sln and start digging through its source to find out how they did it.

When we open up the windows solution of the starter kit we find it contains 4 projects:

  • RolePlayingGameContentWindows
  • RolePlayingGameDataWindows
  • RolePlayingGameProcessors
  • RolePlayingGameWindows
Obviously the only 2 projects that most beginners will be unfamiliar with are the project in bold, the RolePlayingGameDataWindows and the RolePlayingGameProcessors. Since my games uses TiledLib to parse Tiled Map Editor maps I'm just a little bit familiar with Processors, but just a little. As far as I know, they are used to process imported data into usable objects using classes derived from the generic ContentProcessor class.

I think the RolePlayingGameDataWindows project is used to store the classes to be written to some format (the .xnb format) by the writers in the Processors project since their project seems to be exactly the same.


So it seems like we scratched the surface of figuring out how the writers are used to compile classes into .xnb files, or instances of these classes I think.

How are the .XML files read
So now that we have a slight idea of what these new project files are doing we can start and look for how they actually parse .xml on runtime and put them in game. Or maybe they parse the XML on compile time and write them to a better, more optimised .xnb file format. Which seems to be the case since there are to XML files in the compile directory of the game.

Now let's check out the content project, it's not really hard to find our XML files because pretty much everything is defined in XML in this game. So let's open one of these XML files and analyze it. I took the Barbarian.xml class from the CharacterClasses directory.



One this immediately gets my attention. The root node is <XnaContent> followed by <Asset Type="RolePlayingGameData.Monster">. First of all this is not for convenience, for me it looks like proof that a machine is expecting such format, especially since ALL .xml use the exact same root nodes. The this of the <Asset> points to the data classes with RolePlayingGameData being the namespace. If we open the CharacterClass.cs file we can easily see the relation.

If we look at the properties we see that the Content Importer is set to XML Content - XNA Framework and that is great news. I guess that would mean XML is already supported by XNA, just like it already contains Importers for .png graphics. According to this article by Microsoft:
"The objective of the importer is to read asset data from the file in to memory for further conversion by the processor. The importer may also perform some intermediate data transformation if necessary."
There is however no Content Processor set for these XML files, so I wonder how they are handled? Maybe the XML Content Importer is already converting all XML nodes to their appropriate data classes so only writers are necessary to compile them into .xnb files?

Wow, this blog post is getting way too long. During this post  we didn't actually learn anything apart from how thing might be done. But we did learn about what we need to learn more about (huh? ok). So for the sake of clarity, we need to find out more about XNA's Content Pipeline and use Content Importers, Processors, Reader and Writers and eventually use data build from these processed XML files in our game. These is a good tutorial at MSDN about all of this here.

Bullet Revolution


Welcome to my blog about Bullet Revolution. Bullet Revolution is (going to be) a bullet-hell  game I'm developing in XNA 4.0. Since this is my first game, there is a lot of learning to do. I often run into problems I hadn't foreseen, but I find a solution most the the time.

I found myself talk to nobody on Google+ often, and that is not a joke stating Google+ has no users. It is just, explaining a problem really helps in finding yourself an answer. That's why I started this blog, so I can use the internet to explain my problems to and giving thanks you all you lovely internet users by providing my answer to the people of the internets. Of course, since I am a beginner myself all my provided answers should be taken with a grain of salt. But I will do my utmost best in providing a right answer.