Simplified Fluid Storage System

(A flaw in the design of this system was fixed and posted about here.)

One of my game ideas involves constructing 2D spaceships, and the concept of a simplified system for storing fuel, oxygen, water – really any kind of fluid mixture – in storage tanks. Along with this, it allows simulating breaches between containers, hard vacuum, and the pressurized areas of the ship itself!

{ -- a rough approximation of Earth's atmosphere
  pressure: 1
  volume: 4.2e12 -- 4.2 billion km^3
  contents: {
    nitrogen: 0.775
    oxygen: 0.21
    argon: 0.01
    co2: 0.005
  }
}

{ -- hard vacuum
  pressure: 0
  volume: math.huge -- infinity
  -- the contents table will end up containing negative infinity of anything that leaks into the vacuum
}

It all comes down to storing a total pressure and volume per container, and a table of contents as percentages of the total mixture. The total amount of mass in the system can be easily calculated (volume * pressure), as can the amount of any item in the system ( volume * pressure * percent).

Breaches are stored as a reference in the container with a higher pressure, and a size value is added to the container with lower pressure (representing the size of the hole between them).

screenshot of testing my fluid system
A sequence of tests.

Limitations

  • Everything has the same density and mixes evenly.
  • There are no states of matter, everything is treated as a gas.
  • Attempting to directly modify the amount of a fluid is prone to floating-point errors it seems, while mixing containers via the breach mechanic is working as expected.

The code was written in MoonScript / Lua and is available here.

My First Ludum Dare (#32)

Grand Theft Papercut

This was the 4th Ludum Dare that I wanted to participate in, and the first where I actually did. I was inspired by my recent discovery of a GameBoy GTA game, and my unconventional weapon (theme) was a deck of cards.

It was also my first time making anything tile-based, and it worked very well for my experience at the time. Even better, it was the first time I had the capability to load and save, and the game was also the map editor for the game. Very much something I’d like to do again sometime.

You can go play the prototype here.

Realistic Star Frequencies/Colors

UPDATE: A much better resource for frequencies of types of stars is on this wiki page for Elite: Dangerous.

I’ve done a lot of research on stellar classification, perhaps too much. Here’s a visual representation (not at all to scale!) of stars by type from O to L.. and L is a brown dwarf, so it’s not technically a “star” per say.

Stars by type, in order: OBAFGKML

And here’s a table of those color values (in percents RGBA):

  O: {0.521, 0.521, 0.996, 1}
  B: {0.701, 0.898, 1, 1}
  A: {1, 1, 1, 1}
  F: {1, 0.996, 0.780, 1}
  G: {0.988, 0.972, 0.250, 1}
  K: {0.905, 0.549, 0.015, 1}
  M: {0.847, 0.011, 0.031, 1}
  L: {0.302, 0.187, 0.177, 1}

As for the frequencies (as in, percent of stars that are a specific type), they have been slightly manipulated (if I am remembering correctly) to make the rarest types a little more common, but are based on my best guesses from research:

  O: 0.00003
  B: 0.13
  A: 0.6
  F: 3
  G: 7.6
  K: 12.1
  M: 76.45
  L: 0.11

A couple last notes:

  • There are two more brown dwarf / substellar mass classifications I could be using (T and Y), but I am not because they are not commonly visible.
  • Because L-type (and T & Y) “stars” are so hard to see, it is entirely possible they could outweigh the existence of other types, but we just can’t see them!

Code to create the image above is available here.

A Years’ Late Post-Mortem (LD34)

Opcode-Powered Shuttle at the end of LD34

The Beginning

Suddenly it was time. I didn’t plan or prepare, I hadn’t coded in a little while. I decided the jam would jolt me back into coding, I also livestreamed most of my development to force me to keep working at it.

The Story

The first evening and morning worked great (Ludum Dare starts at 6pm in my timezone). A few hours on the idea, several more designing the controls (in retrospect, I spent too much time deciding on the structure of the opcodes). At some point, I hand-drew graphics, but threw them out because I could not get my scanner working.

I built the graphics for a few things, started placing them in-game, and decided I needed to rewrite everything. I quit streaming, took a laptop out to a Starbucks, and spent a few hours doing just that. It was a good break, good exercise (cycling a few miles), but wasted a lot of time.

The 2nd evening involved more streaming, things moving and generating.. Now for the game part, the 2nd morning, I didn’t stream because I was fully in crunch-time-mode over the last few hours. I focused on a communications system (which was broken, badly coded, and led to me releasing a game-crashing bug).

The Result

I decided to make something with a huge scope. All my time went into working on UI components and controls. There is no game, but a few mechanics to build a game within.

Positives? I got back into coding for a bit, I got to check out a lot of others’ games because I made sure to rate a bunch of them, and I felt more on track with my life.

It did burn me out though, so much so that it took a long time to write anything about it.. and even longer to actually publish it!


Want to play it? Click here.

Trying to Understand Noise

Perlin noise and simplex noise are the topics I keep coming back to, because I know they form the basis of a lot of procedurally generated content. All I knew about them to start with was give this function a value for 1 to 4 dimensions, and it will return a “random” value that is constant based on the input.

There is a somewhat ambiguous warning about passing integers “might” lead to a constant result. No, it will always be the same value at any integer. Turns out this is fundamental to how noise functions work:

graphic examples of how Perlin noise is constructed

One explanation I’ve read says that Perlin noise is essentially mixing dot products from 4 vectors from neighboring integers to the exact point you’ve chosen and 4 copies of a constant vector present at each of those “corners.” This is represented by the arrows in the above image.

A consequence of the constant vector at every integer value is that any integer will return the exact same value.

1D simplex noise is remarkably similar to a sine wave

Another explanation describes a noise function as mixed sine functions of differing amplitudes and frequencies. Looking at an output from 1-dimensional noise definitely can make it appear to be that simple, but it isn’t. I mention this idea for three reasons:

  1. It looks similar. This can help trying to visualize it.
  2. It is periodic, you do not have an infinite domain of values to choose from without repetition.
  3. Some terminology can still apply, such as adjusting the frequency or amplitude of noise, and depending on implementation, the range can be the same (or something easy like LÖVE‘s 0 to 1).
visual representation of properties of waves

Noise Usage

I have been trying to use noise for quite a while, with a lot of failure, mainly around not understanding the domain and range of the noise function. As of now, these are the things I’ve learned:

  • Period / Domain: There is a sample of (usually) 256 values used for the constant vectors, this defines the period before the noise function starts repeating. Keep this in mind combined with other adjustments to hide or avoid this repetition. (This is how I discovered the period of LÖVE’s implementation.)
  • Frequency: A higher frequency can be achieved by stretching the input, leading to quicker, more dramatic transitions.
  • Amplitude: This one feels kind of obvious, but with LÖVE, the output is 0 to 1, so that needs to be mapped to whatever range is desired.

Sources (aside from those linked in-article):

My apologies, but any other relevant sources at this time have been lost to the ages, with the possible exception of the source code to a demake of No Man’s Sky I have put some work into. I will revisit that at a later date.