Gleed 2D, by design, makes no attempt to create anything drawable. It's primary purpose is to let the user visually design levels and then work with strongly typed objects to load the level in their game.
So, when you load the level in your game, you end up with a Level
. A Level
has Layer
s, and Layer
s have objects that derive from ItemProperties
. So ultimately, you'll want to check what derived type of ItemProperties
you get when enumerating, and then build your in-game objects from that. Here's an example from a game:
public static class GleedConverter
{
public static void ConvertGleedObjects(LevelScreen levelScreen, Level level)
{
var pathConverter = new ConvertToGameObject<PathItemProperties>(
s => s.GetType( )==typeof(PathItemProperties) && s.Name.StartsWith( @"path", StringComparison.OrdinalIgnoreCase ),
ti =>
{
return new PathObject(
levelScreen,
ti.WorldPoints.ToArray( ),
Convert.ToInt32( ti.CustomProperties[ @"speed" ].Value, CultureInfo.InvariantCulture ),
ti.CustomProperties[ @"followed_by" ].Value as string ) ;
} ) ;
var spikeConverter = new ConvertToGameObject<TextureItemProperties>(
s => s.GetType( )==typeof(TextureItemProperties) && s.Name.StartsWith( @"Spike",StringComparison.OrdinalIgnoreCase ),
ti =>
{
var spike = new SpikeObject( levelScreen, levelScreen.ScreenManager.Textures[ ti.AssetName ] ) ;
ti.CopyPropertiseTo( spike, true ) ;
return spike ;
} ) ;
var boundaryConverter = new ConvertToGameObject<TextureItemProperties>(
s => s.GetType( )==typeof(TextureItemProperties) && s.Name.StartsWith( @"BoundaryBlock",StringComparison.OrdinalIgnoreCase ),
ti =>
{
var bondaryBlock = new BoundaryBlock( levelScreen,levelScreen.ScreenManager.Textures[ ti.AssetName ] ) ;
ti.CopyPropertiseTo( bondaryBlock, true ) ;
return bondaryBlock ;
} ) ;
var enemyConverter = new ConvertToGameObject<TextureItemProperties>(
s => s.GetType( )==typeof(TextureItemProperties) && s.Name.StartsWith( @"enemy",StringComparison.OrdinalIgnoreCase ), ti =>
{
var enemyType = (string)ti.CustomProperties[@"type"].Value ;
if (enemyType == @"WindMan")
{
WindMan windMan = WindMan.FromGleed( ti, levelScreen, levelScreen.ScreenManager.Textures[ @"WindMan60x135" ] ) ;
return windMan ;
}
throw new InvalidOperationException(@"Enemy type '{0}' unknown".FormatWith( enemyType ));
}) ;
[other converters omitted for brevity]
level.ConvertToGameObjects(
levelScreen.ScreenLayers,
new IConvertToGameObject[ ]
{
spikeConverter,
boundryConverter,
enemyConverter,
[other converters omitted for brevity]
} ) ;
LevelScreen
, as passed in the parameters, is a container that contains my drawable in-game objects.
This method creates several objects that convert different ItemProperties
into proper in-game objects. In my game, my some of the in-game objects are spikes, enemies, boundary blocks and paths. Note that the converters don't, at this point, create the in-game object, they're just converters that are ready to convert to in-game objects. Also note that they're entirely lamda based. If you have more complex converters, you can implement IConvertToGameObject
yourself, which is simply this:
public interface IConvertToGameObject
{
bool InterestedIn( ItemProperties gleedItem ) ;
GameObjectBase Convert( ItemProperties gleedItem ) ;
}
At the end of the ConvertGleedObjects
method above, it makes a call to ConvertToGameObjects
. This is an extension method that looks like this:
public static class GleedExtensions
{
public static void ConvertToGameObjects(
this Level level,
ScreenLayerCollection screenLayers,
IEnumerable<IConvertToGameObject> converters)
{
level.Layers.ForEach( l => screenLayers.AddLayer( l.Properties.Name, l.Properties.ScrollSpeed ) ) ;
var pairs = from layer in level.Layers where layer.Properties.Visible
from item in layer.Items
select new
{
LayerName=layer.Properties.Name,
Converter = converters.Single( c => c.InterestedIn( item.Properties ) ),
Item = item
} ;
pairs.ForEach(
p =>
{
GameObjectBase gameObject = p.Converter.Convert( p.Item.Properties ) ;
screenLayers.Add( p.LayerName, gameObject ) ;
} ) ;
}
}
This takes a Level
(the Level
you get from Gleed2D). It also takes a ScreenLayerCollection
(which is a collection of my layers where each layer contains drawable items), and a list of IConvertToGameObject
objects. It then does this:
- Adds layers to the
screenLayers
that were passed
- Creates
pairs
; each pair consists of the visible Layer
and a list of objects that describe: the layer name, a converter that converts the item (the item from Gleed), and the item itself
- Then for each pair, the converter is called which returns a
GameObjectBase
(each game object in my game derives from this). The new object is then added to the correct layer.
This looks like a lot of work, but when you have dozens/hundreds/thousands of different in-game objects, it's nice to have this separation between the gleed level, the thing that converts the gleed item to your in-game item, and the behaviour of your in-game item.
So, in summary, the flow I use is:
- Load the Gleed level
- Declare the things that convert the Gleed items into in-game items
- Enumerate the Gleed items and ask the converters to convert to in-game items
- Add the in-game items to whatever mechanism is used to store and handle in-game items.
LayerItem
extendGameComponent
? msdn.microsoft.com/en-us/library/… \$\endgroup\$Draw()
method ? \$\endgroup\$