The ShooterZero.zip file over on my google pages page contains an XNA project that is a 2D shooter game framework.
The code describes a series of classes that together provide services that a shooter will need:
- Resource management and a game loop with debugging functions (even a simple console!)
- An object model, where all elements of the game are Object Instances that are created from Object Definitions
- A scripting language to define the behaviour of Objects
- A set of services that the Object Instances can employ, e.g. intersection, rendering, input, etc.
- A parser that can create Object Definitions and Object Instances
The implementation here is admittedly very slapdash for lack of time invested, but I believe the principal features of the kind of data driven system I'm trying to demonstrate are evident:
- Game is setup with parameters read from a data file - one engine supports a variety of expressions by implementing common primitives.
- Objects in the game are defined using data driven templates, both properties and behaviors - data is parsed into logical collections of primitives.
- Object instances are created from data - separate structure from content.
- All the Data is reloadable at runtime - faster iteration time when it comes to implementing content.
13 comments:
"... and if there's enough interest I could write a few more posts that break out the details."
I'm interested ...
I'd love to see more detail on this
Nice blog you got here!
I get an error when I try to run Shooter Zero,
"Input string was not in a correct format"
at this line:
"float debounce = float.Parse( function.GetAttribute( "Debounce" ) );"
I'm a newbie and don't know how to fix it...
And I as well like to see more details on this topic.
I also like to see more details on the design structure post. I use Cornflower Blue's method in my attempts at creating games. It works for me but after reading your post I would like to try your method as well, but I don't know how to implement it. If you could post a sample on that too I would be most grateful.
ps. I think it might be a culture error, I'm from Sweden in Europe. ds.
It does sound rather likely that it's a globalisation thing. Doh! How embarrassing...
I have to admit, despite having done a ton of localisation work for games (I wonder why we name it the other way around?), I've yet to do so for a C# app, so I beg ignorance here.
The way I see it, we have two options: either make the scripts use the Invariant culture (as per most programming languages I wager?), or allow globalisation in the scripts. Which choice would be right would depend on the project's deployment pattern and intentions.
For us, I reckon invariant is the way to go, with the assumption that we want our target games to work with any player.
If you'd be so kind to test the fix for me (to make sure that really is the problem), I'll roll it into the zip file.
Please search out any float.Parse functions (there are about half a dozen) and add the invariant culture specification:
float.Parse( string );
becomes
float.Parse( string, System.Globalization.CultureInfo.InvariantCulture );
There's also one float.TryParse in there that needs changing from
float.TryParse( string, out float );
to
float.TryParse( string, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out float )
That seem to be the trick! Works fine now.
Thanks Karl.
I've uploaded a replacement zip file with the appropriate changes made.
First of all, thanks Mr Gamey Little Hacker, this shooterZero framework is a real educational surprise !
For a while I was tweaking my code to achieve what you call "data driven" way of doing (I'm a demo coder not a game coder so I reinvent the wheel each time) and when I looked at your shooter code, I said 'Whaaaaah, amazing, exactly what I want to achieve'
So I have played with it and I started to modify it to add something not available, mapping an objectinstance to an existing DrawableGameComponent.
For example, when moving, sendign a message to the "Background object" which is linked to the Background DrawableGameComponent to change its scroll direction.
So I was wondering if it is the good way to do, I mean adding a reference attribute to the obejct definition which is going to reference the Background object instance, to transalte the Message received into Background scrollUnit modification.
I planned to use this ref feature for any external complex DrawableComponent (tile engine, UI boxes,...)
Am I wrong ?
No, that sounds perfectly reasonable shazz. There are plenty of ways to do this sort of thing, and your proposal, if I understand it correctly is definitely a nice modular one.
To see if I understand this, you propose to:
* Add a way to make ObjectInstances with a reference to another C# object.
* Implement a message handler on that other object that can receive messages from the scripting language.
Sounds good to me. What mechanism will you be using specifically to implement the message despatching?
Thanks for the feedback !
In fact I'm adding a lot of stuff into the framework (I'll be pleased to send it to you for review ;-)) like
- new movements : Jump
- AnimatedVisual (for multi frames sprites)
- a Tile Engine
- idle control (when to key is pressed => set Stand state)
- ...
so for the Reference stuff for the obejct definition I did it like that :
-> added a Reference tag for object tag
< Object TypeName="Background" >
< Reference >
< Ref typeName="Background" Value="Ocean"/ >
< /Reference >
...
-> added message sent from Player to Background ObjetInstance
...
< Control >
< Left >
< Set Parameter="Direction" Value="-256,0"/ >
< Set Parameter="Rotation" Value="-25"/>
< SendMessage To="TileMap" Message="Left"/ >
< /Left >
...
-> added ref to the Background object in the Level object
< ObjectInstance TypeName="Player" Position="64,32" / >
< ObjectInstance TypeName="Background"/ >
< ObjectInstance TypeName="Level" >
< Object Name="back" Value="Background"/ >
< /ObjectInstance >
the only little stuff I add to take care is that the message will control the background scroll but as no message is sent when nothing is pushed the backgroudn will continue to scroll... So I had to tweak it.
so it looks at that you thougt no ?
If you'd like to look at the code just give me an email !
thx again, I love your stuff :D
and for the message dispatching, I have added in the ObjectInstance Draw() :
public void Draw()
{
if ( IsDead )
return;
// Draw the kids first
foreach ( ParameterInstance p in parameters.Values )
{
if ( p.Value is List< ObjectInstance > )
{
List< ObjectInstance > objectInstances = (List< ObjectInstance >) p.Value;
foreach ( ObjectInstance i in objectInstances )
i.Draw();
}
}
foreach (KeyValuePair< string, NamedDrawableGameComponent > pair in definition.Reference)
{
NamedDrawableGameComponent dgc = pair.Value;
object o = this.GetParameter("Position");
definition.Draw((Vector2)GetParameter("Position"), (Vector2)GetParameter("Direction"), dgc);
SetParameter("Direction", Vector2.Zero);
}
as the drawableComponents references are stored into a dictionary
Thank you for the post and the sample code in a game project. I'm having trouble finding good examples of data driven code and may look at your program later if I get stuck.
Post a Comment