Skip to content

Commit 580a73a

Browse files
Tutorial - Building 2D Games - Fix circle collision math and a few typos. (#138)
* Fix circle collision math and a few typos. The circle collision explanation and code sample were incorrect. The Circle class is implemented correctly later in this chapter (see ./snippets/cirlce.cs#methods_intersects). * Add back "Since this forms a right triangle," * Use * instead of _ * Switch circle radii back to 5 * Corrections --------- Co-authored-by: Simon (Darkside) Jackson <[email protected]>
1 parent 458fffb commit 580a73a

File tree

2 files changed

+34
-33
lines changed

2 files changed

+34
-33
lines changed

articles/tutorials/building_2d_games/12_collision_detection/index.md

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ In this chapter you will:
1616
We will first start by understanding the basics of collision detection and the different approaches that can be used.
1717

1818
> [!NOTE]
19-
> There is a lot to understand when it comes to collision detection and the many complex ways that two objects can be considered IN collsion or NEAR collision. It is critical to get an understanding of the basics before jumping into code. So buckle up, we have a story to tell before you can get back to the keyboard.
19+
> There is a lot to understand when it comes to collision detection and the many complex ways that two objects can be considered IN collision or NEAR collision. It is critical to get an understanding of the basics before jumping into code. So buckle up, we have a story to tell before you can get back to the keyboard.
2020
>
2121
> Feel free to keep coming back to this chapter and refer to the content when you need to, with a fresh cup of coffee.
2222
@@ -34,36 +34,36 @@ Shaped based collision detection checks if two shapes overlap. The most common
3434

3535
#### Circle Collision Detection
3636

37-
Circle collision detection is computationally a simpler check than that rectangles. There are also no special considerations if the circles are rotated, which makes them easier to use. To determine if two circle shapes are overlapping, we only need to check if the square of the sum of the radii between the two circles is less than the squared distance between the two circles with the following formula:
37+
Circle collision detection is computationally a simpler check than rectangles. There are also no special considerations if the circles are rotated, which makes them easier to use. To determine if two circle shapes are overlapping, we only need to check if the square of the sum of the radii between the two circles is less than the squared distance between the two circles with the following formula:
3838

39-
Two find the distance between two circles, imagine drawing a line from the center of one circle to the center of the other. This length of this line is the distance, but we could also calculate it by first walking up or down and then walking left or right from the center of one circle to another, forming a right triangle.
39+
To find the distance between two circles, imagine drawing a line from the center of one circle to the center of the other. The length of this line is the distance, but we could also calculate it by first walking up or down and then walking left or right from the center of one circle to another, forming a right triangle.
4040

4141
| ![Figure 12-1: Showing the distance between the center of two circles forms a right triangle](./images/circle-distance-right-triangle.svg) |
4242
| :---------------------------------------------------------------------------------------------------------------------------------------: |
4343
| **Figure 12-1: Showing the distance between the center of two circles forms a right triangle** |
4444

45-
In the *Figure 12-1* above
45+
In *Figure 12-1* above
4646

4747
- $a$ is the distance between the center of the two on the x-axis (horizontal).
4848
- $b$ is the distance between the center of the two circles on the y-axis (vertical).
4949
- $c$ is the total distance between the center of the two circles.
5050

51-
Since this forms a right triangle, to calculate the squared distance, we can use Pythagorean's Theorem:
51+
Since this forms a right triangle, we can use Pythagorean's Theorem to calculate $c^2$ given $a^2$ and $b^2$:
5252

5353
$$c^2 = a^2 + b^2$$
5454

55-
Then we just check if the squared sum of the radii of the two circles is less than the squared distance:
55+
To check for overlap of two circles, we compare whether the *squared sum of the radii* of the two circles is greater than the *squared distance*:
5656

57-
$$(radius_{circle1} + radius_{circle2})^2 < c^2$$
57+
$$(radius_{circle1} + radius_{circle2})^2 > a^2 + b^2$$
5858

59-
If it is less, then the circles are overlapping; otherwise, they are not.
59+
It is easy to confuse the direction of the inequality sign. As a quick mental test, think of how the math works when the origin of two circles are at the same position, i.e., when the *squared distance* is zero.
6060

61-
To calculate the squared distance between to points, MonoGame provides the [**Vector2.DistanceSquared**](xref:Microsoft.Xna.Framework.Vector2.DistanceSquared(Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2)) method:
61+
To calculate the squared distance between two points, MonoGame provides the [**Vector2.DistanceSquared**](xref:Microsoft.Xna.Framework.Vector2.DistanceSquared(Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2)) method:
6262

6363
[!code-csharp[](./snippets/vector2_distance.cs)]
6464

6565
> [!TIP]
66-
> MonoGame also provides a distance calculation method with [**Vector2.Distance**](xref:Microsoft.Xna.Framework.Vector2.Distance(Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2)) which returns the distance by providing the square root of the distance squared. So why do not we use this instead?
66+
> MonoGame also provides a distance calculation method with [**Vector2.Distance**](xref:Microsoft.Xna.Framework.Vector2.Distance(Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2)) which returns the distance by providing the square root of the distance squared. So why not use this instead?
6767
>
6868
> Square root operations are more computationally complex for a CPU. So instead of getting the normal distance, which would require the square root operation, it is more efficient for the cpu to multiply the sum of the radii by itself to get the squared sum and use that for comparison instead.
6969
@@ -113,14 +113,14 @@ Implementing SAT is out-of-scope for this tutorial. If you are interested in fur
113113

114114
#### Choosing a Collision Detection Method
115115

116-
When determining which collision detection method to use, you should start with the simplest one that meets the needs of your game. If distance checks work for your game mechanic, there's no need to implement more complex shape based detections. Similarly, if a circle can represent the bounding area of a game object, start with that before moving onto rectangles.
116+
When determining which collision detection method to use, you should start with the simplest one that meets the needs of your game. If distance checks work for your game mechanic, there's no need to implement more complex shape based detections. Similarly, if a circle can represent the bounding area of a game object, start with that before moving on to rectangles.
117117

118118
Some other points to consider are
119119

120120
- Circles:
121121
- Better for round objects like balls and coins.
122122
- More accurate for rotating objects.
123-
- Simpler check for overlap than rectangles.
123+
- A simpler check for overlap than rectangles.
124124
- Rectangles:
125125
- Great for walls, platforms, and most game objects.
126126
- Easy to visualize and debug.
@@ -137,7 +137,7 @@ A blocking collision response is the most basic response which just prevents the
137137
1. Store the location of an object calculating the new location to move it to.
138138
2. Check if it is overlapping an object at the new location:
139139

140-
- If it is overlapping, then set the position to the the position before it was moved.
140+
- If it is overlapping, then set the position to the position before it was moved.
141141
- If it is not overlapping, set the position to the new calculated position.
142142

143143
For example:
@@ -174,9 +174,9 @@ For example:
174174

175175
#### Bounce Collision Response
176176

177-
For games that need objects to bonce off each other (like a the ball in a Pong game), we need to calculate how their velocity should change after the collision. MonoGame provides the [**Vector2.Reflect**](xref:Microsoft.Xna.Framework.Vector2.Reflect(Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2)) method to handle this calculation for us. The method needs two pieces of information:
177+
For games that need objects to bounce off each other (like the ball in a Pong game), we need to calculate how their velocity should change after the collision. MonoGame provides the [**Vector2.Reflect**](xref:Microsoft.Xna.Framework.Vector2.Reflect(Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2)) method to handle this calculation for us. The method needs two pieces of information:
178178

179-
1. The incoming vector (the direction something is moving).
179+
1. The incoming vector (the direction that something is moving).
180180
2. The normal vector (the direction perpendicular to the surface).
181181

182182
| ![Figure 12-4: A diagram showing how an incoming vector reflects off of a surface base around the normal vector of the surface](./images/reflection-diagram.svg) |
@@ -193,14 +193,14 @@ For example, if we had a ball moving around the screen and wanted it to bounce o
193193
[!code-csharp[](./snippets/bounce_example.cs)]
194194

195195
> [!TIP]
196-
> [**Vector2.UnitX**](xref:Microsoft.Xna.Framework.Vector2.UnitX) is $(1, 0)$ and [**Vector2.UnitY**](xref:Microsoft.Xna.Framework.Vector2.UnitY) is $(0, 1)$. We use these to get the screen edge normal since the edges of the screen are not at an angle. For more complex surfaces, you would need to calculate the appropriate normal vector based on the surface angle
196+
> [**Vector2.UnitX**](xref:Microsoft.Xna.Framework.Vector2.UnitX) is $(1, 0)$ and [**Vector2.UnitY**](xref:Microsoft.Xna.Framework.Vector2.UnitY) is $(0, 1)$. We use these to get the screen edge normal since the edges of the screen are not at an angle. For more complex surfaces, you would need to calculate the appropriate normal vector based on the surface angle.
197197
198198
### Optimizing Collision Performance
199199

200200
When checking for collisions between multiple objects, testing every object against every other object (often called brute force checking) becomes inefficient as your game grows. Brute force checking can be calculated as $(n * (n - 1)) / 2$ where $n$ is the total number of objects. For example, if you have 100 objects in your game, that's $(100 * 99) / 2 = 4950$ collision checks every frame. To improve performance, we can use a two-phase approach:
201201

202202
1. Broad Phase: A quick, simple check to rule out objects that definitely are not colliding.
203-
2. Narrow Phase: A more precise check only performed on objects that passed the broad phase.
203+
2. Narrow Phase: A more precise check that is only performed on objects that have passed the broad phase.
204204

205205
For our simple game with just two objects, this optimization is not necessary. However, as you develop more complex games, implementing a broad-phase check can significantly improve performance.
206206

@@ -352,11 +352,11 @@ In this chapter, you accomplished the following:
352352
- Rectangles for walls and platforms.
353353
- Explored different types of collision responses:
354354
- Blocking to prevent objects from overlapping.
355-
- Triggering to cause events when objects collide.
355+
- Triggering events when objects collide.
356356
- Bouncing to reflect objects off surfaces.
357357
- Created reusable components:
358358
- Implemented a Circle struct for circle-based collision.
359-
- Added methods to detect circle intersection.
359+
- Added methods to detect circle intersections.
360360
- Applied collision concepts to our game:
361361
- Added screen boundary collision for the slime.
362362
- Implemented bouncing behavior for the bat.
@@ -377,10 +377,10 @@ In the next chapter, we will explore using tilesets and tilemaps to create tile
377377
::: question-answer
378378
For two rectangles A and B to collide:
379379

380-
1. A's left edge must be less than B's right edge
381-
2. A's right edge must be greater than B's left edge
382-
3. A's top edge must be less than B's bottom edge
383-
4. A's bottom edge must be greater than B's top edge
380+
1. A's left edge must be less than B's right edge.
381+
2. A's right edge must be greater than B's left edge.
382+
3. A's top edge must be less than B's bottom edge.
383+
4. A's bottom edge must be greater than B's top edge.
384384

385385
:::
386386

@@ -395,8 +395,8 @@ In the next chapter, we will explore using tilesets and tilemaps to create tile
395395
::: question-answer
396396
[**Vector2.Reflect**](xref:Microsoft.Xna.Framework.Vector2.Reflect(Microsoft.Xna.Framework.Vector2,Microsoft.Xna.Framework.Vector2)) needs:
397397

398-
1. The incoming vector (direction the object is moving)
399-
2. The normal vector (direction perpendicular to the surface being hit)
398+
1. The incoming vector (direction the object is moving).
399+
2. The normal vector (direction perpendicular to the surface being hit).
400400

401401
:::
402402

@@ -405,10 +405,10 @@ In the next chapter, we will explore using tilesets and tilemaps to create tile
405405
::: question-answer
406406
Circle collision might be chosen because:
407407

408-
- It is more accurate for round objects
409-
- It handles rotating objects better
410-
- It is simpler for continuous collision detection
411-
- It is natural for radius-based interactions
408+
- It is more accurate for round objects.
409+
- It handles rotating objects better.
410+
- It is simpler for continuous collision detection.
411+
- It is natural for radius-based interactions.
412412

413413
:::
414414

articles/tutorials/building_2d_games/12_collision_detection/snippets/vector2_distance.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44
float circle1Radius = 5;
55
float circle2Radius = 5;
66

7+
// c^2 = a^2 + b^2
78
// c^2 = (8 - 5)^2 + (10 - 6)^2
89
// c^2 = 3^2 + 4^2
910
// c^2 = 9 + 16
1011
// c^2 = 25
11-
float distanceSquared = Vector2.DistanceSquared(circle1Position, circle2Position);
12+
float distanceSquared = Vector2.DistanceSquared(circle1Position, circle2Position);
1213

1314
// r^2 = (5 + 5)^2
1415
// r^2 = (10)^2
1516
// r^2 = 100
16-
int radiiSquared = (circle1Radius + circle2Radius) * (circle1Radius + circle2Radius)
17+
int radiiSquared = (circle1Radius + circle2Radius) * (circle1Radius + circle2Radius);
1718

18-
// They do not overlap since 100 is not less than 25
19-
if(radii < distanceSquared)
19+
// The circles overlap because 100 is greater than 25
20+
if(radiiSquared > distanceSquared)
2021
{
2122

2223
}

0 commit comments

Comments
 (0)