Today we’re going to look into collision detection. Collision detection works very much like our edge detection but we need to keep in mind that the objects location is a point, but it’s representation on the screen is a square.
We’re essentially going to go through the list of objects and, for each other object, see if they are colliding and if so, do something. Because we are using circles the algorithm is a simple check to see if the distance between to objects is less than the sum of their radii. Because we are using square objects we will need to offset our test location by half of the height and width the get the center point of the images.
[pastacode lang=”cpp” manual=”void%20mover%3A%3AobjectCollision(mover*%20m)%0A%7B%0A%20%20%20%20%2F%2Fcircle-based%20collision%20detection%0A%20%20%20%20vec2%20aCenter(%20(position.getX())%20%2B%20(width%20%2F%202)%2C%20(position.getY())%20%2B%20(width%20%2F%202)%20)%3B%0A%20%20%20%20vec2%20bCenter(%20(m-%3Eposition.getX())%20%2B%20(m-%3Ewidth%20%2F%202)%2C%20(m-%3Eposition.getY())%20%2B%20(m-%3Eheight%20%2F%202)%20)%3B%0A%20%20%20%20vec2%20distance%20%3D%20vec2%3A%3Asub(aCenter%2CbCenter)%3B%0A%0A%20%20%20%20if%20(%20distance.getMag()%20%3C%20(%20(width%20%2F%202)%20%2B%20(m-%3Ewidth%20%2F%202)%20)%20)%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Collision%20detected%20between%20%22%20%3C%3C%20id%20%3C%3C%20%22%20%26%20%22%20%3C%3C%20m-%3Eid%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20%7D%0A%7D” message=”” highlight=”” provider=”manual”/]
This will now print to the console whenever it detects a collision between two of the movers, if we add applyForce(distance) to the mix, we can now make the balls bounce off each other using our force system and, because we are using the distance between centers as the force, smaller objects will be bounced off with more force than larger heavier objects, simulating real world expectations!
We can get better results by tweaking the force applied like this:
[pastacode lang=”cpp” manual=”if%20(%20distance.getMag()%20%3C%20(%20(width%20%2F%202)%20%2B%20(m-%3Ewidth%20%2F%202)%20)%20)%0A%7B%0A%20%20%20%20std%3A%3Acout%20%3C%3C%20%22Collision%20detected%20between%20%22%20%3C%3C%20id%20%3C%3C%20%22%20%26%20%22%20%3C%3C%20m-%3Eid%20%3C%3C%20std%3A%3Aendl%3B%0A%20%20%20%20vec2%20momentum(0%2C0)%3B%0A%20%20%20%20momentum.add(m-%3Evelocity)%3B%0A%20%20%20%20momentum.mult(m-%3Emass)%3B%0A%20%20%20%20distance.setMag(momentum.getMag()%2F2)%3B%0A%20%20%20%20applyForce(distance)%3B%0A%20%20%20%20distance.mult(-1)%3B%0A%20%20%20%20m-%3EapplyForce(distance)%3B%0A%7D” message=”” highlight=”” provider=”manual”/]
This approximates the transfer of momentum by the impacting objects current mass and acceleration, the formula is almost certainly not real world accurate as I just came up with it on the spot, but it does produce reasonable visuals!
We can also make the wind function more interesting by making it sure it applies as long as the mouse button is being pressed. What we can do here is add a bool named mousePressed and set it to false. In our event handler we change the MOUSEBUTTONDOWN event to set mousePressed to true and add a MOUSEBUTTONUP event, that sets mousePressed to false. with this mousePressed will only be true if the mouse button is being pressed. In our update loop for our objects we add in:
[pastacode lang=”cpp” manual=”if(mousePressed)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mover%3A%3AmoverList%5Bi%5D-%3EapplyForce(wind)%3B” message=”” highlight=”” provider=”manual”/]
Now we have a little physics toy that is somewhat fun to play with!