Wednesday, October 28, 2015

Capstone Post 3: Circles!

Let's talk about why anything involving circles is both interesting and easy to program. First off, what is a circle? All it really is is a radius. With no information besides a radius, we know everything about the dimensions of that circle (thanks pi!). Alternatively, we can deduce the radius only knowing the circumference, but this is much rarer to find applications for and follows the same algebraic process. And the only algebra involved is a singular multiplication or division, since PI is the ratio of the circumference of any circle to its diameter.


In my first capstone blog post, I discussed programming perfect circular orbits around a body using Newton's gravitational formula. For fun, you can scroll down a bit and replace distance with radius (the radius of our orbit), and it all means the same thing.

Imagine a screen with two circles floating around, given some random velocities. We want those circles to collide with each other in the simplest way possible so they never intersect. What can we do? If we want things to look very bad, we could use AABB collision to define a bounding box around our circles, but that would look silly and actually be more complex than we even need.

We want our circles to collide like circles should! Well, its as easy as knowing the radius of our circles and performing a distance check between them. Each frame, we can check the distance between our two circles. We store that number in a variable: distance.


If our distance is less than the radius of the first circle plus the radius of the second circle, we have a collision! We can simply reflect our velocity vectors and we have created the simplest collision physics I can imagine.



So in Serpent Shadows, I was faced with the problem of spawning planets semi-randomly around the sun. I started out by defining a bounding box of coordinates they could randomly pick from, and it worked fine! Except this box was rectangular, which is about as sensical as performing AABB collision on circles.

In the refactoring phase of the project, I scrapped all that code and replaced it with something much more elegant. I wrote a general use function that returns a random position with the range of a donut shape around the sun. When you call this function, you simply pass the radius of the first layer of donut and the radius of the second layer of donut: the min and max radii.




*min radius = minor radius
*max radius = major radius










Here's a snapshot of the function. The purpose of each line is shown in the comments.


Our game abides by 2D game logic in a 3-dimensional environment, so I needed to return a Vector3 at our fixed z position, so I simply return this function with the zPos variable declared outside this function. But if you replace all the Vector3 stuff with Vector2 stuff, this is very easily translated into 2-dimensional space.

While this is very simple, distance checks can, depending on how often you are performing them, be a burden on the speed of your application. This is a whole other topic that you should absolutely research if you're interested, but there are a lot of other ways to approximate distance without performing that pesky square root operation. But this is really only a problem when you are trying to calculate many, many distances every frame. For our purposes, we do not care as the effect on performance is negligible.

No comments:

Post a Comment