Jump to content
  • Advertisement
Sign in to follow this  
  • entries
    19
  • comments
    10
  • views
    11167

About this blog

Hobby Motivation for the Professional Programmer

Entries in this blog

 

September Update

Recap For September I wanted to 1) hook up my UI to make actual state changes in the game and 2) add a UI for active projects. Results I'd say things went great! I actually got the UI hooked up relatively quickly and was able to take a lot of time for the projects. I even got a little further and was able to add a passage of time that allows for actually completing projects as well.   Here you can see the three new UI elements of my strategy layer game mode: The Shipyard button to the upper-ish left, the Time UI on the lower left and the Projects scroll bar to the lower right. The Marketplace still has all the instantaneous transactions that can be used to trade resources back and forth. The starting "Stardate" of 413469 doesn't really mean anything, it was just a random 6-digit number.   Here's the Projects UI after accessing the Shipyard and selecting to build a Battleship, Cruiser, Destroyer and Frigate. You'll notice that some of the resources have changed too indicating that resources were spent to queue up those construction projects. The first number after the project is the total days until completion (project time plus preceding queue time), the next is the individual project time. The next three grey boxes are the queue controls (from left to right) move up, move down and cancel. I wasn't motivated enough to find art for them right at the moment.   The Destroyer project used to be the third priority, now it's number two (using the 'move up' button). You can see that both the Destroyer's and Cruiser's total time to completion have been updated to reflect the new priority order.   The Destroyer project is now the number one priority (this time using the 'move down' button on the Battleship project). Again, the total time to completion for the re-ordered projects has been updated.   The Cruiser project was canceled and the total completion time for the later project (Construct Frigate) has had it's completion time updated.   This is after passing three days, Stardate 413472. The Destroyer project has been removed and the Battleship project only has 1 day removed from it's remaining time. At this point if you opened up the Launch Mission or Configure ships UI's, there would be a three Destroyer class ships (two starting ships and the one constructed by the project). Trust me   I hit a few technical debt things, but nothing from my backlog. Just things directly related to what I was doing with the UI for the projects work. I also did an interesting (to me) shift of some code from one class to another (related) class. This was a bit of an experiment to see what the code would look like with this change. My game state is stored in a pretty similar way to my project at work and wanted to see if moving this API would improve the use and reliability of the code. I think it does so I committed the change to my project and started a side project at work of a similar refactor. October Goals It's time to move onto something not transaction related, three months is a long time to be working on the same feature even if it is only part-time. It would be nice if I could keep it to two, one for gameplay and one for UI (at least when dealing with strategy systems). If I could get all the gameplay and UI done in a single month that'd be cool but I'm trying my best to set myself up for working on this project when I'm not feeling up to it. Don't want to burn out on development. My main goal is to work on a Strategy Map. My vision is basically a graph where the star systems are the nodes and the edges are the valid transits between them, something like: The real UI should obviously look a bit better, but it should give you an idea. I laid some groundwork for this last month, so I have state and definitions available for the Star Systems and Routes. I also stubbed in classes that will be used as the bases for my tactical and strategy map generators. Most of this sprint should be implementing a first (fairly trivial) strategy map generator and building a UI to display the state data I've already defined. Games I'm Playing Still playing Fate/Grand Order and Fire Emblem. My second playthrough has been interesting if a little boring.  The first half of the game appears to be more or less identical regardless of the house that you're playing so that's a little boring. Plus everyone is way over-leveled because I can do way more extra battles than I could in the first go-around. I just got past the time skip so I'm hoping the story diverges a bit more from here on out. Both my Blue Lions playthrough and this Golden Deer playthrough have been Normal/Casual. I'll probably jump right to Madding/Casual for the last two story lines when I play them.

MagForceSeven

MagForceSeven

 

August Update

Recap For August I wanted to finish up with transactions, building a UI that could execute the system I built in July. Results Again I did okay. With a little tip from one of the UI engineers at work I was able to get my widgets working for a UI that can display and trigger a transaction. The part I didn't get to was the actual execution of the transaction to change the state of my game. Here you can see the new button (on the left) I added for accessing the "Marketplace" and the UI element (on the right) I added to show the current resource counts available to the player. Here's the screen for the Marketplace. I went for transactions that would create new ships instead of resource exchanges. You can even see the last transaction is a project that requires a duration to complete. The unreadable little box is the tool tip for the button to activate the transaction. And the final screen has the debug text that I currently have showing up when the button is clicked. The name of the transaction is included in the string as "proof" that the all the relevant data is being routed to the right places for eventual activation. I also addressed a couple technical debt issues: I removed a few direct dependencies between the system that deal with the tile location of the cursor, the system that tracks the current selection, the system that deals with targeting and the system that deals with the turn order. Instead those functions route through my custom event manager. Added some validation to my event manager events so that the manager can handle invalid events systemically and not pass those events on to the systems listening for those events. New Design Spec I also wanted to get out in front of a design problem that I know I'm going to have. I currently expect to have some limited number of spots per mission for ships to send on a mission, but I don't really want it to devolve to "take my X-biggest ships" every time. What I've more or less settled on is a two-fold system for limiting ship deployments. The first is a limiter based on ship sizes, I'm calling it "tonnage" for now. Each ship will have a tonnage ranking (based mostly on size) and the total for all the ships taken on the mission must be below the tonnage limit for the mission. Hopefully this will encourage including a few smaller ships on missions instead of just a couple big ships. There will probably be a few ways to upgrade this limit, but they will be very few and it will vary primarily on the mission type/location. The second limiter would be a more traditional unit count limit. This limiter is meant to represent command and control systems and the effectiveness of actually controlling lots of ships. This limit will be more constant, usually the same for most missions, but will have ways to upgrade it globally or even based on the equipment of the ships taken on the mission. I'll keep thinking about it for a while, I've got a couple more parts to add to tactical before I start working on an implementation. I'm happy to hear any thoughts or comments that might make this better. September Goals The next step is finishing up the wiring of the UI to my other systems so that pressing the buttons actually does something (other than printing to the screen). I'll also need a new UI element that shows the active projects created through a transaction screen. I'll also continue to address small tasks from my technical debt list. Games I'm Playing Picked up the new Fire Emblem at the end of July and have spent a good chunk of time playing (the save says ~120hrs ). Finished one of the 4 story lines (Blue Lions) and have started up my second playthrough (Golden Deer this time). Should be faster, they've got an interesting NewGame+ system that lets you pull progress from previous playthroughs. It's a pretty good game and I highly recommend it. My only real complaints are the class system can be a little bit unbalanced and the way they've shifted the weapon triangle into skills feels really off.

MagForceSeven

MagForceSeven

 

July Update

Slow, but steady seems to be the name of the game. Recap In July I wanted to finish up with my transaction system. Results I did okay. I was hoping to at least get started on the UI side of things but just didn't have the time. I did finish all the initial gameplay elements that I'll need but that's about it. Since I didn't do any new UI, there aren't any pretty pictures so instead I'll discuss the transaction system that I put together. I actually started by spending some time taking a look at the Actions/Weapon definitions that I already have and use for the actions you can take in Tactical. In a lot of ways the transactions are analogous as the actions that you can take during the Strategic portion of the game. So it seemed appropriate that maybe there was something that could be shared between the two. In the end I decided against it. There's a fundamental difference between the two (at least when I was considering it), and that is state. Weapon definitions have accompanying state for remembering ammo counts or cooldowns or any other gameplay element. Transactions shouldn't. They will modify state for sure, like how much of a resource you have, but they themselves are just kind of fire-and-forget. With that decision out of the way I started on setting up the actual transaction definition. The transactions are meant to be pretty simple so it's basically just a set of inputs and a set of outputs.  Unreal has a pretty interesting mechanism available for member of asset types called instancing that allows having object pointers that can be configured in data to create an instance of a selected type. Then you can setup that type so that you can also edit the instance as part of that asset as well. Where this comes in with transactions is that those sets of inputs or outputs can be sets of a base type (which defines the basic API for an input or output), mark them up to be treated as instanced and bam! to add a new input or output type you just have to derive off the right type and you can plug it into any existing transaction. The other nifty thing is that since it's all reflection powered I can have the transaction code "live" in my StrategyTech plugin and define all the concrete versions of the inputs and outputs in the game plugin.  This isn't the first time I'm doing this, the weapons work pretty similarly for the things that they can do to mutate the state of the game, but it is a pattern that works pretty well given the way the Unreal engine is setup. I also wanted to setup up transactions that had a little state, but only after you executed them (in contrast to weapons that have state all the time). I called these Projects and they are transactions that have a temporal element. I thought about making time just another input type, but couldn't make that work since it could impact how every other input/output of the transaction has to work. So instead I made a derived type of transaction and overrode a few functions. It also meant that I built in to the input/output types the possibility of multi-step execution. They each support a Start (for when the transaction is executed), a Refund (if the project is cancelled) and a Finalize (when it becomes no longer possible to refund). There's also a helper that calls Start immediately followed by Finalize, this is what the base transactions do since there's not supposed to be any opportunity to refund them. Lastly there's a class of objects created by the inputs and outputs that act as receipts of a sort to track what the parameter actually did that can be used by Refund or even by a UI. These classes aren't quite one-to-one with the input/output classes but pretty close. They are shared by the same inputs and output types that manipulate the same type of data. So, while there are separate classes for using a Resource as an input vs using a Resource as an output, both classes can use the same receipt type. This becomes more important when the input or output relates to information that you can't easily rebuild just by looking at the static transaction data. For example, I already made an output type that can be used for spaceship construction.  The output type can't hold onto any sort of reference to it (since it's static/const). So the receipt type does that. I also did a few of the issues from my technical debt backlog. Not many, but they a lot of small things that I can work on during the week without feeling to burdened by work or what needs to be going on at home. August Sprint More transactions, but this time I'll be working on the UI and actually executing the transactions. I'll need to make a few test transactions so that'll probably be super simple, 1:1 resource conversion options. I'll also add something really simple to allow completion of projects since I don't have an actual "passage of time" mechanic yet. Games I'm Playing Fate Grand Order as always. Picked up Fire Emblem: Three Houses and it is a blast. I'm a little worried that the narrative is a little too "on rails" with no way to delay the next story mission if you need to grind out some experience or money. It hasn't been a problem so far, but I've delayed story progression in previous ones, so we'll have to see.
 

June Update

Welcome back! So my June "sprint" (I guess that's what we'll call these) went pretty well goal wise. I may have under-shot for the month, but it's tough when you can't be exactly sure how much time you will have devote to your project. Recap My main goals for June were to be able to select ships to take into combat and to be able to select the weapons that a ship had equipped/installed. A stretch goal was to get rolling on a back end that could support crafting, building and other similar resource transactions. Results UI Goals I was able to accomplish my main goals and worked on a couple UI screens that allow doing those selections and causing game state changes that propagate into tactical and back to strategy. Here you can see just the basic strategy layer screen (which isn't really that impressive with only a couple buttons). Here you can see the starship loadout screen where you can select different ships and then choose the weapons in each slot. The ideal goal would be something more like the paper doll kind of UI's in more traditional RPG's, but that's probably a ways off. Here's the starship selection screen with some ships selected. Once all the spots are filled, the Deploy button becomes enabled which will load into the tactical map. Overall I'm happy with the way these turned out for now. I did run into one annoying bit with UE4 UI. I posted about it here, but didn't really get any traction. The fundamental issue was that I made a new widget type for those drop downs (basically a version of UE4's combo box, but that can store some user data along with each entry). Now, UE4 has two fundamental basis for UI elements Widget and UserWidget. The problem I was having is that I wanted my new type to work in ways that neither base is allowed to completely work on it's own. Widgets are self-contained (contain no sub-Widgets1) and are placeable from the UI Designer. However Widgets cannot be created and added to a UI dynamically, for that you need a UserWidget. Since my version of a drop down started out as basically a copy of the UE4 combo box, it was a widget. Once I encountered the limitation on dynamic creation, I figured what the heck and changed mine to derive from UserWidget instead. With that I was able to do the fleet selection UI and was happy. Later I ran into a problem that when building the loadout UI because I wanted to place my drop down directly in the Designer and it turned out I couldn't place one for some reason. I really thought I was going to have to do some crazy and annoying things to make everything work the way I wanted (which I lay out in my help post I link to), but while talking through the problem with a guy at work I realized that I was able to place other UserWidgets through the designer and it turns out that while native UserWidgets can't be place in the Designer, blueprint ones can. So I left my drop down a UserWidget and created a blueprint of the class that acts only as a way to interact with the designer. Another outcome of that talk was that I probably shouldn't have even bothered with my drop down and instead used one of the other built in UI widgets, the List View. I looked into it a little bit and it does look like it might be a better solution but for now I've just added a note in my project's backlog (ie a text document). Other Goals I got started on the whole transaction back end by creating definition types and test data for resources that will be used as the main kind of inputs to the system, but that's about as far as I got. Unplanned Accomplishments I was able to finish the UI changes about halfway through the month so I ended up letting myself get a little distracted by some other things. While working up the resource definitions, I wanted them to show up better in the UE4 Content Browser and since we've done it at work I knew it wasn't a big deal. The piece that was missing was that none of my plugins had been setup yet to support an editor module. UE4 has a pretty robust runtime linking system for separating libraries from each other as well as separating parts of libraries that should only be loaded certain kinds of builds (like things that can only be loaded when there's an editor running). I've been running on 4.19 for a while so I upgraded to 4.22. Since I'm using a source build this took a bit to rebuild the engine plugins, but it's not a big deal. In theory I could probably even switch back to a precompiled engine version since the one engine change I've made I didn't even port from my 4.19 depot to my 4.22 depot. It's a change that's been obsoleted by a system change that I made improving how I handle my custom event data passing. For now though it's nice knowing it's there even if only for reference. Turns out 4.22 can't be run on Visual Studio 2015, so I also need to update my copy of Visual Studio Community. I went ahead and just jumped right up to 2019. I haven't been as good as I want to be with commenting. I'm pretty good about writing implementations that are pretty small and self documenting, but I find it helps to have more comments in headers for member and method declarations. So I opened up all my source files and improved the commenting in most of them2, a lot were actually pretty good and didn't require anything new. This also gave me a chance to step back and look at some of the code more holistically and reconsider implementations that may have made sense at the time but might no longer be ideal given other support systems and structures that have been written in the meantime. Things like when my custom event handler could be a better option than the UE4 delegates. A couple of things I just cleaned up right then but mostly I added a lot of things to my backlog as technical debt work looking at fixing. Most of them are small items that will be good if I have a short time available to spend, but none of them actively inhibit my ability to move forward on any gameplay feature. July Sprint This month is going to be tricky. A four day weekend, two weekends of trips with my girlfriend, one weekend of a my girlfriend ditching me for her own trip, some house guests and other general summertime activities. Generally I plan to pick back up on the transaction/recipe system. I expect I should be able to finish the gamplay part but may not finish with the UI. I will also probably address a couple (or a few) of the technical debt items that I found, but I'm going to do my best to not let that list distract me too much. Games I'm Playing Really just Fate Grand Order this month. I may have played a mission from Fire Emblem. I'm really looking forward to the new Fire Emblem coming out on Switch at the end of the month and it comes out just in time that I might have a chance to play it on a road trip that weekend. Footnotes Wigets here refer only to the UWidgets class. Unreal also has another set of UI widget types for Slate. Usually a UWidget is implemented as some collection of Slate Widgets. However my point here is that a UWidget does not contain other UWidgets, that's the purpose of UserWidget. At least as far as I have been led to understand. Besides the main SRPG project, I've got two plugins StrategyTech (stuff I could make another strategy game with) and CoreTech (stuff I could use for making any sort of game). SRPG currently has 141 source files and 80 asset files (blueprints and textures), StrategyTech has 162 and CoreTech has 18 files. That feels like a lot, but they're all pretty small. I was also going to give some other stats, but in Visual Studio I can't find any built in analytics for C++. Let me know if you have any recommendations (they don't have to be Visual Studio integrated ones).
 

May Update

Hello again! Let's keep this train rolling, though I don't have anything to fancy to discuss. The month was pretty mixed with some travel, some busy weekends, and some time when my girlfriend out of town. Update If you recall from the April Update, my next goal was the basis of a strategy layer that would bind together the string of tactical battles. I didn't quite get as far as I was hoping when writing my last update, but I got pretty close. The only part that I'm really missing is the ability to make choices in strategy that are reflected in tactical. The structure is there though with respect to data being filled out as part of strategy and passed through to initialize the tactical setup. It just happens to be hard-coded instead of being hooked up to a UI. No pictures this time since the only addition is a screen with a single button that launches into the tactical map I've already shown. So the goals for June (that seems the best way to go about these right now) are 1) finish up the strategy-tactical loop by adding the ability to select which ships are going into combat and 2) adding a UI that allows modifying the weapon selection on a specific ship. A stretch goal would be getting started on a transaction or recipe Definition that would be basis for (primarily) strategy actions that transform one set resources into some other resource as part of buying, building or crafting things. Games I'm Playing Fate/Grand Order - always Steam World Quest - finished Battletech - not much time to make any progress here Fire Emblem Fates - this is the one from 2015, but I never did finish it. But when you've got 6 hours to kill on a plane with no power outlets (stupid Southwest) you play what you have charged batteries.
 

April Update

My friend @slayemin made a good suggestion after my last journal post which was to be sure to post on a regular schedule. Seems obvious, but sometimes someone's got to say the obvious thing. I'm hoping to keep on a monthly schedule at this point, I even planned to have this posted last weekend but had a technical snafu and had to re-write almost all of it. I think that gives me enough time to make some sort of share-able progress. Personally it's always been a little frustrating how much (or little) I can get done on a hobby project. I probably could have done this whole month's worth of work in a few days, maybe a week, if I were working full-time. There isn't really anything to be done about it, for a hobby project I have to be happy with what I can accomplish in the time I have available. Burnout is potentially a real issue, but it's a nice change to work on a project where I can decide and execute. No consensus, no meetings, just work. Asset Mangement UE4 has a pretty slick asset management tool available call the AssetManager (introduced in 4.17 I believe) that does a lot of really great things but it also has a couple really annoying features. The first is that it treats asset types (which exist as normal UE4 C++ classes) differently than the rest of the engine treats types. For example if you were to ask the engine to iterate all Equipment, you'd visit all the Weapons and Armor in the game, but if you ask the AssetManager for all the Equipment it's loaded it will only give you back assets that are the exact type match. The other is that because of this you have to add an ini setting for every asset type you want the AssetManager to support. Now these are really only an issue because basically every one of my assets right now derive from a single type that I call DataDefinition. A DataDefinition is a pretty classic Flyweight pattern and is the shared static data that all versions of the same object would have. On X2 they were called Templates, at Volition they were called Infos, but everyone seems to have their own version. Mine also act as a sort of factory for game objects, but that's a discussion for another blog. The Definition was an asset so that all the derived types would be able to leverage the AssetManager to do the bulk of asset management for them, unfortunately the interface the AssetManager provides isn't how I want to access my Definitions.
As with most of the UE4 engine types, the AssetManager is designed to be derived from and extended. So I had previously done that and added a whole new API for dealing with Definitions. After having loaded all the definitions at startup (more on that later) I keep track of them in my own maps so that I query them based on classes and get the instances back that I expect (like all the Weapon and Armor when I ask for Equipment). I also made my Definition API only provide access to const instances because the whole point of the static data is that it shouldn't be getting changed during run-time (they're still plenty editable by a user in the Editor though). That basically solved my first issue with the AssetManager. The thing that I did this month was attempt to fix my other issue with the AssetManager which was the ini configuration for each type that was derived from DataDefinition. I was basically able to hook into the AssetManager before it looks for assets and update the list programatically by going through the UE4 reflection to add entries for every class that is a child of DataDefinition but didn't' have an entry already specified in the ini file. For those that were missing, I looked for the nearest parent type that was included. This way I can just have a config setting for DataDefinition for now, but if I add a type that should live someplace else, I could add a specific entry for that type only when I need it and not as boilerplate when adding any type that derives from DataDefinition. I was pretty happy with it and so reimplemented it at work since we've already had a number of bugs caused by missing ini entries. Definition Loading You may think it's crazy to load all my DataDefinitions at the start of the game, but that's the beauty of them being assets within the AssetManager. Firstly, it really helps with game play to have the full breadth of game options available all the time even if there isn't an instance running around the world. Secondly the Definitions themselves are small, almost tiny, and all of the really heavy data like textures or models or sounds are other assets that aren't immediately loaded. Plasma Weapon Most of what I've been working on this month has been a new weapon currently being called a Plasma Bolt. I designed it to require quite a few specific elements I wanted to include support for: The Plasma Bolt requires no energy to fire (already supported) but does require ammo (already supported) Plasma Bolt ammo starts at zero (already supported) Includes a supporting action that allows spending energy to create Plasma Bolt ammo Damage increases for additional ammo above the minimum requirement to fire the weapon Damage decreases based on distance between the source and target Firing the Plasma Bolt uses up all the ammo the weapon has I ended up working my way up from the bottom of the list. Adding a toggle to the ammo feature was trivial. It was also pretty quick to add the two damage modifiers. I wrote a nifty structure of int/float pairs that can be used to calculate a value. One form of calculation is a just a linear interpolation of the input in-between the int's to generate a value between the floats, this is the version I currently use for the damage reduction by range. The other version uses the same data but for every multiple of an int in the value it adds that multiple of the float as the output. It starts at the high values and works backwards so that it will use an entry for 5 before using the 1 entry 5 times. The biggest change was for the supporting action. I already had a weapon definition that included a lot of what an action would have to have: various display elements, cost handling, game state mutation, etc. But there was also an awful lot that I didn't really need like everything related to targeting. The game play changes were again pretty easy and straight forward, it was the UI that took me a while. I had already made a button that could be used with a weapon and display the icon and stat values, but now a weapon should actually be a collection of those buttons, one for the weapon and a few for it's supporting actions. That took awhile to restructure to having an action button and a weapon button that contained action buttons and showed a hide them based on hover events. The most annoying bit I ran into was that apparently you don't get hover events from disabled buttons. Since the action button was already intercepting the events from the basic button it contained to trigger it's own delegates to anyone interested, I resorted to just adding an invisible button on top that is never disabled, but uses the state of the other button to decide if it should inform listeners about a click event. It's probably something worth revisiting eventually, but not now.
Here's the redone UI, but like any good refactor it's looks basically the same. You can see the Plasma Bolt is currently disabled due to the lack of ammo available to fire.
When hovered you can see the extra action button shows up.
After clicking the action button, the Plasma Bolt now has 2 ammo available and can fire (that's the minimum). What's Next So now that I think that I've got enough structure and support for the tactical mode, I'm going to be moving onto a strategy layer that can string tactical battles together. It should be mostly UI, so I've already started trying to get more familiar with some of the other UI elements. Up til now, I've mostly been making do with buttons and static text boxes. Ideally, I'd like to be able to load into one map with a UI, make a few minor choices (like fleet configuration), load into my tactical map and have those choices be represented in the tactical map. Games I'm Playing  Fate/Grand Order - my one mobile game.  Battletech - Yeah, the one from last year. Got a key through someone at work recently and finally am getting around to it.  Steamworld Quest - A few guys were talking about it at work and it seemed up my alley. Not too far yet. Looking at picking up Steamworld Heist too, that one looks like it was interesting as well.
 

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.
 

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.

MagForceSeven

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!

MagForceSeven

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!

MagForceSeven

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!

MagForceSeven

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.

MagForceSeven

MagForceSeven

 

Journal #6: Kryptonite

I'm back! I told you Sid Meier's Civilization was my Kryptonite and it basically stole my last two weekends playing it. The first weekend was no real surprise and I had planned to just play it all weekend. But I got sucked in again the following one while doing a few productive things like laundry. In any case it's a very good continuation of the franchise and worth a look if you like that sort of game. Now, onto what I worked on this last week. I decided to put more console work off to the side (with appropriate notations on my todo list) in favor of something a little more in the vein of a gameplay feature. So to that end I implemented what is the core gameplay loop of a tactical strategy game (along the lines of XCom or Final Fantasy Tactics). Now I obviously already had the game loop doing all the windows messaging, managing frame processing and rendering. This was the gameplay loop to control the player's interaction with the game. I added a new component and couple objects to act as players. Right now this component consists of an array of handles which are the ships controlled by that player. I also added a new component to handle unit stats and added that to all the ships that I had created and added them to one of the two players. The stats component isn't particularly complicated right now, just an arbitrary mapping of keys & values. Long term I don't expect that gameplay will rely heavily on this, but it's really nice for experimentation and prototyping. And it's not unit/spaceship specific. Right now all the ships have two stats: Power & Supply. The game loop then consists of:

Player Turn Start - Set all that player's ships supply stat to their power stat value
Move unit - User clicks another tile, path the unit to that tile, decrement supply by 1
When supply reduced to zero, move the selection to the next unit
Continue moving units and rotating the selection until all units controlled by player have a 0 supply stat
When there are no units with available supply, move to the next player and return to step 1

This should be fairly recognizable to strategy game players and it's nice to have moved my program closer to "game" territory. I also added a few other related elements like:
tabbing to rotate the selection of the current unit
preventing pathing from occurring when the current unit has a 0 supply stat
preventing the current unit from becoming one controlled by other players if you clicked a tile that had a unit you didn't own in it. Using the mouse to change unit selection was already supported.

This is the point at which I would/should have a video to show off the various unit moves and player turn transitions but I haven't familarized myself with video capture tools quite yet.

MagForceSeven

MagForceSeven

 

Journal #5: Not a Holiday

I didn't have a whole lot of time this week. Instead there was a trip to a Renn Faire and touring a US Navy missile cruiser as part of Baltimore Fleet Week. I did find a little time to implement a search feature to my console. It searches through both the name and the description (or just one depending on the input parameters) and outputs the name of all the results to the console history. Now this isn't particularly exciting I know, but what I found along the way was a little bothersome. It turns out that there is not a case insensitive version of 'strstr'. Usually for every flavor of string function I've ever run across there's a version 'strcmp' and a version 'stricmp'. And I couldn't find a 'stristr', and a little Google searching latter confirmed there isn't one! That's crazy. So I wrote one really quick. I'm going to try to find another small thing I can work on this week because I won't have time during the weekend. Civilization 6 comes out Friday and that series is my Kryptonite. Seriously, I've taken days off from work in previous years to play it. So I'm going to be sitting on my butt all weekend playing it this time.

MagForceSeven

MagForceSeven

 

Journal #4: Holiday

I didn't do more than a smattering over this last week, mostly because I knew that I had today as part of a three-day weekend (Columbus Day). That meant that, apart from some stuff in the morning, I had a relatively huge block of time to sit around the house and just code. To start, part of my mouse controls was really bothering me. When I activated my console I would lose mouse input, or more accurately I would stop updating the render position of my mouse cursor. So I did the small amount of work (mentioned in a previous journal entry) to split up my logic control and move the mouse processing to the primary control loop. Which is probably where it belongs. Now my game loop looks like this (roughly):// init logic stack with logic instanceswhile( running ){ while( PeekMessage( ... ) ) { // message stuff } // calculate frame delta Input->Poll( ); // update mouse render position running = process_logic_stack( ); render_logic_stack( ); // render mouse cursor Graphics->Present( );}
I added an output history to my console so that all the commands and the strings that they decide to print are stored for immediate or later display to the user. Next I got a handle on the rendering of my console. Here you can see it in the single-line mode. After the user commits a command, this UI goes away. The command and all it's output are still committed to the history, so you can open up the normal console if something goes wrong. You can also see how the logic for the main game isn't processing the mouse position to update that blue tile highlight to be the one that is beneath the cursor (the white square). Here you can see the standard mode of the console. The last line is the text in progress (still need a cursor of some kind), and above that is the history. All the "testX" strings are what I typed and, because I don't have very many commands, all the 'fail' strings are the feedback output generated by the console. If it successfully executed something, it wouldn't print out anything unless the command itself printed something out. The history can be scrolled through with fairly standard PageUp and PageDown controls. The rendering was kind of a pain in the butt, but I only have myself to blame for that. I'd still like to get to an immediate rendering mode to simplify what the console is doing, but that was already part of my todo list. At least I didn't find any new work that I wanted to do because of what I was working on today. Features to still work in: text cursor, search, auto complete options I'd also love to hear from anyone out there with regards to features of console systems like this that they like that I might appreciate including both as a user and from a technical implementation perspective. Until next time!

MagForceSeven

MagForceSeven

 

Journal #3

So there is still plenty of features that I want (or need) to add to my console system, but as far as being able to execute semi-arbitrary commands at run-time it works. So at the end of the day this is what one of my console commands looks like:SF_CONSOLE_COMMAND_BEGIN( command_test, "A test command" ) const char * test_string = SF_CONSOLE_GET_ARG( const char * ); int test_int = SF_CONSOLE_GET_ARG( int ); float test_float = SF_CONSOLE_GET_ARG( float ); bool test_bool = SF_CONSOLE_GET_ARG( bool ); bool test_opt_bool = SF_CONSOLE_GET_ARG_OPT( bool, true ); double test_opt_double = SF_CONSOLE_GET_ARG_OPT( double, 0.0 ); const char * test_opt_string = SF_CONSOLE_GET_ARG_OPT( const char *, "default" ); const char * test_opt_string2 = SF_CONSOLE_GET_ARG_OPT( const char *, nullptr ); // Do stuff hereSF_CONSOLE_COMMAND_END
A few things of note:
All the code for defining a command is designed in such a way so that client code only has to include the header with these macros. They don't have to include & compile all the other systems level stuff. In fact that header should only be needed by the project main file that handle the frame loop.
nullptr - All my hobby code has been converted over to use this. It's a definite improvement over the old NULL macro.
SF_ - Since these are macros, they're all namespaced in the only way that you can namespace macros. SF is short for Starfire which is what I decided to name my library of code/engine way back when I started putting it together.
I'll probably need a different set of macros that can leverage my reflection information to covert strings to enumeration values. You can pass an enumeration type to the macros, but the string parameter will first go through a conversion to integer and then then integer will be converted to the enumeration type. Not terrible; user friendly for the person writing the command but not for the person trying to execute it.
BEGIN/END - I'm not as happy with having to do a BEGIN and END macro. I'd rather be able to do something more like:
SF_CONSOLE_COMMAND( command_test, "A test command" ){}
but that wasn't really in the cards given how I wanted to get the arguments. The BEGIN/END macros are roughly this#define SF_CONSOLE_COMMAND_BEGIN( name, desc ) void cmd_func_##name( const char * const * const params, const int param_count ) static const console_command Console_##name( #name, desc, sfcc_##name ); void cmd_func_##name( const char * const * const params, const int param_count ) { int _arg_idx = 0; bool _arg_error = false;#define SF_CONSOLE_COMMAND_END }
The 'console_command' type is just a struct with those few parameters. We're basically using the pre-main static initialization execution as our command registration mechanism. A pointer to it is then added to a singleton-ish array in the actual console system file. I don't foresee this as a problem since by the time that any other code is executing and any multi-threading concerns can come into play that array will basically be treated as read-only. Not that I have any realistic plans to do multi-threading any time in the near future. The parameter macros aren't really that interesting, just wrappers so that the console command only has to specify the type and default. They shouldn't have to worry about those function parameters or the '_arg' variables declared by the BEGIN macro. And the error flag is actually used in such a way that if one of the non-optional macros is used (so the parameter is required for the command to function properly) there is an early return from the function. I'm also a big fan of symmetry in code which is really the only reason that the END macro exists. I could have left the closing brace as just a "that's how you define these things", but that seemed a bit goofy. All-in-all I think it covers all the bases that I wanted. It's well insulated, dropable anywhere, flexible parameters. At least this next weekend I won't feel the need to spend quite as much time with LEGO Dimensions.

MagForceSeven

MagForceSeven

 

Journal #2: Momentum

No, I didn't do any physics code this weekend. I didn't have much free time this week, but at this stage it's important to recognize what I could get done to keep the momentum up. I continued to work on my debug console. I was able to add the mechanism for actually registering console commands in other parts of my code, parsing the inputs into the parameter strings and actually executing the command. I was also able to get started on the APIs for accessing the params inside the command. When the command is executed, I pass an array of strings to the function (basically an argv, argc arrangement if you're familiar with a console main function). I just want to write a few functions that can do the various transmutations of strings to more useful local types. At my previous job I wrote some really nice code (I thought) combining macros and templates to read and write the parameters from a Lua stack object. Now, it won't be able to be quite as fully featured as those were (I'm missing all the type information that the Lua stack made available) but I think it will do a good job. I'll share some example code when I'm done with it. And a new thing for my todo list: Because of the way that I layer my execution, right now when I open my console it freezes my mouse processing because I basically pause the processing of the layer beneath the console. That's not really ideal so I need to update and split my control logic so that the gameloop is making two separate calls to do the processing and rendering. Then the main loop can be in charge of the mouse like it probably should have been from the start. The good news is that the one control function I'm calling right now, internally it is already splitting up the processing and rendering so this shouldn't be a terribly time consuming fix/improvement.

MagForceSeven

MagForceSeven

 

Journal #1: Black Triangles

It's been a week and change since I decided to launch my developer journal and I actually got some things accomplished. It's hard not to compare my hobby development with what I do in the office every day. On the one hand, it doesn't feel like I really accomplished a weeks worth of work. On the other hand I have other priorities/drains outside of the office that don't allow for the same kind of large blocks of time that I'm used to from professional development. I suppose that's just the nature of hobbies, right? There's also a weird symbiosis with work that, at least this week, influenced what I decided I would like to work on. I was doing an automatic test harness that could play the tactical battles of XCom to hopefully spot issues faster. Because of that work, I decided that what I really needed in my hobby project was a console and something generic to handle command line arguments. Neither of those sound particularly important, but it's easy to notice when they're not there. Plus I figured that they were small enough things so that for my first week at this I could have something crossed off my todo. Which brings me to a short tangent: Black Triangles. A number of years ago I came across a blog post called Black Triangles talking about tasks that don't look like much but have a lot of meaning. If you haven't heard the term, go read the story. When I first read it, the story and term struck a real cord with me because it described a lot of what I was doing and what I've continued to do in my career. On the Saint's Row games, I had a tendency to do some big refactors to improve on an aging code base. As a systems engineer, I tend to do work on things that are almost impossible to point at something in the game and say "I did that thing". And I'm okay with that. I've found the Black Triangles to be really interesting technical challenges. It's also describes what I focused on this week; not direct features per-se, but things that will allow me to work smarter, faster, better in the future. So, first off I wrote some code (I wouldn't even call it a system) to parse the command line and throw all the data into a map so that anybody else could check what was specified when the game started up. Not earth shattering, but command line options are so useful that it was easy to bang out last weekend to get some momentum going. Next I started on my console. Almost immediately I noticed that I had a problem with how I do my rendering. It's all currently done with registering objects with a scene and rendering that scene from frame to frame. Which is great for most game things, but it's a little much for rendering a console to say nothing of the kind of debug rendering that I will probably need in the future. For a moment this was a bit disheartening because I didn't really want to spend my week adding rendering support, so I didn't. I added it to my todo list and moved forward on the console making use of old school printing to the debug output window. Along the way I found some small things I absolutely needed to add to other supporting systems like a function here, a function there. I reordered my enumeration of keys I use with my input wrapper so that all the alphabetical keys were together instead of being interspersed with the other keys that are on the same rows on the keyboard (or at least a QWERTY keyboard). I also tried to take advantage of the keybinding system that was part of my input library but ran into a snag there too. It seems I wrote it so that it basically maps from one enumeration (the gameplay actions) to the enumeration of keys, which sounds totally reasonable. Except that that enumeration lives in the wrong place right now, the input library should be game agnostic and shouldn't have an enumeration of gameplay actions! So I'll skip that for now and just do the regular key checks against key enumeration and add another thing to my todo list. Even at work that thing always seem to grow faster than things are marked off. I didn't finish the console, I'll set it up with rendering without the immediate mode stuff eventually. But for now I can open & close it (so says my debug output) and I can edit (what will be) the command line including arrow keys, backspace, delete. It's also got a switch so that I can open it up normally or in a mode that will just show the command line and will go away after inputting the command (it's one of the things I like about the Unreal console). That's a Black Triangle for you, it doesn't sound like much but there's a whole lot more going on underneath than what is apparent. General Summary: Completed:
Command line param cache

Ongoing Console work:
Actual console commands, registration mechanism and execution
Tab completion
Command history (ideally from previous executions of the app)
Rendering

New Todos:
Immediate mode rendering
Input refactor to eliminate an enumeration

And now that you've reached the end you should read Black Triangles.

MagForceSeven

MagForceSeven

 

Introduction & Motivation

Perhaps it's because I'd just like to do more hobby programming. Perhaps it's because a friend of mine (slayemin) has just published a game of his for early access on Steam. Perhaps my girlfriend keeps super-productive on the weekends and want something other than playing video games to do with that time myself. Perhaps work just doesn't scratch the same engineering itch it once did. I'm not really sure but I'm pretty I need something more than just a text log at home ('cause that obviously hasn't been working). Working with Unreal 3 is definitely partly to blame (more on that later). So, after looking over slayemin's journal I decided to start one myself on the theory that I'd be a little more motivated if other people were judging me for not posting for a while. Guilt is a powerful tool :wink: I don't really expect anyone to call me out on that sort of thing but it's at least possible. And if someone reading this wants to make it their mission to keep me honest, well so much the better for both of us. That's my motivation for this journal, to try another tool to advance my hobby. I hope this also gets me to be more involved in the community. I've lurked here on and off since at least college (2000ish) even though my profile join date is 2010. My quicky resume: By day I'm a Senior Systems Engineer at Firaxis Games in Baltimore. I've only been here a little while but helped ship XCom 2 (at least as of this writing). Before that I worked at Volition in Champaign, Illinois. While there I helped make Saint's Row. You may ask, "But there have been 4 of them. Which one?" and I would answer, "Yes" because I worked on them all. Not really my kind of games but fun to work on. And lastly, before that, I attended DigiPen. All in all that 5 titles in 12ish years. Not too bad. Technically I have a credit on one more, Red Faction: Armageddon, because I was in a shared technology group but I don't really count that since nothing I was did actually applied to that title. Which I guess brings me to my goals with my hobby programming. Unlike a lot of other hobbyists, I'm not particularly concerned with a large scale release of a game. Would it be nice? Sure. Would it be cool? Sure. But I'm not an artist and I'm not a designer and I very much understand the impact of both of those professions on a quality title. That means I don't have to be looking around for engines or frameworks to reduce my time to a product I can shop around. Plus I use an engine (heavily modified Unreal 3) every day so my hobby programming is meant as a way to explore or experiment in ways that I can't at work. It also gives me the control to do whatever I want, where ever in the code I want (like converting over to new language features). Engines are great, but at some level there's just a limit to what you can rip out, rewrite, or re-engineer. Like I said, I already have that at work. I don't need it at home. Now, I wouldn't call what I currently have an engine. Not exactly. It's more like a loose collection of libraries I've written (C++) and attempted to keep in a reasonably organized way to be able to share between projects that I start. I've written almost all of it because of that OCD-like control I talked about wanting above and I don't really want my hobby programming to be spent gluing together 3rd party bits and pieces. I want to (mostly) build, not assemble if that makes sense. The only a few places that I've really outsourced any code are:
DirectX because that's the graphics pipeline I've used since high school and I don't care enough to jump, and D3D9 (no seriously that's what my code still uses! :lol: ) is super easy
a JSON parser because writing parsers in annoying, time consuming and error prone
WxWidgets, but only for UI for Windows based programs

And I won't mind including more libraries in the future because a library has limited scope and impact in a way that an engine doesn't. In fact, given my experience on Saint's Row, I'll probably integrate Lua as a scripting language. Or Python since I used that too. Plus libraries are easy to hide behind custom abstractions, in my case D3D is hidden away completely, the JSON less so. Part of my problem might be the number of projects I have "in progress". I won't go into much detail about them here, perhaps a followup journal entry, but to summarize there's 3 programming solutions and 2 design documents. However the design documents are mostly historical and I haven't made additions to them in a while. One of the programs is a campaign tracker for Descent: Journey into Darkness by Fantasy Flight Games, which is of less use since moving to Baltimore meant leaving the friends that actually owned the game that I would play with. I'd still like to finish it but upgrading Visual Studio threw a wrench in its use of pre-built WxWidgets binaries. To close I thought I'd list a few of the pieces of tech that I have in my libraries. I don't claim any of this as revolutionary or special other than to myself since I wrote it all. Consider it a snapshot of the systems I have in place as of today. There won't be much detail here but if anyone wants to pipe up in the comments about a specific system I'd be happy to do a more detailed write-up. So here we go:
Static Initialization time C++ reflection information (using a combination of macros and templates)
Component based object system (with type-safe dynamic casts that doesn't use RTTI)
Flexible delegate structure (based on the impossibly fast C++ delegates, but not using that code directly)
General event manger
math library with vector/matrix/orientation types and all sorts of utility functions
Collection of assert macros (based loosely on what I worked with at Volition)
A finite state machine
A priority queue using an internal heap/tree structure
File Cache data structure (with an asynchronous loading API even though it's not asynchronous under the hood quite yet)
Hexagonal gameboard with various utilities for working with hexes. Basically a height-map with a height for each hex tile. Some pathfinding support as well.

Two biggest todos:
A Redscreen system (to display issues that aren't quite asserts but should be attended to)
A Console (usually accessible in PC games from the '~' key)


MagForceSeven

MagForceSeven

Sign in to follow this  
  • 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!