Raycasting is made up of two parts in total. A ray that will be pointing in a direction and a Wall that the ray will be pointing to. So following that logic we’ll want to have two objects for our raycaster. A class of Ray and a class of Wall. If we can prove that a certain ray is pointing to a wall then we should be able to calculate the line to the wall and create a raycaster that will show what is visible
Starting we will create two classes that will be dedicated to our two objects within the scene. These will be labeled Ray and Boundary. We will separate these between two files, we’ll also have a third file which will be labeled sketch. This is going to host the bulk of our application and will be where we will have each of our classes interacting with each other and hold our setup() and draw() functions.
Our Boundary constructor will simply take in 4 arguments for x1,y1,x2,y2. These points will point to the first and second points of each line that we create. We will then store these vectors in two variables a and b with createVector(). Afterward, we will use show() to display/draw the vector.
We now want to cast the ray onto a boundary and have it stop. To do this, we have to calculate the intersection of a line and then cast a “light” outwards until it intersects with that wall. It’ll take in a position and an angle in this case as we’re going to end up attaching this to a point, which we’ll label particle so that we can move this around the map.
Within the cast method, we are creating we will be feeding in an array of the boundaries that will be created on our canvas. With the information of the walls, we’ll be calculating where the line of the boundary and the ray intersect using this formula =>
We first create a constant for the denominator and then create constants for the value given by the division of T and U by the denominator. We also create a check for when T is greater than 0 and less than 1 and U is greater than 0. If these checks are passed then we go ahead and return points x and y of the intersection by creating a vector and setting the x any y’s of that vector to the sum of x1+t(x2 — x1) and y1+t(y2 — y1) each respectively. If the check is not passed then it means that the lines are parallel and will never intersect given an infinite scale.
Now in our Particle class, we will have our constructor, update, look, and show methods. Our constructor will have a position using the width and height supplied by p5js, and an array of Rays that will be set in a circle around our position. We will update our position with our update method which will set the positions X and Y values with whatever we give it. It could be static points or the position of our mouses x and y values.
Our next method will be look(walls) which will take in an array of boundaries, walls in this case, and run each ray from our constructor through our cast function from our Ray class which will give us a point of intersection if the ray does intersect. We check to see if the distance between the point and the boundary is less than our recorded distance and if so we will set our record to the distance and our closest point to the output of our cast function. From here we’ll take the closest variable that is outputted and create a stroke/line from our position to the closest.x and closest.y and show the output at the end for each ray in our array.
Finally, to put this all together, we create a sketch.js file which will create our canvas and draw everything onto the screen using the setup and draw methods. we first init our array of walls, ray, and particle, then we create a canvas, you can choose any size you want to. We will create random boundaries in this example but you can make custom boundaries or even set it so that boundaries are created on mouse clicks. each boundary will be stored in our walls array. we will also create 4 custom boundaries which will be the size of our full canvas to act as encapsulating walls. finally, we’ll create our instance of our particle. Now, all we have to do is call the methods update, show, and look(walls) and wallah we’re done! now with these working classes, you can instantiate as many particles as light sources that you want! we’re done!