createCanvas(windowWidth, windowHeight);
energyKept = 1 - energyLoss
energyKeptOnMirror = 1 - energyLossOnMirror
snapAmount = snapSliderS.value()
zoom = zoomSlider.value()
for(let i = 0; i < walls.length; i++){
for(let i = 0; i < rays.length; i++){
returnedI = rays[i].move()
if(!rays[i].newRay && walls[returnedI].type == 'Wall'){
for(let a = 0; a < 360; a+=360/spread){
if(rays[i].brightness*energyKept > 2){
newRays.push(new ray(rays[i].x-rays[i].xVel*1 + sin(a)*4, rays[i].y-rays[i].yVel*1 + cos(a)*4, a, rays[i].brightness*energyKept))
if(walls[returnedI].type == 'Wall'){
for(let w = 0; w < walls.length; w++){
for(let r = 0; r < newRays.length; r++){
{x: newRays[r].x, y: newRays[r].y}, {x: newRays[r].x-newRays[r].xVel*4, y: newRays[r].y-newRays[r].yVel*4},
{x: walls[w].x, y: walls[w].y}, {x: walls[w].x2, y: walls[w].y2})){
if(walls[returnedI].type == 'Mirror'){
let wallAngle = atan2((walls[returnedI].x-walls[returnedI].x2),(walls[returnedI].y-walls[returnedI].y2))
let normalLine = wallAngle - 90
let a = (normalLine - (rayAngle - normalLine)) + 180
newRays.push(new ray(rays[i].x-rays[i].xVel*1 + sin(a)*1, rays[i].y-rays[i].yVel*1 + cos(a)*1, a, rays[i].brightness*energyKeptOnMirror, false, returnedI))
if(rays[i].brightness < 2){
else if ((rays[i].x > (width+20)/zoom || rays[i].x < -20) || (rays[i].y > (height+20)/zoom || rays[i].y < -20)){
for(let i = 0; i < newRays.length; i++){
rays.push(new ray(newRays[i].x, newRays[i].y, newRays[i].a, newRays[i].brightness, true, newRays[i].lastMirrorI))
if((keyIsDown(83)) && (frameCount%15==0 || (frameCount%5==0 && tool == 'Lazer'))){
if(typeSelected == 'Mirror'){
stroke(235, 236, 240, 170)
} else if(typeSelected == 'Wall'){
stroke(152, 107, 65, 170)
let snapAngle = atan2((x-snapX),(y-snapY))
if(abs(snapAngle%45) < 0+snapAmount){
snapAngle -= (snapAngle%45)
if(abs(snapAngle%45) > 45-snapAmount){
snapAngle += (45 - abs(snapAngle%45))
snapAngle -= (45 - abs(snapAngle%45))
if(abs(snapAngle)%45 == abs(round(0)) && snapOn){
let snapDist = abs(dist(snapX, snapY, x, y))
snapY = y - cos(snapAngle)*snapDist
snapX = x - sin(snapAngle)*snapDist
if(typeSelected != "Eraser" && typeSelected != "Curved"){
} else if(typeSelected == "Eraser"){
for(let e = 0; e < walls.length; e++){
if(distanceSegmentToPoint({x: walls[e].x, y: walls[e].y}, {x: walls[e].x2, y: walls[e].y2+0.01}, {x:mouseX/zoom , y:mouseY/zoom}) < 25/zoom){
if(typeSelected == 'Eraser') {
ellipse(mouseX/zoom, mouseY/zoom, 50/zoom, 50/zoom)
if(typeSelected == 'Curved'){
let parabolaPoints = createParabola(3)
stroke(235, 236, 240, 170)
for(let p = 1; p < parabolaPoints.length; p++){
line(parabolaPoints[p-1].x, parabolaPoints[p-1].y, parabolaPoints[p].x, parabolaPoints[p].y)
translate(mouseX/zoom, mouseY/zoom)
rect(0, 0, 50/zoom, 10/zoom)
if(key.toLowerCase() == 's'){
function mouseReleased(){
if(pointToSquare(mouseX, mouseY, 0, 0, 270, 80) || pointToSquare(mouseX, mouseY, 0, 0, 130, 250)){
if(pointToSquare(x*zoom, y*zoom, 0, 0, 270, 80) || pointToSquare(x*zoom, y*zoom, 0, 0, 130, 250)){
if(typeSelected == 'Curved'){
let parabolaPoints = createParabola(3)
for(let p = 1; p < parabolaPoints.length; p++){
walls.push(new wall(parabolaPoints[p-1].x, parabolaPoints[p-1].y, parabolaPoints[p].x, parabolaPoints[p].y, "Mirror"))
if(typeSelected == 'Eraser'){
let snapAngle = atan2((x-snapX),(y-snapY))
if(abs(snapAngle%45) < 0+snapAmount){
snapAngle -= (snapAngle%45)
if(abs(snapAngle%45) > 45-snapAmount){
snapAngle += (45 - abs(snapAngle%45))
snapAngle -= (45 - abs(snapAngle%45))
if(abs(snapAngle)%45 == abs(round(0)) && snapOn){
let snapDist = abs(dist(snapX, snapY, x, y))
snapY = y - cos(snapAngle)*snapDist
snapX = x - sin(snapAngle)*snapDist
walls.push(new wall(x, y, snapX, snapY, typeSelected))