Click to Interact and Launch UI

Hey Folks! Finally got back to some gamedev today. I returned to work on the ship equipment UI system, and I think I have a working prototype now, albeit with minor issues to sort out.

Basically, I've setup a way for the game to launch different UIs based on what the AI is doing at the time. This is the precursor to controlling important ship actions using the crew.

The way it works is that the player left-clicks the crew they want to use, then right-clicks the target item. The game will first check for any valid interactions between the AI and the item. If it finds one, it'll check to see if the AI can pathfind to that interaction's specified point on the ship (usually next to the item). If that passes, the AI is ordered to walk to the item and the interaction is queued for when it gets there.

If that interaction has a GUI specified, the interaction will raise that GUI with any parameters that were specified in the interaction's data. These params will define things like label names, min and max values, and probably, which items and stats to connect to which UI elements.

And so far, it works! I have a simple charge meter UI setup for the battery, and choosing an AI and then right-clicking on the battery causes the AI to walk across the ship, opening doors as needed. When it gets to the battery, a charge meter opens on the screen, showing real-time battery charge. Pretty cool!

Of course, it has some kinks to work out. For one thing, the UI appears as the AI is finishing the interaction, instead of when it starts interacting. Also, the UI never goes away. Also, the UI is just the first valid interaction, and should probably have some list of options present for the player to choose from (in cases where more than one UI is possible).

Also, as evidenced in this discussion from an earlier post, I have a lot of thinking to do about how the player controls the crew.

There are pros and cons to each approach, and likely, I'll have to try them out to see which feels the best. For now, the easiest will be to have the AIs autonomously self-care (i.e. eat, sleep) but have the player direct them to do more complex stuff (e.g. steer ship, change life support settings). But there may be compelling reasons to make the AI handle those more UI-centric tasks, in which case I'll need to work on a way for AIs to do these widget tasks.

Anyway, progress! This is a subtle upgrade with serious power potential. Lots of cool shipboard items to interact with through widgets now!

Epic Paperwork Continues

Hey Folks! Hope everyone had a good weekend. We're gearing-up for a camping trip later this week, so we broke out the tent and took a test nap in it. Looking forward to getting some not-computer-time :)

The parade of paperwork continues this week, as I resume transferring distribution and licensing agreements from my old personal business to the new LLC. Plus, it turns out Seattle-based LLCs have some really nice bonus features, such as State and local tax filing, business licenses for each, and other LLC requirements. I may even have to get new business cards and letterhead to protect the liability shield the LLC provides.

This is how bureaucracy spells F-U-N!

Needless to say, not much excitement to report. I think I might be able to squeeze some dev time in again tomorrow, though, so hopefully more then!

GUI Baby Steps, and Business

Another mixed dev and business day. Though, I had a special treat today!

I had a nice lunch with another indie who used to work at BioWare with me. Over beers and lunch, we chatted about such things as Pokemon Go, sales tax, indie publishers, motivation, and our current projects. We also had a really interesting talk about procedural drama. Dusty had some really cool insight into ways to string together characters' stories, as well as persistence of personalities and named characters vs. strictly procedural characters. Food for thought!

In the dev time I had this morning, I tackled a bit more of the item GUI system. I think what I'm aiming at is a system where each interaction has an optional "RaiseGUI" property. If the player selects an AI that's in an interaction with this property set, the game will show that named GUI. The widgets in that GUI will be wired to in-game data through the interaction's settings.

So if Akiko interacts with the battery using the "inspect" interaction, it can have "RaiseGUI" set to show a meter, and the meter's value will be set to the battery's current charge. So far, this seems pretty easy to do with some data files and Unity's component-based architecture. We'll see next week!

Lastly, more business stuff. Now that I'm incorporated, I have to update all of my distribution agreements with Valve, GOG, etc. So lots of paperwork to rifle through. Fortunately, it's pretty straightforward stuff. Just takes a while to sort out.

Anyway, that's all for this week. Have a good weekend, all!

Equipment UIs, and Business Stuff

Hey Folks! Short dev day today as I had to take care of some business banking stuff. But I think I've figured out where to "jam" next: equipment UIs.

Part of the experience I want to give players in this space prototype is the joy of flipping switches and turning knobs that actually mean something in the game world. I want them to enjoy examining the controls like the owner of a new car, and design/choose ships based on their "feel," and not just stats. Manual override on an airlock is actually by the airlock, not some translucent menu floating in one's field of view. And like Ripley in Alien, if you're going to self-destruct a mobile factory, you'll have to navigate the annoying self-destruct sequence through a series of failsafes, not just through a cascading on-screen menu.

For this to work, AI is going to have to be able to raise a UI when interacting with an object. E.g. if it goes to the ship's helm, it'll show the helm controls. If they approach the navigation console, they'll see the System map, orbital projections, and possibly RADAR/LADAR readings.

To work towards this, I setup a simple bar meter UI to see if I could attach it to the battery to monitor charge. And without too much effort, that's up and running. It's hooked up to a debug hotkey, and has lots of hard-coded values, but it works.

The next step is to find a way to launch the GUI when the AI reaches a control panel. And I'm thinking this will be in the interaction system. I.e. the interaction should have an optional UI it raises while running, and that UI closes when the AI finishes the interaction.

This raises a few questions, though. For one thing, what's the AI doing when using the UI? Can the AI bail out before the user is done with the UI? What if the user switches AIs?

Also, how will UI layouts and data-mapping work? If I want a UI to monitor temperatures around the ship, how to I define all the gauges' positions on-screen, their data sources, and what various buttons and knobs do when clicked? Making stuff data-driven isn't too hard, but what data format to use so it doesn't get too complex is a harder question. Especially for something like this. Which is complex :)

Anyway, that's where I'm headed next. I'll start simple, and hopefully some patterns will emerge that show me how to solidify the system. More on that later!

Batteries Working

Hey Folks! Got the batteries working today. And also a slight change to the power transmission system.

Yesterday's post prompted some useful discussion of the power system, and Malocodor's suggestion turned out to be a better approach than mine. I originally had each of the powered items check surroundings and try to draw power from them, and each of those surroundings would chain-request power back towards the source. This worked, but required the system to re-check each request.

Malocodor's recommendation was to instead map out all the power connections once, and just update it whenever conduits are added or removed. This way, powered objects just checked their last known connections without all the back-tracing. And since I already had a lot of the grid-walking code to trace rooms, I could easily make a tweaked copy to trace conduits.

And once I had setup the air pump to use power, it (correctly) stopped operating since none of the connected conduits had power. Time to add some batteries!

Yesterday's post showed the battery art I added as a placeholder, so the bones of the item were already done. All that remained was to setup the various properties on the battery to make it store power. Namely, it has a stored power limit and some placement rules that prevent stacking, etc.

Then, it was just a matter of hooking up the air pump and battery with appropriate stats. Since I'm trying to be near-future, hard sci-fi, I want the numbers to make sense. So as a baseline, I'm going with some current-tech values for things that NASA and industry use. So the battery is assumed to be a big nickel-hydride bank, like NASA uses. And for the in-game size of about 0.25 m3, that means it stores about 41kWh.

Similarly, a typical, 2-stage vacuum pump used industrially consumes about 100W. So each time "use power" is triggered, I made it consume 0.1 kW. Hooked up to the above battery, it'll run continuously for about 410 hours, or 17 days. I have no idea if that's accurate, but it seems reasonable at first glance.

Then, it was time to try it out. And I'm happy to report that it seems to work! Cutting down the battery capacity for testing to last about 15 seconds, I saw the pump run for 15 seconds, then cut out. And when I added a second battery to the network of conduits, the running time capped at 30s.

Mission successful! Probably some bugs yet to find, but good enough. Jam on!

What's next? Currently, I'm leaning towards item UIs. Each item that the AI can interact with is probably going to have a UI the player can tinker with to make stuff happen on the ship. E.g. AI can sit down at a nav panel on the ship, and it opens a UI where the player can plot their route. Or an AI standing at the outer airlock control panel can control pressurization to exit/enter the ship.

The idea here is that pressing buttons, looking at meters and flashing lights, and throwing switches that actually do stuff can be fun. Won't know until we try it, though!

More Power!

Work continues today on the power system.

I think I've got a working set of code to emulate power needs on a ship, and I'm now in the process of filling-in some content to test it. And since seeing it makes it easier to explain, here's what I have so far:


Comes in trusty Weyland Yutani blue!

The above room is a continuation of the air pump simulation from a few days ago. To recap: an air tank (orange cylinder) is to the right of an air pump in the wall, which gathers gas from the room to its left, and pumps it into the tank. The new part are the snaking blue conduits and the battery in the lower right (below the light).

As described yesterday, ship items are going to need power, and to get it they'll request power from points specified in their data. If the thing under that request point has power, it's delivered to the requester, and it runs for one more turn. If not, the requester shuts down until it can have its power needs fulfilled again.

In the example room above, the air pump needs some kWh per "turn," something like 1 kW/h. So when the pump is ready, it checks its nearby points for power input. Assuming one of those points is the tile to the right, we find a conduit, air tank, and floor there. Since the conduit is the right type, it tries to get power from that.

The conduit, however, has no power stored, so it requests power from its nearby points. Since this conduit is an "L" shape, it tries to get power from the tile "south" of it. That, in turn, tries to get power from the conduit to the right, and so on until we reach the battery. Since the battery actually has power stored, it deducts from its charge (if any), and sends a message back up the chain about how much it gave. Assuming we have enough to fulfill the pump's request, the pump triggers another "turn's" worth of action until it makes the next request.

So far, I think this'll work. It'll allow distant power sources to supply components around the ship. It also allows power to reroute around faults in the path, in case one of the conduits is damaged. More importantly, I'm hoping this will be one of the "fun" bits of ship building: planning system layouts, power needs, redundancies, etc. Then, setting the ship loose and watching it succeed, or more likely, fail.

Spectacularly :)

One of the risks of this system is performance. Each power cycle is a series of connection requests, possibly many for complex layouts. And this could eat into performance. However, I'm hoping that by keeping the rate of requests for power limited, it won't kill performance. E.g. if each item on the ship requests power once per second, that shouldn't be too bad. And if power fails on the ship, a 1-second lag time to shut-down of connected equipment won't be unrealistic.

The other, more scary, risk is that this won't be fun. I was reading Tynan Sylvester's AMA today on reddit, and one of the things he discusses is the core of a game's design. He warned against adding complexity to compensate for lack of fun, or not identifying the fun soon enough. He explained that core game concepts should be identifiable as fun early on, and can be reached by trimming out excess fat over and over until there's one irresistible experience.

I'm not sure that I'm doing this very well. I mean, I expect to enjoy this, but it's not enjoyable right now. Heck, there's not much to do besides build. And maybe watch funny AI bugs. It's no more a game than a Lego set. An unfinished, glitchy Lego set.

Then again, I think I'm building towards an experience I already know I like. Namely, Prison Architect or Rimworld within the context of a spaceship. It'll have differences, but a lot of the fun I have in those games is coming up with a new design for a prison/colony, and testing to see how well it works in practice. That's the core experience, and it may be that it cannot exist without a certain minimum number of interacting systems.

Which I guess Tynan also admits in his StarCraft example. One can strip out a lot in SC to reach the core, but the core still has several parts. 4 unit types, AI for the units, a map with resources, and an opponent. I can probably narrow down the number of systems I have to a minimum, and add code to test it with a crew in space. Maybe that should be a "game jam" goal I set for the near future?

Worth serious thought.

The Power Is Yours! Also, Sale!

Hey Folks! Hope everyone had a good weekend. Pretty low-key, here. Yard work, a park visit, Skyping with family. Maybe a quintessential summer weekend?

Back at the office, Tiago's shared his latest mobile port work, and still looking good! One of the bigger features he's working on is a zoom lens for making it easier to interact with tiny objects/UI items on small screens (or for those of us suffering from "fat finger"). This will also be a chance to look at the context menu and pop-up tooltips for things, and hopefully make them all play nice together and make the users' lives easier.

On the space prototype, I've decided to try tackling power as my next task. Ship equipment is going to require power to work. And though the gas stuff I added has many similarities with power (drawing from a source, depositing in a destination, and changing status based on whether any is available), it's different enough to warrant a closer look.

The current thinking is that I'll be doing everything in Watt-hours (or kWh, or MWh), since that's a pretty universal measure of a machine's power needs. Batteries will store kWh, machines will consume kWh while running, and generators will create kWh while running.

That can all be done using the ICS stat system, so I'm not too worried. The trickier part, though, is transporting power from the source to the destination. How will a player be able to define which areas of the ship are powered? And how machines get their power from local surroundings? If a chunk of the ship is damaged, which things lose power?

For that, I need some more spatial code, like the gas stuff. And since power travels differently than a gas, it'll probably use separate (but similar) special code.

So far, I'm working on a system where objects can have two points specified: a point from where they draw power, and a point to which other, downstream things can tap for power. Only the first is required for powered objects. The latter will be optional. Sort of like this:

source A---object1---B A---object2

The source will generate power, object1 will grab power from point "A" which overlaps the source, and object2 will grab power from object1's point "B." I'm hoping that this allows for a variety of powered system designs. E.g. object1 could be a simple conduit with input and output points, or it could be a working machine that has a way to transmit power downstream, like a daisy chain or string of lights.

Or so goes the theory.

Also, in case you missed it, NEO Scavenger's on sale again. This time, at the lowest price since launch: -75% off!


And it comes with a Steam key!

When purchasing, you can choose how much to pay, with a minimum of $3.74 USD. You can also choose to give 10% of the purchase to the Child's Play charity. Plus, you'll be supporting Indie Game Stand, who are all-around good folks.

So as usual, if you've been holding out, now may be your time :)

Air Tanks

Hey Folks! I think I've got the air tanks up and running now. I spent most of the day fixing up the code for gas pumping to be compatible with both rooms and items, and then setup an "Air Canister" item to test pumping gas into a non-room item. Here's how it looks right now:


Like a colorful tax rate table.

In the screenshot above, we're looking at a couple of rooms separated by walls and doors, an air pump, an air tank, and our trusty crewman Mann. Each grid tile has a debug overlay to help me see partial pressures of each gas present, so that's what all the numbers and red/green tint are. (Green means pressure is close to atmospheric, or breathable. Red means near vacuum.)

The air tank is the orange circle with the white bracket around it, in the "red" room. Immediately to it's left is an air pump in the wall drawing air from the room to the pump's left ("orange" room) and into the air tank on its right. Mann is standing in the "green" room, which is sealed off from both the red and orange rooms.

There are a few things going on here.

First, you can see the pressure is high in that air tank. The numbers are partial pressure of each gas in kPa, and atmospheric pressure is 101.3 kPa. So that tank is quite a bit higher than normal air pressure on Earth. Though, probably still only about half of an industrial air canister pressure when full.

That air tank is being filled from the orange room. It was originally higher pressure (like the green room), but has been sealed off with the pump running a few minutes. Given enough time, the orange room would turn closer and closer to red, though probably never reaching it due to diminishing pump performance at low pressure.

Speaking of red, the red room is a total vacuum, and is demonstrating that the air pump and air tank are sealed off from it.

Finally, we see that the pressurized rooms have mostly N2 (nitrogen), some O2 (oxygen), and trace CO2 (carbon dioxide). When the simulation started, I pumped in roughly Earth-like atmospheric constituents (so about 80/20 N2/O2). All of the CO2 you see in the image was generated by our trusty windbag, Mann. Given enough time, the ship's air will have more and more CO2 and less O2. That's where future equipment will come in, such as CO2 scrubbers, ducting, and either O2 reservoirs or O2 generation beds, to create a life support system (at least the breathable component).

The question now is, what next?

I see a few options. I could go ahead with the aforementioned life support equipment to try and create a closed system. I could also start thinking about power and electricity for the systems, and how they interact with that. There needs to be some new data added to handle asphyxiation in crew (and what happens when a crew dies).

There are also higher-level systems I haven't touched yet. I want there to be a console the crew can interact with to load a UI for navigating the Solar System. And for that matter, a system to open a UI based on crew interacting with it.

So lots to choose from. I'll let that stew over the weekend, and see what I'm leaning towards on Monday. Until then, have a good weekend!

Air Pumps, Respiration, and Filters

I did some refactoring today, to try and get the recently-added respiration code to work for things like air pumps and filters, too. I think I've got most of the code and data for it in place now, and I'm in the process of debugging it.

Basically, I took all the remaining gas functions and stats and moved them from Room to Condition Owners (COs). The idea is that life support systems will need to pump gas to and from ship equipment (like O2 canisters). And since equipment and rooms both have COs attached to them, I just made those the home for all that logic and data. COs are getting a bit heavy, but I can optimize and organize later.

So now, my COs have a few tools in their tool belt for managing thermodynamics:

  • GasExchange() - takes params for point A, point B, and flow rate. The function looks for rooms at A and B, and performs a gas exchange between them as if there is a giant hole between each. The flow rate controls the rate of exchange, so it's possible to slow or speed the equalization, if needed.
  • TempExchange() - like GasExchange, except it equalizes temperatures between A and B over time.
  • GasRespire() - Takes a huge param list defined in a new data type. Basically, this handles the transfer and/or processing/filtering of a single gas within a mixture. Things like a human breathing O2 and exhaling CO2, or a CO2 scrubber pulling CO2 from a gas mixture. Source and destination for gases can be either a room or CO (like a canister), and is defined by filters and coordinates in the param list.
  • GasPump() - Like GasRespire above, except is does the entire gas mixture and no processing/filtering. Basically, just moves gas from container A to B.

Together, this should cover breathing, leaks, room atmo mixing, scrubbing, filtering, and just about any other gas process on a ship.

I'm also hoping that this is a good starting point for interoperating ship equipment. In theory, this could allow a chain of rooms and COs to function as a complex machine. Room A could feed an air pump which moves gas to an adsorbent bed for scrubbing CO2, and another air pump pulls the scrubbed air into room B. And since the scrubber would use GasRespire() to pull CO2 out, it could be setup to gradually increase a "saturated" stat on itself each time it activated. Once this "saturated" stat reached a threshold, the scrubber would shut down or lose efficiency.

In other words, we may have our first ship repair situation! Granted, it's pretty janitorial in nature. But hey, blue-collar sci-fi isn't exactly glamorous :)

Breath of Fresh Air

The AIs are finally breathing!

I tried the "just game jam it" approach today, and so far, it's paid off. I now have a respiration command I can attach to my condition owners (COs) that lets them take a gas from the room, use it to pump up one of their stats, and expel another gas in its place. And the data files can control which rooms the gas comes from and goes to, which gas to use, the volume of gas to process, and the conversion rate of the gas. Those last two are useful for making the breathing process scale with gas pressure/concentrations, and modeling inefficiencies.

So now, I'm able to plop an AI into a room, pump it full of N2 and O2 at air-like proportions, and watch as the O2 partial pressure ticks down slowly, being replaced by CO2. Neat!

In the process, I also had to setup the network of data files for things like breathing stats, timers, and critical conditions (e.g. hypoxia), and they seem to be working correctly. Nothing fancy yet. The AI doesn't dramatically keel over when asphyxiated. But the chain of "bad-to-worse" conditions for not getting O2 are there and working, just like hunger would in NEO Scavenger.

It's not the most extensible code, but it works. And it has a lot of flexibility. So score one for game jamming?

In fact, my next task, air pumps and filters, may already be partially done since the function above is customizable. Air pumps need to move air from point a to point b, and are more or less effective based on the pressure of the source container. The above breathing function already does that. And if I choose the output gas to be the same as the input, it's basically just a pump. And if I wanted to make it a filter, I could make the output gas a nonexistent one, so input gas gets converted to nothing (and using the condition stat build-up, maybe I could convert the filter/scrubber to a used version that needs to be replaced by crew).

So far so good, but there are a few catches.

First, pumps work on the mixed gas, not just a constituent of it. I could work around this by just calling the pump command for all possible gases, but that's a bit inefficient (and hard to maintain). I could possibly add a parameter to the breathing function to work on all gas and not just one.

Another catch is that not all gas is going to come from or go to a whole room. There are going to be containers to store gas, and more than likely, there will be multiple of these in a single room. (Otherwise, there would have to be walled rooms for each container, which is a huge waste of deck space.) The breathing code could be made to check input and output points for containers first, and if none found, then use the room.

Finally, I'd have to tweak a few parameters in the code so that it is more customizable. E.g. the pump needs to add or subtract stats, not just subtract, the stat to be changed needs to be exposed as a param, and the timer condition that triggers it would need to be a param. These last few are easy to do, but do inflate the function param list quite a bit.

This is pretty doable. But the other approach might be to just have a separate pumping command. It just feels weird making it separate when so much of it is identical code.

More than anything, though, I should probably sort out that container issue. That seems like it's the biggest unknown in terms of architecture, and if solved, also opens up the most useful options. (E.g. more complex ship machinery, like water systems, propulsion, reactors, etc.)

More on that tomorrow. Have a good night, all!