MOVING TO OBJECT-ORIENTED COLLISION
Congrats! You've made it through a lot of collision-detection code. But these examples are meant as simple demonstrations of how the algorithms work. Combining them into bigger projects probably means moving your code to an object-oriented approach. (For an excellent introduction to object-oriented programming, see Daniel Shiffman's book "Nature Of Code".)
Why? Let's say we have a circle and a bunch of rectangles (like above). We could store separate positions, sizes, and collisions for each, but that would quickly get messy. Instead, a Circle
and Rectangle
class will give our code a lot more power and flexibility. And, of course, we'll be using the brand new ES6 classes.
Let's start with our Circle class:
{ thisx = _x; thisy = _y; thisr = _r; } { thisx = mouseX; thisy = mouseY; } { ; ; ; }
Now that we have the template, let's make an object:
var mouseCircle = 0 0 30;
Pretty straightforward. We can also make a basic Rectangle class:
{ thisx = _x; thisy = _y; thisw = _w; thish = _h; thishit = false; } // check for collision with the circle using the // Circle/Rect function we made in the beginning { thishit = ; } // draw the rectangle // if hit, change the fill color { if thishit ; else ; ; ; }
Notice we have a variable for the Rectangle called hit
. This way we can keep track of whether or not the circle has hit a particular rectangle and change its fill color accordingly. By default, the value is set to false
.
We have just one Circle
, but we create an Array of Rectangle
objects. To run everything, here's what our main draw()
loop looks like:
{ ; // go through all rectangles... for var i = 0; i < rectslength; i++ rectsidisplay; // and draw // update circle's position and draw mouseCircle; mouseCircledisplay;}
So how do we test if the circle has hit something? Let's create a method (an internal function) of the Rectangle class called checkCollision()
. We'll pass the Circle
object as an argument, then do a basic Circle/Rectangle collision test.
// check for collision with the circle using the// Circle/Rect function we made in the beginning { thishit = ;}
The result of circleRect()
sets hit
to be true
or false
, which in turn changes the fill color. Now we just add the test to the draw()
loop:
// go through all rectangles...for var i = 0; i < rectslength; i++ rectsi; // check for collision rectsidisplay; // and draw
Pretty cool! Here's the full code:
// a single Circle object, controlled by the mousevar mouseCircle; // a list of rectanglesvar rects = 8; { var canvas = ; canvasparent"sketch"; // create a new Circle with 30px radius mouseCircle = 0 0 30; // generate rectangles in random locations // but snap to grid! for var i = 0; i < rectslength; i++ var x = * 50; var y = * 50; rectsi = x y 50 50; } { ; // go through all rectangles... for var i = 0; i < rectslength; i++ rectsi; // check for collision rectsidisplay; // and draw // update circle's position and draw mouseCircle; mouseCircledisplay;} // Circle class { thisx = _x; thisy = _y; thisr = _r; } { thisx = mouseX; thisy = mouseY; } { ; ; ; } // Rectangle class { thisx = _x; thisy = _y; thisw = _w; thish = _h; thishit = false; } // check for collision with the circle using the // Circle/Rect function we made in the beginning { thishit = ; } // draw the rectangle // if hit, change the fill color { if thishit ; else ; ; ; } // CIRCLE/RECTANGLE { // temporary variables to set edges for testing var testX = cx; var testY = cy; // which edge is closest? // test left edge if cx < rx testX = rx; else if cx > rx + rw // right edge testX = rx + rw; // top edge if cy < ry testY = ry; else if cy > ry + rh // bottom edge testY = ry + rh; // get distance from closest edges var distance = ; // if the distance is less than the radius, collision! if distance <= radius return true; return false;}
You can see another, more complex example of object-oriented collision in the Introduction. It uses a class for circles, rectangles, and lines.