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!
<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)
Offline
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
Offline
Noooo!!! You made my triangles green!!
Just kidding
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)
Offline
MoreGamesNow wrote:
Noooo!!! You made my triangles green!!
![]()
Just kidding![]()
Thanks for putting it online!
lol! just expirimenting! They're red now!
Offline
MathWizz wrote:
Niiiiiiiiice!
Thanks
Whoops, might have been braking some kind of agreement with Zymic (the website hoster). Fixed now (the copyright stuff at the bottom)
Offline
WindowsExplorer, I think you messed it all up
Besides, you don't need a web server to view HTML
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
LS97 wrote:
WindowsExplorer, I think you messed it all up
![]()
Besides, you don't need a web server to view HTML![]()
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?
Offline