Saturday, December 27, 2014
Got tired of being sick. We all know what happens when unused code potential energy becomes greater than resistance induced by sickness
Turret Camera
While working on handling today, I remembered how cool the 'turret' cam was in Freelancer. Would sure be nice to control turrets individually when you want to, especially when you've got a big ship set on autopilot and want to have some fun while you head towards your destination. Or, you know, when the tie fighters are coming in too fast ("great kid, don't get cocky!") So I implemented a hardpoint camera. Two buttons cycle between camera positions on your ship. In the future it can be easily extended to include rear / side / top / bottom / whatever views. But right now the point is already achieved: I can "jump in" to a turret and start shooting
Fun. Also fun doing this with a transfer unit ("
real men mine with their gloves on the transfer unit control switches, not at some pansy ship control panel!")
Dynamic Dispatch in LTSL
Still haven't been able to push forward with text generation as I would have liked. Decided that I need to do more than just a grammar, and that I would rather structure it all using real classes as the 'objects' in the grammar rather than just strings. This way, I can have
functions deciding how to produce a given element of the grammar, which answers the questions posed previously about how we will take certain things into account to make the text natural. With arbitrary functions, we can, of course, make the actual rules of the grammar as fancy as we like to provide convincing results.
The problem? Now we're getting into some
heavy programming territory in LTSL. In particular, the 'right' way to handle this would be through virtual functions. Oh boy. Now listen, I've thought about it before during my usual ruminations on
that which could be. I'm not afraid of base classes and virtual tables and such, and I'm sure that, given a day or two, we could have them working in LTSL. But today, I just wanted to work on my text generator, not get lost in some technical feat. That's when it occurred to me that there was
another way to achieve this, one that would take me about 30 minutes to implement
30 minutes later, LTSL supports
dynamic dispatch! What this means is that we can make a function call on an object that will not be resolved until run-time, because we don't know what type of object it is. In particular, using the 'Data' type in LTSL (which is a type-erased piece of data, meaning it can hold anything), we can perform a dynamic dispatch like such: (call myVar MyFunction arg1 arg2 ...). Simple! The function gets resolved based on the type of 'myVar' at run-time. Voila, we now have a way of making all this work! The 'phrases' of a grammar no longer need to have a base class, they just need to expose a common function ('ProduceText,' for example), and then we can store them in 'Data's and use dynamic dispatch to call said function. Easy!
But hold on, did we just cheat? How can we achieve the same thing that virtualism achieves without any mention of base classes or virtual functions or vtables? Well, I'll give the short answer, which comprises two pieces: first, we lose compile-time error checking. Second, we lose (some) performance. If a dynamic dispatch fails, it's likely going to fail at
run-time because it can't resolve the function. Contrast this to virtual functions, for example, which can be type-checked at compile-time even though they're resolved at run-time. On the performance end, looking up the function in this type of dynamic dispatch is marginally more expensive than grabbing it out of a known offset in the vtable (as in the C++ implementation). Thing is, I'm not using this in a performance-critical piece of code. I'm using it to for one-shot text generations based on a grammar. The performance overhead is going to be completely negligible in this case
HUD & Reticle
That wasn't all for the day, though! I continued to work on the HUD. I replaced the left/right velocity bars of the reticle with a single velocity bar on the left, and introduced a single integrity (health) bar on the right. I've debated for a long time where health should be shown, but, ultimately, I just don't see why we wouldn't put that front-and-center as part of the reticle. It's still minimal, unobtrusive, but super-fast to check health status. In other HUD news, I have now official finished porting the HUD over from C++. The last remaining piece was handling target leading & automatic aiming. This has all been implemented in LTSL now, so the LTSL HUD is now capable of computing / drawing target leads and performing automatic aiming. Great
---
Anddd that's what happens when you try to keep the code suppressed! It doesn't work
Gotta leave now to head back to the coding cave. Looking forward to some long, long nights here soon. Please pray for me or do your tribal dances or burn incense or whatever, because I
really don't want to have a flat tire when I pull in tonight (or worse, while I'm on the road
)