Let's say a bit about how the standard void cCritter::collide(cCritter *pother) method should work. Before thinking about the code, we need to think about the physics. Consider the collision of two objects a and b with masses ma and mb and velocities va and vb which our collision is to convert into new velocities newVa and newVb. According to physics, (a) the total momentum is conserved and (b) the total energy is conserved. This means the following two conditions should hold, where we write |v| to mean the magnitude of a vector v.
Ma x newVa + Mb x newVb = Ma x Va + Mb x Vb
(1/2) x (Ma x |newVa|2 + Mb x |newVb|2) = (1/2) x (Ma x |Va|2 + Mb x |Vb|2)
The newVa and the newVb quantities are our unknowns, and the old Va and Vb are like constants fed into the equations. Geometrically speaking, condition (1) describes a 'line,' while condition (2) describes an 'ellipse.' The intersection of a line and an ellipse gives two solutions: the pre-collision and the post-collision solution.
To find them, you can replace (1) by two linear equations in the x and y components and replace equation (2) by a single quadratic equation in the x and y components. These equations can be solved by hand, though what the author did was feed them into the Mathematica symbolic computation program to come up with the two solutions, the pre-collision solution, newVa = Va and newVb = Vb, and the post-collision solution, in which some of the energy and momentum have been exchanged:
If we divide both numerators and denominators by Ma, and call Mb/Ma massratio we get
Simplifying a little more, we get
Note that if massratio is 1, then this is simply newVa = Vb; newVb = Va, which is the standard billiard-ball collision that one first thinks of. The case where the masses aren't the same is the less obvious case; this is the case we are doing all the work for. And if a has a huge (infinite) mass compared to b, then massratio is about 0 and we get newVa = Va; newVb = 2Va ? Vb, which, if a is motionless, amounts to b simply bouncing off of a, which is another standard kind of collision example.
A third thing that needs to be taken into account is that we shouldn't have two objects in the same place at the same time. Usually when two critters are touching, they will actually be overlapping. We add code to our cCritter::collide so as to move the pair of critters apart along the line connecting their centers, moving them just far enough so they don't overlap.
A final issue in writing this algorithm is that we need to avoid having a collision move any critter that has its _fixedflag set to TRUE; such a critter might appear as a bumper in a pinball game or as an obstacle in a maze game. You can look at the full code in the critter.cpp file.