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:

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.

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).

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.

Breakable Objects & Walls: A One Hour Game Jam Post-Mortem

(This post has been imported from an old blog of mine.)

The One Hour Game Jam is a weekly game jam, of one hour. I participated in #64 long time ago (though I did not get anywhere), and more recently, #152. The submission period is for the entire week, so if you can’t make the official hour, you can still participate. There’s also a Discord server for it, and weekly livestreams during the official hour and playing the games after.

Breakable Objects (#152)

Long story short, this one was a big success for me. I took about 2 hours to make the game* and a couple hours over the next couple days polishing it and adding quality of life features. I made a simple asteroid-dodging game, Asteroid Dodge. Newtonian physics, the number of asteroids increases every second, and your score is based on how quickly you travel between randomly created waypoints. Everything is circles and lines, inspired by a realistic air traffic control project I had just started (see Endless ATC, a game similar to what I’m aiming for).

My biggest success and failure was the same thing: Deciding to make a version-checking library during a game jam. I knew very quickly that I was going to be rapidly iterating on the idea (even once published), and I wanted to be able to notify players. I’d done this for SCP Clicker some time ago, but that was hardcoded for it only, and I needed something for any game project going forward. It was a success because I made something I’m happy with, a failure because it took too much time away from the game itself.

I’m very glad to have managed to get my game shown on the livestream, even though it required making them wait and was the last thing shown (whoops!). I was able to watch people have their first impression and read comments from stream viewers, and thus noticed bugs and improvements to be made. Also, the original score was based on velocity alone, which made it feel like there was no goal. What I had when the jam was over was pretty crap, but I also knew exactly what to do to make it a finished (albeit small) game.

Walls (#153)

Or, as is relevant to here: Ambition Destruction. I spent the first 20 minutes thinking of an idea, ultimately deciding to make a clicker/incremental-type game about being contracted to build Trump’s “great wall”. After struggling through some GUI code and realizing I needed to make a vector map of the southern border of the US for what I was imagining, wasting another 20 minutes, I realized this idea was waaay too ambitious for the timeframe and my knowledge, and did something simpler: click to place bricks on a wall. After working on the graphics of building a brick wall for the last 20 minutes, I realized even this was too ambitious, as it required me to code something I hadn’t done before, and figure out how to do incremental upgrades (something I’ve only done very limited experimentation with so far).

Ultimately, I never submitted anything for this jam. A couple days after those two failures, I had another idea based on the player being a firewall, that slowly morphed into the player running an ISP, building out a network (how does this relate to the theme? well eventually you’d put in firewalls when there was too much traffic). I still want to finish that idea someday, but even after working on the plans for a while without coding it, I realized that I would again need to code some things I am unfamiliar with, and I believe it too ambitious to work on right now.

Lessons Learned

Some of these became much more apparent the second time around, but all of these are relevant to both weeks:

  • Use libraries that are simple, or that you have used recently. The second week, I struggled a lot using Pop.Box, an alpha-stage GUI library. I hadn’t worked with it in a very long time, so I ended up spending way too much time looking into the code or documentation to remember how to use it. If I had been using it more recently (or, let’s be honest here, if it was a better library), I wouldn’t have had nearly as much trouble and wasted time there. I could also say don’t use alpha-stage libraries, but as far as I am currently aware, there isn’t a good general-purpose UI library for LÖVE just yet. (To the point where I am developing my own..twice now.)
  • Do not create new components. By that, I mean any aspect of code that is something you are unfamiliar with. In the simplest case, this could be something like the algorithm I made for Walls to generate a brick wall from a number (how many bricks it has). That’s a very simple piece of code (once done!) but took way too much time. Likewise, you really shouldn’t go make a version-checking library during your one tiny little freaking hour for the whole project. I got away with that once, only because I was given more time and had made something very similar to it before.
  • Strip your idea to less than the minimum, or abandon it immediately. This lesson applies a lot more strictly here than in general, but one concept that I hear is core to game design in general is to fail faster, that is, to go as quickly as you can from an idea to realizing the idea won’t work, so that you don’t waste time on it. This is especially true when you only have an hour to go from nothing to finished. Both times I spent too long thinking about ideas, and while I managed to pull something off the first time, both times I was too ambitious initially.

* Half an hour thinking of ideas, half an hour coding it, half an hour making a version-checking library for it, half an hour setting up a page on Itch.io and building it.