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.

Capstone Post 2: Possessive Protection

Figure 1: Hugging a planet back together.


I'm excited with the thematic, feel-y direction our game has taken. After teetering between arcade and casual markets, we've reached a nice middle ground with a leaning towards casual. More importantly, we've nailed down a core experience we want the player to have: an abstraction of motherhood.

There are many types of play we as developers can craft for players. Combat games are quite common, but a lot of games that aren't directly about war can be seen as analogs for war: typically there is some sort of enemy force that you the player must defeat. Mario versus Bowser's minions, Leon Kennedy v zombies, Gordon Freeman v the Combine, etc. While this type of experience is tried and tested fun, with Serpent Shadows we are aiming for an experience that I haven't really seen before.

I think we are used to seeing a lot of masculine experiences in video games, and feminine experiences get chalked up to not a whole lot of fun. I'd like to keep masculine and feminine in the abstract: let's take a look at adjectives usually associated with these two genders:
I think games largely lean towards the masculine side: in characters, in theme, in challenges: most elements of popular games lean heavily towards masculinity. While there is always some crossover, somewhere along the way we decided that masculine energy is more fun to have in video games than feminine energy. 

What we are trying to accomplish with Serpent Shadows is not a game marketed towards women, but rather a game that puts the player into a character radiating with feminine energy, with challenges and rewards that are very feminine in nature.

In the game, you play as a dragon with this long tail flying around its little solar system, protecting the planets that reside in it. When arrows hit your planets, the glass casing around them shatters, leaving them unprotected. In this state their "bubble," so to speak, is broken and they venture out of the solar system until you come along and encircle them, "hugging" their protective bubbles back. The underlying idea here is that you are a mother figure to these planets; protecting them from harm by using your own body as a shield.

So, without outright saying it, we want the player to, on a more unconscious level, be playing a game that is an analog for a specific type of protective parenting. Our design choices moving forward will revolve around this idea. We will probably make it so you can create planets by encircling yourself, and a planet will be born from your tail, severing your tail. This works both thematically and mechanically: your tail is shorter so it's harder to defend your planets, but you have another planet. Many, many iterations have brought us to this mode of play, and I have to say I'm excited to see where we go with it!





Tuesday, October 27, 2015

Capstone Post 1: Programming Gravity

Simple forms of Newtonian gravity are very simple to emulate in code. We will take a look at how to achieve the effect of bodies moving about a perfectly circular orbit around a fixed point in space. The essence of this code will work in any environment; I will be using Unity C# to demonstrate the concept.

To start, let's create a new Unity project and set it to 2D mode. Then let's toss some planets and a sun into our game world.



Next, let's attach a script to our planets that will give them this gravity behavior. Let's also attach a rigidbody that, ironically, does not use gravity. In the editor, simply turn off gravity for our rigidbody. We don't need predefined gravity; we are going to write our own!

























Now that we've finished setting up our scene, let's give these planets some Newtonian physics! To perform our calculations, we're going to need some information about our scene. We can start by defining the following variables in our script:
























A good practice with Unity C# is to define your components as member data to avoid littering your code with GetComponent calls. In the editor, we can simply grab our sun GameObject and drop it into the public variable slot for sun, and set the sun's mass and G to be whatever we would like.

Newton's actual gravitational constant (G) is approximately equal to 6.67 x 10^-11, but we can define our own G for this simulation (and I would recommend you not actually use that value unless you are placing your planets millions of miles away in Unity, which will cause you floating point errors). 

Let's step away from our code for a minute and examine the physics we are attempting to emulate. Newton defines the force of gravity between two bodies as follows:


where m1 is the mass of one body, m2 is the mass of the other body, and r is the distance between their centers of mass. 

Often, with this formula, one mass is so large in comparison to the other, that we can remove the smaller mass from the equation altogether. We will be doing this in our code. Let's start our calculation by finding the force of gravity between our two objects, in precisely the same way Newton's formula says to:












Here, we do a simple distance calculation to find r. We then use this distance in our Fg calculation, removing the mass of the planet because it is negligible in our system. This in reality only gives us the magnitude of force, a directionless value.

So, we must apply this force in the direction towards the sun. We do this by subtracting the position of the sun from the position of the planet of the sun, normalizing it so we can get our x and y components to be between 0 and 1, and then applying our force magnitude into our force vector.

 If we were to apply this force to our rigidbody, the planets would plummet into the sun quite quickly (distance squared). So, we must apply a velocity perpendicular to the direction of Fg in order to retain orbit. In essence, we want our planets to fall into the sun due to the force of gravity, but maintain a perpendicular velocity which makes it miss.

To achieve this, we can use the following simple formula to find our magnitude:


And finally, some code:


And that's it! We simply plug in our values, give that velocity magnitude a direction and apply Fg and our velocity to the rigidbody attached to the planet. The -90 degrees is so we apply this velocity perpendicular to the direction of our Fg vector.

I implemented this Newtonian gravity into Serpent Shadows, and frankly it was more because I felt like having fun with it. Spoiler alert, about the same effect could be achieved by creating a new transform at the position of the sun, child-ing the planet to this transform, and rotating the transform. But this only took about an hour, and I had a bunch of residual physics excitement from my physics class that day.

Programming gravity is quite interesting, especially when you attempt to put lots of bodies with varying masses and velocities, however the principles of Newtonian motion can apply in a virtual space. If nothing more, by doing so we can, in a sense, write proofs (in a theoretical sense) of Newton's gravitational formula in a virtual environment which can emulate the impossible perfection that comes from elimination of real-world variables.