Thursday, December 17, 2009

Fun with Math: Goblyn Chunks

One of the things I wanted to accomplish with Goblyn Stomp was to create these mobs of monsters, and a real sense of destruction when you kill large numbers of them. I tried to give that sense by having a few pieces of each Goblyn fly away with each "Fantastic Stomp" and each "Remote Myne" blast. However, if each Goblyn Chunk traveled along identical trajectories that were simply translated to different positions it would look a bit lame, so I have the game generate a unique Goblyn Chunk trajectory for each Goblyn, which is a function of the position of the Goblyn relative to the source of the blast. Here's how it works:

There are two different components that make up the Goblyn Chunk starting velocity vector. One is a straight line from the source of the blast to the Goblyn's location, and the other is the upward angle at which the Goblyn chunks fly out. Figuring out the first component is easy, it's just a matter of subtracting the source vector from the Goblyn's position vector:

Vector2.Normalize(Vector2.Subtract(GoblynPosition, Source)) * blastvelocity;

The normalize function gives you a vector with a length of 1 in the direction of the input vector. This way all of the Goblyn Chunks are blasted at a uniform velocity, determined by the variable blastvelocity.

I wanted the upward blast angles to be such that an explosion with many goblyns would have this sort of fountain effect:
To achieve this, you can see that the blast angle is flatter for points further from the center of the blast, and in the center of the blast the blast angle is pretty much 90 degrees. So this statement is used to determine the blast angle:

blastangle = 90f - Vector2.Distance(GoblynPosition, Source) / baScale;
if (blastangle < 10)
{ blastangle = 10; }

Note the baScale factor which is used to adjust the relationship between upward angle and distance from the blast, and the conditional statement that is used to make sure the blast angle is always at least 10 degrees.

Now these two components can be used to create a 3D vector representing the initial Goblyn Chunk velocity, where the XY plane extends across the ground, and the Z component determines a chunk's height above the ground:

ChunkVelocities[0].X =
Vector2.Normalize(Vector2.Subtract(
GoblynPosition, Source)).X * blastvelocity * (float)Math.Cos(blastangle * Math.PI / 180);
ChunkVelocities[0].Y =
Vector2.Normalize(Vector2.Subtract(
GoblynPosition, Source)).Y * blastvelocity * (float)Math.Cos(blastangle * Math.PI / 180);
ChunkVelocities[0].Z =
blastvelocity * (float)Math.Sin(blastangle * Math.PI / 180);


This creates a starting velocity for each Goblyn Chunk. The z component is affected by a gravity value that reduces the upward velocity with each frame, and the x and y components remain constant until the chunk hits the ground (z=0).

Finally, to create slightly different trajectories for multiple chunks coming from the same Goblyn, a random number generator is used to add in slight variations to the trajectory of the first chunk:

for (int i = 1; i < ChunkVelocities.Length; i++)
{
ChunkVelocities[i].X = ChunkVelocities[0].X +
4 * (float)GobRand.NextDouble() - 2;
ChunkVelocities[i].Y = ChunkVelocities[0].Y +
4 * (float)GobRand.NextDouble() - 2;
ChunkVelocities[i].Z = ChunkVelocities[0].Z +
4 * (float)GobRand.NextDouble() - 2;
}


And that's how you create flying Goblyn Chunks! I hope this was informative and somewhat interesting. Leave a comment if you have anything to add or if you'd like anything clarified.


No comments:

Post a Comment