This is a read-only archive of the old Scratch 1.x Forums.
Try searching the current Scratch discussion forums.

#1 2011-11-12 15:15:39

MoreGamesNow
Scratcher
Registered: 2009-10-12
Posts: 1000+

HTML5 canvas and shadow rendering

Here's a program that renders shadows.  Your mouse is the light source.  I've included comments that should, hopefully, demonstrate the purpose:  to easily add triangles to the canvas and have to code adjust.  I've commented out a sixth triangle, and by un-commenting the lines of code out, you should end up with a sixth triangle, and hopefully a good idea of how to add more:

This should work in any internet browser that supports HTML5 canvas (e.g. Not Internet Explorer).  I've tested it on Firefox and Safari.

To run, save it as a .html file using Notepad (or Textedit on a mac).  Then open it using an internet browser (e.g. Firefox).

Edit: click here to see the program in action!

Code:

<HTML>
<SCRIPT TYPE="text/javascript">
var MouseX = 0;
var MouseY = 0;
function getMouseXY(e)
{
    MouseX = e.pageX;
    MouseY = e.pageY;  
    if (tempX < 0)
    {
        MouseX = 0;
    }
    if (tempY < 0)
    {
        MouseY = 0;
    }
}


/*

To add a triangle:
a) add an array to the arrays below (e.g. t6 = [x1,y1,x2,y2,x3,y3])
b) go to the for loop that has t[i]=t1[i], and add your triangle (e.g. t[i+30]=t6[i] )
c) render the triangle similar to the others (e.g. see below)

    context.beginPath();
    context.moveTo(t2[0],t2[1]);
    context.lineTo(t2[2],t2[3]);
    context.lineTo(t2[4],t2[5]);
    context.fill();

*/

var t1 = [100,100,180,140,100,180];
var t2 = [50,200,140,240,140,280];
var t3 = [250,250,250,300,300,250];
var t4 = [250,300,300,300,300,250];
var t5 = [400,300,450,300,425,350];
// var t6 = [400,125,450,175,350,125];
function Draw()
{
    var cvs = document.getElementById("cvns");
    var context = cvs.getContext("2d");
    context.fillStyle = "tan";
    context.fillRect(0,0,cvs.width,cvs.height);
        
    var t = new Array(12);
    var i;
    for(i=0; i<6; i++)
    {
        t[i]=t1[i];
        t[i+6]=t2[i];
        t[i+12]=t3[i];
        t[i+18]=t4[i];
        t[i+24]=t5[i];
//        t[i+30]=t6[i];
    }
    var points = Triangles(MouseX-8,MouseY-8,t);
    
    context.fillStyle="black";

    for(i=0; i<points.length; i+=6)
    {
        context.beginPath();
        context.moveTo(points[i],points[i+1]);
        context.lineTo(points[i+2],points[i+3]);
        context.lineTo(points[i+4],points[i+5]);
        context.fill();
        
        context.beginPath();
        context.moveTo(points[i],points[i+1]);
        context.lineTo(points[i+2],points[i+3]);
        context.lineTo(points[i+4],points[i+5]);
        context.fill();
    }
    
    context.fillStyle = "gray";        // draw triangles
    context.beginPath();
    context.moveTo(t1[0],t1[1]);
    context.lineTo(t1[2],t1[3]);
    context.lineTo(t1[4],t1[5]);
    context.fill();
    
    context.beginPath();
    context.moveTo(t2[0],t2[1]);
    context.lineTo(t2[2],t2[3]);
    context.lineTo(t2[4],t2[5]);
    context.fill();

    context.fillRect(250,250,50,50);        // the square is two right triangles
    
    context.beginPath();
    context.moveTo(t5[0],t5[1]);
    context.lineTo(t5[2],t5[3]);
    context.lineTo(t5[4],t5[5]);
    context.fill();
    
//    context.beginPath();
//    context.moveTo(t6[0],t6[1]);
//    context.lineTo(t6[2],t6[3]);
//    context.lineTo(t6[4],t6[5]);
//    context.fill();

    context.beginPath();
    context.fillStyle="red";
    context.arc(MouseX-8,MouseY-8,3,0,2*Math.PI,false);
    context.fill();    
}
function theta(x,y,t)        // used in farpoint function
{
    return Math.acos(((t[0]-x)*(t[2]-x)+(t[1]-y)*(t[3]-y))/(Math.sqrt((t[0]-x)*(t[0]-x)+(t[1]-y)*(t[1]-y))*Math.sqrt((t[2]-x)*(t[2]-x)+(t[3]-y)*(t[3]-y))));
}
function farpoint(x,y,t)  // finds the point that is between the other two, and therefore can be ignored
{
    var a = theta(x,y,[t[0],t[1],t[2],t[3]]);
    var b = theta(x,y,[t[2],t[3],t[4],t[5]]);
    var c = theta(x,y,[t[0],t[1],t[4],t[5]]);
    if(a>b && a>c)
        {
        return 2;
    }
    else if(b>c)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}
function Triangles(x,y,t)
{
    var far = new Array(t.length/6);
    var i;
    for(i=0; i<far.length; i++)
    {
        far[i] = (farpoint(x,y,[t[i*6],t[i*6+1],t[i*6+2],t[i*6+3],t[i*6+4],t[i*6+5]]))
    }
    var j = 0;
    var slope = new Array (2);                // the slope of the shadow
    var b = new Array (2);                    // the y-intercept of the shadow (y=mx+b)
    var r = new Array(4*t.length/3);        // return the points
    var rr;                                    // used to correlate the "r" list (quadrilateral points), to the "t" list (old triangle points)
    for(i=0; i<t.length; i+=6)
    {
        rr = (8*i/6);
        if(far[i/6]==0)
        {
            slope[0]=(y-t[i+3])/(x-t[i+2]);
            slope[1]=(y-t[i+5])/(x-t[i+4]);
            b[0]=y-(slope[0]*x);
            b[1]=y-(slope[1]*x);
            r[rr]=t[i+2];
            r[rr+1]=t[i+3];
            r[rr+6]=t[i+4];
            r[rr+7]=t[i+5];
            if(t[i+2]>x)
            {
                r[rr+2] = 10000;
                r[rr+3] = slope[0]*10000+b[0];
            }
            else if(t[i+2]<x)
            {
                r[rr+2] = -10000;
                r[rr+3] = slope[0]*-10000+b[0];
            }
            else
            {
                r[rr+2]=x;
                if(t[i+3]>y)
                {
                    r[rr+3]=10000;
                }
                else
                {
                    r[rr+3]=-10000;
                }
            }
            if(t[i+4]>x)
            {
                r[rr+4] = 10000;
                r[rr+5] = slope[1]*10000+b[1];
            }
            else if(t[i+4]<x)
            {
                r[rr+4] = -10000;
                r[rr+5] = slope[1]*-10000+b[1];
            }
            else
            {
                r[rr+4]=x;
                if(t[i+5]>y)
                {
                    r[rr+5]=10000
                }
                else
                {
                    r[rr+5]=-10000
                }
            }
        }
        else if(far[i/6]==1)
        {
            slope[0]=(y-t[i+1])/(x-t[i]);
            slope[1]=(y-t[i+5])/(x-t[i+4]);
            b[0]=y-(slope[0]*x);
            b[1]=y-(slope[1]*x);
            r[rr]=t[i];
            r[rr+1]=t[i+1];
            r[rr+6]=t[i+4];
            r[rr+7]=t[i+5];
            if(t[i]>x)
            {
                r[rr+2] = 10000;
                r[rr+3] = slope[0]*10000+b[0];
            }
            else if(t[i]<x)
            {
                r[rr+2] = -10000;
                r[rr+3] = slope[0]*-10000+b[0];
            }
            else
            {
                r[rr+2]=x;
                if(t[i+1]>y)
                {
                    r[rr+3]=10000;
                }
                else
                {
                    r[rr+3]=-10000;
                }
            }
            if(t[i+4]>x)
            {
                r[rr+4] = 10000;
                r[rr+5] = slope[1]*10000+b[1];
            }
            else if(t[i+4]<x)
            {
                r[rr+4] = -10000;
                r[rr+5] = slope[1]*-10000+b[1];
            }
            else
            {
                r[rr+4]=x;
                if(t[i+5]>y)
                {
                    r[rr+5]=10000;
                }
                else
                {
                    r[rr+5]=-10000;
                }
            }
        }
        else
        {
            slope[0]=(y-t[i+1])/(x-t[i]);
            slope[1]=(y-t[i+3])/(x-t[i+2]);
            b[0]=y-(slope[0]*x);
            b[1]=y-(slope[1]*x);
            r[rr]=t[i];
            r[rr+1]=t[i+1];
            r[rr+6]=t[i+2];
            r[rr+7]=t[i+3];
            if(t[i]>x)
            {
                r[rr+2] = 10000;
                r[rr+3] = slope[0]*10000+b[0];
            }
            else if(t[i]<x)
            {
                r[rr+2] = -10000;
                r[rr+3] = slope[0]*-10000+b[0];
            }
            else
            {
                r[rr+2]=x;
                if(t[i+1]>y)
                {
                    r[rr+3]=10000;
                }
                else
                {
                    r[rr+3]=-10000;
                }
            }
            if(t[i+2]>x)
            {
                r[rr+4] = 10000;
                r[rr+5] = slope[1]*10000+b[1];
            }
            else if(t[i+2]<x)
            {
                r[rr+4] = -10000;
                r[rr+5] = slope[1]*-10000+b[1];
            }
            else
            {
                r[rr+4]=x;
                if(t[i+1]>y)
                {
                    r[rr+5]=10000;
                }
                else
                {
                    r[rr+5]=-10000;
                }
            }
        }
    }
    
    /*To make a long story short, my brother and I are trying to add multiple light sources to this.  This meant that I had to change this code to return triangles, rather than quadrilaterals.  The code above was supposed to return the "r" list of quadrilateral points, but the code below rewrites each quadrilateral as two triangles, and returns that instead*/
    
    
    slope = new Array (3*r.length/4)    // reusing the slope array
    var j;
    for(i=0; i<r.length; i+=8)
    {
        j = 3*i/2;            // 2*(3/4)
        slope[j] = r[i];        // first triangle
        slope[j+1] = r[i+1];
        slope[j+2] = r[i+2];
        slope[j+3] = r[i+3];
        slope[j+4] = r[i+4];
        slope[j+5] = r[i+5];
        
        slope[j+6] = r[i];    // second triangle
        slope[j+7] = r[i+1];
        slope[j+8] = r[i+6];
        slope[j+9] = r[i+7];
        slope[j+10] = r[i+4];
        slope[j+11] = r[i+5];
    }
    return slope;
}
</SCRIPT>
<BODY onLoad="setInterval(Draw,0);" onMouseMove="getMouseXY(event);">
<CANVAS ID="cvns" width="600" height="400">
Your Browser Does Not Support HTML5 Canvas
</CANVAS>
</BODY>
</HTML>

Last edited by MoreGamesNow (2011-11-12 18:28:42)


http://images2.layoutsparks.com/1/218929/rubiks-cube-animated-rotating.gif
"Cogito ergo sum" --  I think, therefore I am

Offline

 

#2 2011-11-12 16:02:29

WindowsExplorer
Scratcher
Registered: 2011-02-25
Posts: 1000+

Re: HTML5 canvas and shadow rendering

Coooool!! For those of you that don't have a webserver to view it, just use this link: http://www.plaxon.comyr.com/lightsource.html


http://i.imgur.com/H6LLdnK.pnghttp://i.imgur.com/VYuD7BY.png

Offline

 

#3 2011-11-12 16:06:22

MoreGamesNow
Scratcher
Registered: 2009-10-12
Posts: 1000+

Re: HTML5 canvas and shadow rendering

Noooo!!! You made my triangles green!!  yikes

Just kidding  big_smile

Thanks for putting it online!

Edit: I just clicked your link again.  Now they're red, but why is it glitching up now?  Did you change the code?

Last edited by MoreGamesNow (2011-11-12 16:07:51)


http://images2.layoutsparks.com/1/218929/rubiks-cube-animated-rotating.gif
"Cogito ergo sum" --  I think, therefore I am

Offline

 

#4 2011-11-12 16:07:35

WindowsExplorer
Scratcher
Registered: 2011-02-25
Posts: 1000+

Re: HTML5 canvas and shadow rendering

MoreGamesNow wrote:

Noooo!!! You made my triangles green!!  yikes

Just kidding  big_smile

Thanks for putting it online!

lol! just expirimenting! They're red now!


http://i.imgur.com/H6LLdnK.pnghttp://i.imgur.com/VYuD7BY.png

Offline

 

#5 2011-11-12 20:33:08

MathWizz
Scratcher
Registered: 2009-08-31
Posts: 1000+

Re: HTML5 canvas and shadow rendering

Niiiiiiiiice!


http://block.site90.net/scratch.mit/text.php?size=30&amp;text=%20A%20signature!&amp;color=333333

Offline

 

#6 2011-11-13 13:18:11

MoreGamesNow
Scratcher
Registered: 2009-10-12
Posts: 1000+

Re: HTML5 canvas and shadow rendering

MathWizz wrote:

Niiiiiiiiice!

Thanks  smile



Whoops, might have been braking some kind of agreement with Zymic (the website hoster).  Fixed now (the copyright stuff at the bottom)


http://images2.layoutsparks.com/1/218929/rubiks-cube-animated-rotating.gif
"Cogito ergo sum" --  I think, therefore I am

Offline

 

#7 2011-11-13 14:30:27

LS97
Scratcher
Registered: 2009-06-14
Posts: 1000+

Re: HTML5 canvas and shadow rendering

WindowsExplorer, I think you messed it all up  hmm

Besides, you don't need a web server to view HTML  big_smile

The original version is pretty cool, except that with some fine mouse action, you can get the shadow to end before the edge of the screen (a finite shade).

Pretty cool anyway!

Offline

 

#8 2011-11-13 15:21:46

MoreGamesNow
Scratcher
Registered: 2009-10-12
Posts: 1000+

Re: HTML5 canvas and shadow rendering

LS97 wrote:

WindowsExplorer, I think you messed it all up  hmm

Besides, you don't need a web server to view HTML  big_smile

The original version is pretty cool, except that with some fine mouse action, you can get the shadow to end before the edge of the screen (a finite shade).

Pretty cool anyway!

Do you mean is the light source is inside an object the shadows don't always go to the edge?


http://images2.layoutsparks.com/1/218929/rubiks-cube-animated-rotating.gif
"Cogito ergo sum" --  I think, therefore I am

Offline

 

Board footer