Monday, July 23, 2012

Finally a level editor!

Well it took a bit of time, but it's finally in working order! To elaborate a bit further, here's a list of things that are now possible in the Portal debug mode:

  • Load levels from Ruined Level Portal files (*.rlp)
  • Switch to portal editor mode - I edit individual portals at a time
  • Select just about any object in the level, and edit its properties with the Property-grid control and my "gizmo" control
  •  Load new models and collision meshes while the game is running
  • Save portals into *rlp format

To make loading, and saving levels possible, I had a couple of options.

  1. Use reflection to process and load the level data to and from XML files
  2. Use reflection to process and load the level data to and from "binary" files
  3. Write my own format, importer and processor
I went with option number 3, for a couple of reasons:
  • I could make my format as size efficient as possible ( I'm using bits, bytes, and uint16's)
  • I could store just enough data ,as opposed to too much junk
  • I could store what I wanted and know where to find it in the file
  • XNA makes writing importers and processors REALLY easy
  • I just like the flexibility
Now my format may not have the readability of XML, but it is sure a LOT more readable than XNA's binary-serializer. If someone needed to, they could parse through the level files by hand and make changes - with the right documentation of course.
Here's a little bit of the level parser to give you an idea of what I mean:
ushort Type = input.ReadUInt16();
if (Type == 0x0000) // Torch
     portal.DynamicObjects.Add(new Engine.DynamicObjects.Torch(input.ReadVector3(), input.ReadSingle(), portal, input.ReadBoolean()));
else if (Type == 1)
     // Door
else if (Type == 0x0002) // Ladder
     portal.DynamicObjects.Add(new Engine.DynamicObjects.Ladder(input.ReadVector3(), input.ReadSingle(), input.ReadSingle()));
else if (Type == 0x0003) // Chest
     portal.DynamicObjects.Add(new Engine.DynamicObjects.Chest(input.ReadVector3(), input.ReadSingle(), Index, input.ReadUInt16(), input.ReadUInt16()));

So as you can see, I'm only reading the data used to initialize the torch, I don't need to store all the other fluff XNA's-serializers store - and I'm not talking about the stuff you can mark to ignore.
For example: things like strings can be stored as a char[] instead of 2 bytes per letter, or if i had an object that contains both a model and a collision mesh, I can have an unique type saying, "Hey, this object's model and collision mesh are the same, I don't have to store the file name twice."

Enough talk for now though, here are some pictures of the level editor in action-

I can even edit instanced-objects individually!

Friday, July 6, 2012

Trees and God Rays

Yep, another one of those posts where the title summarizes its content.
So, as far as eye-candy goes, Ruined should more than fill ones appetite - at least for an indie game.

First up it's:
Dynamic Trees - the kind with leaves.
  • You heard right, trees will appear to blow and sway in the wind. 
  • I'm also using hardware instancing for drawing trees/bushes/grass, so I should be able to have a considerable amount of vegetation on the screen at once. 
  • Trees are pretty awesome...

Followed by:
God Rays a.k.a. Light Shafts
  • God rays create the effect of sun-rays shining around sun-occluding objects.
  • In other words, it's nothing but eye candy, but delicious eye candy at that!

A word on implementation
God-rays are actually really easy to program.
  1. Draw the sky, masked by the environment into a TINY render-target (you can use your depth buffer for this)
  2. Radially blur this image into another TINY render-target, using the sun-screen-space position
  3. Additively blend the blurred image with your final output.
Here are some links where you can find out more on programming god-rays
  1. Your model needs to have certain values painted to each of it's vertices
  2. In the vertex shader you transform each vertices position taking into account it's vertex color
  3. Blender doesn't support painting a single channel of a vertex color at a time (ie Red, Green, or Blue), so a processor must be written to combine three separate vertex color channels into one. So you have to make a channel for Reds, a channel for Greens, and a channel for Blues, then you combine all three of these channels into one.
  4. I then wrote my own simple model format to allow me to hardware instance with ease
Again, here are some links that have some more information on the topic

Note: The tree model used in this post is provided as free-ware from the Loopix-Project in its original form.

Night Sky

Well, this post will be a quick one.
As the title implies, I have a working night sky, complete with stars clouds and a moon!

Oooooh! The Red moon.