C++ Game Initialization and Game Loop
by Smaug · in Torque Game Builder · 04/11/2005 (1:51 pm) · 3 replies
So, yesterday, I went through the process of creating an alternate implementation of GameInterface (as opposed to the DemoGame one). It bypasses any script loading; I can tell because it fails to spawn even a window ;).
The next step would (and will) logically be to re-implement at least some portion of the tutorial through this interface. This means, effectively, replicating the code that main.cs uses.
This is all well and good of course. However, I would like to provide a quick overview of some of the code I had to push around in order to make this possible, and offer suggestions to the developers on ways to improve this process in the future.
The initialization and game loop code is a combination of good object-oriented practice and some of the worst C-style programming imaginable. Obviously, this code hasn't been really touched (aka: cleaned up) in a while, and it shows. But, I've seen far worse startup code; this kind of code has the tendency to be touched only when there is a problem, and these kinds of problems tend to only manifest themselves 1 hour or so before you need to make a shipment burn. As such, it tends to be layer upon layer of quick hacks.
Functions like "initGame", "initLibraries", and their respective shutdown functions are these file static functions, while GameInterface exists as a perfect way to allow them to be virtual members of a class that can be overriden at the user's request. At the very least, some of these should be functions declared in a header file somewhere, so that the user can call them when needed. The "preamble" to initGame(), for example (the stuff that happens before trying to run the scripts) should be in a function somewhere. That way, we can pick and choose which functionality to override.
I would suggest that GameInterface (the base class) be where these functions go. This allows these functions to be virtual, and allows us to use pieces of those virtual functions while still being able to override specific behavior.
As for the particulars of what I did, I just basically copied DemoGame out into a separate file, tracked down all of the implementations of DemoGame (spread across 3 .cc files), and coped a few of the initialization/shutdown functions (and externed others) as needed in order to make the code run. Then, I just took out the section of code in initGame() that would call the script. I abstracted this into its own function (member of my new GameInterface-derived class), and I currently have it doing nothing.
The next step would (and will) logically be to re-implement at least some portion of the tutorial through this interface. This means, effectively, replicating the code that main.cs uses.
This is all well and good of course. However, I would like to provide a quick overview of some of the code I had to push around in order to make this possible, and offer suggestions to the developers on ways to improve this process in the future.
The initialization and game loop code is a combination of good object-oriented practice and some of the worst C-style programming imaginable. Obviously, this code hasn't been really touched (aka: cleaned up) in a while, and it shows. But, I've seen far worse startup code; this kind of code has the tendency to be touched only when there is a problem, and these kinds of problems tend to only manifest themselves 1 hour or so before you need to make a shipment burn. As such, it tends to be layer upon layer of quick hacks.
Functions like "initGame", "initLibraries", and their respective shutdown functions are these file static functions, while GameInterface exists as a perfect way to allow them to be virtual members of a class that can be overriden at the user's request. At the very least, some of these should be functions declared in a header file somewhere, so that the user can call them when needed. The "preamble" to initGame(), for example (the stuff that happens before trying to run the scripts) should be in a function somewhere. That way, we can pick and choose which functionality to override.
I would suggest that GameInterface (the base class) be where these functions go. This allows these functions to be virtual, and allows us to use pieces of those virtual functions while still being able to override specific behavior.
As for the particulars of what I did, I just basically copied DemoGame out into a separate file, tracked down all of the implementations of DemoGame (spread across 3 .cc files), and coped a few of the initialization/shutdown functions (and externed others) as needed in order to make the code run. Then, I just took out the section of code in initGame() that would call the script. I abstracted this into its own function (member of my new GameInterface-derived class), and I currently have it doing nothing.
#2
That being said, I've been able to make nearly all of my changes simply by adding code to a new C++ source file -- not bad. The problem is that I need to register a callback that is executed when the initialization is complete, and I can't find a way to do that without modifying main.cc. It isn't a difficult change, but modifications are more awkward to maintain than extensions.
05/26/2005 (5:21 pm)
For what it's worth, I'm strongly in favour in Smaug's proposed changes. Extending T2D is a bit frustrating, because the code for the game initialization/loop lacks "seams" (a nice metaphor coined by Michael Feathers, author of "Working Effectively With Legacy Code").That being said, I've been able to make nearly all of my changes simply by adding code to a new C++ source file -- not bad. The problem is that I need to register a callback that is executed when the initialization is complete, and I can't find a way to do that without modifying main.cc. It isn't a difficult change, but modifications are more awkward to maintain than extensions.
#3
I am also messing around in the initialisation code at the moment. It would be nice if you could share your code and any useful information about the source. It seems lacking in 'in-code' comments.
03/29/2006 (2:33 am)
Hi,I am also messing around in the initialisation code at the moment. It would be nice if you could share your code and any useful information about the source. It seems lacking in 'in-code' comments.
Torque Owner Josh Williams
Default Studio Name
We won't change this in T2D unless it changes in the core Torque project, and changing it in core Torque wouldn't be a super-high priority right now. But you are doing a good job figuring out the initialization stuff, and if you wanted to pass along on the changes you're making here, Ben and I would certainly take a look and see if it'd be worth the time to put them in the core engine. :)