Table of contents

How To Tame Your DragonRuby Color Palette

A common problem I’ve been noticing in my DragonRuby projects is I’m not really consistent with colors in the palette. Now generally we’re going to be using sprites which have their own colors defined, but it can be nice to be able to draw primitives with consistent colors.

So here’s a very simple approach you can use. Feel free to extend it to fit your needs.

Ruby

If you’ve never seen the ** syntax in Ruby, it is basically an easy way to “merge” a hash into another hash.

Think of it like a shortcut to doing:

Ruby
  blue_box = box.merge({
    y: 125,
  }).merge(PALETTE.blue)

Sometimes its referred to as a “double splat operator” and has other use cases for things like keyword arguments that we won’t cover here.

The above code will produce 2 solid colored boxes like so:

Picture of 2 boxes, one red, one blue stacked on top of each other.

Now we could go one step further and define some “alpha” channels for our boxes.

Ruby

And now lets take these added alpha channels and change the blue box to be “mostly_transparent”

Ruby

Picture of 3 boxes, one red, one blue, and one violet stacked on top of each other.

Did that do what you expected? Probably not. The alpha channel made it like a “violet” color, but you probably expected it to just “lighten” the box, not change the actual color. We won’t dig into the “why”, but just know the color of the box will change depending on the background of your canvas. If I made the canvas black for example, the box would actually darken instead of lighten.

Since we probably want a more “consistent” transform irrespective of the background, lets look at how we can add “light” / “dark” filters on top of the box. But first, lets add a “white” and “black” to our color palette which will help us write the code for light / dark filters.

Ruby

Now that we have “black” and “white”, we can use them to “overlay” on top of a box and provide lightening / darkening of the box.

To do so, we will need 2 sprites. One will be the actual box, and the other will be a box with either white / black background color and then the corresponding “alpha” channel applied to it.

Ruby

All boxes stacked

And there we have it! Using our palette, we wrote some boxes and even added a way to lighten / darken our sprites by overlaying another sprite with a different alpha channel!

The beauty of the palette is you can always override for one offs where needed.

You can do things like:

Ruby

Overall, I think its a fairly flexible pattern, and if you’re feeling real spicy, you could structure it “semantically” where you use things like “success”, “warning”, “danger” for your color tokens, or you could even have numbered tokens like many popular web libraries. Heck, you could even provide both and mix / match!

Ruby

We could even do other things like make a palette class and define different themes.

Ruby

The world is your oyster! I thought of this pattern while I was tired of constantly doing {r:, g:, b:, a:} everywhere and yearned for a better way to define color tokens.

Bonus points

Sometimes you have color palettes defined in hex codes. Thanks to Levi from the DragonRuby discord we can also define our colors as hex codes (both string and integer format)

https://discord.com/channels/608064116111966245/608064116984250379/1277372253889232989

And for posterity, here is the code in case the discord link wants to be silly.

Ruby

Also of note:

it is not performant in the slightest but it does work

So be mindful when using hex codes, probably dont want to do this on every tick. But one time on startup initialization shouldn’t be a problem.

EDIT: Thanks to TheCire from Discord for pointing out the “Color” module for predefined colors and converters!

https://github.com/xenobrain/rubycolors/blob/main/color.rb

That is all folks! Thanks for reading! Time to get back to making games…