Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The ShapeCollection provides a CollideAgainst method which tests if any shape contained in the calling ShapeCollection collides the argument shape. The CollideAgainst method can also be called to test if two ShapeCollections have any shapes that collide between the two.
The CollideAgainst method can be used to test collision against argument shapes. At the time of this writing, some shapes are not completely supported, but this is changing. If you encounter a NotImplementedException, please post on the forums requesting the implementation needed for your project.
The following overloads are available:
The ShapeCollection class can also collide against other ShapeCollections:
The AttachTo method is a shortcut method which can be used to attach all contained shapes to the argument object. In other words, the following two blocks of code are identical:
and
The AttachTo method is a shortcut method which attaches all contained objects to the first argument. The ShapeCollection itself does not remember the existence of an attachment. This means:
If a shape is later added to the ShapeCollection, it must also be manually attached to the parent object, at least if the desired behavior is to have the entire ShapeCollection be attached as a whole.
It is possible to have different shapes in the same ShapeCollection attached to different objects.
The AxisAlignedRectangles property is a property of type PositionedObjectList. Therefore, you can use this member the same way you would use a PositionedObjectList<AxisAlignedRectangle>.
The following shows how to loop through all rectangles in a ShapeCollection and perform collision between the rectangles and a Circle named CircleInstance:
The LastCollision properties in the ShapeCollection can be used to identify which shapes were collided with on the last collision. This is useful because many games need to know specifically which shapes were collided against to perform custom logic. For example, you may be working on a platformer which includes collision shapes representing spikes. If the character touches a spike then he should lose a life. The LastCollision properties enable checking for this information.
The following example shows how to check which shapes the user collided against. It will check collision against a shape collection. If the user touched an AxisAlignedRectangle which has the name that includes the word "Spike" then the game responds appropriately:
The ShapeCollection class is a container for a variety of shapes. The ShapeCollection class is often used for collision maps and to define triggers. ShapeCollections are often loaded from .shcx files created by the PolygonEditor. ShapeCollections are a very common class due to the support of .shcx files in Glue.
The ShapeCollection provides a number of methods that can be used to perform actions on all contained Shapes (such as AttachTo). However, you may be working on a game that requires access to individual shapes. The ShapeCollection exposes its shapes. The following members are available:
AxisAlignedRectangles
AxisAlignedCubes
Capsule2Ds
Circles
Lines
Polygons
Spheres
These are all PositionedObjectLists which can be accessed like regular lists. You can add and remove elements from these lists as well as modify the individual members inside the lists. If your need to perform special actions on all elements in a ShapeCollection you can do the following:
Of course, you can also access the shapes using a foreach statement. Keep in mind that foreach statements may have performance penalties compared to regular for loops.
ShapeCollections can be created by loading .shcx files.
The following code loads a .shcx file into memory, adds all contained shapes to the ShapeManager. If you are using Glue you can add ShapeCollections to Screens and Entities just like other files. For an example on how to add a ShapeCollection to Glue, see the Beefball tutorial on creating Screen collisions. File used: ShapeCollection.shcx Add the following using statements:
Add the following to Initialize after initializing FlatRedBall:
Although most games do not need ShapeCollection saving support, FlatRedBall provides easy-to-use classes for saving a ShapeCollection. For more information, see the ShapeCollectionSave page.
All shapes in the ShapeCollection can be accessed through its member lists. The available lists are:
AxisAlignedRectangles
AxisAlignedCubes
Circles
Polygons
Lines
Spheres
The ShapeCollection can be thought of as a container for all of these lists. Therefore, you can use the individual lists to do anything you would do with a normal list such as:
The Visible property allows setting the visibility of all contained shapes in a ShapeCollection. It's important to note that the ShapeCollection does not itself store any visibility data, so there is no getter for Visible. The Visible setter loops through all contained shapes and sets their Visible property accordingly.
The following code shows how to make a ShapeCollection invisible. It assumes that there is a ShapeCollection named ShapeCollectionInstance:
The SortAscending method sorts all contained elements in the ShapeCollection by their position values on the given axis. In other words, if this method is called with an argument of Axis.X, then all contained shapes will be sorted so that their X values are increasing. The sort uses a stable insertion sort making it incredibly fast on nearly-sorted or already-sorted lists.
ShapeCollections are often sorted so that axis-based partitioning can be performed when testing for collisions. If the ShapeCollection will not change after being created, then it only needs to be sorted once (likely when it is first created). Otherwise, it needs to be sorted whenever a change occurs - which may be as frequent as every frame. However, sorting every frame and using partitioning is likely faster than performing a brute-force collision check.
The following code can be used to sort a ShapeCollection along its X axis, then test for collisions using axis-based partitioning:
Note that CalculateMaxRadii must be called in order for the ShapeCollection to know the maximum radii of all shapes (by category).
CollideAgainstMove is a function which takes any shape type (such as or ) and calls CollideAgainstMove between the argument and all shapes contained in the ShapeCollection.
This method is an alternative to writing loops for all of the contained objects and manually calling CollideAgainstMove. Using CollideAgainstMove has a number of benefits:
Less code to write - CollideAgainstMove will perform collision against all contained objects in a ShapeCollection. The ShapeCollection object can contain many types of objects, and manually writing for-loops means that one for loop for each type of object is required.
Partitioning (optional) - CollideAgainstMove can perform partitioning which can greatly speed up collision calls. See the later part of this page for information on partitioning.
The following example creates a ShapeCollection, populates it with a very large number of AxisAlignedRectangles, then performs CollideAgainstMove between a free-floating AxisAlignedRectangle and the entire ShapeCollection.
This example assumes that the ShapeCollection and AxisAlignedRectangle (named ShapeCollectionInstance and AxisAlignedRectangleInstance) are both valid instances. The syntax used here assumes a Glue screen. AxisAlignedRectangleInstance is also colored red to help differentiate between it and the static shapes.
Add the following to CustomInitialize:
Add the following to CustomActivity:
The example above shows how to use CollideAgainstMove with the optional partitioning arguments. To recap, to perform partitioned collision, the following are required:
The ShapeCollection must have CalculateAllMaxRadii called prior to the CollideAgainstMove method. If the ShapeCollection adds objects, or if the objects in the ShapeCollection change size, then CalculateAllMaxRadii must be called again.
The ShapeCollection must have SortAscending called prior to the CollideAgainstMove method. If any objects move or are added to the ShapeCollection, then this method must be called again. Notice that the argument for which axis to sort on must match the axis used in CollideAgainstMove. This axis should equal the most distributed axis.
The benefit of this call is that it is considerably faster than simply calling CollideAgainstMove. The downside is that it requires some setup (calling the two functions), and maintenance (calling the two functions again if anything changes). Keep in mind that CalculateAllMaxRadii and SortAscending can be expensive functions for large ShapeCollections, so this method of collision is most effective when the ShapeCollection does not change at all, or if it changes very infrequently.
The number of rectangles in this sample is limited to 5000, but this number could likely be increased to to be much higher. It is very likely that a program with a larger number of rectangles would experience slowdown from rendering the rectangles before it would experience any slowdown on collision due to the efficiency of the partitioned CollideAgainstMove method. If the rectangles were invisible, then the number could go very high without any performance problems.
The ShapeCollection provides a CollideAgainstMoveWithoutSnag method which tests if any shape contained in the calling ShapeCollection collides the argument shape and moves the argument shape accordingly. This method is different from CollideAgainstMove where CollideAgainstMoveWithoutSnag is an order independent operation where CollideAgainstMove is a order dependent operation. CollideAgainstMoveWithouSnag may be slightly slower than CollideAgainstMove and is recommended only if the order of the collisions matters.
The CollideAgainstMoveWithoutSnag method can be used to test collision against argument shapes. At the time of this writing, some shapes are not completely supported, but this is changing. If you encounter a NotImplementedException, please post on the requesting the implementation needed for your project.
The following overloads are available:
The ShapeCollection provides a CollideAgainstBounceWithoutSnag method which tests if any shape contained in the calling ShapeCollection collides the argument shape and moves the argument shape accordingly while also adjusting velocity. The "WithoutSnag" portion of the method name indicates that the method will attempt to perform the collision such that snagging will not occur. In other words, a row of rectangles should behave the same as one long rectangle.
This method is different from CollideAgainstBounce where CollideAgainstBounceWithoutSnag is an order independent operation where CollideAgainstBounce is a order dependent operation. CollideAgainstBounceWithouSnag may be slightly slower than CollideAgainstBounce and is recommended only if the order of the collisions matters.
The CollideAgainstBounceWithoutSnag method can be used to test collision against argument shapes. At the time of this writing, some shapes are not completely supported, but this is changing. If you encounter a NotImplementedException, please post on the requesting the implementation needed for your project.
The following overloads are available:
- Talks about axis-based partitioning which is what the CollideAgainst uses internally when performing partitioned collisions.