So, I didn't quite make "tomorrow" with this post, but better late than never. I've actually decided that the Blender physics engine is not predictable enough for what I need to do, and I've decided to try using some of the great gaming libraries available for C# to roll my own. I have a bunch of Blender tips I still want to get out, though, so I'll keep posting stuff here for a while.
A lot of head scratching has led to a number of Blender realizations. First is that I discovered the Blender API reference
here, and it took me quite a while to realize that the GameLogic API, which you need to do anything related to the sensors and actuators, is
here. In a completely separate page. Wish I had caught that one a litte earlier.
I spent a long time poking around trying to find example of mouse input in a Blender game, but came up largely empty handed. I found
this tutorial, and
this thread which convinced me that Blender could handle things of the complexity I was shooting for. That was nice, but I still didn't understand exactly how to get scripts to run, say, once. I could get them to run "always" but not once, when the game starts up.
It turns out, you really can't. Or at least, you don't. You just let scripts run "always" and then cross your fingers that things run smoothly enough. You could try to use global variables to get things to run once, but global variables don't persist across "frames" of "always".
In fact, there is only one way to get global variables to work in the game engine that I found. You need to store them in the GameLogic object, which persists. Like so:
GameLogic.yourvar = "your value"
Unfortunately, if you put a statement like that in your "always" script, it'll run over and over, re-initializing your variable in every frame. And it's not exactly a "variable" if it stays constant now, is it?
So, you'd think you could do something like:
if not GameLogic.yourvar:
GameLogic.yourvar = "your value"
But that doesn't work either. You get an error when you try to use GameLogic.yourvar without initializing it. What you have to do instead is a little more circuitous:
try:
GameLogic.yourvar
except AttributeError:
GameLogic.yourvar = None
if not GameLogic.yourvar == None:
GameLogic.yourvar = "your value"
And that, my friend, is the way you get some code to run once, and only once. You set a global variable called runonce, in the method explained above, and then if it's unset you run your code.
What a hack. Now you can see why I wanted to bail out of Blender.