3A custom ruby library

The custom ruby library library/palette/palette.rb

class Palette
  include Propane::Proxy # needed to access 'color' and 'map1d'
  attr_reader :palette

  def initialize
    @palette = make_palette
  end

  def make_palette
    (0..256).map do |i|
      # Create the bands of colour for the palette (256 is the maximum colour))
      case i
      when 0..64 # Range of reds
        color(*[map1d(i, 0..64, 1..255), 0, 0])
      when 64..128 # Range of orange
        color(*[255, map1d(i, 64..128, 1..255), 0])
      when 128..172 # range of yellow
        color(*[255, 255, map1d(i, 128..172, 1..255)])
      else
        color(*[180, 0, 0])
      end
    end
  end

  def self.create_palette
    Palette.new.palette
  end
end

A sketch using the custom palette library:-

require 'propane'

# After original by Alex Young https://github.com/alexyoung/fire-p5r

# Algorithm:
# 1. Create an indexed palette of red, orange and yellows
# 2. Loop:
# 3.   Draw a random set of colours from the palette at the bottom of the screen
# 4.   Loop through each pixel and average the colour index value around it
# 5.   Reduce the average by a fire intensity factor

# jruby fire.rb
class Fire < Propane::App
  load_library :palette

  def settings
    size 320, 240
  end

  def setup
    sketch_title 'Fire'
    frame_rate 30
    @palette = Palette.create_palette
    @fire = []
    @scale = 8
    @width = width / @scale
    @height = height / @scale
    @intensity = 2
  end

  def draw
    background 0
    update_fire
  end

  def update_fire
    random_line @height - 1
    (0..@height - 2).each do |y|
      (0..@width).each do |x|
        # Wrap
        left = x.zero? ? fire_data(@width - 1, y) : fire_data(x - 1, y)
        right = (x == @width - 1) ? fire_data(0, y) : fire_data(x + 1, y)
        below = fire_data(x, y + 1)
        # Get the average pixel value
        average = (left.to_i + right.to_i + (below.to_i * 2)) / 4
        # Fade the flames
        average -= @intensity if average > @intensity
        set_fire_data x, y, average
        fill @palette[average]
        stroke @palette[average]
        rect x * @scale, (y + 1) * @scale, @scale, @scale
      end
    end
  end

  def fire_data(x, y)
    @fire[offset(x, y)]
  end

  def set_fire_data(x, y, value)
    @fire[offset(x, y)] = value.to_i
  end

  def random_offset
    rand(0..@palette.size)
  end

  def random_line(y)
    (0...@width).each do |x|
      @fire[offset(x, y)] = random_offset
    end
  end

  def offset(x, y)
    (y * @width) + x
  end
end

Fire.new

See also this example, makes most sense when you might re-use your library for several sketches.