Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

520 Good

About MagForceSeven

  • Rank

Personal Information

  • Role
  • Interests

Recent Profile Visitors

3266 profile views
  1. MagForceSeven

    Back (Provisionally)

    So, it looks like it's been a little over two years since the last time that I updated this blog. It doesn't feel that long ago, but the calendar tells no lies. I think I'll start with some general updates on what I have been up to since my last post. Or maybe it could be called my list of excuses? Probably either... or both. Finished work on the expansion to XCom 2, called War of the Chosen. There were some long hours but nothing on the order of some of the high profile crunch stories that have recently been in the news. At least for me. Was received very well by the community and that's always makes the time you put in worth it. It's already hard enough trying to work on a side project in addition to a full time job, but it doubly tough towards the end of projects. Even if there aren't longer hours, the process of finishing is always seems more exhausting than the normal day to day. Started work on my next project at Firaxis (I'll just refer to it as Project Firaxis or PF in these blogs). While others worked on a throwaway prototype, a couple of us started laying the some of the groundwork and structure that would be needed regardless of the finer details the prototype lead to. The biggest change was switching over to build it in UE4. XCom and XCom 2 were built on a modified UE3 engine (pretty common knowledge) but UE3 is getting pretty old and isn't being supported by third parties well or at all anymore. The switch isn't exactly a secret, we're actually hiring for UE4 experience right now in a couple openings (hint, hint, hint). Towards the end of '17 I was pulled off PF to work on what would be released as the Tactical Legacy Pack. It was meant to be content heavy so they didn't want many full time engineers supporting it which meant it boiled down to a UI programmer (and there was a lot of new UI) and me (doing everything else). That took over a good chunk of '18 and since it was meant for a super-short turn around we kind of went straight into 'finishing mode'. I continued to contribute the non-prototype portion of PF as much as my Legacy Pack schedule would allow since it was expected I be going back to that project eventually. As the Legacy Pack wound down I was asked to fill the spot of Lead Gameplay Engineer on PF. That's a bit of a change from Systems Programming but I've always been slightly more aligned with gameplay systems programming than what one might consider "proper" systems programming. It's been a whole lot of fun and I've felt like I've been able to have been able to shape the overall technical architecture of our game in a solid direction. The not so great part has been that almost from the start we've been having to deliver back-to-back-to-back milestones to our publisher so we've been having to settle for expedited solutions instead of solid ones. Recently we've had the breathing room to start addressing some of the debt those milestones accrued. All that brings me to what I'm working on these days. For the most part, I haven't really touched the project that I was showing off in my previous journal entries. Even as a systems guy at heart, there are places that I just don't want to have to go like rendering engines, physics, audio systems, animation, etc. For where I was in that project and the things I wanted to do those were starting to be real hurdles (especially my rendering engine). However about the time that I was really starting to feel that way some of the preliminary discussions were taking place for PF, mostly along the lines of could we shepherd along a UE3 build or did we need to jump to UE4. It became pretty clear that we did need to and that PF would be in UE4. Now, I learn best by doing and trying out things so I went ahead and downloaded UE4 at home so that I could have a test bed at home to mess around and learn about UE4 before needing that info at work. Plus it would allow me to focus much more on gameplay systems then the minutiae of supporting systems (no offense animation or graphics programmers that are out there). After a minor stumbling block with the basic download, I pulled the engine source from github and got a buildable project going. Based on my local source control, my first UE4 change was July '17 and I've been making incremental updates since then. It's still hard with a full time job, other obligations and trying to no burn myself out on programming (I hear that's a think that can happen ) so it's doesn't actually look like a project with a year and a half of changes. With that I present SRPG (Strategy Role Playing Game): You may say that looks an awfully like the game that I had been building my home-rolled engine and you'd be right. It's still the game that I basically want to be making just in a different engine. I even ported quite a bit of my code (primary dealing with the hexes) over into my UE4 project. The main difference is that instead of being a test bed of a pure component architecture that mine was, it's organized in a way much more similar to what I deal with at work (not exactly of course, but similar) so that systems and patterns that I try out at home are more easily applicable to work. It doesn't hurt that it makes it easier to apply the things I learn at work to my game either. The biggest difference between old project and SRPG is that you'll notice that SRPG actually has something that looks like a UI instead of a bunch of random display strings. Chalk that one up to for UE4 blueprints. All the icons I got from game-icons.net. It also does have a few additional gameplay features like ammo, cooldowns and obstacles that weren't in the OldVersion. I even started a separate todo file for my UE4 project(s). I think I'm getting pretty close in my tactical element that it may be time to start working on a meta element for in between tactical battles. Tactical still needs objectives, mission scripting, map scripting and (probably) a fog of war. And the map needs to be way bigger. And AI. And... And... And... so not done-done but enough that I could add another axis of gameplay.
  2. MagForceSeven

    Dell World 2018 in Las Vegas

    Lookin' good dude. Regarding looping video problems: If there is looping support on playlists but not on individual video, couldn't you make a playlist of 1 video and loop that? or, fill in whatever the minimum number of videos is in with the same movie? Another alternative: could you treat a non-looping playlist like a ring buffer? Always keep two copies of the movie in the playlist (the current and the next). When 'current' completes, remove it from the playlist, next becomes current, append a new copy that becomes next. Of course both of these assume that the playlist playback doesn't introduce black frames when switching from one movie to the next within the playlist.
  3. MagForceSeven

    Spellbound: Winter Update

    It was great to see and chat with you over the holiday and check out all your VR stuff! Very exciting! The 360 hikes sounds like something you could proof-of-concept using Google Street View data.
  4. MagForceSeven

    Spellbound: October Update

    I'm really happy to hear that you've recognized that particular trap. It's one of those tough choices that is hard for someone on the outside to convince you of and have to learn how to recognize it for yourself. Game development can easily get pulled into traps where you think you're building simulations but simulations are complicated. I think one of the best lessons I've learned is to try and recognize when the illusion of simulation is good enough. However, it is worth keeping in mind that your impetus for the machine learning was coming from a good place: reducing system maintenance and iteration time of new features. It sounds like it's worth it to continue ways to explore how to make your AI scripts in ways that don't require as much rework when you add new features. And it sounds like your writing tasks line up nicely with NaNoWriMo which just started. There are probably some great resources to help springboard your writing efforts, even if you're not planning a novel. Great update!
  5. MagForceSeven

    Spellbound: September Update

    Your description of an AI decision graph sounds a lot like Behavior Trees. Is that something that you've looked into at all? I know you're in Unreal 4, I believe it's got some form of built in support for them. Or do you see there being some core difference between the two concepts?
  6. MagForceSeven

    Principles of Debugging Effectively

    One more thing.  Like I mentioned in my original post, I tend to have to fix bugs in code that I don't know that well which usually leaves me with insufficient knowledge to form any sort of hypothesis in the first place so I have to fall back on the facts of empirical results.  So if there's a 12 failure locations I have to instrument them all because I'll have little to no systemic knowledge that allows for any sort of culling.
  7. MagForceSeven

    Principles of Debugging Effectively

      I guess my point is that when using the debugger I'm not trying to make hypotheses and test.  I'm trying to work from empirical events.  It can't be wrong because I just watched it do the thing that causes the problem (or causes the sequence of events to occur that cause the problem).  If a variable is wrong, don't hypothesize about why it's wrong, set breakpoints or other catches so that the moment that it becomes wrong you drop into the debugger to see empirical cause.  This makes the answer to the question "Why?" not a hypothesis but fact. I agree that they are related processes, but for some bugs it's faster (sometimes lots if depending on the repro steps).  For example, say that a variable is the wrong value and it's set from places A, B & C.  You could hypothesis that it's B, change B, reproduce to verify your hypothesis which may or may not be right.  Or you could trap A, B & C.  See that C, for a fact, is setting it incorrectly and fix C.  Now sometimes proper abstractions help with this.  When a is private with a Setter, you implicitly trap all change cases.  But not all code is that convenient.  Even if there are 10+ reasons, computers are great a complicated checks and when you have the source you can make all sorts of temporary local changes to catch problems that you never have to actually check in.  Trap them all! Fundamentally this is what assertions are for, proactively identifying conditions that will cause problems further along the line if allowed to persist and stopping execution or logging it so that they can be identified and fixed. In addition, hypotheses have no place in a bug report.  A bug report is an empirical report of something not functioning in the expected manner.  They may have needed to build a hypothesis to build steps they could reasonably reproduce the effect, but it's the repro steps that belong in the bug and not their working hypothesis.  The distinction can be mostly easily seen retroactively when the problem has been found and the listed repro steps include things that have no actual impact reproduction.  I've sent many bugs back to test (or onto other programmers) with modified repro steps saying that one or more of the steps are unneeded to actually reproduce the problem. I think there is a place and time for both methods of testing (and as it happens we're primarily in bug-fix mode at the office right now so this is right in the forefront of my mind).  The Scientific Method is great/useful for black-box testing (QA) and for low reproduction rate problems.  This "Mindy Method" is primarily for white-box testing (ie. when you have the source) and high repro rate issues.  It really only helps if you can cause the problem to happen repeatedly to power the "Why? Because..." loop. I'm not saying my screwdriver is better than your hammer.  I'm just saying that I've had a lot more success handling screws with a screwdriver than with a hammer.
  8. MagForceSeven

    Principles of Debugging Effectively

    I agree with a lot of that in-theory.  In practice I've found it less useful but I think that's because of working in a different environment.  Which is to say a collaborative studio environment as opposed to a one-man or small team.  The main issue is in order to come up with a hypothesis you have to have some level of understanding of how things are supposed to work so that hypothesis about potential failure points.  I've routinely gotten bugs from QA or other devs that include hypotheses of what is wrong that make no sense when you know how the system works. And I'm asked on way too many occasions to find & fix bugs in code I have only a passing familiarity with.  Definitely not enough to form a hypothesis about what is broken. For those types of bugs I've come up with the "Mindy Process", named after Mindy from the "Buttons and Mindy" segments of Animaniacs.  If you're not familiar with that character, part of her shtick was asking someone a question and then responding to every answer with "Why?"  (I swear I tried to find a video to explain it better with little luck). 1) Reproduce 2) Why are we doing that? 3) Oh, that's why.  Is that supposed to happen? 4a) No? Make it not do that 4b) Yes? Something must be wrong earlier.  Goto 2. 5) Reproduce That process looks kind of like the loop of "Why? Because... Why? Because..." that Mindy gets into. Now this mainly useful when you're able to work with a debugger and can break, step, inspect everything and watch what the program does live.  It also tends to much less useful the lower the reproduction rate is since you have to be able to stop the program when the case you care about is going wrong.
  9. MagForceSeven

    Journal #11: Combat Update

      They do a little.  I haven't made any effort in that area quite yet, partly because I'm pretty sure I need to do something drastic like swap out my whole rendering solution to something else.
  10. MagForceSeven

    Journal #11: Combat Update

    Combat In my last entry I mentioned the few things that were really remaining for my tactical gameplay. I spent the time since working on the weapons issue. I added a few more weapons definition entries and updated the ship definitions to be the owner of the weapon slots. Those slots define limitations of that weapon location on the ship like the maximum available firing arc. I also updated my prototype harness so that a bunch of the testing stuff that was in there has been removed and all that remains is stuff that should move forward as part of the tactical game. I make a copy of it first so that I still had a version with that testing stuff that I could go back to though if I need it. Seemed like a good idea to include some new pictures. The red tiles are those in the arc, a blue tile is the cursor highlight when it's within the arc and a green tile is the cursor highlight when it's outside the arc. The lower right still has the text indicating which player's turn it is and the upper right has a display string indicating the name of the arc being used. Here you can see multiple weapons & weapon selection with two different firing arcs coming from the same ship. I think I have a some technical debt to address before I move onto either of the other two tactical features I mentioned in my last post. The main one is support for STL containers in my reflection system. I need it for a few cases, but the bothersome case right now is that I can't properly initialize my ship definition weapon slots from the data file. And the temporary solution involves a const_cast which is usually an indicator you're doing something weird. Random I did a few other random things I switched all the copy constructor or assignments from private & unimplemented to public and using the "= delete" modifiers (see Readings section below) I added some macros to make it a little easier to use my function delegate object. There was a bit of type data duplication, especially when creating a pointer to a class member function. It's a lot easier to use and look at now. I added a placeholder for localization. This may sound a bit crazy, but I'm having to add a lot of to-be localized strings at work so it's at the forefront of my mind and it's one of the things the Unreal makes pretty painless to do when you're working in UnrealScript. Since I don't actually need localization quite yet the entirety of my localization header consists of: typedef std::string localized_string. This way I can at easily identify the things that are display strings and when a real solution goes in (if ever) the compiler should catch just about everything that needs to be updated for me. Readings I've had a few technical books on my desk to read for quite a while and have spent a good chunk of the new year working my way through them. They've been Effective Modern C++ and Effective STL, both by Scott Meyers, and C++ Gotchas, by Stephen Dewhurst. C++ Gotchas was a little tough sometimes because it was written in 2003 so it's pretty ancient for the tech world. It would have been a better read for me while in college and a few of the "gotchas" aren't really as big of an issue if you're using C++11 or C++14. I've only just started Effective STL but it looks like it's also pretty ancient by tech lifetimes (2001) but I've only just started it so we'll see how well it actually holds up. Effective Modern C++ was pretty great. There were a few things I knew in the back of my head from looking writeups about the new features. My home codebase is still pretty small so it's easy for me to blast in some types of language changes. I had previously already gone through my code and replaced NULL usage with nullptr. As I mentioned above, using "= delete" instead of private unimplemented functions I'm on board with (since it more clear on intent and generates a compiler error instead of a linker one), so I made that change as well. I added a couple of things to my todo list for improvements that I might be able to make to certain things using certain features. I'll probably make a pass to add the override keyword in all the appropriate places as well as start using it for all new code. While reading C++ Gotchas and Effective Modern C++, I've played around with the notion of writing up a coding style guide for my home codebase. I contributed a bit when we revamped the one at Volition to bring it into the world of C++ and it was kind of fun. It would be nice to have something like that around if I ever tried to get someone else to contribute to my projects. Random C++ Gotchas musings The "Pimpl Idiom" is also called the "Cheshire Cat Technique"?! How did I never hear this?! That is such a cooler name! The example code for the pimpl idiom was pretty standard except that the structure used as the implementation had private members and accessor functions. What is the purpose in that? You're already isolated from the client code through the private-ness of the pointer and the API of the public data structure. I seems weird to then force your own code to go through a second API for data access. Maybe it was just copy/paste. It suggested using 0 over NULL due to implementation differences in the macro. I couldn't get behind that. NULL indicates intent to the reader in a much clearer fashion. Shouldn't be an issue going forward as everyone should be using the built-in nullptr.
  11. MagForceSeven

    Journal #10: Combat

    Over the last few weeks I've made some good incremental progress on the combat in my little strategy game. 1) I added shields to both my starship class definition as well as to the starship data component. (We're in space so what fun is space combat without shields of some kind). 2) I added a new component to act as a damage interface. In other engines you might have an IDamageable that the component would be able to derive from in addition to the regular damage tree. At the moment I don't support multiple inheritance with my component definitions (I'm developing in C++ so there no real distinguishing between what you're deriving from). I'm okay with this for now. For now in my engine it's just a separate component on the entity with a delegate that can be called. I considered the more traditional derivation with a virtual function, but opted for something that involves a little less boilerplate code to do something slightly different. If I hadn't already had this delegate structure sitting around (I mentioned it in my first post as being based on the impossibly fast C++ delegates found here) I probably would have done it that way. 3) Fixed some bugs in a couple of previously unused functions and added a few new small helpers to some of my other systems that were needed in order to make all the new combat bits work the way that I wanted them to. 4) Added to my Todo list because every time a programmer writes code, they find related things they want to fix or add to. Some are technical debt, some aren't. Combat Now, I'm a huge fan of Star Trek (if you don't recognize my avatar image, that's were it's from) and I wanted my damage to have a bit of the feel I got from watching the combat of that show (mainly TNG/DS9/Voyager). To that end I want basically 3 things when it comes time to apply damage to a ship in my game. 1) Below a certain point, a weapon should do nothing. 2) Within a certain range, the shield takes the majority of the damage. 3) Above that range the shields take extra damage. Currently I'm basing that all these on the ratio of the weapons power to the shields power. So the more powerful the shield vs the weapon, the more effective the shield. For now I have it all coded, but it's hard to tell at this point the "fun" since it's all pretty garbage numbers. A few other things: 1) Each ship has 6 shield entries, one for each side of the hexagon that it's occupying. Right now they all start at the same value, but eventually I plan on that changing. 2) Some combat could apply damage to multiple shields at once. In this case (for now) it divides the damage equally among all the shields but still uses the full damage to determine the power ratio for how to apply the damage to the shield. 3) Right now once you get through the shields, the ship just has a bucket of hit points that is decremented by damage. Eventually I'd like that to be applied to ship systems and affected by armor for that hex side as well. Somewhat in the vein of Star Fleet Battles & similar games. What's Next I feel like I'm really only missing three things from my tactical combat: 1) Real/diverse weapons. Right now all my ships have the same weapon with the same stats. Plus the weapon is using the general purpose stats component (Journal #6). Neither of which is ideal. 2) Energy use model. The idea is that each ship generates points from it's various power supplies and then moving and using weapons reduces that amount. Kind of like the action points used in the original X-COM games (not the new ones by Firaxis). Right now all the ships start the turn with 2 points. The place holder weapon costs 1 and movement (to any space on the board) costs 1. Technically I do have a placeholder value in the weapon for a cost but it's set to 1. The movement should use up power proportional to distance traveled with, I think, some max travel limit that is smaller than the total power available. Obviously the number of points a ship will start out with will have to be much higher than 2, but it was a good placeholder. 3) Pathing turning limits. I have basic A* pathfinding though the hex grid already. The part that is missing is that currently a ship can basically path to where ever it wants. The models have a facing, but if they're told to move to the tile right behind them they will rotate in place and then move forward into the tile. That may be fine for some games (and possibly even fine for mine for some ship types like fighters if they get added) but I want my combat to be maneuver driven. It's meant to mesh with the shield arcs and (eventual) weapon firing arcs. I think that once I get those pieces in place I'll feel good about where the tactical game sits and I'd like to move onto an overarching strategy element that would bind all the tactical combat into a cohesive whole. Then I can go about refining the interplay between those two elements into an actual game!
  12. MagForceSeven

    Journal #9

    January has not been particularly kind to me. It started with getting sick (you always seem to pickup a bug of some kind from planes) and after getting over that I had wisdom teeth extraction to look forward to and recover from. In fact, I'm currently writing this entry on the last day of my 4 day weekend to recover from that particular adventure. Thankfully everything on that front has gone super smoothly and am doing really well. So on to the parts that everyone here is way more interesting to the folks here. I started 2017 with the decision that I wanted to move on adding elements that are more about gameplay than development utilities. As much as I like that sort of work, it's time to move onto things to actually making a game. I'll swing back to utilities for a change of pace or as needed to support gameplay. As I mentioned in Journal #6, I'm working on a tactical strategy game. I've got some basic movement supported already, so the main missing tactical element is combat. I added (for now) another stats component (also Journal #6) to act as the data for a weapon attached to the each unit. For now all the ships have the same weapon with the same values. The stats my weapons are starting out with are Range (how far it can deal damage), Power (how much damage it does) and Cost (how much of the ship's supply stat is used to use). Since I don't really have a good solution for UI, I'm outputting most feedback that would be UI updates to the standard out for now. I added to the starship data definition (Journal #7) to include the mesh information and then reordered my object construction so that given one of those definitions I could construct an object. I also swapped out the generic stats component that I was using for the ship's runtime data (health and power) with a component specific to the job of tracking starship data. Since this component was meant to have a reference to the data definition it was created from, I added support to my reflection system so that it knew about the data definition library. That way the JSON data I use can include a serialization safe string (as opposed to a doing crazy things with pointers) that the reflection system knows how to turn into a definition entry pointer. Lastly, for use on my starship component I wrote up a data structure for gameplay stats (not to be confused with the stats component) and modifiers to those stats. In a typical RPG this would be used for values like Strength or Agility or the like. The modifiers would be things applied by equipment (like +50 Str or +25%) while they are equipped. For now the modifiers only support addition and multiplication. The stat starts with a base value that is the value when there are no modifiers, then multipliers are applied and then the additions to calculate the maximum value for that stat. It also keeps track of the current value over time. So in the case of a Health stat, it's tracking your current health, maximum health, base health and all the modifiers to the base that determine what your maximum actually is. We'll see how that goes for now. New todos: - Logging: I can generate output to the debug window but it's not really a log. At some point I'll want a logging solution that can save to a file and do some basic filtering on what output is saved. - Reflection: Support for dynamic arrays. My reflection system already supports normal C arrays but to finish my gameplay stats structure it needs to support dynamic arrays (std::vector). I haven't decided yet if I'll just do support for vector or if I'll try to implement something that is more general right off the bat. - Console: I realized I forgot to include scripts in list of console todos. It's nice to be able to write up a series of console commands in a text file that you can then reference repeatedly and across multiple executions. The console I worked with at Volition supported this and it was super useful. - Strong typedef: This was something I introduced at Volition and thought I had a version of it here at home. When working in C++, typedefs are great but in a great many circumstances they just aren't typesafe enough. For this reason I wrote up (as have many others include one that is part of boost) a macro that simply wraps an instance of a type in a struct to prevent general type conversions from happening when you don't want them to. I need to find some time to recreate that in my home project. I guess I didn't need it, but I'd like to use it as part of how the stats and their modifiers interact with the clients that are applying the modifiers. New project idea: - I mentioned in my first post a tool I had been working on for the Fantasy Flight game, Descent. A campaign tracker. Well I started collecting and playing another game by Fantasy Flight called Star Wars: Armada. I think it would be very interesting to put together a tool to help keep track of things there. It could even spiral out to three tools, Fleet Construction, Combat tracker, Campaign tracker (campaign play being a thing that was just released). I'd need to work on upgrading my copy of the wxWidgets library since the one I currently have isn't compatible with the version of Visual Studio I'm currently on. Really just an idea right now. Edit: I am aware of online tools for this game in regards to Fleet Construction so it might not be the highest priority tool of the three. Well, that's it for January of 2017!
  13. MagForceSeven

    Journal #8

    Howdy GameDev.net! Welcome to 2017! It's been tough finding time over the last month, December is a tough month to carve out personal time. That's not to say I didn't get anything done, just not a whole lot in my hobby code. I was hoping to have some more time during my Christmas vacation but instead spent most of it sightseeing Seattle with my girlfriend. And I seem to have picked up a bit of a bug on our way back and writing code while sick and/or medicated is tough. The thing that I did get accomplished was a small refactor of my input code. When I had originally written it, I had included an API for working with keybindings. But since I wasn't actually using it anywhere it wasn't really battle-tested as it were. My input library included an enumeration for identifying the actions to be bound to, but that wasn't really extensible or flexible enough to be used in multiple projects without hard-coding game-specific references into the library. So I rewrote that API so that instead of mapping an enumeration to keys, I map strings to key combinations. Well not arbitrary key combinations, just a key plus some combination of alt, control and shift. As with all things programming, this worked pretty well except for one tiny detail. It turned out that (given the way I wanted to be able to write the client code) if I had two bindings, one bound to and one bound to + , then pressing the + would trigger both bindings! Imagine pressing ctrl+c to copy some text and it also added a 'c' to the document. That wouldn't do. My current solution is a priority system based on the number of modifiers. The potential downside is that when checking a particular keybinding, I also need to check all other keybindings associated with the same key and more associated modifiers. 'Potential' downside, at worst there are currently only 8 possible combinations of keys possible for any given key with modifiers. It's currently only 8 because I don't make any distinction between the left & right versions of the modifier keys. I don't expect anyone would every possibly bind all eight combinations of a key to a game command, but even in the worst case checking 8 combinations shouldn't be a big deal. Anyway, the priority mechanism means that if there is a key-binding for + and it's down, then anything bound to just won't be triggered. Similarly if ++ is down, then + won't be triggered. And this is just for active keybindings, so if the only thing bound to is without any modifiers, holding down one of the modifier keys will have zero effect on the input reporting. Here's looking forward to much new code in 2017!
  14. MagForceSeven

    Spellbound: December Update

    As a solo developer, what benefits do you get from maintaining an office?  If work that you're not doing personally is contracted out and completed remotely anyway I don't see why you would spend on something like that.  The few indie developers I've had any view into (though documentaries, not personal contact) seem to eschew that sort of cost until they have released in a way that allows for a revenue stream that actually supports those costs.  It seems like that is a relatively simple cost to remove, but maybe the realities of VR development are a large enough departure from regular software development.   Also, with respect to voice acting: you should consider looking into text to speech.  We've been using it to some degree to generate temporary assets until we got actual voice actors, but from the little that I've seen from the Windows documentation it seems like there is some good potential for independent developers like you to use it in place of actors.  And to be clear, I'm not suggesting on-the-fly text to speech as part of the shipped game.  What I am suggesting is a one-time system that allows you to output audio files that are played by the game the same as if the audio had been created by a person.  Perhaps it's not ideal, but it might be good enough so that you could delay the costs (time & money) of dealing with that.   All-in-all a great update and I'm looking forward to 2017!
  15. MagForceSeven

    Journal #7

    I hope that everyone (at least in the US) had a good holiday. I took the week off from work and while I couldn't devote the entire time to working on my hobby code I was able to get a nice chunk of something done. First I took some code that I had written for my component system and generalized it a bit so that I could reuse it. I call it an 'instantiator' and it's designed to do two things. The first is to act as an object pool, managing resource allocations and memory reuse as instances are needed and discarded. The second function is to manage some super-simple type information to allow for fast and safe type checking and casting. The instantiator comes in two flavors 'virtual' and 'concrete', the virtual instantiator just does the type stuff and acts as a kind of place holder. It also acts as the base instantiator type, defines a static public interface that the client systems go through and defines the private virtual interface that the concrete instantiators implement to do all the allocation stuff. Lastly the virtual instantiator defines a static array of instantiator pointers that it uses to route all the static API calls to the instantiator for the desired class. The concrete instantiator inherits from the virtual one picking up the type information support and implementing the virtual memory management interface. Now to support all this, the classes using the instantiator (which relies heavily on templates) have a few required members to them for things like class name strings and other static members. I've setup macros to simplify a lot of these things, but really all's that left to do is declare a type and then declare an instance of either a virtual or concrete instantiator for that type in a cpp file at file scope. The constructor for instantiator then registers itself (during pre-main construction) into the static array of instantiators. The basic gist of the implementation looks like this:class virtual_instantiator{private: // a few class identification members std::vector parenting_types; static virtual_instantiator *set[ MAX_TYPES ]; virtual type* alloc_internal( ); virtual void free_internal( type* ); // other various system virtual callspublic: static type* alloc( ); static void free( type* ); static bool is_type_of( is_type, of_type ); // static versions of the other virtual system calls virtual_instantiator( type, parent_type, classname );};class concrete_instantiator : public virtual_instantiator{private: // memory allocation stuffprotected: // implementations of virtual interfacespublic: concrete_instantiator( );}; This obviously doesn't compile. I've attached the full header to this journal entry if you're interested. During system initialization (inside main) a static function is called for the virtual_instantiator which then calls the initialization function for all the instantiator instances. One of the primary things that happens here is filling in the parenting_types vector of bools. This basically makes a copy of the bools from the instantiator for the parent type and then sets the bool for the current type. Then anytime that I want to know if one type is part of another's tree it's just a bit check. As part of the instance allocation, I also store the most derived type into a variable of the instance so that I know what it was allocated as. Some limitations: it only supports single inheritance and it's currently limited to an unsigned short (65535) worth of different types. Other than that the tree of classes can be as deep or as wide as I want it to be. The single inheritance limitation doesn't bother me personally and 65K of types seems more than enough for one game (since any game specific type ids could be used for different types in different projects). Now, I had originally written this whole setup pretty specifically for the creation and management of components and it was working quite well. But I decided that I would also like it to manage my data driven type definitions, things like class or weapon stats. So I refactored what I already had a bit (mostly adding more templates) so that my components and data definitions used the same code but used different instances of the static instantiator array. This refactored version is what is attached to this journal. I was also pleased that for the most part this worked out relatively painlessly. I did have to do some looking up of more recent C++ template features to get a couple things working the way I wanted in other headers but learning that stuff is one of the reasons I want to make an effort on this hobby code. The main effort of my holiday coding was actually writing up the code for my data definitions types. This code consists of two parts, the data_definitions base class and a class I named definition_library. The data_definition class was mostly a bit of copy/paste from the component class; all the bits and pieces that are required to interact with the instantiator and the macro for declaring derived types. The definition_library wraps up access to the instantiator (forcing an additional construction requirement), handles parsing of certain json files into data_definition instances and manages a mapping of string names to the data definitions (the name being the additional construction requirement). The main thing I decided I wanted to really enforce is that when accessing any of the definitions that have already been created, was that they should be const. If you create an instance at runtime, the creation interface does return a non-const instance, but once you let that go and get it by name through the library, the only way to do it will give you const data. My reasoning behind this is that the definition structures are intended as application-static data. Once the game is running and has loaded up that data it should be treated as unchanging. Now for purposes of development it probably makes sense that I can tweak some of those numbers at runtime. For now, that task has been relegated to my todo list. I'll always have the option of making type specific console commands for the definitions that I specifically want to be able to tweak, but I think I'd like to find a way to leverage my reflection system to write a single console command as part of the definition library that can modify any member of any type. Lastly, once I had all that setup I built my initial test case of a type that actually derived from data_definition and had instances that were created when a file was loaded. Continuing the theme of game design I'm working through, the data definition was the start of information about ship classes. Right now it just has a hull class (cruiser, battleship, etc) and an optional modifier (command, missile, escort). Happy to answer any questions about anything in this writeup. I know I probably touched nerves of a few people mentioning components and/or reflection without going into a whole lot of detail. I do plan to do a journal about them at some point, so you can look forward to that. Probably save that for a week when I don't have a chance to write much code or make a major addition to them.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!