3
\$\begingroup\$

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.

\$\endgroup\$
  • 2
    \$\begingroup\$ Do you have a runnable example (perhaps in a jsFiddle)? It's hard to run performance tests on a piece of code that you can't run because you're missing pieces that are need to make it run or don't know what sequence to call it to make it run. \$\endgroup\$ – jfriend00 Mar 21 '12 at 3:29
1
\$\begingroup\$

I'm not really an expert on speed optimization, but here are some thoughts:

  • You should keep references/copies to often used objects/values instead of accessing them repeatedly through properties, e.g:

var bufferp = this.bufferp;
var width = this.options.width;
var height = this.options.height;
  • There are some variables (such as x and y which you haven't declared as local with var).

  • What is the point of (Math.random() * 32767) / 32767? As far as I can tell it does nothing.

| improve this answer | |
\$\endgroup\$
-2
\$\begingroup\$

(Math.random() * 32767) / 32767 - induced giggles. :)

(Not very helpful I know but hey, ‘we can’t all be Astronauts’)

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ This looks a comment to RoToRa's answer - just comment there, and or post your own answer. \$\endgroup\$ – greybeard Dec 23 '17 at 10:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.