Components w/ different timings?
I like the model of specifying
Game.TargetElapsedTime and responding to update events, but can I conrtol this on multiple components? For example, let's say that I want to randomize the weather conditions in my game. I'd like this to update every minute or so. On the other hand, some things need to update every frame (ike controller input or sprites positions).
One way to handle this would be to simply have methods likeUpdateWeather(), andUpdateSprites() and so on, and have multiple if/then blocks in my mainUpdate() code that determine whether it's time to call one of the other update methods. However, it'd be nice to offload this monitoring somehow so I could just declare in my init code how often certain components get updated.
Any ideas? Also, if I'm approaching this the wrong way let me know. Thanks! -nm
Well, this would be my first reaction. I would create my own class derived from GameComponent called something like TimeableGameComponent (or something with quite a better name that I can't think of off the top of my head :P). Then, derive the components you wish to update periodically from TimeableGameComponent rather than GameComponent. Or, even better, create a class called TriggerableGameComponent that you can configure with any triggers you wish (time, event, keyboard/gamepad, etc.). Although, now that I think about it, that may not be the best way to go.
This is where I personally believe the power of XNA lies. You can create your own reusable GameComponents like this that you can then share with the community.
Of course, another question you need to ask yourself is why you need this. For most components, the computation in Update() shouldn't be intensive enough to require. However, for those few components that are intensive (like Weathering patterns like you stated, or game AI), you could simply add code like the following:
protected override Update()
{
if (timeSinceLastUpdate >= updateFrequency)
{
// Do your thang!!
}
}
I'm just not sure if the scenario is common enough to push down into the framework. I think the best thing with the XNA framework would be to keep it light and extensible. The more functionality you push into it, the less usable it can become if not careful (and the more people have to learn to use it).
This is just my opinion though :).
How about a WeatherComponent and a SpriteManager that contains a List of Sprites, all of which are derived from TimeableGameComponent? The nice thing is that they all get called automatically by the Game's call to UpdateComponents. The SpriteManager just goes through the list of Sprite objects, calling their Update method. Piece of cake (in theory at least

).
I had wondered at this before. Is the System.Timers namespace supported on the 360? If it is, there is no reason you couldnt create a class or component that your other objects registered a callback with to be culled every X seconds. I would recommend it for things directly related to the game loop ( aka... render or update of i/o ), but for game state related functions, it could work quite well.
I like the System.Timers idea, because I'd prefer to respond to events rather than check the elapsed in each of my updateable components.
I thought that I read that anything in System namespace was available, is that true?
Maybe the Compact Framework's System namespace + some custom tidbits. I'm pretty sure it won't be the regular System namespace.
I see the System.Timers idea being potentially problematic. If you go the route of doing it via the GameComponent's Update() method, than you can guarantee what order the updates occur in. However, if using a timer, there is no guarantee. Will it be executing while (between) your other GameComponents. Will the timer actually fire _during_ the time the GameComponent's are actually drawing, etc. There is no guarantee when the event fires.
And if you're trying to alter appearance/behavior based on this, I think it might introduce subtle timing bugs that are hard to track down. And take into account that this method goes outside of the "pattern" of how GameComponents update themselves so anyone trying to use the component (even if it is yourself coming back to it six months from now) will have to learn a non-XNA-esque way of programming. IMHO, keeping within the patterns of the XNA Framework itself will help you in the long run.
Jason Olson wrote: |
I see the System.Timers idea being potentially problematic. If you go the route of doing it via the GameComponent's Update() method, than you can guarantee what order the updates occur in. However, if using a timer, there is no guarantee. Will it be executing while (between) your other GameComponents. Will the timer actually fire _during_ the time the GameComponent's are actually drawing, etc. There is no guarantee when the event fires. And if you're trying to alter appearance/behavior based on this, I think it might introduce subtle timing bugs that are hard to track down. And take into account that this method goes outside of the "pattern" of how GameComponents update themselves so anyone trying to use the component (even if it is yourself coming back to it six months from now) will have to learn a non-XNA-esque way of programming. IMHO, keeping within the patterns of the XNA Framework itself will help you in the long run. |
|
Those are very good arguments. I think you're right that it'd get pretty confusing to follow/debug. I like your TimeableComponent idea. I'm thinking that I could have a TimedGameComponents collection, and with a UpdateTimedComponents method that trolls through all of the timed components and determines which ones it calls update() on based on a component's TargetElapsedTime. Or something like that.
Jason Olson wrote: |
| protected override Update() { if (timeSinceLastUpdate >= updateFrequency) { // Do your thang!! } } |
|
This would be the usual solution I have seen.
I was bothered by this also...
IMHO, we need events to decouple the components.
You could have a CountdownTimer component that you give a time, say 1 minute and when it counts down to zero it will execute an event that you can hook into from your other game component (much like the .NET timer but one that derives its time from the Game time)
just add a property in your weather component of type CountdownTimer, link it up on the designer and implement the event raised from the CountdownTimer.
Maybe you could have a Repeat property to tell the CountdownTimer to repeat or not.
Of course you might not want to have to link components together to do this but you could also just make it an ordinary class that your components use for timing rather than making it a component itself or using inheritance just for timing.