Game Design, Programming and running a one-man games business…

New Production Line car design interface

When I initially designed the Production Line ‘car design’ system it sounded like it made so much sense. Cars were a list of ‘features’ such as ‘electric windows’ etc, and whenever a car came to be sold, we would see if we had sold a car with that list of features before or not, and if not, we popped up a dialog box asking the player what to call this design and how much to charge with it, along with information on the market value (fair price) for that combination of features. This seemed perfectly reasonable.

The problem is that a) there are about 999,999,999 permutations of features and b)actual cars arent really sold that way anyway.

If you buy a car, you decide to buy (for example) a Vauxhall Astra, and then you decide which options you want, effectively from a price-list of add-ons. Usually car companies bundle a set of features together as certain ‘models’ such as ‘deluxe’ or ‘GT’ or whatever, but essentially there is a base body design and a price list of features to go on top. In order to reduce the amount of pointless GUI and busywork in Production Line I decided to switch to a similar model for patch 1.13.

Now we have a new button in the GUI, which launches the ‘design browser’ in the game which shows you all of the actual properly different body types of cars you currently produce. (for now its hacked showing designs from an earlier version, so they all have the same body type, but for new games you will only have one here for now). That window lets you select which car design you want to view or edit.

That then brings up this new window, which will also pop-up when you produce a car for the first time, or when you ship a car with a feature that was not previously available in this design. (That should happen only when you have researched a new upgrade and then shipped an upgraded car).

This is where the GUI gets a bit confusing. Essentially any design is just a shopping list of features with the base feature being ‘basic car’. For each feature you can see the market value of that feature (the consensus in the market place for the fair value for one of those), the price you are currently charging, and the markup over the market value in both percentage and dollar terms (with buttons to adjust this).

You can price cars at a premium to earn higher profits, or a discount to shift them quicker. This is where the confusion will come..

This does not represent a hard profit or loss for that car.

because there are so many fixed costs, its very very hard to work out how much each feature really costs you to add, so you have to separately keep an eye on what that feature is costing you. The premium/discounts here are only a guide as to how competitive you are with your rivals, who may be more or less efficient than you. My big dilemma here is how confusing is this? and is there a better way to explain/present it? Obviously there will eventually be a tutorial.

I also think that probably what I need here is some option to copy a single premium/discount to all features, so you are not adjusting each one manually. I’m not sure of the best way to present that from a GUI POV. In terms of ‘why would you ever not want to do that?’ consider this: You rush ahead in the early stages of the game to research cruise control before anybody else. As a result, you have the ONLY cars with cruise control. You can therefore charge a whacking great premium for that feature, way above the premium you would charge for other car features.

Does that make sense? Is this an improvement on the old model? Feedback most welcome. This is hopefully going into the 1.13 patch coming this week. maybe even Wednesday! (more likely Thursday).

BTW don’t forget the price goes to $12 from Sunday. If you know you are going to get it anyway, order it below :D

New Production Line Blog Video

I missed two weekends of doing these due to GDC but worry ye not, I am back working on the game with a vengeance:

I currently have a minor routing issue with the new sped-up code, but I’m getting closer to squashing it. The next big change to the game will be design pricing, and after than its likely to be some new components, machines and slots. New cars hopefully next month.

 

Major code speedup. Big factories ahoy!

I recently got sent a HUGE factory in a savegame for Production Line. It has over 600 production slots and 24 resource importers, and its MASSIVE. Here are some screenshots:

Despite its awesomeness it was MASSIVELY slow. Not only did loading it take forever, but whenever you changed any of the resource conveyors the game would hang for about 20 seconds. hardly ideal, especially given that I have an 8core i7 PC. So I set to work trying to optimize the code. I did some fairly small optimisations first, which boosted processing by 12% but I needed more fundamental re-design.  After chatting to a fellow indie coder, I agreed that my currents system of always calculating the optimum route to everywhere, for everyone, when something changed, was clearly not viable. I switched over to a new system of ‘lazy’ computation. Basically when I change a route somewhere, it now sets a flag on every production slot saying ‘you should recalculate your nearest slot soon’. That flag gets checked every frame, and sometime in the next 120 frames 92 seconds) each slot will calculate the route from its location to all the importers, and store the nearest two. It needs this so slots seem to import from a sensible location, as opposed to an importer that is miles away.

This was good, and sped things up a LOT. Now instead of hanging, the game would stutter for about 10 seconds. better but nowhere near good enough. I then realised I was doing something seriously dumb. I was going through all those routes I calculated, and picking the nearest, THEN doing it again, to pick the second nearest. doh! This sped things up, but in retrospect, it was trivial, it just alerted me (alongside my profiler) to the fact that when I tried to get (for example0 15,000 routes, I actually calculated 30,000. How come?

It turns out that the code that multithreaded all of the ‘calc the routes’ code, was not storing any of the results, so the code that came after it which then went through the (not saved) routes to pick the nearest ones was having to recalculate them anyway. I was essentially doing everything twice.l Worse…this second bit of code was single threaded, meaning all my multithreaded time was wasted and all the work happened in a single thread. What a dork.

A nice simple change to the code to make sure those multithreaded route calcs are actually stored *doh* means that not only did the processing time half, it now gets split over potentially 8 cores instead of 1, so on my PC its now running 16x faster. Combine that with the earlier speed-ups and its likely 18x faster, and because of the frame-spanning over 120 frames, it *feels* fluid as hell, even on insane maps.

Here is the concurrency visualiser showing the loading of the insanely big map.

And here it is zoomed in showing the multithreaded bits.

Those gaps are because each slot makes a single-threaded call to evaluate all of the import bays (each colored block is the code to get a route from one import bay to one production slot), and that call (in the main thread), then spreads it over the worker threads. Ideally I’d find time to eliminate that single thread blocking. Also I have some gaps in there because the end of each threads Calc() has to use a critical section lock to deposit its new routes safely in the main thread. Ideally I’d bunch them up inside a thread structure and dump them at the end.

Anyway, enough tech bollocks, the upshot is that massive factories will now be uber-fast :D.

Legacy Business

Having a long established business brings benefits (FWIW Positech was formed in 1998, as I recall). You get tons of experiences, and contacts yada yada. It also has a negative side.

British Airways used to be a really major force in UK aviation, but got hammered badly by ‘low-cost’ airlines and is struggling to compete. One of the many reasons it finds it hard is that BA has been around long enough that it has a bunch of retired pilots 0n decent pensions. Thats a considerable cost that its new upstart challengers do not have, and its just one example of the negative side of legacy business.

Having been around for so long and shipped so many games, I have a lot of legacy crap to deal with too. I get emails (often) from people who have lost their Kudos or Kudos 2 download link. Its a 1 or 2 minute distraction at best, but it involves mental context switching that is expensive for a coder. I even get the odd request from someone to buy/re-register their shareware demo of Asteroid Miner/Star Miner (my first commercial game). FWIW, don’t email me, the serial code for every copy is the same (what a n00b huh?) its the serial number of the trash compactor in star wars, if that helps…

Emails about long dead games are one thing, but it also means you have communications about long dead publisher deals and other biz stuff. I am owed tiny amounts of money by at least 4 different publishers and payment providers which are below the threshold for paying out, yet spam me each month with an automatic royalty report. (RealGames, I can guess I’m not selling any copies next month, so lets give it a rest shall we?). This sort of stuff is long redundant and could probably be spam filtered out, but actually its not the ‘really’ old stuff that is the biggest legacy distraction.

Believe it or not, Democracy 3, a game which still generates comfortably enough for me to live on, and for which we will soon release a Unicode update with exciting new language support… is now considered legacy in my mind. This is partly because Jeff now deals with it, but mostly because I have moved on to do other stuff. We did D3:Africa, then Political Animals, and Shadowhand is coming, and of course I code Production Line. Frankly, in my mind, Democracy 3 is history, at least in terms of day to day concerns.

Yet to loads of people, it absolutely is not history, but a current, new game. I get emails from publishers wanting to discount it in sales, I get more requests to do academic stuff around it than you would ever guess, I get a bunch of interesting emails about modding it, I get requests to bundle it, requests to list it on new stores, obviously I get some tech support (not much now, happily), and so-on and so-on.

I know this sounds a little ‘first world problems’ but actually, you don’t realize how much this stuff builds up. If you are working on your first indie game, or have just released it, you have 100% focus. When you get an email about ‘your game’ you KNOW which one. You never get confused as to whether its Democracy 3 or Production Line that has a fix for certain sound card bugs. You never forget which game you are running an ad campaign on, or confuse which one is in a sale this week. (FWIW several of my games are likely in this weeks GoG sale. Off the top of my head…no idea which ones).

I am beginning to think there is a very good argument for restricting the game output for a single-dev studio to below my current level. Make a few games, make them long-form hits. There is definitely a diseconomy of scale when it comes to multiple projects over time.

 

 

Should you go to GDC 2018?

You definitely get a skewed view of GDC from general media and social media. If you are a penniless indie dev, or just someone who hasn’t been to GDC, you might think it is an exciting wonderland full of product releases, wild parties, great deals being done, and venture capitalists throwing bags of cash at grateful developers. The truth is, its much more variable.

GDC Tweetage is generally “Just had an awesome meeting, so excited” and “So amazing to meet up with so many talented people again #GDC17” and so on. The non-tweeted thoughts are more like…

“Sat alone in hotel room eating crisps again.” “Can’t afford the pass to go to the cool talks :(”

The reality is a mix of the two. I’ve had some great times, met with nice people, and some kinda dull, boring, miserable times. All my real ‘biz’ stuff is done now, so its just the nice socializing with buddies stuff ahead of me, then the inevitable long flight home. At this point, I think I have enough data to provide some pseudocode to determine if you should attend 2018:

bool ShouldIAttendGDC()
{
float ValueOfGDC = 0
float relative_cost = CostOfAttending / IncomeFromGameDev;
if(relative_cost > 0.5f)  return FUCK_NO;
if(relative_cost < 0.01f) return HELL_YEAH;
ValueOfGDC += (0.02f * NumFriendsAttending);
if(CanAffordBusinessClassSeats) ValueOfGDC *= 2.0f;
if(NeedFunding || LookingForFirstIndustryJob)
{
 if(IsExtravert) ValueOfGDC += 0.2f;
 else return FUCK_NO; 
} 
if(HasNeverAttendedGDC) ValueOfGDC += 0.20f; 
if(AboutToReleaseGame) ValueOfGDC += 0.05f; 
ValueOfGDC += (0.075f * NumConfirmedPartyInvites);
if(WorksForMiddlewareCompany) return WHO_CARES_BOSS_PAYS; 
if(YouGetAFreePass) return LOL_YEAH; 
if(ValueOfGDC >= 0.5f) return MIGHT_AS_WELL;
else return NAH_FUCK_IT;
}

I hope this is helpful.