Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Entities can be created simply by calling their constructors. Entity Constructors provide a number of overrides allowing you to customize how Entities are created. If you have Entities created in Glue then you may not need to instantiate Entities in code. Entities can be created in code if you are dynamically creating Entities (often to put in a list), or if you are creating instances of entities which will be managed purely in custom code. For additional information on creating Entities in custom code, see this page.
FlatRedBall Entities are used in every FlatRedBall Game. An entity is a reusable definition which you can instantiate (create copies) in your screens. Examples of entities are:
Player
Enemy
Coin (something you can collect)
Bullet (something that can deal damage)
To create a new Entity:
Right-click on the Entities folder
Select Add Entity
Select the desired options for the entity in the pop-up window
Click OK
The CustomActivity function is called once per frame (unless the entity is paused). This method is private so it cannot be directly called, but it is called by an entity's Activity function. This method is usually called automatically by generated code.
CustomActivity is used to perform every-frame logic in your entities. Not all entities need to have CustomActivity logic. For example, a bullet may have its Velocity set upon creation, and it may get destroyed through collision events in the GameScreen. In this case, the bullet may not need any CustomActivity.
However, more complex entities, such as a Player or Enemy, may need additional logic in CustomActivity. The following list includes common types of logic which might be added to an Entity's CustomActivity:
Shooting bullets in response to input
Custom movement beyond what is handled by top-down or platformer generated code, such as dashing
Changing movement variables, such as assigning Water movement
Timing-based logic, such as ending an invulnerability state after a certain amount of time
Playing sound effects, such as step sounds if moving
Playing special effects or particles
Performing AI or pathfinding
Entity instances have their CustomActivity called automatically if any of the following are true:
The entity is created directly in the FlatRedBall Editor
The entity is added to a list which is part of a Screen in the FlatRedBall Editor
Usually entity instances (such as bullets) which are created while the game is running are created using factories which automatically place the newly-created instance in its list.
If an entity instance is added to the FlatRedBall Editor directly, or is added to a list which was created in the FlatRedBall Editor, then its CustomActivity is called automatically. Entity CustomActivity is called before a Screen's CustomActivity.
Entities are free to destroy themselves in the CustomActivity call. For example, if a bullet should only survive for 10 seconds, the following logic may exist:
When calling Destroy, keep in mind that the entity may be needed in situations outside of typical usage in GameScreen. For example, at some point in the future you may decide to have a screen where the user can view all of the different types of bullets that can be shot when the player is upgraded. In this screen you may want to display the bullet. As written the bullet would automatically destroy itself after BulletLifeInSeconds, which may not make sense in this particular screen. Therefore, consider whether the logic that you are writing in CustomActivity should be active whenever a bullet is alive, or only in certain screens.
An entity should not destroy other entities in CustomActivity. Typically this type of destruction should belong in the owner of the entities, which is usually the GameScreen.
Destroying other entities can also cause crashes in your application if the type of entity being destroyed is of the same type as the current entity. This happens because of how list activity is performed. The following code shows how the BulletList is iterated through in the GameScreen's Generated code:
Although the code above performs a bounds check, it is possible that instances are removed such that the same instance has its Activity called multiple times per frame. FlatRedBall's generated code checks for multiple Activity calls per frame and throws an exception if this is detected.
If an entity must destroy other entity instances, a flag or event should be used so that this destruction can be performed in the GameScreen (or owning screen).
Every Entity in Glue has a ConvertToManuallyUpdated method in generated code. This method will remove all contained objects in the Entity from their managers - including removing the Entity itself from being a managed . ManuallyUpdated Entities with visible objects (such as will still be rendered. This method is not the equivalent to Destroy, so it should not be used as a substitute for this method. This method also recursively call ConvertToManuallyUpdated on any contained Entity instances. Note that manually-updated Entities will still have their CustomActivity called if they are added to other Entities or Screens through Glue, or if they are a part of PositionedObjectLists which have been added to Glue. For information on how to turn this off, see the property.
Assuming myEntity is valid Entity, you can simply call ConvertToManuallyUpdated on it:
Once ConvertToManaullyUpdated is called, objects (such as Sprites) within an Entity will no longer respond to position or rotation changes on the Entity. Therefore, if you plan on calling this method, you should do so *after* you have finished positioning your Entities. For example, we'll assume an Entity type called Tree which you are placing in your level. You would want to do something like this:
ConvertToManuallyUpdated is usually called in CustomInitialize of other Entities or containing Screens. ConvertToManuallyUpdated should be used on Entities which either have no every-frame activity (such as movement),or Entities which are manually updated to improve performance. For example, if an Entity has a large number of contained objects, but only one of them has any activity, it may be beneficial to call ConvertToManuallyUpdated, then manually update the single objects that are moving in the Entity's CustomActivity.
Once an Entity is converted to manually updated, it will not have any automatic properties applied - such as Velocity, Acceleration, or Attachments. If an Entity is manually updated, you can select which updates you care about. For example, if you have an Entity which does not use Acceleration, then you can ignore this property and save some processing time (when compared to automatic FRB updates). This is especially important if you are using a large number of Entities in your game.
The Entity Performance tab provides options for improving the runtime performance (reducing CPU usage) for an entity. This tab is only needed for games which include a large number of entities (typically many hundreds or thousands of instances). Common types of entities which benefit from this tab are enemies and bullets.
Entities and objects within entities, such as Sprites, inherit from the PositionedObject class and have default engine-level functionality for applying velocity, rotation, acceleration, drag, and attachments. Although this functionality does not take much time to perform on a single entity, some games may include thousands of entities.
In this case, the number of update calls may impact a game's framerate. If a game includes entities which are completely static (do not move after being created), then every instance of this type of entity can be converted to manually updated, which means that engine-level updates are disabled. Manually updated entities have minimal resource requirements, allowing games to instantiate tens of thousands of instances at once. Entities generate a ConvertToManuallyUpdated method which converts the entity itself and any contained objects to manually updated. This method can be used if your entity requires no every-frame management. However, these situations tend to be fairly rare.
In many cases entities require some of the automatic update logic provided by the engine, but not all. For example, a Bullet entity which moves along a straight line after being created requires velocity to be applied every frame, but does not require acceleration, drag, rotational velocity, or attachment logic. This mixed-case is very common, and this is the case where the Entity Performance tab can be used.
By default, entities are fully-managed by the engine. This means that the engine automatically updates all properties on an entity and its children. For example, the following image shows a Bullet entity and its default Entity Performance tab.
Notice that the entity itself has its own management settings, and each object within the entity (SpriteInstance and CircleInstance) also have their own management settings.
As mentioned before, these settings provide all management functionality, but also have the highest performance requirements.
The Entity Performance tab provides a visual interface for selecting which properties are managed. Since every game is different, it does not provide any standard presets, but rather exposes all possible values. An entity which does not require all properties to be managed every frame can use the Select Managed Properties option.
For example, a Bullet entity which requires only velocity values can check just the XVelocity and YVelocity properties. Note that most entities do not require ZVeocity movement, so that option is left unchecked in the following image:
Changes to an entity's managed properties or changes to managed properties on an object inside of an entity result in code generation and storage of these properties in a EntityPerformance.json file. The EntityPerformance.json is necessary to re-generate the code whenever an entity changes, so it should be included in a game's version control repository.
The generated code for an entity includes the management of all properties selected the Select Managed Properties option is checked. For example, the following code is generated for the Bullet entity using the options shown above:
Of course, if custom code modifies the entity (such as by re-adding it to be managed by the engine), this generated code can result in double-management. The symptom of this is that an object may move twice as fast, animate twice as fast, or have other variables such as drag applied twice in one frame.
If an entity has its Select Managed Properties option checked, then only the properties which are checked will be managed in code generation. While this can greatly reduce the amount of logic which runs every frame, it can introduce problems in your game if your entity depends on functionality which is not managed.
For example, as you develop your game you may decide that some bullet variants acceleration. If these options are unchecked then acceleration values will not be applied every frame. This creates a situation where you must remember to make modification in the Entity Performance tab.
Similarly, if your game is particulary complex it can be difficult to remember exactly which properties are needed if you decide to swithc an entity from Fully Managed to using selected managed properties. Unfortunately the only solution to this problem is to become familiar with the properties available in the list and compare them to the code you have written.
CustomInitialize is called once per entity instance when it is initialized. Initialization happens in any of the following situations:
When an instance is created either in code by using the "new" operator, or if an instance is added through the FRB Editor. See below for more information.
When an instance is created through tiles in a Tiled map (tmx)
When an Entity is recycled through a factory
By default CustomInitialize is an empty function.
Any code can be added to CustomInitialize to prepare an entity for use. Simple entities may not require any code in CustomInitialize, but code can be added for the following:
Preparing animations (using )
Dynamically creating FRB objects such as populating a List of Sprites
Adding conditional debug code such as turning on the visibility of collision shapes
CustomInitialize should not include any code that depends on the current screen. For example, if an Enemy entity needs to initialize its logic according to the current PlayerList in GameScreen, CustomInitialize should not access GameScreen. Instead, initialization which requires external context (such as a list in a Screen) should do so in a function which is called by the Screen. This keeps your entity portable, and reduces the chances of errors occurring due to improper casting or unexpected access of lists before they are available.
Using the example of initializing enemy logic, an Enemy entity may have the following code for initialization:
In this case, InitializeAi would be called by the GameScreen, as shown in the following example code:
The CustomInitialize method will only be called when an Entity instance is added to managers.
The most common method of creating entities is to use a factory. For example, creating an Enemy entity with the EnemyFactory will result in the newly-created instance being added to managers and having CustomInitialize called:
The additon of managers can be controlled by calling an Entity's constructor. Of course, doing so may result in the entity being created but not being added to the proper lists. If you are manually creating entities, make sure that you add them to the appropriate lists (such as the GameScreen lists).
Entities and Screens which have base types (inheritance) have two or more CustomInitialize functions depending on the inheritance depth. For example, if an entity Skeleton inherits from Enemy, each class (Skeleton and Enemy) has its own CustomInitialize method. Both are called by generated code - an explicit base.CustomInitialize();
call is not needed. CustomInitialize is called on the base class first, then to more-derived. Using the example above, Enemy.CustomInitialize is called first, then Skeleton.CustomInitialize.
The Destroy method is used to completely destroy an entity. Generated code calls Destroy for any entity and any list of entities in your current Screen whenever the Screen is destroyed (when the game moves to a different screen). Destroy may need to be manually called if an entity is created manually in game code.
Destroy can also automatically called on Entities which take or receive damage based on properties assigned in their collision relationship. For more information on destroying entities when taking damage, see the Damage Dealing Tutorials.
When an Entity's Destroy method is called, the following happens:
Generated code destroys any contained object which has been added through FlatRedBall Editor. For example, if your Entity has a Sprite and a Circle, both are automatically removed from the engine, resulting in the Entity no longer being visible on screen.
The entity is removed from the engine (SpriteManager) management, so its automatic properties such as Velocity and Acceleration will no longer be applied. Specifically, FlatRedBall.SpriteManager.RemovePositionedObject is called.
The entity is removed from any list that it is a part of. For example, if your GameScreen contains a BulletList, calling Destroy on the Bullet will remove the Bullet instance from the BulletList. This is done through the FlatRedBall.SpriteManager.RemovePositionedObject call.
If the entity is an IWindow-implementing Entity, the entity is removed from the GuiManager so it no longer receives clicks or other UI interaction
If the entity is a collidable entity, its collision is cleared so future collision calls will return false
The entity's CustomDestroy is called, enabling custom code to perform additional object removal.
Note that when writing code in CustomDestroy, the entity should not unload content. The content manager used to load content for the Entity should be provided by the Screen that contains the Entity. Screens automatically unload their content managers, and this will clean up content loaded by the Entity.
As mentioned above, Destroy is automatically called by generated code in the following situations:
Whenever a screen is destroyed, all of the entities added to the screen through the FlatRedBall Editor will also have Destroy called
Whenever a screen is destroyed, all of the entity lists added to the screen through the FlatRedBall Editor will also have their Destroy called. Typically this includes all entities which have been created by a Factory when the GameScreen (or a derived Level Screen) is destroyed.
Whenever an entity is destroyed, any entities that it contains will also be destroyed.
Custom code may need to call Destroy. Usually custom code only needs to destroy entities that it creates on its own. The most common case is when entities should be destroyed as a result of collision, such as when a bullet hits a wall.
The most common situation where Destroy is explicitly called is in collision handling events. For example, consider a game like Pac-Man where the Player is moved around the screen and "eats" pellets. Whenever the player collides with a Pellet, the Pellet instance should be destroyed. In this type of game, the GameScreen would contain two lists: PlayerList and PelletList. A collision relationship between the PlayerList and PelletList would define an event where the destruction of a pellet occurs:
The collision relationship event handler might look like as shown in the following code snippet:
Situations where damage is dealt (such as a bullet hitting a player) should be handled using the IDamageable and IDamageArea interfaces. FlatRedBall provides automatic destruction of entities which use this interface.
The two-way relationship between Entities (and all other PositionedObjects) and the PositionedObjectList class is what enables the Destroy method to remove an Entity from the engine. In fact, the PositionedObjectList (and any class which inherits from PositionedObjectList) is the only reference that Entities know about. If you store a reference to an individual Entity, the reference will still be valid after you call Destroy unless your code handles this case. Let's look at some simple examples. In our first example we'll create some code where the user is keeping track of an individual player and enemy: At class scope:
This piece of code checks for the player attacking the enemy:
This piece of code checks for the player touching and being hurt by the enemy:
The code above has a logic bug which will cause the game to behave improperly. When the Enemy is destroyed (through mEnemy.Destroy();) then all of its components will be removed from the engine. Its visible representation and collision will be removed from the appropriate managers. It will also be removed from the SpriteManager so that it is no longer managed by the Engine. However the collision check between mPlayer and mEnemy is still being done! If you think about it a bit, this makes sense. This is because your code doesn't check if mEnemy is dead. It does the check no matter what. However, since mEnemy is destroyed, it is no longer part of the engine. The result is that mEnemy will seem to completely disappear, but its Collision object will still be sitting there, invisible, in the level. Even though it is not part of the engine, it can still be used to test collisions. There are two solutions to this problem:
(Preferred solution) Create a PositionedObjectList<Enemy> and add your Enemy to that list. Then replace all code which checks against mEnemy to instead loop through your PositionedObjectList<Enemy> and test collision. This should be done for all logic including player attacking enemy and enemy attacking player. When your Enemy is destroyed, it will be removed from the PositionedObjectList<Enemy> and your game will function properly.
(Necessary if you need to keep track of specific Entities) Check your mEnemy's Health before performing collisions. If its health is less than or equal to 0, then it is dead and you shouldn't perform collisions. For example, your collision check should look like:
Many types of entities can die, be collected, or have other types of removal through custom logic. These entities may create additional visuals when removed. Examples include:
A collected coin may create a sparkle
A dead enemy may fall to the ground the flash for a second
A barrel may create an explosion when shot
A boss may explode and break apart gradually
Projects which include entities like the ones listed above are encouraged to destroy the entity immediately rather than modify properties to indicate that the entity is in a destroyed/dead state. For example, when a coin is collected it should be immediately destroyed and a new entity or Sprite should be created in its place to play the sparkle effect. Similarly, a dead enemy should be immediately destroyed, being replaced by an entity (such as DeadEnemy).
This approach is encouraged for a number of reasons:
By destroying entities immediately, collision relationship events can be simplified. If dead enemies are not destroyed immediately, then additional checks may be needed in the collision event handlers to check if an enemy is alive or dead. For example, a dead enemy should probably not damage the player or absorb bullets.
Game state which depends on entity instances (such as a game progressing after all enemies are dead) is simplified since it does not need to consider the state of entities. Instead it can rely on the count in the relevant entity list.
A typical game may have over a dozen collision relationships for entity lists which are core to the game logic, such as PlayerList, EnemyList, or BulletList. Simplifying the collision event handlers can make it easier to maintain the game as it grows.
Keep in mind that even though entities should be destroyed immediately when killed or collected, adding post-removal animations to their AnimationChain file (.achx) is common.
The Implements IClickable property tells the FlatRedBall Editor whether to generate a HasCursorOver method for a particular entity. In other words, Entities which are IClickable can be tested to see if the user has highlighed or clicked an object with the Cursor.
Existing entities can be converted to IClickable in the Properties tab
Select the Entity
Click the Properties tab
Set Implements IClickable to True
This method returns whether the Cursor is over any visible part of the Entity. You could use this function to detect UI activity such as Cursor clicks. The following code can be used to perform logic if the user clicks on the Button:
HasCursorOver can be used to select entity instances in a RTS. The following code shows how to handle unit selection in an RTS. It assumes that UnitList is a list of entities which implement IClickable.
The CreatedByOtherEntities property controls whether a Factory is created for a given Entity. The name "CreatedByOtherEntities" suggests that an entity may be created in the CustomActivity of another entity, such as a Bullet being created in the Player's CustomActivity in response to a button press. Despite its name, Factories are not limited to use inside other entities - the can (and often are) used inside screens as well as entities.
CreatedByOtherEntities defaults to true for Entities which have been created using the default configuration. This value can be changed at any time to modify whether a Factory class is created for the given Entity.
Setting this property to true does the following:
FlatRedBall generates a factory for the Entity type which includes a CreateNew for creating new Entity instances.
FlatRedBall automatically adds any newly-created instance of the given Entity to any PositionedObjectLists created in any Screens in Glue.
FlatRedBall displays an additional property "PooledByFactory" for enabling pooling to reduce post-load memory allocation.
For more information on Factories, see the Factories page.
The BaseEntity property controls the inheritance of a given Entity. An Entity can inherit from another Entity, or it can inherit from a FlatRedBall type, like Sprite.
Entities can inherit from other Entities. Entity inheritance is the current recommended approach for creating a variety of common entities, such as multiple Enemy types in a game. To do this:
Click on the Add Entity quick action
Use the Base Entity dropdown to select the base entity. Note that when a Base Entity is selected, most of the options are hidden since the new entity inherits those properties from its base.
Click OK
The new entity now inherits from the selected Base Entity.
A new entity can be created as a derived entity in the new entity window.
Entities can inherit from FlatRedBall types, such as Sprites. By default Entities inherit from PositionedObject, but this inheritance can be modified through Glue. The reason this feature exists is primarily to improve performance and reduce memory consumption. For more information, see the Inheriting from FlatRedBall Types tutorial.
CustomDestroy is a method that is called once on every Screen/Entity instance when it is no longer needed. Any objects that are created in custom code (as opposed to objects added through Glue) need to be removed/destroyed in CustomDestroy.
Objects which are created in CustomInitialize or CustomActivity must be properly destroyed in CustomDestroy. There are two categories of objects which must be destroyed:
Entities must have their Destroy method
Objects added to the engine (like Sprites) must be removed from the engine
The following example shows a Sprite created in CustomInitialize, then later destroyed in CustomDestroy:
The Implements IDrawableBatch tells the FlatRedBall Editor to generate code for custom rendering including:
All necessary properties for the IDrawableBatch interface
Empty implementation for IDrawableBatch.Update and IDrawableBatch.Destroy. These are are empty since entities already have update and destroy methods.
Addition of the entity to the SpriteManager as an IDrawableBatch
Removal of the entity to the SpriteManager as an IDrawableBatch
Setting ImplementsIDrawableBatch to true does not result in code generation writing a Draw method implementation, so this must be implemented in custom code.
The following instructions show how to use the ImplementsIDrawableBatch property to create an entity which is drawn using the SpriteBatch class. Before writing code, the following steps are needed to create an IDrawableBatch entity:
Create an Entity, or select an existing entity which should have is own Draw method
Set the Entity's ImplementsIDrawableBatch property to True
Add a .png file to the entity. This will be used in the Draw call
Once the entity has been created, we must define a Draw call in the entity's code file. Notice that the Draw method has a Camera parameter. This allows entities to perform rendering relative to the current Camera. In this example the entity ignores the Camera for simplicity.
The IDamageArea interface creates a standard way to define that an entity can deal damage to other entities. It has built-in support for teams and damage over time.
To set an entity as a damage area, set the property on entity in the Properties tab.
A game which has entities implementing IDamageArea will also need entities which implement IDamageable.
For this example uses two entities:
Bullet - an entity which implements IDamageArea and is ICollidable
Enemy - an entity which implements IDamageable and is ICollidable
The GameScreen also has a list for each and a collision relationship with an event.
When the bullet and enemy collide, the ShouldTakeDamage method can be used to determine if the enemy should take damage from the bullet, as shown in the following code snippet.
The ShouldTakeDamage method is available on the Enemy since it implements the IDamageable interface, but the enemy.TakeDamage and bullet.DamageAmount are not provided automatically and must be implemented in custom code.
The IDamageArea interface includes a DamageDealer property which can be used to store a reference to the damage dealer. This is typically used if the damage area is created by another entity, and that entity needs to be referenced upon collision. For example, in a multi-player game, each player may have a separate score. If an enemy is killed by a bullet, then the player who fired that bullet should be awarded points. For example, the following code could be used to assign the DamageDealer on a bullet created inside the Player class:
The Implements IVisible property controls whether an entity implements the IVisible property. If true the following is performed by the FlatRedBall Editor:
The Entity implements the IVisible interface
The Visible property is available in code
Children of the entity will be hidden if instances of the entity have their Visible property set to false
The entity provides the Visible variable for tunneling and assignment per-instance
Entities which can collide with other entities or environments (such as terrain in a platformer) can have their ImplementsICollidable property set. Setting this property to true simplifies writing collision code and makes your code more resistant to changes made to collision objects in Glue.
When creating a new Entity, Glue will give you the option to mark it as ICollidable. The most common approach is to add a shape on the entity when creating it. For example, if the AxisAlignedRectangle check box is checked, Glue will automatically check the ICollidable check box.
Assuming that you are dealing with instances of entities which implement ICollidable, you can call CollideAgainst, CollideAgainstMove, and CollideAgainstBounce between them regardless of the shapes that they use for collision. The benefit of this is that you no longer have to explicitly access the collision objects in an Entity - you can write the code the same regardless of the shape type, and you do not have to change your code if you end up changing your shape objects in Glue.
CollideAgainst is useful when you only need to detect if two things are touching, but the objects do not need to be re-positioned in response to the collision. For example, the following code shows how to perform collision between a ship and a list of enemy bullets:
CollideAgainstMove can be used to collide two objects, and re-position them according to their masses, as shown in the following code:
Notice that the code above did not have to access the specific shape(s) in FirstBallInstance or SecondBallInstance to perform the collision.
For more information and code samples related to IDrawableBatch, see the page.
IVisible is a code interface defined in FlatRedBall. This interface primarily provides a Visible property. For information on working with IVisible in code, see the .
If an entity is already created but not yet marked as a ICollidable, it can be marked as ICollidable in its Properties tab. When marking an existing entity as ICollidable, be sure that your entity has a collidable object, such as a circle.
For more information on the ICollidable interface as defined in FlatRedBall, see the page. For more information on colliding Entities and using ImplementsICollidable, see .
IWindow serves as an interface for creating button-like Entities in Glue. Using the IWindow enables you to do the following:
Respond to clicks (release of mouse-button or touch screen)
Respond to pushes (initial press of a mouse-button or touch screen)
Respond to dragging
Prevent click-throughs on overlapping IWindows
For initial information on how to use IWindows in Glue, check out the IWindow in Glue tutorial page. For more information on IWindow in raw code, check out the IWindow code reference page.
The most commonly-used event when using IWindows in Glue is the Click event. The Click event is an event that is raised whenever the user "clicks" on an IWindow. FlatRedBall considers a Click as occurring if:
The user pushes on a button
The user clicks (releases) while still on the button
When these two events occur, then a button's Click event is raised.
Entities that implement IWindow automatically receive an Enabled property. The Enabled property controls whether the GuiManager's Cursor can interact with the Entity. Disabled Entities will not have their GUI events fired. This Enabled property uses explicit implementation which means you can only access this property by casting an instance of your Entity to IWindow. In other words:
The SlideOnClick event is an event that is raised when the user releases the cursor over a given IWindow, but only if the window was not initially clicked on. To contrast with Click, if the user both pushes and releases the cursor over an IWindow, then Click (or ClickNoSlide) will get raised. If the user pushes the cursor off of an IWindow, then releases it on the IWindow, then SlideOnClick is raised.
SlideOnClick is commonly used for drag+dropping elements onto an IWindow.
The PooledByFactory property on Entities tells Glue that the Factory for the given Entity should perform pooling. For this property to appear, an Entity must have its CreatedByOtherEntities property set to true. More information on CreatedByOtherEntities .
What is pooling? In programming a "pool" of objects is a group of objects which are instantiated but unused. Whenever a new object is needed, an instance from the pool is returned. Whenever an object is no longer needed, it is returned to the pool - in other words, it's recycled. This allows your game to create and destroy objects without having to allocate memory. This is important for reducing memory allocation, which in turn reduces the number of times that the garbage collector has to run. If your game is experiencing jumps in frame rate you may be suffering from the garbage collector firing frequently, and pooling may help resolve this problem.
The first step, as mentioned above, is to set "CreatedByOtherEntities" to true. Once this is done, you will see a "PooledByFactory" property. Setting "PooledByFactory" to true will enable pooling. The syntax to create an object will be:
This code is identical whether PooledByFactory is true or not. This means that you can switch between PooledByFactory at any point in development. As long as you are using Factories, you will not have to change any code!
You may be wondering about recycling. The great thing about pooling in Glue is that the PooledByFactory will both modify the Factory code for your Entity as well as the Destroy code for your Entity. To recycle an Entity you simply call Destroy on it, just as you would if you weren't pooling. In other words, there is no code change here either!
Pooling allows your game to use the same Entity instance over and over to eliminate new memory allocation. While this is great for performance, it can cause some very confusing bugs. The following sections will help you prepare your Entity so that it does not suffer from poling-related bugs.
Consider the following code for a Bullet object:
The code simply marks the time when the Bullet is instantiated, then checks to see if more than 3 seconds have passed since it has been instantiated, and if so, the Bullet is destroyed. This code will work without pooling; however, if you turn on pooling the Bullet objects will stop appearing after a few rounds are fired. The reason for this is because the Bullet's mTimeCreated is only set when the Bullet is instantiated. Once it is recycled, its mTimeCreated remains at its old value, and since it has already been destroyed once due to time, then more than 3 seconds have passed since it has been instantiated. The end result is, as soon as it is recycled, it is immediately destroyed and put back in the pool. The solution is to move any instantiation into CustomInitialize:
Once this change is applied, the Bullet will work as expected. Since this is a common gotcha, we recommend never setting default values to objects outside of CustomIntialize. For non-pooled objects it makes no difference, but if you do decide to switch to a pooled Entity, you will be avoiding possible bugs.
Another common problem related to pooling is the starting values of objects added to an Entity in Glue. The way that Glue performs attachments depends on the absolute position of attached objects when Initialize is called. For example, if an Entity has a Sprite object, then that Sprite object will be attached to the Entity. The position of the Sprite matters - if it is moved to the right in the .scnx that it comes from, then it will be attached with an offset. The reason this matters regarding pooling is because pooled objects often move. This means that when a pooled object is destroyed, the Sprite attached to the Entity (or any other object attached to the Entity for that matter) will not be in its original position. This is a very common problem regarding pooling, and it can be difficult to solve. Fortunately, Glue can help. If you have switched an Entity to be pooled, you can tell it to reset its attached objects as follows:
Right-click on the Entity
You will be asked for a confirmation. Click "Yes".
Your contained objects will now have reset variables. If you'd like to view what has been reset, you can do the following:
Select an object inside your pooled Entity
A set of static variables which store the values to reset
The setting of these static variables in Initialize (Initialize is only called once for a Pooled object)
The setting of instance variables according to the static variables in "AddToManagersBottomUp" which is called whenever an instance is created or pooled.
Keep in mind that Glue only adds variables to existing objects. If you ever add a new object (such as a collision object) to an Entity that is pooled and which has already had its reset variables set, you will need to right-click on the Entity and select "Add Reset Variables For Pooling" to tell Glue to add reset variables for your newly-created object.
Select "Add Reset Variables For Pooling". This option is only available if "PooledByFactory" is set to True
Right-click on the object and select "Edit Reset Variables"
A window will appear showing the variables that are being reset for the given object: These variables are automatically set by Glue to capture the most common cases of variables which should be reset. You can also view the result of these variables in code by opening the Generated code. You will notice:
For information on how factories, pooling, and inheritance all work together see the .
FlatRedBall can provide standardized top-down movement code for entities. This code provides movement code which includes:
Acceleration/Deceleration
AI (for pathfinding)
Default input handling
Input customization
Animation
For information on getting started with top down movement, see the Top Down Games tutorial.
Screens and Entities can be exported from Glue. These exported Screens/Entities can then be imported back into a project. You can get exported Screens/Entities from files that you have previously exported, from other Glue users, or from GlueVault.com.
To import a Screen/Entity:
Right-click on the "Screens" or "Entities" item in Glue and select "Import Screen"/"Import Entity"
Navigate to the location of the .scrz or .entz file you want to import and click OK
Your Screen/Entity should now appear in your Glue project
The UseGlobalContent property tells an Entity/Screen to use the "Global" content manager when loading its content. This means that its content will only be loaded the first time it is accessed and it will never be unloaded. The UseGlobalContent is not the same thing as Global Content Files. Global Content Files is a collection of files which by default are pre-loaded when the application starts and are never unloaded. Files which are part of Screens and Entities which UseGlobalContent will not be preloaded, but will never be unloaded once they are loaded. It is possible for a file to both be part of an Entity as well as Global Content Files, as shown here.
The default value for UseGlobalContent is false. Entities will (by default) use the ContentManager given to them by their containing Screen. Screens will by default use a content manager unique to the given Screen. This means that any time a Screen is unloaded, all content referenced by that given Screen and any contained Entities will automatically be unloaded. This unloading behavior reduces the likelihood of accumulating too much memory through content loading, meaning simpler games will be able to ignore content loading and unloading. However, this also means that content may be unnecessarily loaded and unloaded. For example, consider a game which has a number of UI screens which use the same font files. If this font is used in a lot of Screens, it may be beneficial to always keep it in memory rather than to unload and re-load it on every Screen transition. If this font exists in a Text object Entity which is reused in multiple Screens, then the Entity's UseGlobalContent property can be set to true, resulting in it never being unloaded.
UseGlobalContent can be set by:
Selecting an Entity/Screen
Changing the "UseGlobalContent" property to "True"
Your Entity/Screen will no longer unload files that it uses.
Setting the UseGlobalContent tells an Entity to use the "Global" ContentManager which means it won't unload. If you are familiar with the "Global Content Files" tree item in Glue then you are aware that you can also make files global by adding them to Global Content Files. You may be wondering what the difference between the two approaches is. Here are some characteristics which may help you identify when to use UseGlobalContent and when to use "Global Content Files".
Files added in "Global Content Files" will be loaded immediately when your game begins to run (or asynchronously if the LoadAsynchronously property is set to true). Files which are a part of an Entity that has UseGlobalContent to true will only be loaded when the Entity is first instantiated, or if the Entity's LoadStaticContent method is manually called.
Files added in "Global Content Files" are accessible through the GlobalContent class, which is a standard way to access global content. Files added to an Entity that has UseGlobalContent set to true will be associated specifically with that Entity. This can improve the organization of your project.
As suggested above, files added through "Global Content Files" can be loaded asynchronously. This means you can avoid long load times and delay in application startup by putting files in "Global Content Files".
There may be situations when a file should both be part of "Global Content Files" as well as part of an Entity which has UseGlobalContent set to true. The most common case is if a piece of content is associated with a particular Entity, but should be asynchronously loaded. For example, you may be working on a game that does not load some in-game content (such as the main character's content). If this is the case, making the main character's content exist in "Global Content Files" allows you to begin loading this content at the very beginning of execution. Depending on the menu flow of your game, you may end up loading your character before the player gets to the game Screen. This could improve load times when going into game. If you set an Entity to UseGlobalContent, and also add its files to the "Global Content Files", then the generated code for the Entity will use the GlobalContent class to get reference to the appropriate files. This means that it will obey the async loading, and even update the content lock record if appropriate.
The MoveToLayer method will place the entity on a Layer (if it is not already on a Layer) or will remove the entity from its current Layer and place it on the argument Layer. This method will assign the entity's LayerProvidedByContainer property, and will move all contained visual elements (such as Sprites) to the new layer.
The following code moves an entity to a layer called HudLayer :
Marking an entity as implementing IGumCollidable enables the creation of shapes for standard FlatRedBall collision using a Gum object. This can be useful for visually creating complex shapes in Gum, for aligning shapes with visuals created in Gum, or for implementing collision animation using the Gum animation system.
The following example shows how to create shapes in Gum and use them as the entity's collision. This example will use a default Player using the top-down controls, however it can be used on any type of entity.
First, we'll delete the existing collision from the entity since it is not needed - Gum will be responsible for adding collision:
Next, we'll define a Gum object which has collision. Keep in mind - any visuals will also be rendered on the entity, but for this example we'll use only shapes for collision.
Gum objects can contain Circle and Rectangle instances, and these should not be rotated. Notice that the component uses the center alignment. The center of the FlatRedBall entity will line up with the center of the Gum entity. Once a Gum component has been created, it can be added to the Player object:
Right-click on the Player's Objects folder
Select Add Object
Select the Gum Object Type
Scroll down or search for the name of your Gum component - in this case PlayerGumComponentRuntime
Click OK
Finally, verify that the Entity is both an ICollidable and IGumCollidable:
Select the entity
Select the Properties tab
Set ImplementsICollidable to True (this is usually true if the Player object was created by the wizard)
Set ImplementsIGumCollidable to True
Now the Player object will have its Collision populated by any Circle and Rectangle instances from any Gum objects (in this case PlayerGumComponentRuntimeInstance). Setting the collision to Visible can be helpful for debugging. Add this code in the Player's CustomInitialize method:
The Collision ShapeCollection will be visible and collides with solid collision.
This tutorial will walk you through how to create entities which inherit from FlatRedBall types. More accurately, the process of having Entities inherit from FlatRedBall types is very simple - all you have to do is change the BaseType to the desired type. However, this tutorial will discuss how to work with entities that inherit from FlatRedBall types, and why taking advantage of this feature can be helpful.
First we'll create a simple project with a single Entity that includes a Sprite, and a Screen which includes a large list of instances of this entity.
To create the Entity:
Right-click on Entities
Select "Add Entity"
Name the Entity "SpriteEntity"
Right-click on the newly-created Entity's Objects
Select "Add object"
Select "Sprite" as the type
Click OK
Now that we have an Entity, let's set the Sprite to use a Texture:
Download the Bear.png image from here:
Go to the location where you saved the file
Drag+drop the PNG from the location where you saved it into the SpriteEntity's "Files"
Select the SpriteInstance object
Set its Texture to "Bear"
Now that we have an Entity, let's create Screen:
Right-click on Screens
Select "Add Screen"
Name your Screen "MainScreen"
Click OK
Next let's create a List of SpriteEntites:
Right-click on Objects
Select "Add Object"
Select "PositionedObjectList<T>" as the type
Select "Entities\SpriteEntity" as the List Type
Name the list "SpriteEntityList"
Click OK
Finally let's populate the List in code:
In Glue select the "Project"->"View in Visual Studio" menu option
Open MainScreen.cs
Add the following in CustomInitialize:
If you're running this project on a modern computer then it's likely that you may not be noticing any performance problems. However, despite running without problems on the PC, this same project may have significant performance and memory consumption issues on less powerful devices, such as the iPhone. One solution to this problem would be to make the Entities be manually updated; however that may not be so easy in this particular case. The reason is because our Entities are all spinning and require every-frame logic to have their rotation applied. However, making the Entities inherit from sprite can actually improve performance and memory usage. To understand why this is the case, let's first investigate how many manually updated objects are in the FlatRedBall engine. To do this:
Open your MainScreen.cs in Visual Studio
Add the following code to CustomActivity:
Now that we have this set up, let's change our SpriteEntity to inherit from a Sprite. To do this:
Select SpriteEntity in Glue
Change "BaseEntity" to Sprite
Now we can simply have the SpriteInstance inside of SpriteEntity be a reference to the SpriteEntity itself. To do this:
Select SpriteInstance
Set "IsContainer" to true
You should see a large number of spinning bears:
Now your program will be outputting information about how many automatically updated objects exist in the engine: For more information on this method call, see the WriteAutomaticallyUpdatedObjectInformation page. We can see that we have 4000 Sprites (one for each instance of our SpriteEntity) and also 4000 PositionedObjects (each SpriteEntity inherits from PositionedObject).
Now that the SpriteEntity inherits from a Sprite, and the SpriteInstance is the container, we have essentially eliminated half of our runtime objects. To see this result, run the game again: You can see that since all of the entity instances are Sprites, all PositionedObjects have been removed (the engine reports 0 PositionedObjects).
Screens and Entities can be exported through Glue and later imported. An exported Screen/Entity can be easily transferred to other projects, sent to other developers, or uploaded to GlueVault.com to be shared with the community.
Once you have a Screen/Entity that you are ready to export, you can:
Right-click on the Screen/Entity and select "Export Screen"/"Export Entity"
Navigate to the folder where you would like to save the exported element and click OK
An Explorer window will appear showing you your exported file
You can share the exported Screen/Entity on GlueVault.com
Exported Screens and Entities create .scrz (Screen zip) or .entz (Entity zip) files, respectively. These files are standard zip files which can be unzipped with any unzipper. Of course, Glue understands these files as well so there is no reason to unzip these files if you plan on using them in Glue. Exported Screens and Entities contain the following:
An XML file containing the information set in Glue
A C# code file containing custom code
All referenced files (such as .scnx or .shcx) and any files that the referenced files include
The LayerProvidedByContainer property gives you access to the layer that the containing Screen or Entity has passed to this through Glue or through the AddToManagers method call. For more information on working with Layers in code, see the Layer page.
You can access the Layer simply by using the LayerProvidedByContainer property:
The LayerProvidedByContainer can be used to add additional objects to the same Layer. The following code shows how to create a new Sprite using an existing entity's LayerProvidedByContainer:
The following code shows how to create new entities using an existing entity's LayerProvidedByContainer: