Skip to content

Commit 4f49f25

Browse files
Final batch
1 parent f6e9587 commit 4f49f25

File tree

6 files changed

+484
-0
lines changed

6 files changed

+484
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
title: How to test collisions with Bounding Volumes
3+
description: A walkthrough what is involved in figuring out if two objects collide for MonoGame!
4+
requireMSLicense: true
5+
---
6+
7+
## Overview
8+
9+
Collision detection determines whether objects in a game world overlap each other.
10+
11+
The MonoGame Framework provides several classes and methods to speed implementation of collision detection systems in games.
12+
13+
* [Bounding Volume Classes](#bounding-volume-classes)
14+
* [Non-Bounding Volume Classes](#non-bounding-volume-classes)
15+
* [Contains and Intersects Methods](#contains-and-intersects-methods)
16+
* [Adding New Collision Data Structures](#adding-new-collision-data-structures)
17+
18+
## Bounding Volume Classes
19+
20+
The MonoGame Framework has three classes that represent three-dimensional volumes. Use a bounding volume class to approximate the volume occupied by a complex object using a volume that is less complex and faster for performing collision checking. All of the bounding volume classes support intersection and containment tests with each other and the plane and ray classes.
21+
22+
### Bounding Sphere
23+
24+
The [BoundingSphere Structure](xref:Microsoft.Xna.Framework.BoundingSphere) represents the space occupied by a sphere.
25+
26+
There are several benefits of using a bounding sphere for collision detection.
27+
28+
* Sphere to sphere checks are very fast. To check for collision between two spheres, the distance between the centers of the spheres is compared to the sum of the radii of both spheres. If the distance is less than the combined radii of both spheres, the spheres intersect.
29+
* The [BoundingSphere Structure](xref:Microsoft.Xna.Framework.BoundingSphere) class is compact. It stores only a vector representing its center and its radius.
30+
* Unlike a bounding box, a bounding sphere does not need to be recreated if the model rotates. If the model being bounded rotates, the bounding sphere will still be large enough to contain it.
31+
* Moving a bounding sphere is inexpensive. Just add a value to the center.
32+
33+
There is one major drawback to using the bounding sphere class for collision detection.
34+
35+
* Unless the object being approximated is sphere shaped, the bounding sphere will have some empty space, which could result in false positive results. Long narrow objects will have the most empty space in their bounding spheres.
36+
37+
### Bounding Box
38+
39+
The [BoundingBox Structure](xref:Microsoft.Xna.Framework.BoundingBox) represents the space occupied by a box. The bounding box class is axis aligned. Each face of the bounding box is perpendicular to the x-axis, the y-axis, or the z-axis.
40+
41+
There are several benefits of using the bounding box for collision detection.
42+
43+
* The bounding box class fits rectangular shapes aligned with the axis very well. Compared to the bounding sphere class, the bounding box class provides a much tighter fit for non-rotated rectangular objects.
44+
* Because the bounding box class is axis aligned, you can make certain assumptions that result in collision checks between bounding boxes being quicker than a bounding box that can be rotated.
45+
46+
There are a few drawbacks of using the bounding box for collision detection.
47+
48+
* Rotating a bounding box causes it to no longer be axis aligned. Because of this, if you rotate a model being bounded, you will need to recreate the bounding box. Doing so can be slow, since all the points in an object are iterated through to get the bounding box. If the model has not changed orientation, you can translate the bounding box instead of recreating it.
49+
* If the model being bounded is not aligned to the axis, the bounding box will have some empty space. The amount of empty space will be greatest when the object is rotated 45 degrees from an axis.
50+
* Empty space in the bounding box can result in false positives when checking for collision.
51+
52+
### Bounding Frustum
53+
54+
Use a [BoundingFrustum Class](xref:Microsoft.Xna.Framework.BoundingFrustum) to create a bounding volume that corresponds to the space visible to the camera. You create a bounding frustum from the combined view and projection matrix that the camera is using currently. If the camera moves or rotates, you need to recreate the bounding frustum. The bounding frustum is not used to determine when two objects collide, but rather when an object intersects with the volume of space viewable by the camera. Objects that do not intersect and are not contained by the bounding frustum are not visible to the camera and do not need to be drawn. For complex models, this can reduce the number of pixels that need to be rendered.
55+
56+
## Non-Bounding Volume Classes
57+
58+
### Plane
59+
60+
The [Plane Structure](xref:Microsoft.Xna.Framework.Plane) describes a 2D plane. The plane is defined by a normal vector (perpendicular to the plane) and a point on the plane. The plane class supports intersection tests with the bounding volume classes. The plane class’s intersection test returns the tested object's position relative to the plane. The return value indicates whether the object intersects the plane. If the object does not intersect the plane, the return value indicates whether the object is on the plane’s front side or back side.
61+
62+
### Ray
63+
64+
The [Ray Structure](xref:Microsoft.Xna.Framework.Ray) describes a ray starting at a point in space. The ray structure supports intersection tests with the bounding volume classes. The return value of the ray intersection tests is the distance the intersection occurred at, or null if no intersection occurred.
65+
66+
### Model
67+
68+
In addition to the information needed to draw a model, the [Model Class](xref:Microsoft.Xna.Framework.Graphics.Model) contains bounding volumes for its parts. When a model is imported, the content pipeline calculates the bounding sphere for each of the model's parts. To check for collision between two models, you can compare the bounding spheres for one model to all of the bounding spheres of the other model.
69+
70+
## Contains and Intersects Methods
71+
72+
Bounding volume classes have methods to support two types of collision tests: intersection tests and containment tests. The intersects methods check whether the two objects being tested overlap in any way. As soon as the test finds that the objects do intersect, it returns without trying to determine the degree of the intersection. The contains methods determine whether the objects simply intersect or whether one of the objects is completely contained by the other. Since the intersects methods need only determine whether an intersection occurred, they tend to be faster than the contains methods.
73+
74+
## Adding New Collision Data Structures
75+
76+
When implementing other bounding volume classes and intersection tests, you will probably need to add a custom content pipeline processor. For example, your game might need to use convex hulls for collision detection. You could use a custom processor to determine the convex hull and then place it in the model's tag field. Then, when the model is loaded at run time, the convex hull information would be available in the model. For more information, see [Extending a Standard Content Processor](Content_Pipeline/HowTo_Extend_Processor.md).
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
title: How to restrict Aspect Ratio on a Graphics Device
3+
description: Demonstrates how to create a custom GraphicsDeviceManager that only selects graphics devices with widescreen aspect ratios in full-screen mode.
4+
requireMSLicense: true
5+
---
6+
7+
## Overview
8+
9+
Certain games require a fixed resolution that is only suitable for Wide-Screen devices (e.g. a TV). The steps below show how to implement a custom `GraphicsDeviceManager` to provide such a restriction.
10+
11+
## To restrict graphics devices to widescreen aspect ratios in full-screen mode
12+
13+
1. Create a class that derives from [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager).
14+
15+
```csharp
16+
public class CustomGraphicsDeviceManager : GraphicsDeviceManager
17+
{
18+
public CustomGraphicsDeviceManager( Game game )
19+
: base( game )
20+
{
21+
}
22+
23+
}
24+
```
25+
26+
2. Add a **WideScreenOnly** property to the class.
27+
28+
The property is used to turn on and off the widescreen-only behavior.
29+
30+
```csharp
31+
private bool isWideScreenOnly;
32+
public bool IsWideScreenOnly
33+
{
34+
get { return isWideScreenOnly; }
35+
set { isWideScreenOnly = value; }
36+
}
37+
```
38+
39+
3. Determine the minimum desired aspect ratio.
40+
41+
```csharp
42+
static float WideScreenRatio = 1.6f; //1.77777779f;
43+
```
44+
45+
4. Override the **RankDevices** method of [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager).
46+
47+
Note the call to [base.RankDevices](xref:Microsoft.Xna.Framework.GraphicsDeviceManager). This call ensures that the new version of **RankDevices** has an already ranked list of available devices with which to work.
48+
49+
```csharp
50+
protected override void RankDevices(
51+
List<GraphicsDeviceInformation> foundDevices )
52+
{
53+
base.RankDevices( foundDevices );
54+
}
55+
```
56+
57+
5. Add a check to see if the **WideScreenOnly** property is **true**.
58+
59+
```csharp
60+
if (IsWideScreenOnly)
61+
{
62+
...
63+
}
64+
```
65+
66+
6. In the **if** block, loop through all found devices, and check whether the [PresentationParameters](xref:Microsoft.Xna.Framework.Graphics.PresentationParameters) indicate the device is full-screen.
67+
68+
7. If the device is full-screen, determine the aspect ratio of the device by dividing the **BackBufferWidth** by the **BackBufferHeight**.
69+
70+
8. If the aspect ratio is less than the desired aspect ratio, remove the device from the list of found devices.
71+
72+
```csharp
73+
for (int i = 0; i < foundDevices.Count; )
74+
{
75+
PresentationParameters pp =
76+
foundDevices[i].PresentationParameters;
77+
if (pp.IsFullScreen == true)
78+
{
79+
float aspectRatio = (float)(pp.BackBufferWidth) /
80+
(float)(pp.BackBufferHeight);
81+
82+
// If the device does not have a widescreen aspect
83+
// ratio, remove it.
84+
if (aspectRatio < WideScreenRatio)
85+
{
86+
foundDevices.RemoveAt( i );
87+
}
88+
else { i++; }
89+
}
90+
else i++;
91+
}
92+
```
93+
94+
9. Replace the default [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager) with the derived [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager).
95+
10. To test the new component, set the **WideScreenOnly** and **IsFullScreen** properties to **true**.
96+
97+
```csharp
98+
public Game1()
99+
{
100+
graphics = new CustomGraphicsDeviceManager(this);
101+
Content.RootDirectory = "Content";
102+
103+
this.graphics.PreferMultiSampling = false;
104+
#if WINDOWS
105+
this.graphics.PreferredBackBufferWidth = 1280;
106+
this.graphics.PreferredBackBufferHeight = 720;
107+
#endif
108+
#if ANDROID
109+
this.graphics.PreferredBackBufferWidth = 400;
110+
this.graphics.PreferredBackBufferHeight = 600;
111+
#endif
112+
113+
this.graphics.IsFullScreen = true;
114+
this.graphics.IsWideScreenOnly = true;
115+
graphics.ApplyChanges();
116+
}
117+
```
118+
119+
## See Also
120+
121+
- [How to articles for the Graphics Pipeline](index.md)
122+
123+
### Concepts
124+
125+
- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md)
126+
- [What Is a Back Buffer?](../../whatis/graphics/WhatIs_BackBuffer.md)
127+
- [What Is a Viewport?](../../whatis/graphics/WhatIs_Viewport.md)
128+
129+
### Reference
130+
131+
- [GraphicsDeviceManager](xref:Microsoft.Xna.Framework.GraphicsDeviceManager)
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
title: Selecting an Object with a Mouse
3+
description: Demonstrates how to check whether the mouse is positioned over a 3D object by creating a ray starting at the camera's near clipping plane and ending at its far clipping plane.
4+
requireMSLicense: true
5+
---
6+
7+
## Overview
8+
9+
A common requirement in game development is to select 3D objects in a scene. This example walks through the most common method for achieving this.
10+
11+
> [!NOTE]
12+
> This example applies only to Desktop or mobile development. The [Mouse](xref:Microsoft.Xna.Framework.Input.Mouse) and [MouseState](xref:Microsoft.Xna.Framework.Input.MouseState) objects are not supported on consoles.
13+
>
14+
> On consoles however the same pattern applies, you simply need to use either a fixed point (where the camera is looking, or screen center) or a cursor controlled by a stick to get the position.
15+
16+
## Detecting Whether a User Clicked a 3D Object
17+
18+
1. Get the current state of the mouse by using [GetState](xref:Microsoft.Xna.Framework.Input.Mouse).
19+
20+
``` csharp
21+
MouseState mouseState = Mouse.GetState();
22+
```
23+
24+
2. Get the current screen coordinates of the mouse from [X](xref:Microsoft.Xna.Framework.Input.Mouse) and [Y](xref:Microsoft.Xna.Framework.Input.Mouse).
25+
26+
``` csharp
27+
int mouseX = mouseState.X;
28+
int mouseY = mouseState.Y;
29+
```
30+
31+
> [!NOTE]
32+
> Replace mouse position with a virtual cursor or the screen centre for consoles.
33+
34+
3. Using [Viewport.Unproject](xref:Microsoft.Xna.Framework.Graphics.Viewport#Microsoft_Xna_Framework_Graphics_Viewport_Unproject_Microsoft_Xna_Framework_Vector3_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_), determine points in world space on the near and far clipping planes. For the point on the near plane, pass a source vector with x and y set to the mouse position, and z set to 0.
35+
36+
4. For the point on the far plane, pass a source vector with x and y set to the position, and z set to 1.
37+
38+
5. Create a translation matrix for a point that is the origin, (0,0,0).
39+
40+
6. For both points, pass [Viewport.Unproject](xref:Microsoft.Xna.Framework.Graphics.Viewport#Microsoft_Xna_Framework_Graphics_Viewport_Unproject_Microsoft_Xna_Framework_Vector3_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_Microsoft_Xna_Framework_Matrix_) the current projection matrix, the view matrix.
41+
42+
``` csharp
43+
// The closest point at which an object can interact.
44+
Vector3 nearsource = new Vector3((float)mouseX, (float)mouseY, 0f);
45+
// The furthest point at which an object can interact.
46+
Vector3 farsource = new Vector3((float)mouseX, (float)mouseY, 1f);
47+
48+
Matrix world = Matrix.CreateTranslation(0, 0, 0);
49+
50+
// Assuming you have the current Projection and View Matrices available.
51+
Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearsource,
52+
proj, view, world);
53+
54+
Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farsource,
55+
proj, view, world);
56+
```
57+
58+
7. Create a [Ray](xref:Microsoft.Xna.Framework.Ray) whose origin is at the near point and whose direction points to the far point.
59+
60+
``` csharp
61+
// Create a ray from the near clip plane to the far clip plane.
62+
Vector3 direction = farPoint - nearPoint;
63+
direction.Normalize();
64+
Ray pickRay = new Ray(nearPoint, direction);
65+
```
66+
67+
8. Loop through each object in the scene using the [Intersects](xref:Microsoft.Xna.Framework.Ray) method to check whether the [Ray](xref:Microsoft.Xna.Framework.Ray) intersects each object. If it is hit, store the object and the distance at which it was intersected.
68+
69+
```csharp
70+
// Assuming you have an array containing a list of all "hittable" objects in your game
71+
foreach (var obj in objects)
72+
{
73+
float? distance = ray.Intersects(obj.BoundingSphere);
74+
if (distance.HasValue)
75+
{
76+
// A cachable list of all object "HIT" this frame.
77+
intersectedObjects.Add(new Tuple<MyObject, float>(obj, distance.Value));
78+
}
79+
}
80+
```
81+
82+
9. Sort the items that have been hit in order of which is closest.
83+
84+
```csharp
85+
// Sort the intersected objects by distance
86+
intersectedObjects.Sort((a, b) => a.Item2.CompareTo(b.Item2));
87+
```
88+
89+
10. When you completely loop through the objects, the last object stored will be the closest object underneath the area the user clicked.
90+
91+
## See Also
92+
93+
- [Rotating and Moving the Camera](HowTo_RotateMoveCamera.md)
94+
95+
### Concepts
96+
97+
- [What Is 3D Rendering?](../../whatis/graphics/WhatIs_3DRendering.md)
98+
99+
### Reference
100+
101+
- [Ray](xref:Microsoft.Xna.Framework.Ray)
102+
- [Ray.Intersects<BoungingBox>](xref:Microsoft.Xna.Framework.Ray#Microsoft_Xna_Framework_Ray_Intersects_Microsoft_Xna_Framework_BoundingBox_)
103+
- [Ray.Intersects<BoungingSphere>](xref:Microsoft.Xna.Framework.Ray#Microsoft_Xna_Framework_Ray_Intersects_Microsoft_Xna_Framework_BoundingSphere_)
104+
- - [Ray.Intersects<Plane>](xref:Microsoft.Xna.Framework.Ray#Microsoft_Xna_Framework_Ray_Intersects_Microsoft_Xna_Framework_Plane_)
105+
- [BoundingBox](xref:Microsoft.Xna.Framework.BoundingBox)
106+
- [BoundingSphere](xref:Microsoft.Xna.Framework.BoundingSphere)
107+
- [Plane](xref:Microsoft.Xna.Framework.Plane)

0 commit comments

Comments
 (0)