2
\$\begingroup\$

I'm trying to create a light system, with the midpoint algorithm and Bresenham Line Algorithm. I'm trying to redraw all the time (1 option) or redraw when I need to. When the circles are too big it becomes a bit laggy.

Example

function Light(x, y, range)
{
    this.CordX = x;
    this.CordY = y;
    this.LuminosityRange = range;
}
   setInterval(function(){
        stats.begin(); // Begin to count FPS
        ctx.clearRect(0, 0, Width, Height); // Clear Canvas

        // STEP 1 -- DRAW THE BACKGROUND (BLACK)
        for(var y = 0; y < Height; y++)
        {    
            for(var x = 0; x < Width; x++)
            {
                var index = x + (y * Width),
                    indexColor = index * 4;

                shadowBitMapData[indexColor + 0] = shadowBitMapData[indexColor + 1] = shadowBitMapData[indexColor + 2] = 0;
                shadowBitMapData[indexColor + 3] = 255;
            }
        }

        // SETEP 2 -- DRAW THE LIGHT
        for(var light = 0; light < lamps.length; light++)
        {
            var currentLight = lamps[light];
            var xCL = ~~currentLight.CordX,
                yCL = ~~currentLight.CordY,
                iCL = xCL + (yCL * Width),
                rCL = ~~currentLight.LuminosityRange;

            // MidPoint Algorithm
            var xMP = rCL,
                yMP = 0,
                rEMP = 1 - xMP;

            while(xMP >= yMP)
            {

                var x1 = xMP + xCL,
                    x2 = yMP + xCL,
                    x3 = -xMP + xCL,
                    x4 = -yMP + xCL;

                var y1 = yMP + yCL,
                    y2 = xMP + yCL,
                    y3 = -yMP + yCL,
                    y4 = -xMP + yCL;

                var index1 = x1 + (y1 * Width);
                var index2 = x2 + (y2 * Width);

                var index3 = x3 + (y1 * Width);
                var index4 = x4 + (y2 * Width);

                var index5 = x3 + (y3 * Width);
                var index6 = x4 + (y4 * Width);

                var index7 = x1 + (y3 * Width);
                var index8 = x2 + (y4 * Width);


                // Fill Top
                //shadowBitMapData[index6 * 4 + 3] = 0;
                //shadowBitMapData[index8 * 4 + 3] = 0;
                BresenhamLine(x4, y4, x2, y4, shadowBitMapData, Width);

                // Fill Mid Top
                //shadowBitMapData[index5 * 4 + 3] = 0;
                //shadowBitMapData[index7 * 4 + 3] = 0;
                BresenhamLine(x3, y3, x1, y3, shadowBitMapData, Width);

                // Fill Mid Bottom
                //shadowBitMapData[index1 * 4 + 3] = 0;
                //shadowBitMapData[index3 * 4 + 3] = 0;
                BresenhamLine(x1, y1, x3, y1, shadowBitMapData, Width);

                // Fill Bottom
                //shadowBitMapData[index2 * 4 + 3] = 0;
                //shadowBitMapData[index4 * 4 + 3] = 0;
                BresenhamLine(x2, y2, x4, y2, shadowBitMapData, Width);

                yMP++;

                if (rEMP < 0)
                {
                    rEMP += 2 * yMP + 1;
                }
                else
                {
                    xMP--;
                    rEMP += 2 * (yMP - xMP + 1);
                }
            }
        }

        ctx.putImageData(shadowBitMap, 0, 0); // Draw Shadow
        stats.end(); // End to count FPS
    }, 1000 / 60);

function BresenhamLine(x0, y0, x1, y1, bitmap, Width)
{
    var dx = Math.abs(x0 - x1);
    var dy = Math.abs(y0 - y1);

    var sx = x1 < x0 ? 1 : -1; 
    var sy = y1 < y0 ? 1 : -1; 

    var err = dx - dy;
    var e2;

    var lm = 0;
    while (true)
    {
        bitmap[(x1 + y1 * Width) * 4 + 3] = 0;

        if (x1 == x0 && y1 == y0) break;

        e2 = 2 * err;
        if (e2 > -dy) 
        {
            err = err - dy;
            x1 = x1 + sx;
        }

        if (e2 < dx) 
        {
            err = err + dx;
            y1 = y1 + sy;
        }
    }
}
\$\endgroup\$
5
  • 4
    \$\begingroup\$ Greetings, it would help us tremendously if you could set up a working jsbin/jsfiddle/plnkr and provide us the link. \$\endgroup\$
    – konijn
    Aug 19, 2014 at 19:45
  • \$\begingroup\$ Also, can you define what too big is ? \$\endgroup\$
    – konijn
    Aug 19, 2014 at 20:30
  • 1
    \$\begingroup\$ Sorry!, here is the example! jsfiddle.net/876mv13n \$\endgroup\$ Aug 19, 2014 at 22:53
  • \$\begingroup\$ Minor point: ~~ is cute but doesn't offer a huge performance gain over Math.floor(), which is infinitely more readable. \$\endgroup\$
    – Schism
    Aug 20, 2014 at 3:02
  • \$\begingroup\$ Why are you not using the drawing functions of the canvas? \$\endgroup\$ Sep 24, 2014 at 15:27

1 Answer 1

2
\$\begingroup\$

Don't Reinvent the Wheel

In your "STEP 1", you are manually setting each pixel of the background to black. This is expensive and unnecessary. You can simply draw a black rectangle the size of the canvas:

ctx.fillStyle = "rgb(0, 0, 0)";
ctx.fillRect(0, 0, Width, Height);

Next, in "STEP 2" why are you using your own line drawing routines? You could simply call the built-in routines, like:

ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.stroke();

And to draw circles, you can use the arc() method:

ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2.0 * Math.PI, false);
ctx.fillStyle = "rgb (1, 1, 1);"
ctx.fill();

This will likely be much faster than rolling your own.

Naming

I find your variable names hard to read and understand. Names like xCL, yCL and xMP, yMP are not very descriptive. Maybe centerX, centerY and midPointX and midPointY instead?

Also, iCL seems to be unused. It can be removed.

Abuse of Lambdas

Your entire drawing function (the main purpose of your program) is an anonymous function passed as an argument to another function. It's difficult to follow the flow of it all, and it's odd that the most important thing in your code is a single argument to a function that merely collects stats.

And then you mix in stats collection in the actual function that does the drawing. I'd separate it all out, like this:

function draw()
{
... all the drawing code...
}

function collectDrawStats()
{
    stats.begin();
    draw();
    stats.end();
}

setInterval(collectDrawStats(), 1000 / 60);

Avoid Magic Numbers

What is the 1000 / 60 in the call to setInterval()? Does that have something to do with the refresh rate being 60 fps? You should create a named constant that tells a reader what it means. Is it milliseconds per 60th of a second? If so, what's the significance of that?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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