PROCJAM is a relaxed game (or anything) jam with the motto “Make Something That Makes Something”. It basically ran from 4 NOV 2017 to 13 NOV 2017, but the organizers emphasize not stressing out about deadlines.
Procedural generation is my jam, as you may have noticed from my Pathfinder Twitterbots and the little generators on my site. I didn’t want to generate terrain, caves/dungeons, or planets, because so many generators like that already exist. I had no shortage of ideas to choose from, though. Deciding which one to pursue took quite some time! Some potential projects:
- Generate spaceships from subsystems that produce & consume various resources
- Generate fantasy creatures with different senses & capabilities, and individuals of those races who may have disabilities or mutations
- Generate buildings that accommodate multiple fantasy creatures with widely varying needs.
- A MUD Twitterbot with emoji visualization
- Generate footprints that players can follow, and a field guide that identifies the creatures that leave the footprints.
The generators I want to make have lots of constraints and dependencies. Many generators are stateless: the number of projectiles the gun fires can be chosen without regard for the projectiles damage, or fire rate, or elemental affinity. Not so the fantasy creatures, who won’t use a spoken language if they can’t hear, or the spacecraft, who can’t use a science lab without a generator to power it. I feel the added complexity in generation is worth it, because it forces the generated artifacts to make sense.
I chose “Spaceship Wrecker”, which generates a spaceship full of subsystems, then lets the player launch an asteroid or bullet to damage some of those systems and watch the failures cascade across the ship. In my mind I envision players boarding wrecked spaceships, prying open airlocks, re-routing cables, and getting the ship back online, but let’s start small, build up incrementally, and see how far I get in a week.
What parts do I need, and what do they depend on?
- Engines (move the ship)
- Fuel tanks (supply the engines)
- Generators (supply electrical power to all kinds of parts)
- Life support (supply air to rooms with people in them)
- Crew quarters (supply crew to operate various parts)
- mission systems (sensors, cargo, labs, etc.)
This gave me my list of resources:
- Thrust (technically that’s two resources: engines overcome inertia with thrust, but it’s simpler to create demand for engines by saying that parts consume thrust.)
I built some placeholder assets as Unity prefabs: 1-meter cubes, color-coded by function, with positive or negative resource values to indicate what they produced and consumed. At first I kept track of supplies at the ship level. If the need for power across all parts on the ship was X, I added enough generators to supply X power. I didn’t care which generators supplied which components yet. I would add some graph system later to distribute the resources.
I could specify a few components to start with, and the generator would add components until all components were satisfied. Fun edge case: a ship with no components has no unmet needs, and thus is a valid ship.
Right after finishing that working algorithm that created sensible ships, I changed my data model & threw that algorithm out for a better one. I made “ResourceProducer” and “ResourceConsumer” components to add to spaceship parts. Producers could form connections to Consumers, so each component knew how its resources were allocated. When a component was damaged (remember the player-launched asteroid?) it could notify its consumers that the supplies were gone. Those parts would shut down, and their producer components would revoke resources from other components, spreading destruction across the ship.
Here a part has been hit by an asteroid (indicated by the green line) and it turns red to show its not working. Events propagate and three other components also shut down. Success!
Let’s talk a bit about that asteroid. I imagine a tiny thing going extremely fast. Anything it hits is wrecked, and it penetrates to a significant depth. Multiple parts can go offline from the initial hit, if it’s lined up correctly. I let the player orbit the ship with the camera, then click to launch the asteroid from the camera position to the cursor position. I RayCast to find the impact point, then spawn a trigger volume oriented in the same direction as the RayCast. Spaceship parts know they are damaged when their colliders intersect with the trigger. I took a few tries to get the trigger volumes transform correct. I learned that some angle vectors contain Euler angles, so the 3 components degrees of rotation around each axis. Other angle vectors are unit vectors that point in the desired direction.
The ring structure was a placeholder for a more meaningful arrangement that I had been putting off because it was difficult. I wanted the parts clustered together because that’s how we envision cool spaceships and because the player could then line up asteroid impacts on multiple parts. Parts should be connected by wires or corridors. Parts that shared resources should be close together. Engines should be in the back. Fuel tanks should be far away from crew quarters. There were so many constraints I could place on the system!
I was also replacing my 1-meter cubes with low-poly models of differing sizes. I tried spawning parts with space in between them, and using SpringJoints to pull them together, but SpringJoints maintain distance. I found a way to push parts away from each other, but that’s the opposite of what I wanted.
I thought about trying to place parts at the origin, seeing if they collided with anything, and pushing them to the edge of that hitbox if they did. I wasn’t sure what would happen once several parts were placed, and the first push might push the new part out of one part and into another.
I made a 2D Boolean array in which each cell represented a square meter that was either empty or occupied. As I spawned a new part, I’d get its size from its collider & try to fit a box of that size into the grid, starting at the center. If it didn’t fit, I pushed it in a random direction until it did. So my ships expanded from the center and all the parts touched each other.
But the parts only knew that other parts took up space. Related parts didn’t cluster together, and engines pointed their nozzles into bedrooms. Some algorithm research revealed that the “bin packing” problem was NP-hard, so I felt better about not immediately knowing how to proceed. I decided to sidestep the problem by rotating the engines so their nozzles were pointing down. All the parts were on the same 2D plane, so there would never be a part below an engine to get scorched. I finished replacing all the placeholders with low-poly models and felt pretty good about my complex creations.
As a final step, I added another shader to differentiate between destroyed by the asteroid (bright pink) and shut down by system failure (dark red). I’m still looking to the future, when players go inside these ships to repair them.
So it’s done! Basically. I should add some UI:instructions for how to interact with the ships. Of course, graphically indicating the connections between parts would be cool. A spiral search is probably better than random walk for placing new components. A graph-based approach could improve co-location of related parts. It would be nice to have corridors for the crew to move through. Those could be hit by asteroids too, so each room would need airlocks. Are the airlocks dependent on main power to operate….?
Like I said, it’s basically done!