This class is used to draw an old school flame on a canvas element. I'm wondering if there is any way to speed up the fire
method. The class is based on old C code.
LayerFire = {
init : function(options, elem) {
this.options = $.extend({
width : '320',
height : '240'
},
this.options, options);
this.elem = elem;
this.$elem = $(elem);
// Create our buffer
this.bufferp = [];
this.buffer = [];
var i = this.options.width * this.options.height * 4;
while (i--) {
this.bufferp[i] = 0;
this.buffer[i] = 0;
}
// Create the palette
this.palette = [];
this.makePalette();
// Initilize our main loop
var t = this;
this.updater = setInterval(function() {t.fire.apply(t);}, 125);
},
makePalette : function ()
{
// make a nice looking color palette for a flame
for (i = 0; i < 256; i++) {
this.palette[i] = Object.create(VideoColor);
}
for (i = 0; i < 32; i++)
{
/* black to blue, 32 values*/
this.palette[i].b = i << 1;
this.palette[i].a = 255;
/* blue to red, 32 values*/
this.palette[i + 32].r = i << 3;
this.palette[i + 32].b = 64 - (i << 1);
this.palette[i + 32].a = 255;
/*red to yellow, 32 values*/
this.palette[i + 64].r = 255;
this.palette[i + 64].g = i << 3;
this.palette[i + 64].a = 255;
/* yellow to white, 162 */
this.palette[i + 96].r = 255;
this.palette[i + 96].g = 255;
this.palette[i + 96].b = i << 2;
this.palette[i + 96].a = 255;
this.palette[i + 128].r = 255;
this.palette[i + 128].g = 255;
this.palette[i + 128].b = 64 + (i << 2);
this.palette[i + 128].a = 255;
this.palette[i + 160].r = 255;
this.palette[i + 160].g = 255;
this.palette[i + 160].b = 128 + (i << 2);
this.palette[i + 160].a = 255;
this.palette[i + 192].r = 255;
this.palette[i + 192].g = 255;
this.palette[i + 192].b = 192 + i;
this.palette[i + 192].a = 255;
this.palette[i + 224].r = 255;
this.palette[i + 224].g = 255;
this.palette[i + 224].b = 224 + i;
this.palette[i + 224].a = 255;
}
},
fire : function() {
// create a ransom flame at the bottom of the screen
y = this.options.width * (this.options.height- 1);
for (x = 0; x < this.options.width; x+=3)
{
var random = 1 + (16 * ((Math.random() * 32767) / 32767) + 1.0);
if (random > 11) {
/*hot*/
this.bufferp[y + x] = 200;
this.bufferp[y + x + 1] = 255;
this.bufferp[y + x + 2] = 200;
} else {
this.bufferp[y + x] = 50;
this.bufferp[y + x + 1] = 20;
this.bufferp[y + x + 2] = 50;
}
}
// move the flame up
var top = this.options.height;
if (top > 110)
top = 110;
for (index = 0; index < top ; ++index)
{
for (x = 0; x < this.options.width; x++)
{
if (x == 0) /* at the left border*/
{
temp = this.bufferp[y];
temp += this.bufferp[y + 1];
temp += this.bufferp[y - this.options.width];
temp /= 3;
}
else if (x == this.options.width - 1) /* at the right border*/
{
temp = this.bufferp[y + x];
temp += this.bufferp[y - this.options.width + x];
temp += this.bufferp[y + x - 1];
temp /= 3;
}
else
{
temp = this.bufferp[y + x];
temp += this.bufferp[y + x + 1];
temp += this.bufferp[y + x - 1];
temp += this.bufferp[y - this.options.width + x];
temp /= 4;
}
if (temp > 1)
temp -= 1; /* decay */
this.bufferp[y - this.options.width + x] = Math.round(temp);
}
y -= this.options.width;
}
// copy the palette buffer to display buffer
for (x = 0; x < this.options.width; x++)
{
for (y = 0; y < this.options.height; y++)
{
var index = (y * this.options.width + x) * 4;
var c = this.bufferp[(y * this.options.width) + x];
//console.log(c);
this.buffer[index+0] = this.palette[c].r;
this.buffer[index+1] = this.palette[c].g;
this.buffer[index+2] = this.palette[c].b;
this.buffer[index+3] = this.palette[c].a;
}
}
}
};
Working demo here.