The CollideAgainstBounce is a collision method which performs the following:
Returns true if a collision has occurred.
Repositions the calling Circle and/or the argument object depending on the argument masses.
Changes the calling Shape's Velocity and/or the argument object's Velocity depending on the argument masses.
Note: All collision methods, including CollideAgainstBounce, are methods common to all Shapes. If you came here through a link on a page beside the Circle (such as Polygon), don't worry, the code for all shapes is identical.
The signature for CollideAgainstBounce is as follows:
Arguments:
Circle circle (or other shape) - the shape to collide against. This method supports other shapes as well, and if you find a shape that you'd like to collide against which is not supported, please request this feature in the forums.
float thisMass - the mass of this shape. This does not have to be an absolute mass since it will only be used relative to the otherMass argument.
float otherMass - the mass of the argument shape. Just like thisMass, otherMass does not have to be absolute. It will be compared against thisMass.
float elasticity - The amount of bounce that will result. A value of 1 results in all momentum being preserved through the collision. A value of 0 results in no momentum being preserved. Negative values should not be used. Values greater than 1 introduce extra momentum. Values greater than 1 can be used to simulate "bouncing" against a wound-up spring, or to create false physics.
The following code creates a Plinko board.
Add the following using statements:
Add the following at class scope:
Add the following in Initialize after initializing FlatRedBall:
Add the following in Update:
Since CollideAgainstBounce returns a bool, your code can use the return value to modify your game when a collision occurs:
The Collision tutorial mentions:
"For bouncing to behave properly, we have to make sure that we're not controlling the involved Shapes' position or velocity"
Let's consider why this is the case. Imagine a situation where a shape (or parent of a shape) is moving toward the right. This is being done with the following code:
If this code is called every frame, that means that the XVelocity will be set to 1 every frame, regardless of what it was before. Imagine that "someShape" performs bounce collision against a wall. When collision occurs, the shape's XVelocity will get inverted (that is, set to -1) so that it moves to the left. However, if Velocity is set to 1 every frame, than the -1 would get changed back to 1. In other words, the setting of velocity every frame would cancel out the velocity change from CollideAgainstBounce. Let's look at another example: one where an object is moved with the mouse. In this example, the mouse is simply setting the position of an object:
In this case, someShape will have a velocity of 0 (assuming there is no other code that sets its velocity. Therefore, even though someShape appears to be moving smoothly with the mouse, if another object bounces against it, it may not bounce at all.
The following example shows a problem with using CollideAgainstBounce and Mouse control and how it can be corrected.
Add the following using statements:
Add the following at class scope:
Add the following in Initialize after initializing FlatRedball:
Add the following in Update:
The CollideAgainstBounce method is effective for performing bouncing physics, but it can also be used in situations where you'd like collision to reset velocity, such as in platformers. It's very common to have acceleration in platformers, and the easiest way to do this is to set the player Entity to have a negative YAcceleration. However, if the player collides with the ground using CollideAgainstMove, the YAcceleration will continue to accumulate the YVelocity value. Eventually this value will build up to be so large that the player will fall through the level. Even if this doesn't occur, the player will show weird behavior if it walks off of a ledge. To solve this, you can simply use CollideAgainstBounce instead of CollideAgainstMove. An elasticity of 0 will result in the same behavior as CollideAgainstMove, but the velocity will be modified according to the velocity to solve accumulation errors. You can try this in the demo above by setting the elasticity argument to 0.