So, scene graphs! I used to love the darned things, but now I have some mildly mixed feelings on them. Regardless, they're still pretty awesome, so I whipped up a quick bit of sample code! (Full source can be found at the bottom of the article)
But first, a quick description of what a scene graph is. It's basically a tree-like structure used to represent the data in your game's scene. The advantage of using a tree structure, is that you can use the parent/child relationship to inherit information, like position and orientation! This can make it extremely easy to do things like... stick arrows into people's knees! Or a helmet on top of your player's head, y'know, possibly even things like containers and inventories.
Just re-using an illustration I made last time I talked about scene graphs. It's still pertinent ;)
As it so happens, it's not all that hard to do this through code. So here's a quick 3D example of using a scene graph inside of XNA 4.0.
It's impossible to use a DrawableGameComponent for our scene graph nodes, primarily because the LoadContent method is declared as protected, but if you're familiar with XNA, then you'll notice that the SceneNode class very much resembles a DrawableGameComponent.
And that's reasonably straightforward, there's really nothing all that tricky in there. After that's out of the way, all you need to do is.. either inherit from it, or set up a component system! Inheritance is the easiest, so here's an example of a basic 3D object that uses the SceneNode.
And again, you can see it behaves almost exactly the same as a regular DrawableGameComponent! So it's not all that different from what you've already been working with~ Lastly, putting it all together in an example:
Spinning spaceships! Not the most practical thing, but hey.
So hopefully that's at least a little bit informative =D The full source code includes a few extra things not shown above, so check it out!
Source code can be downloaded here
Sunday, December 11, 2011
Friday, December 09, 2011
Scripting
So I was recently linked to an article about using scripting languages instead of 'real' languages. tl;dr, he talks about how scripting languages are just as powerful, just as fast, and frequently use a simpler syntax. They also compile separately, and can literally be treated as content, almost like a texture, or a map.
But, he somehow managed to briefly brush past the biggest reason why scripting languages are important to game development. They allow you to code for your game using a far higher level of abstraction! This is especially true for custom scripting languages, created for a specific game, a whole genre of games, or merely for games in general. One of my favorite examples of this is Age of Empires II, a game I spent significant amounts of time building and testing AI scripts for.
Though technically, I preferred it without the expansion. Martyrdom made monks really boring.
The fun thing is just how simple AI scripting is for AOE II. It lets you completely define the personality of the AI player, the style they play in, their priorities, the types of troops that they build, and on and on. Here's a quick snippet of what the language looks like:
As you can see, the syntax is extremely simple, almost LISP-like, but it's set up in a fashion where it's incredibly easy to define rules for the AI to follow. AOE II still uses an AI framework built into the game itself, but it does that to simplify the scripts that people would work with on a more frequent basis. It does mean there are a few things that are impossible for the scripter to change the behavior of, but that's alright in moderation.
Compare the above snippet with this bit from an XNA game that I'm currently working on.
Yeah, definitely not my prettiest bit of code, but that seems to be a theme with basic Finite State Machines when I code them. Imagine if I set up a basic framework, and did this in a custom scripting language? Quite possibly, I could reduce this into 3-4 lines of script, and easily swap out for different fish, types of fish, or even fish with different personality. When you have a really simple scripting language with which to express your ideas, then it suddenly becomes far easier to express more complex thoughts!
I think I'm going to leave it at that, there's plenty of other thing that the author of the article left out or glazed over, but I think this was one of the more important bits. Thanks for reading~
But, he somehow managed to briefly brush past the biggest reason why scripting languages are important to game development. They allow you to code for your game using a far higher level of abstraction! This is especially true for custom scripting languages, created for a specific game, a whole genre of games, or merely for games in general. One of my favorite examples of this is Age of Empires II, a game I spent significant amounts of time building and testing AI scripts for.
Though technically, I preferred it without the expansion. Martyrdom made monks really boring.
The fun thing is just how simple AI scripting is for AOE II. It lets you completely define the personality of the AI player, the style they play in, their priorities, the types of troops that they build, and on and on. Here's a quick snippet of what the language looks like:
(defrule (strategic-number sn-minimum-town-size == military_townSize_1) (soldier-count < military_townSize_army_1) => (chat-local-to-self "Lowering town size to level 0.") (set-strategic-number sn-minimum-town-size military_townSize_0) (set-strategic-number sn-maximum-town-size military_townSize_0) ) ;Attack Now ;start timer (defrule (true) => (chat-local-to-self "Activating attack delay timer.") (enable-timer military_timer_attack_delay 1) (disable-self) ) ;acknowledge timer w/ other conditions (defrule (strategic-number sn-minimum-town-size == military_townSize_6) (not(enemy-buildings-in-town)) (timer-triggered military_timer_attack_delay) => (chat-local-to-self "Attacking without town size attack.") (chat-to-allies "31 Attack an Enemy Now") (attack-now) (disable-timer military_timer_attack_delay) (enable-timer military_timer_attack_delay military_attack_delay_min) )
As you can see, the syntax is extremely simple, almost LISP-like, but it's set up in a fashion where it's incredibly easy to define rules for the AI to follow. AOE II still uses an AI framework built into the game itself, but it does that to simplify the scripts that people would work with on a more frequent basis. It does mean there are a few things that are impossible for the scripter to change the behavior of, but that's alright in moderation.
Compare the above snippet with this bit from an XNA game that I'm currently working on.
case AIState.Check: { AIFish fish = FindFish(); if (fish != null) { target = fish; if (fish.size > size) { state = AIState.Run; stateTime = (float)gameTime.TotalGameTime.TotalSeconds + 3 + RandomUtil.CreateFloat(0, 2); Vector2 runDir = -(target.position - position); runDir.Normalize(); dest = position + runDir * 400 * size + RandomUtil.CreatePoint(new Rectangle((int)(-200 * size), (int)(-200 * size), (int)(400 * size), (int)(400 * size))); } else { if (RandomUtil.CreateFloat(0, 1) > 0.5f) { state = AIState.Hunt; stateTime = (float)gameTime.TotalGameTime.TotalSeconds + 3 + RandomUtil.CreateFloat(0, 2); } else { state = AIState.Wander; stateTime = (float)gameTime.TotalGameTime.TotalSeconds + 4 + RandomUtil.CreateFloat(0, 2); dest = position + RandomUtil.CreatePoint(new Rectangle((int)(-200 * size), (int)(-200 * size), (int)(400 * size), (int)(400 * size))); } } } else { state = AIState.Wander; stateTime = (float)gameTime.TotalGameTime.TotalSeconds + 4 + RandomUtil.CreateFloat(0, 2); dest = position + RandomUtil.CreatePoint(new Rectangle((int)(-1000 * size), (int)(-1000 * size), (int)(2000 * size), (int)(2000 * size))); } } break;
Yeah, definitely not my prettiest bit of code, but that seems to be a theme with basic Finite State Machines when I code them. Imagine if I set up a basic framework, and did this in a custom scripting language? Quite possibly, I could reduce this into 3-4 lines of script, and easily swap out for different fish, types of fish, or even fish with different personality. When you have a really simple scripting language with which to express your ideas, then it suddenly becomes far easier to express more complex thoughts!
I think I'm going to leave it at that, there's plenty of other thing that the author of the article left out or glazed over, but I think this was one of the more important bits. Thanks for reading~
Subscribe to:
Posts (Atom)