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...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Files added to the FlatRedBall Editor are managed for you automatically, simplifying the game development process. When a file is added to the FRB Editor the following occurs:
The file is listed in the tree view
The file is added to the proper Visual Studio project(s)
A static member is added for the file in the appropriate screen, entity, or global content
Code for loading the file is generated automatically
png (image files)
achx (animation files)
tmx (tiled map files)
gusx (Gum screen files, usually automatically added when creating a new FRB Screen)
mp3 (music)
ogg (music)
wav (sound)
csv (spreadsheet files for data)
The following types are also supported, but are not commonly used in modern FlatRedBall game development
scnx
shcx
emix
splx
nntx (node network files)
Additional files can be added to the FlatRedBall Editor and supported through plugins. For example, see the Spine plugin for supporting Spine files.
FlatRedBall supports multiple ways to add a file to your project:
Right-click on the Files folder and select to add a new file
Right-click on the Files folder and select to add an existing file
Drag+drop a file from a Windows Explorer window onto the desired Files folder in the FlatRedBall Editor
Usually if a file is loaded in your game, the File should be located relative to the Content folder of your project. This is important so that your game is portable. Therefore, whenever an existing file is added to your project, the FlatRedBall Editor checks if it is already inside the Content folder. If not, it is copied to the desired folder in a Screen, Entity, or Global Content Files.
If you would like to control the organization of your files, then you should always manually copy the files into your Content folder in their desired location first, and then add them to FlatRedBall. By using this approach, the files will remain in the same place after you add them to FlatRedBall. Otherwise, you can drag+drop files from anywhere (such as the desktop) and FlatRedBall will organize them based on where the files are dropped.
For example, if a file is located on the desktop then it will be copied to the game's content folder when it is drag+dropped. The original file is left untouched. Any modifications to the file should be made on the file inside the Content folder rather than the original file.
In this case the file is copied to the game's Content/GlobalContent folder. Note that the prefix "Content" is omitted in the Name property as this is assumed for all content.
If the file is already a part of the project's Content folder, then it is not copied when drag+dropped into FlatRedBall.
For convenience, existing files in the Content folder are shown when adding new files.
Some file types can reference other files. If FlatRedBall understands this file type, then only the root file must be added to the FlatRedBall project - all referenced files will be automatically added to your game project.
This feature is especially useful for file types which can reference lots of other files. For example, consider that a Gum project (.gumx) can reference dozens of other files such as texture files (.png) and font files (.fnt). By adding the .gumx file to your project (which is done automatically when creating a project with the New Project Wizard, all other files are automatically added to your project.
The following screenshot shows a typical game with the GumProject.gumx added to Global Content Files.
Every file referenced by the Gum project (and any of the Screens and Components in the Gum project) is automatically added to your game project (.csproj). For example, all font files are automatically added to the game project, as shown in the following screenshot from Visual Studio.
The FRB Editor also supports adding files using a wildcard pattern. For more information on using wildcards, see the Wildcard Files page.
Files added through the FRB Editor can be accessed in code. Files added to Global Content Files can be accessed in any location through the GlobalContent
class. Files added to screens and entities can safely be accessed within the respective screen or entity's custom code. Files from other screens or entities can be accessed so long as the owning screen or entity has had its LoadStaticContent
method called prior to accessing the file.
Note that files can also be accessed through the generated "Type" class generated by FlatRedBall. For more information on derived types and accessing files, see the Entity Variants Using Inheritance page.
Files added to a Screen or Entity create a member which can be accessed in code. For example, if a .png file is added to an Entity, it can be used to assign a texture on a sprite. In the example below, the FlatRedBall Editor generates code for a Texture2D called MonsterTexture .
This Texture2D can be accessed in custom code, such as to assign a Sprite's Texture. Since MonsterTexture is a static Property of the Monster entity, access to this property is checked at compile time and auto complete displays it as an option when writing code.
Global content files are loaded when the game first starts, and remain in memory for the remainder of a game's execution, so they can be accessed at any time. For example, the following file named MainSpriteSheet.png is part of Global Content Files.
This can be accessed anywhere in a game with the following code:
Single files can be shared across multiple Screens, Entities, and Global Content. For example, a file may be added to Global Content Files, but then also added to an Entity to be accessible by that Entity in the FlatRedBall Editor. This does not create a copy of the file - both Player and Global Content Files reference the same file on disk and in memory:
Files can also be shared between entities and screens. For example, the following shows a single file shared between two entities:
Notice that the file being moved is in the Entities/Player folder. When it is moved to Monster, the file in the Monster files is still named Entities/Player.CharacterSpriteSheet.png. The FlatRedBall Editor does not duplicate the file on disk when it is drag+dropped from one Entity to another. At runtime the image is only loaded once if both Player and Enemy are created in the same screen.
The "Files" tree node supports folders. To add a folder:
Right-click on the "Files" node
Enter the name of the folder
Click OK
This creates a folder both in the FlatRedBall Editor as well as on the file system.
The Name of a file in the FlatRedBall Editor reflects its location. For example, the following shows a file located in the Animations folder of a Ball entity:
Shared files display the name of their location on disk. For example the following shows a file which is located in Global Content, but shared with an entity. When the shared copy is selected the file's actual location is show in the Name property:
Notice that the file above is located in GlobalContent/ball.png, but it appears in both the Global Content Files folder and the Files folder of BallEntity. To view a file in its location on disk, right-click and select View in Explorer.
Files can be deleted by right-clicking on a file and selecting the Remove option.
The Delete key on the keyboard also serves as a shortcut for removing the file.
If a file is removed, the FRB Editor scans the project to determine if the file is still referenced elsewhere. If no refernces are found, then FRB asks what you would like to do with the file.
Nothing - this option removes the file from the FRB Editor, but the file remains part of the Visual Studio project and is not removed from disk. Select this option if you would still like to use this file in code. Note that you must manually load the file in custom code - the FRB Editor no longer generates any code for files which have been removed.
Remove them from the project but keep the files - this option removes the file from the the FRB Editor and also from your game project (.csproj). Select this option if you do not want to use the file in your project, but you want to keep it on disk so you can access it later. Since the file is no longer part of Visual Studio, it will not be copied to your game's bin folder, so it cannot be loaded at runtime - even in custom code.
Remove and delete the file - this option removes all traces of the file including the FRB Editor, your game project (.csproj), and on disk. Select this option if you are sure that you no longer need this file.
If FlatRedBall detects that a file is still used by your project, it does not display the dialog asking you what to do with the file.
For example, if the same file appears in two entities, it can be removed from one safely and FRB will not ask what to do with the file since it is still needed. The following animation shows a file which is part of both the Monster and Player entities. If removed from Monster, you will not be asked to remove it from your project or disk since it is still part of the Player entity.
If the file were to also be removed from Player, then FRB would ask how to treat the file (nothing, remove from project, delete).
A file can have references from other files. For example, a .png file can be referenced by an .achx file. FlatRedBall understands file references in common file types such as .achx, .tmx, and gum files. Therefore, if a file is removed but still referenced by a different file, FRB will not ask about removing the file from Visual Studio or the file system.
For example, the Player's AnimationChainhListFile.achx references the CharacterSpriteSheet.png. If CharacterSpriteSheet is removed from the Player entity, the FRB Editor recognizes that it is still needed and does not ask about whether it should be deleted or removed from the game project.
CSVs are often used to define data for games, but it's common for one CSV to need to reference information from another CSV. This tutorial will walks you through creating two CSVs, with one referencing the other.
We will be creating two CSVs:
The first defines the weapons in your game. The weapons defined for this game are for a traditional RPG.
The second will define the shops in the game which will contain a list of the weapons which they can sell.
First we'll create a CSV for weapons called WeaponInfo:
Right-click on Globa lContent Files
Select "Add File"->"New File"
Select "Spreadsheet (.csv)" as the type
Enter the name "WeaponInfo" as the new file's name
Click OK
Next create the CSV for StoreInfo:
Right-click on Global Content Files
Select "Add File"->"New File"
Select "Spreadsheet (.csv)" as the type
Enter the name "StoreInfo" as the new file's name
Click OK
You should now have 2 CSVs in your Global Content Files uner Global Content Files:
Fill the WeaponInfo file so it appears as follows:
Sword
3
Spear
4
Dagger
2
Fill the StoreInfo so it appears as follows:
CapitalCity
Sword
Spear
SouthCity
Dagger
Spear
Note that the StoreInfo CSV file uses a List<string> instead of a List<WeaponInfo> for the WeaponTypes it contains. Specifically the StoreInfo references the Name of the WeaponInfo, similar to a key in a database.
Next we'll need to write some simple code to associate the values in the WeaponTypes column in the StoreInfo CSV to the weapons defined in WeaponInfo.csv. To do this:
Open your project in Visual Studio
Expand the "DataTypes" folder in the Solution Explorer
Right-click on the "DataTypes" folder and select "Add"->"Class..."
Name the class "StoreInfo". This should be the same name as your CSV.
You should now have a file called StoreInfo.cs and a file called StoreInfo.Generated.cs
Next, open the newly-created StoreInfo.cs file and make it a "public partial" class. After you do this, your code should look like:
Finally save your project through the "File"->"Save All" option in Visual Studio. This saves changes to the project so that if the FRB Editor is open it will reload the changes.
Next we'll add a property to the StoreInfo.cs file to make it more convenient to access which WeaponInfo's a Store contains. To do this, add the following code to StoreInfo.cs:
Now each ScreenInfo which is loaded into GlobalContent has an IEnumerable of WeaponInfo's that can be used to populate UI, menus, and drive game logic.
By default Glue creates a new class in the DataTypes namespace for every CSV in your project. For example, consider a game where each enemy can have multiple types of attacks. Each enemy might store the attack information in its own CSV file. In this example the CSV files would be called:
SoldierAttackData.csv
OgreAttackData.csv
SlimeAttackData.csv
ZombieAttackData.csv
We will assume that each CSV file has the same columns, and we would like to have the same code handle enemy attacks regardless of which type of enemy is performing the attack. However, by default Glue will create four classes - one for each CSV. To solve this problem, we can create a common class to be used by all CSV files. This can be done by right-clicking on each of the CSV files and selecting the Set Created Class option.
This example uses enemy entities which each provide their own attack data in CSV files. Each CSV has its Created Class set to Enemy Data.
A new class can be added in the Created Class window.
Once added, classes appear in the list below.
This class can be used for the current CSV by selecting the class and clicking the Use This Class button.
Once a class is added, Glue generates a file for this in the DataTypes folder.
The four CSVs specified above will deserialize into AttackData Dictionaries or Lists.
Glue automatically creates a class called PlatformerValues if a game includes platformer entities. Every entity will store its platformer values in instances of the common PlatformerValues class. Removing this class can cause compile errors.
Font files (.fnt) are produced by AngleCode's Bitmap Font Generator ( ). These files can be loaded through the FlatRedBall Editor and used on FlatRedBall Text objects. Note that the recommended approach for working with files is through Gum. If using Gum, you do not need to explicitly load font files in the FlatRedBall Editor.
To load a font file:
Verify that you have the .fnt file and any referenced files already placed in the correct folder. This is important because both files must be part of the project.
Drag+drop the .fnt file into your Files folder - either in Global Content Files or the Files folder of a Screen or Entity
Your font file should appear in the Files folder.
This file can now be referenced on a Text's Font property.
JSON files can be added to FlatRedBall projects. JSON files are treated as content and their membership in the game's .csproj is automatically managed by FlatRedBall, but they must be manually loaded in code. JSON files can be used to store definition data - data which is defined during the development of a game and which does not change while the game is running. Examples of game definition data incude
Weapon damage, cost, rarity, and description text
Enemy health, movement speed, and experience awarded
Level difficulty rating, preview image name, and description text
JSON can also be used to store game progress or game settings, but these files are usually created and loaded during runtime so they are not added to the FlatRedBall Editor.
Both JSON and Comma Separated Value files can be used to store data. JSON data provides more flexibility and also can integrate with more standardized deserializers such as JSON.net and System.Text.Json. However, due to this flexibility FlatRedBall does not automatically generate classes for deserialization. You must create your own to load a JSON file.
Ultimately both JSON and Comma Separated Values can be used to store and load definition data, so usage often comes down to developer familiarity.
The first step in loading a JSON file is to define either the JSON or the desired C# class for JSON. You can start with either depending on which you are more familiar with.
If you are more familiar writing C#, then you can define your class and create a simple example object which can be used to create your JSON. For example, the following code could be used to define definition data for enemies in a game:
Be sure to delete the constructor which populates the Data list after you have created your JSON file. Leaving this code in may result in additional data when loading your JSON.
The output JSON might look similar to the following text:
Notice that the generated C# does not include names like Enemy and EnemyData so you may need to make modifications to the generated C# to make it more expressive.
Once you have created a JSON file and a C# file, you can add the JSON to FlatRedBall. JSON files can be added to any location - Global Content, Screen Files, or Entity files. Since you will be performing the loading in custom code, the only difference between these locations is organization. JSON data tends to be relatively small compared to other game data (such as textures and audio), so adding it to Global Content is usually preferred.
To add a JSON file to your project:
Save the file to disk in its desired location, such as your game's content folder ( Content\GlobalContent
)
Drag+drop the file into the Global Content Files in the FlatRedBall Editor
The steps above ultimately add the JSON file to your .csproj file. If you are comfortable adding this file manually (such as through Visual Studio, Rider, or Visual Studio Code), you can do so through your IDE rather than using FlatRedBall. Ultimately, the only thing that matters is that the file ends up in the built directory.
Now the file is part of your project, so you can load it in your custom code. For example, the following code could be used to load the data in Game1.cs:
We can add a breakpoint to verify that enemyData contains the data we added to our JSON file:
Notice that EnemyData includes a constructor which populates the Data list - this is only being done temporarily to obtain valid JSON. You can use similar code to obtain a valid data object which can be used to create JSON. You can either add this code to a C# console project and serialize the JSON, or you can use an online tool such as
if you are more familiar writing JSON text first, you can write this JSON and use online converters to create C# classes. For example, the code above could be used on the website to produce the following C# classes:
The contents of the JSON are loaded using FromFileText. For more information, see the page.
The .splx file format is an XML file that stores a list of Splines. For more information on using Splines in code, see the Spline page.
To add a new SplineList file:
Create a Screen or Entity which will contain the SplineList file
Right-click on the Files item
Select "Add File"->"New file"
Select "Spline List (.splx)" as the file type
Click OK
Glue screens and entities support folders inside of their Files object. Folders can be used to organize files and to support multiple files with the same name in a single screen or entity.
To add a folder to an existing screen or entity:
Right-click on the "Files" node under the screen or entity
Select "Add Folder"
Enter the new folder name and click "OK"
The newly-created folder will appear under the Files node. New files can be added to this folder.
Any file added to a Screen or Entity will have a corresponding member in code which represents the already-loaded file. You can access this object in custom code without having to worry about whether it has been loaded or when to load it (at least under default settings).
To see how a file is accessed in code:
Create a new Screen called "TestScreen"
Find a .png through windows explorer
Drag+drop the .png into your TestScreen's Files in Glue
Notice that the newly-added File will indicate which type it will load to at runtime
Open TestScreen.cs in Visual Studio
Add the following code to CustomInitialize:
Note:Since the purpose of the code above is to simply show that the file added to TestScreen can be accessed in code, it does not cover removal of the Sprite. In an actual game you would want to keep track of the Sprite at Screen level and remove it in the Screen's CustomDestroy. Not doing so would result in your game crashing when you transition to a different Screen.
The AnimationChainList type is the runtime type for the .achx file type. AnimationChainLists are used to store a collection of animations. Examples of AnimationChainLists might be all of the animations for a Player in a platformer game, such as:
WalkLeft
WalkRight
IdleLeft
IdleRight
JumpLeft
JumpRight
AttackLeft
AttackRight
The easiest way to add an AnimationChainList to your game is to add a new .achx file to a Screen, Entity, or global content:
For information on how to add a Sprite to your Entity, see this page. For information about how to use the AnimationEditor, see the AnimationEditor documentation.
AnimationChainLists are ultimately lists of textures and texture coordinates. They must be used on an object to be seen in game. Therefore, if you are creating an Entity or Screen which includes an AnimationChainList file, you will likely also need to add a Sprite to view the AnimationChainList.
CSV (comma separated values) is a spreadsheet file format which has extensive support in FlatRedBall.
CSV stands for "comma separated values". If you are familiar with Microsoft Excel, then you may be familiar with the .xlsx or .xls file format. The .csv file format is similar to the .xlsx file format in that they are both spreadsheet file formats. One main difference between the two is that the .csv file format is much easier to read and edit in a text editor. For example, consider the following:
If this were a CSV file viewed in a text editor then it would appear as follows:
You can see above that the values (such as "Column 1" and "Column 2") are separated by commas. This is where the name "comma separated values" comes from.
When you create or modify a CSV which is part of your FlatRedBall project, FRB automatically creates code files (classes) which can be used to store information that is loaded from a CSV in your project. These files/classes are often referred to as "data" files and classes because FRB generates them in the Data namespace of your project. The data file will include a class with the same name as your CSV file. This will include members matching the headers of the columns of your CSV. For example, consider a file EnemyInfo.csv which contains the following:
If this file is added to a Screen, Entity, or Global Content, then FlatRedBall automatically creates a file called EnemyInfo.Generated.cs:
To add a CSV file:
Open the FlatRedBall Editor
Pick a place for your CSV file in your project. Usually CSV files are added to Global Content Files
Right-click on on the location which should contain the new CSV and select Add File -> New File
Enter the name for the new file. Although not necessary it's common to end the file name with "Data". For example, EnemyData if the file is to include data about enemies.
Once you have added a new CSV file you can edit it in any editor you prefer, such as Excel, Libre Office, or even a text editor.
CSV files which are added to the FRB Editor are automatically loaded. If your CSV is added to Global Content Files (as is usually the case), then its contents can be accessed through the GlobalContent object.
For example, consider an EnemyData.csv file added to Global Content Files.
This file can be accessed in code through the GlobalContent object in code as shown in the following code snippet:
The example above assumes a row for the "Monster" enemy and a column for Health as shown in the following image:
As mentioned above, the FlatRedBall editor automatically generate a code file based on the CSV. Specifically, FRB looks at the top row (headers) of the CSV file to determine the class members. If a header does not specify a type, then it will default to a string type.
The example above has two string members: Name and Texture. Headers can also define the type of a class. For example, the header above Speed (float) results in the EnemyInfo class including a Speed property of type float. FRB supports comments for headers resultingin the exclusion of the property. For example, the following CSV would include a single Name property, and the other column is ignored:
Columns in a CSV may be of a list type (such as List<int>). These types can be specified in parenthesis just like any other type. When a CSV includes a list, the required row defines how many entries are in the CSV. For example, the following CSV contains two car definitions, and each car has multiple features.
The generated code file for the data class is marked as "partial". This means that you can add additional code files to add additional variables and functionality to data that is created by FRB. To do this:
Find the data file in Visual Studio
Right-click on the folder containing the Data file
Select "Add"->"Class..."
Enter the name of your CSV file without the extension. For example, if using EnemyInfo.csv, the new Class name would be EnemyInfo (so it matches the class name in the generated file)
Once the file is selected, find the header of the file and make it partial. In other words, change:
to
Now you can things to EnemyInfo to help you work with the generated class. Note that this approach of using partial classes is the same as what FRB automatically does for you when you create a Screen or Entity. Custom code is very common in Screens and Entities, so FRB automatically creates a custom code file for you. Custom code in data classes is less common so FRB does not automatically do this for you; however if you do it manually it works the same way.
Note that if you add additional rows or columns you can access these in your code. Also note that this code assumes that the CSV is loaded into a dictionary. For more information on List vs Dictionary loading, see the property.
Bear
Bears are strong
Slug
Slugs are slow
Accord
Power Windows
Power Locks
Anti-lock Brakes
Leaf
Electric Motor
Electric Motor
Value 1
Value 2
Value 3
Next Row
Next Row 2
Next Row 3
Bear
60
Bear
Slug
20
Slug
CSVs are a common way to define game data in FlatRedBall games. Examples of game data include the cost, damage, and rarity of weapons or stats of enemies like Orc, Dragon, and Elf. Usually this information is used in game logic to determine information like the maximum speed of a car or how much damage an attack deals. Fortunately Glue provides a flexible, powerful way to use CSV data in your game. This article provides an example of loading a CSV into an entity to control its movement speed.
The type of information can be categorized into three groups:
Simple coefficients like HP or AttackDamage for enemies in an RPG, or like Horsepower and Weight for cars in a racing game
Content information such as which .PNG to use for a enemy, or which .scnx to load for a level
Behavioral classes such as ability classes. Usually this feature requires usage of advanced CSV functionality such as lists and inheritance.
You will need a Glue project to follow along this tutorial. For information on how to create Glue projects, see this page.
In this tutorial we'll use an Entity called Animal. To create the Animal Entity:
Right-click on the Entities item in Glue
Select Add Entity
Enter the name Animal and click OK
Next we'll add a Sprite to the Animal Entity so that it can be seen in our game. To do this:
Expand the Animal Entity
Right-click on Objects
Select Add Object
Select the Sprite type
Enter the name MainSprite and click OK
The default Sprite will not have a Texture associated with it, therefore it won't be visible. To make the Sprite visible:
Select the MainSprite object
Set the ColorOperation value to "Color"
Set the Red value to 1
Set ScaleX to 64
Set ScaleY to 64
Next we'll create a Screen to verify that our Animal is working properly. To do this:
Right-click on the Screens item in Glue
Select "Add Screen"
Enter the name "GameScreen" and click OK
Move the mouse over the Animal Entity and push/hold the mouse button
Drag the mouse down to the newly-created GameScreen and release the button
Click "Yes" when prompted if you want to add an Animal to GameScreen
We will also want to set up our camera to be 2D. To do this:
Click on the Settings menu item
Select "Camera Settings"
Change "Is 2D" to "True"
Now you can run the game and you should see your Animal appear as a red square:
At this point we have a basic project up and running: We can see our Animal Entity in our screen, although at this point the Animal Entity is simply a red square that doesn't do anything. Next we'll define a few animal types. To do this:
Right-click on the "Global Content Files" item
Select "Add File"->"New File"
Select the "Spreadsheet (.csv)" file type
Enter the name AnimalInfo for the file type
Once the file is created, double-click the file to open it in a spreadsheet editor. Modify the file so it contains the following information:
Name (required)
Speed (float)
Texture
Bear
60
Bear
Slug
20
Slug
Save the file to cause Glue to update the AnimalInfo class to match the new data entered in the CSV file.
Next we'll make the AnimalInfo file create a Dictionary - this will make working with the AnimalInfo easier. To do this:
Select the AnimalInfo.csv file in "Global Content Files"
Change the "CreatesDictionary" property to "True"
If you have used Glue before, you may expect the next step to be adding a variable called "Speed" to the Animal Entity which can be assigned from the CSV. Instead of creating a new variable for Speed, we'll instead add a reference to the entire AnimalInfo inside the Animal Entity. To do this:
Expand the Animal Entity
Right-click on the Variables item
Select "Add Variable"
Select the "Create a new variable" radio button
Select "GlobalContent/AnimalInfo.csv" as the type
Enter "AnimalInfo" as the name
Click "OK"
This new AnimalInfo variable can now be set in code or in Glue. For simplicity we'll set it in Glue; however, CSV variables like AnimalInfo are usually set in code according to player actions or game data. To set the variable:
Select the newly-created AnimalInfo variable
Set the DefaultValue to "Bear" using the drop-down
Now we can use the AnimalInfo variable in our Animal's behavior code. To do this, add the following code in the CustomActivity in Animal.cs.
Notice that the AnimalInfo and Speed variables are both supported in Visual Studio's autocomplete. Working with these Glue-created types and variables provides full autocomplete support so you know that you're writing the code correctly. Now try running the game and using the arrow keys on the keyboard to move your Animal entity. Also, try changing between the Bear and the Slug and you'll notice the Slug moves much slower. You can also modify the values in the CSV, then run your program again to notice the changes.
Memory Benefits: Since the types defined in CSVs are reference types (classes), then the Entity simply points to a reference of an AnimalInfo. While this might seem like a small gain (in the case of one Entity, it may not be a gain at all), consider a situation where you have numerous variables defined in a CSV, and you may have dozens or even hundreds of Entities that use these CSV values. In this case the reference characteristics of the CSV types is very beneficial. Furthermore, these references are not destroyed or recreated, so you will save on memory allocation and garbage collection if you are creating and destroying Entity instances.
Next we'll look at how to load content dynamically according to information in the AnimalInfo CSV. The approach we're going to show is a very powerful approach because it only loads information as needed. We'll be loading a Texture2D to apply to the Animal Sprite, however this approach can be used for any other data such as AnimationChains, Scenes, and ShapeCollections. Also, keep in mind that this is not limited to Entities - you can also use it on Screens to dynamically load data according to information in a CSV that defines level info. To add the textures to your project:
Return to Glue
Expand the Animal Entity
Right-click on the Files item under Animal
Select "Add File"->"Existing File"
Select the Bear and click OK
Repeat the above 3 steps and add the Slug
Select the Slug and also set its "LoadedOnlyWhenReferenced" to "True"
Now we need to write a little bit of code to modify the Sprite according to the AnimalInfo. To do this:
Open Animal.cs and delete the contents of CustomInitialize - we won't need this code anymore now that we're going to use textures.
Select the AnimalInfo variable under Animal in Glue.
Right-click on the "Events" item under Animal in Glue
Select "Add Event"
Verify "Expose an existing event" is selected
Verify "AfterAnimalInfoSet" is selected as the existing event
Click OK
Expand the Events item and select the "AfterAnimalInfoSet" event
Add the following code to the text box which appears on the left:
Next we'll modify the Sprite's variables. To do this:
Select the MainSprite object in Glue
Right-click on the "ScaleX" variable and select "Reset to Default"
Right-click on the "ScaleY" variable and select "Reset to Default"
Set the PixelSize varaible to .5
Set the ColorOpeartion to "Texture"
A very common mistake when working with CSVs is to not properly order your variables. If you followed the tutorial above word-for-word, then your project will not have any variable order issues because there is only one variable - the CSV variable. However in larger Entities variable order problems can emerge. For starters, let's consider the example above where we have a single CSV variable which has a script that sets the Texture on a Sprite. The setup may look like this:
Specifically, we have just a CSV variable, and an event that is raised when the CSV variable (called AnimalInfo) is set. Next we'll tunnel in to the Sprite's Texture. To do this:
Right-click on Variables
Select the "Tunnel a variable in a contained object"
Select "MainSprite" as the Object
Select "Texture" as the Variable
Set the Texture to "Slug"
Set the AnimalInfo to "Bear"
So far we've shown how to set AnimalInfo in Glue. This is very handy for previewing things in GlueView, or for setting initial values; however it is likely that you will want to set values in custom code according to player actions or scripted events. To do this, you can simply access the AnimalInfo variable. To do this:
Create a Screen (you don't need to do this if your game already has a Screen)
Add an instance of Animal in your Screen
Add the following code in your Screen's CustomInitialize:
Note: You may need to fully-qualify
. You can do this with CTRL+dot. More info here
You can change this from Bear to Slug and the AnimalInstance will respond appropriately. Of course, you don't have to do this just in CustomInitialize, you can do this at any point, and on any Entity that supports this pattern, whether it is created in Glue, or created purely in code.
While this example may seem to be simple, the approach we've taken here is incredibly scalable, efficient, and flexible. However, as with all approaches there are some things to consider:
All Entities that are given the same CSV object reference will share the same exact instance. This means that if you change a value (like the Bear's Speed) it will apply to all bears. Also, the CSVs are not destroyed when Entities or Screens are destroyed if put in Global Content Files, so changes will persist until the program is restarted. This can all cause confusing behavior if you are editing the CSV but not seeing changes that you expect to see. You should never change these values in code unless you have a very good reason to do so.
If you intend on modifying values, such as allowing each individual instance to have a speed boost according to the Animal's level, you should make a custom property that uses the base value and returns a modified value.
The texture for the Bear and Slug will not be loaded until either is needed. Since the AnimalInfo is set after content is done loading, it is done on a primary thread. In other words, this means you may notice a slowdown or freeze when loading content if you are loading a lot of content. For simplicity this tutorial only covers how to load the content on the primary thread, but you may want to pre-load content that you know you will need in CustomLoadStaticContent.
Changes in the CSV will immediately show up in code (as long as Glue is open). This means that if you remove a column from the CSV (such as the Speed column), then that variable will be removed from the matching class. Be careful removing or renaming columns as this may break existing code.
CreatesDictionary is a property that controls whether to deserialize a given CSV file to either a List or Dictionary. If true, the CSV file is deserialized to a Dictionary. Otherwise, it is Deserialized to a List.
If you are accessing entries within a CSV according to some common key (such as the Name of an enemy type), then you should use the CreatesDictionary property to simplify access in code.
CreatesDictionary can be set on a CSV file in its properties tab or when first adding a new CSV. The following shows the option for specifying Dictionary or List when creating a new CSV:
Dictionaries in code require a key. This is typically the Name property which is marked with the required
keyword. For example, the following CSV marks the "Name" as required:
Name is common The most common key for data is "Name". Unless you have a reason to not use this, consider using "Name" as your required property.
If you have a CSV without a "required" field, then FRB cannot create a Dictionary out of the CSV. Just like any other CSV, once you have saved this file, the generated class will be added/updated.
Now that you have created a CSV that has CreatesDictionary set to true, you can access the file in code and get instances using the Name property:
You may be wondering if it is a good idea to access objects using strings as the key. For example, let's consider the following line:
As you may have realized, this can be an unsafe line of code. What if, for example, the CSV changes so that it no longer contains the "Imp" object? Then that code would compile, and the error would only be discovered if that particular piece of code was executed. In other words, there is a risk of having hidden bugs associated to this line of code. First, we should mention that the reason the code above uses the hardcoded "Imp" value is to show the connection between code and the CSV. In final game code this is not good practice. Fortunately this type of code is usually not necessary. Let's look at the two most common situations where values are retrieved:
It is common to use values form CSVs in Lists. For example, let's say that the TestCsv used above is being used in a screen where the user picks which enemies to take into battle. Your code may look something like this:
This would dynamically loop through the list and create UI elements for each item in the CSV. If an item is added or removed, your code would automatically adjust to this and only show which values are appropriately.
Dictionary order is undefined. The order of entries in a dictionary is not always the same as the order of entries in a CSV. For more information on retrieving the order, see this page.
In some cases you may need to access values directly. This can happen if:
You need to set a default value for something in code
You need to create a script in code, such as defining which enemies appear in a particular level
Fortunately the generated code creates const string values to allow you to access values in a compile-time-protected way. For example, the code above to access the imp could be more-safely done as follows:
The TestCsv class has one constant for each entry in the CSV, so the code above will work without any other code.
If a CSV is loaded as a dictionary, then FlatRedBall generates an OrderedList
property. this property can be useful if you would like to have your data loaded in to a Dictionary while also providing its order. One example of this usage might be to include a list of data for each level in your game. This CSV could be used to populate a level selection ListBox which should show the levels in a particular order. Keep in mind that the Dictionary collection does not guarantee preservation of order, so if you intend to show your data in the same order as the CSV, be sure to use the OrderedList
property.
Note that OrderedList
is only generated if CreatesDictionary is set to true.
The IncludeDirectoryRelativeToContainer property controls whether the generated code for a file includes the directory name in the property created. By default this is false, but setting it to true allows the addition of multiple files with the same name in the same screen, entity, or global content as long as the files are in different folders.
As mentioned above, by default this value is false. Therefore, files added to folders will not include their folder in the generated property name. For example, consider the InFolderTexture.png file which is contained in Folder1
This produces the following code in GlobalContent:
Notice the name in code does not include Folder1. If this file is copied into Folder2, the FlatRedBall Editor renames the copy as to avoid naming conflicts.
The generated code matches the name:
If the IncludeDirectoryRelativeToContainer can be set to true so that the generated property includes the folder name.
Once this is set, the property generated includes the Folder1 prefix:
This allows the same-named files to exist in different directories, because they will ultimately produce different property names. For example, copying the InFolderTexture.png file into Folder2 now results in the file copied without being renamed.
Each property is now uniquely qualified by its folder.
The RuntimeType property controls the type that contains the data loaded from a given file when the game is running. Some types, such as .wav files, can be loaded into multiple runtime types such as SoundEffect
and SoundEffectInstance
.
If you are adding a new file using the Add File window, the runtime type is displayed in the window. For example, notice that a Texture is created (Texture2D in code) when selecting a .png file type.
When a new file is added, the RuntimeType is automatically selected.
Similarly, if a new PNG is added by drag+dropping the file into the FRB editor, the runtime type is selected automatically based on the file's extension. Usually this does not need to be changed.
The selected runtime type ultimately controls the type of the property created in the Screen, Entity, or Global Content. For example, MyFile.png is loaded as a Texture2D as shown in the following screenshot of Visual Studio:
Files may be loaded as fields or properties depending on properties assigned on the file in the FRB Editor.
RuntimeTypes can be changed through the dropdown in the Properties window. FlatRedBall provides options for the file according to its extension.
Some file types may only have a single RuntimeType associated with the extension.
Other types may provide multiple runtime types, such as SoundEffect and SoundEffectInstance for .wav files.
FlatRedBall provides standard RuntimeTypes for many extensions, but plugins can add additional runtime types. You can even create your own plugins to load your files into types that are not supported by FlatRedBall out of the box.
RuntimeType should not be changed through the dropdown if the file is a wildcard file. To change the runtime type, the edit must be performed in the .gluj file for global content. Be careful, you must assign a type that is understood by FRB or currently-loaded plugins.
GlobalContent is a category of content which is available anywhere in your project as opposed to being tied to a specific Screen or Entity. All content that is added as GlobalContent is available at all times. Globalcontent doesn't have a lifespan tied to any ContentManager - normally content is loaded and tied to a ContentManager associated with the active Screen which is unloaded when the current Screen is Destroyed. Content can also be globally loaded if an Entity's property is true. For information on this property and also on how it interacts with GlobalContent, see .
Adding GlobalContent to your game is the same as adding content to any Screen or Entity. To do this:
Right-click on "Global Content Files" in Glue
Select "Add File"->"New file"
Enter the type and name just like a regular file
Repeat this for as many files as you'd like
Once a file has been added to the "Global Content Files" tree item, it can be accessed anywhere in code at any time after GlobalContent has been initialized. To do this, simply use the same name as the file name after "GlobalContent."
Global Content Files are usually used:
For data that is needed across multiple Screens, like .
For data that is not tied to any particular Screen or Entity.
The GlobalContent object may take a while to load depending on your game. This can both be inconvenient for players and it can also cause to fail meeting requirements for certain platforms - for example something must render to the screen within 5 seconds of a game's launch on Windows Phone 7. Fortunately you can make GlobalContent load asynchronously. To do this:
Select the "Global Content Files" tree node
That's all you need to do - your GlobalContent will now load asynchronously.
"Lock contention" occurs when one thread has to sit and wait because another thread has locked a piece of code. This can commonly occur when dealing with async GlobalContent Initialization. Let's look at why this is the case. Imagine a situation where you have 10 CSV files, each representing a level in your game. You've decided to put them in "Global Content Files". You've also decided to put a click sound effect in your game for when the user clicks on a button. For this example we'll say that the Click sound effect will get loaded after the 10 level CSV files. To help the example, we'll also say that the CSV files take a long time to load, and that the first Screen contains a button that the user must click on to proceed. It is possible for the user to click on the button before the level CSVs are loaded. Of course, this would mean that the click sound effect must play; however, since it's loaded after the level CSVs, it won't be ready to play. So what happens in this case? The generated code for GlobalContent recognizes that you are trying to access a property (specifically the click sound effect) which hasn't been loaded yet. But since this content will be loaded, the primary thread waits for the sound to be loaded before playing it. Of course, this means your entire game will appear to freeze until the sound is loaded. This may not be an issue at all depending on how quickly your content loads and depending on how quickly the user can get to the button to click; however, when dealing with very large projects you may have dozens of files under Global Content, and if you encounter a data contention, this can make your application appear to stall. The worst case would be a situation where you are trying to access the very last-loaded property in a starting Screen. This may result in a contention that freezes your application as long as it would freeze if you didn't even use async loading. Fortunately, Glue can generate code to help you solve this.
The RecordLockContention property can be very useful on larger projects when you are trying to improve load times by eliminating lock contention. To use this to improve load times:
Select the "Global Content Files" tree node
Open your GlobalContent.Generated.cs file in Visual Studio
Run your game
Once you've identified lock contentions, you can easily reorder your content to help eliminate - or at least reduce - lock contentions. To do this:
Right-click on the "Global Content Files" tree item
Right-click and select one of the movement options, or click+drag to reorder the content files.
Depending on the order of your content, you may find that you have a particular file causing data contention. For example, the very last file in "Global Content Files" may be needed early in your game, and this could cause a very long lock contention. Once you resolve this by moving it to the top (so it is loaded first), you may actually see more, not fewer lock contentions. Don't worry, the important thing is not the number of contentions, but the amount of time spent in them. As you reorganize and run your code, you may find different contentions. Keep the following in mind:
Keep running, changing, and re-running your game to minimize the amount of time spent in contentions
You may not be able to eliminate contentions completely, but you can definitely reduce them. For example, if you have a contention on the very first file in your "Global Content Files", then there's probably nothing else you can do - it's just that the file is needed before it's finished loading.
Check for contentions from time to time throughout development. As you add more content to Global Content Files you may create a new lock contention that didn't exist before.
UniformRowType can be used to load the CSV data in a more raw format rather than generating a custom class for the CSV. This is useful if the data in the CSV needs to be accessed by row and column index rather than by class member names. For this guide we'll be using a CSV with the following data:
Before changing the UniformRowType value, we should look at the code generated by Glue for this CSV. The class that contains the CSV will have a dictionary of objects as shown in the following code:
In this case the Csv class is generated as shown in the following snippet:
In this case we could access the CSV data through the CsvFile member. If the CSV were part of GlobalContent we could get the information as shown in the following code:
Note that we access the first column using the Column1 property.
We can change the UniformRowType to string[] to change how Glue generates the CSV code.
This setting tells Glue to generate each row in the CSV as a string[], allowing us to index into each column as shown in the following code:
Glue offers two options for UniformRowType:
String
String[]
The most commonly used value is String[] which tells glue that each row contains multiple values. Since each value in a row may need to be independently accessed, each row is represented as a string array. For example, to access index 3 in a row, your code may look like:
If your CSV has only one column, then the UniformRowType can be String. This can simplify accessing the row. For example, to access the first item in the row at index 2, your code may look like:
The OrderedList property is a List of values which correspond to the order of values in a dictionary CSV. A given CSV must have its property set to true for OrderedList to be generated.
OrderedList is not dynamicThe OrderedList is a hardcoded list. It is not dynamic, meaning if you make any modifications to a CSV at runtime, the OrderedList property will not update according to these changes.
The OrderedList property can provide access to entries in a dictionary CSV when order is important. The reason this is necessary is because values in a Dictionary at runtime are not guaranteed to be in the same order as the values in a CSV. For more information, .
Each row in a CSV can be a basic type or an instance of a full class/struct. This tutorial shows how to add structs and classes to your CSV file.
Many games require data types which are more complex than can be identified with simple primitives. For example, you may be creating a game which needs enemy types defined. Each row in your CSV may represent an enemy type; however each instance may also need a non-primitive type to define the type of attack damage it does. If these classes were laid out in code, they might look like this:
As we'll see later in the tutorial, using classes and structs also allows for your CSV to benefit from inheritance.
First we start by creating the CSV that contains our information, then we'll explain the syntax. The following is a screenshot from Excel, but you can use any spreadsheet editing program (such as LibreOffice):
A few things are worth mentioning:
The Name property is marked as "required". This is common practice so that the CSV can be deserialized to a Dictionary.
The type for AttackInfo must be fully-qualified - in other words we use "MyGame.DataTypes.AttackInfo", not just "AttackInfo".
Each parameter can be assigned to any value valid for the type. Note that order does not matter (AreaOfEffect could be assigned before Damage), and it is not necessary to assign variables. For example, you could simply have "Damage=4" and AreaOfEffect would remain as its default value.
Types used by the CSV must be defined manually. FlatRedBall automatically defines the type that the entire CSV is using - in this case "EnemyInfo", however types used inside the CSV (such as AttackInfo) must be manually defined inside your current project.
Objects in CSVs also support inheritance. Inheritance allows you to define a base type for a property on your objects, but then specifying derived types in each individual row. First, we modify our data classes as follows:
Using the code above, we now have FireAttackInfo and SlashingAttackInfo, both of which inherit from AttackInfo. We can now instantiate any of those three types in our AttackInfo column. The following shows a CSV that instantiates different types:
When using inheritance we must specify the type that we want to use in each column. The syntax for this is the same as it is when instantiating an object in code - use the keyword "new" followed by the type. The contents of the parenthesis are the same as as before. You can assign values defined in the derived class as well as the base class. You can also leave out assignments that you want to keep as the default. For example the EndBoss enemy does not define the AreaOfEffect - it defaults to 0.
The CsvFileManager doesn't differentiate between types that you have defined and types that are defined by other libraries (such as types in the XNA libraries). This means that you can immediately add a lot of types of objects to your CSV without ever having to define them in your project. For example, the following shows how to define a column of XNA Rectangles:
Shader Effect Files (.fx) can be added to FlatRedBall projects. At runtime this produces an Effect object which can be used to perform custom rendering. FlatRedBall FNA projects require extra steps to use FX files as explained below.
FlatRedBall can import existing .fx files, but also provides a standard way to create effect files for post processing. The easiest way to add a post processing effect file to your project is to use the Add File dialog:
Right-click on the Files folder where you would like to add your .fx file (such as Global Content Files or GameScreen) and select Add File -> New File
Select Effect (.fx) as the file type
Check the Post Processing Shader option
Verify that the Include YourFileName.cs Post Process File option is checked
Select the type of shader you would like to use. For example, Saturation.
Enter a name for your new effect file, such as SaturationEffect.
Click OK
This creates the following files in your project:
The .fx file. This is a text file using the HLSL syntax which you can edit
The .xnb file (if you are using MonoGame or targeting Web)
The accompanying PostProcess file
A FullscreenEffectWrapper.cs file. This file is only created one time when the first post processing effect is added
If you intend to use the effects as they are when created, you do not need to make any changes to these files. However, these files can also serve as a starting point for your own shaders so you may be interested in locating them.
Once a shader has been added, you can add it to the Renderer's GlobalPostProcesses
list. If your shader is part of Global Content Files, the addition can be performed in Game1. The following code shows how to add the shader to post processing in Game1.
Alternatively, shaders can be added per-camera to enable post processing that does not apply to the entire game. For example, you may want to add a bloom effect to only your game camera, but place the UI above the bloom as shown in the following code:
If your shader is part of a screen such as GameScreen, you can add it in the Screen's CustomInitialize
. Note that if you add it in the Screen's CustomInitialize
, you should also remove it in CustomDestroy
. The following code shows how an effect might be added through GameScreen.
Note that by using a SwapChain, FlatRedBall internally creates and assigns a RenderTarget when performing rendering, so you should not manually create and assign a RenderTarget prior to drawing FlatRedBall.
Effect files require the use of the MonoGame Content Pipeline. If you are using the FlatRedBall Editor, this is automatically handled for you. You can verify that this is the case by checking the UseContentPipeline property.
Effect files can be used on web projects just like effect files in MonoGame projects. The FlatRedBall Editor automatically selects the proper builder as long as the Effect file has its UseContentPipeline set to true.
FNA does not provide a content pipeline, and use of XNA Content Pipeline is discouraged because it does not function in newer versions of Visual Studio.
Instead, FNA recommends compiling shader files in the fxc.exe tool which is available as part of the Windows SDK.
fxc.exe can be used to build effect files which can be consumed by FNA (and FlatRedBall FNA) using syntax similar to the following command:
In the command above, ShaderFile.fx
is the input file and ShaderFile.fxb
is the output file. FlatRedBall recommends using the extension .fxb as the output file.
Once an .fxb file is built, it can be added to FlatRedBall just like any other file (by drag+dropping it into the FlatRedBall Editor) and it will be loaded into a standard Effect object.
Save the following Bear.png and Slug.png images to your computer
Select the newly-added Bear file and set its "LoadedOnlyWhenReferenced" to "True"
Set its "CreatesEvent" variable to "True"
Run the game and you should see either the Slug or the Bear texture as your Entity.
At this point your Entity will show the Slug. You can verify this by either running GlueView, or by dropping the Animal Entity in a Screen and running the game. If you change the AnimalInfo variable, you will notice that the enemy continues to display the Slug no matter which value you set on AnimalInfo. The reason for this is because order matters. Since MainSpriteTexture appears below the AnimalInfo variable, it is set after. A good way to think about it is that variables are set from top to bottom - the same way that code is executed. You can fix this by right-clicking on the AnimalInfo variable and selecting to move it to bottom: This will make the CSV variable be set last. In general you will want to make CSV variables - and for that matter any variable which has events tied to it - as set last in your Entities and Screens.
Change the "LoadAsynchronously" property to "True"
Change "RecordLockContention" to "True" (make sure "LoadAsynchronously" is also set to "True")
Scroll to the very bottom where the Intialize method ends and place a breakpoint on the last line of AsyncInitialize which should be "IsInitialized = true;"
Once you hit the breakpoint, add "LockRecord" to your watch window
If you notice that it has a count of 0, then congratulations - you are not experiencing any lock contention in your Global Content's initialization. You can easily create a locking case if you'd like to see the result and how to resolve it. To do this, simply access the very last property in GlobalContent right after the GlobalContent.Initialize call in your Game class: In this case the file "ShapeCollectionFile" is the last property listed under GlobalContent. It is likely that accessing it immediately after the Initialize call will result in a lock contention. Running the game now verifies this: This case was fabricated, and as a result rather trivial; however, if you have multiple locks, this approach can help you reorganize your global content to improve load times. Speaking of reorganizing, keep reading to see how to do this.
Select "View File Order"
A window will appear listing all of the files in "Global Content Files". This window shows the current order of content loading.
To use the built in GlobalPostProcessing, a SwapChain must be created. The code above creates default SwapChains for us in the CreateDefaultSwapChain
method. For more information on SwapChains, see the page. If you need more control you can manually create a SwapChain as shown in the following block of code:
If FlatRedBall is displaying output about not being able to load libmojoshader_64.dll then you need to install Visual C++ Redistributable Packages for Visual Studio 2013. For more information, see the page.
The fxc.exe program can also be downloaded directly from the FlatRedBall repository:
X=0, Y=0, Width=64, Height=64
X=40, Y=30, Width=80, Height=55
ShapeCollections can be created through files. To add a ShapeCollection to a Screen or Entity:
Create a Screen or Entity which will contain the ShapeCollection file
Right-click on the Files item
Select "Add File"->"New file"
Select "Shape Collection (.shcx)" as the file type
Click OK
Most FlatRedBall files can be used to display something graphical in your game. For example Scene (.scnx) files can be used to display Sprites, Text, and SpriteFrames. However, for an object to be drawn it must be added to the FlatRedBall engine.
In the simplest (and most common) cases, adding objects from files to your game is very simple. The simplest case is when a file (such as a .scnx file) is part of a Screen. In this case the file will automatically show up in your game and in GlueView with no additional changes needed. In other words, if you simply add a .scnx file to a Screen, it should show up automatically in your Screen and in your game.
Entities behave slightly differently from Screens. For a file which has been added to an Entity to appear, it must have an Object which references it. Most of the time Glue will ask you if you want to create an accompanying Object for new files - if you click the default Yes, then the file will automatically appear in your Entity.
The .fbx file format can be loaded into a MonoGame Model class which can be drawn to the screen. The FlatRedBall Camera provides matrices which simplify the drawing of a Model object. Since the Model object is a native MonoGame object, it must be draw either your Game1's Draw method or in an IDrawableBatch.
Models can be loaded just like any other FlatRedBall file. For example, .fbx files can be dropped into Global Content Files.
Once the file has been added to global content, it can be drawn in Game1.cs as shown in the following code:
A NodeNetwork is a collection of nodes (points in world space), connected by links. A node network is used to perform "pathfinding" - the movement logic for navigating a map with obstacles.
Glue has built-in support for working with NodeNetworks. To add a NodeNetwork to your level screen:
Expand your level Screen in Glue
Right-click on the Files folder
Select Add File -> New File
Use the dropdown to select Node Network (.nntx)
Change the name of the file if desired
Click OK
To edit a NodeNetwork file, double-click the file in Glue and the AIEditor should open. If you have not set up the file associations, you can do this by following these steps:
Right-click on the node network in Glue
Select View in Explorer
Right-click on node network file (.nntx) in Windows Explorer
Select Open with...
Click More Apps to expand the list
Scroll to the bottom of the list and select Look for another app on this PC
Navigate to the location where the FRBDK was unzipped (this is also where Glue is located)
Find the AIEditor.exe and select that as the default application
Note that you may need to install XNA 3.1 Redistributable to run the AIEditor. For more information, see the AIEditor page.
By default CSVs added to Glue will create a matching class in the DataTypes folder of the game project. For example, adding a file EnemyInfo.csv will create a class GameName.DataTypes.EnemyInfo. While this behavior is convenient it is sometimes too restrictive. For example, games may benefit from fully-defining their data classes by hand - even in other projects completely - rather than letting Glue generate the data classes automatically. Setting Generate Data Class to false allows the code project to specify its own data class.
The following screen shot shows a CSV called EnemyInfo which is tied to a data class with the fully-qualified name of GameProject.DataTypes.EnemyDataClass:
The "Custom Namespace" field allows using classes defined outside of the GameName.DataTypes namespace. For example in the following image the class BuildingInfo is placed in the BaseDataTypes.Buildings namespace (resulting in the fully qualified name BaseDataTypes.Buildings.BuildingInfo):
Texture2D instances can be created through Glue by adding image files to entities, screens, or global content. By default, any image file added to Glue will be loaded when the containing screen/entity is created. Files added to Global Content can be accessed as soon as the game launches from any screen or entity.
Texture2D's which are added to a screen or entity can be accessed by objects in the same screen or entity. The following steps show how to add a Texture2D to an entity and reference it on a sprite:
Create an entity with a Sprite object. See the Sprites in Glue page for more information.
Drag+drop a .png file from any location on your computer onto the entity's Files object. Note that if the file is not located outside of your game's Content folder, the file will be copied.
Select the Sprite object
Locate the "Texture" property
Use the drop-down to select the desired texture
The sprite will now use the selected texture.
Texture2D instances added to Glue can be accessed in code. If a Texture2D is added to a screen then the custom code for that screen can access the Texture2D variable name matching the name of the file (excluding extension). Similarly, if a Texture2D is added to an entity, then the custom code for that entity can access the Texture2D as well. If a Texture2D is added to global content, then any code in the entire game can access the Texture2D at any time. For this example, consider the CharacterEntity shown in the example above. The custom code for CharacterEntity can access the Character PNG as follows:
Similarly, files added to global content can be accessed in code through the GlobalContent object. For example, consider a file Background.png which could be added to global content:
This file could be accessed in code as shown in the following snippet:
The UseContentPipeline property on files controls whether a file is loaded using the content pipeline. By default files do not use the content pipeline - they load "from file".
Files which are added to FlatRedBall (such as .achx or .png) are considered "raw" files. These are files which generally use a standard file format which can be edited in a variety of applications. For example, .png files can be opened in any image editing software. The .achx file format is a simple XML file which can be opened in the AnimationEditor and also in any text editor.
Content pipeline files are "processed" when the program builds to create .xnb files. These files can be smaller, load faster, or use fewer resources. There is also a small security benefit to using the .xnb file format. Therefore you may want to use the content pipeline on your files prior to shipping your game.
Note that some files, such as .wav, must use the content pipeline if you are targeting MonoGame, so you may not have a choice.
If .xnb files are smaller, faster, and safer you may wonder why FlatRedBall offers a from-file option...and why FlatRedBall defaults to from-file.
The first reason is build time. By default files which are built as from-file do not have to built when the game is built - they are simply copied to the output directory. This process is much faster than using the content pipeline. Another reason is not all files support a content pipeline option. For example, Gum and Tiled plugins produce files which are loaded "raw" and currently do not support using the content pipeline.
The recommended approach is to use from-file loading whenever possible throughout development, and switch to using the content pipeline near the end of development for file formats which support it and if you need it.
To switch to the content pipeline:
Select a file in your project
Change the "UseContentPipeline" property to True
Your game will now load this file from content pipeline.
Note: Not all file formats support using the content pipeline. Also, not all platforms support the content pipeline.
Many files (like .achx files) depend on other files (like .png files). When you switch a file to use the content pipeline, the name of the file changes too. A file which used to be called "MyFile.png" (with extension) may get loaded as "MyFile" (no extension), and this impacts the name. Fortunately, FlatRedBall automatically handles this for you by generating a list of aliases. In other words, you can set your PNG's UseContentPipeline to true and everything should continue to work just like it did before.
Files in Glue can support "external" or "source" files. A source file is a file which must be processed before it can be used by Glue/FlatRedBall. Source files enable using files created by 3rd-party applications to be used in FlatRedBall. For example, the source file functionality would allow you to use a .psd file (Photoshop file) as a texture file. However, for a source file to be usable, a specific program (which is often referred to as a "builder") must exist to convert the source file to a file format which is understood by Glue/FlatRedBall. For example if the source file were a .psd file, then the destination might be a .png, and a PSD to PNG builder would be needed.
To add a file with a source file:
Right-click on the "Files" item under a Screen or entity
Select "Add Externally Built File"
Glue must be told how to convert a source file to the file type that Glue understands. To do this builders must be set up. To set up a builder, see the article on builders.
The File Build Tools window allows adding command-line build tools for your files for converting from one file format to another. Conceptually file build tools are similar to the MonoGame or XNA Content Pipeline, but they are run through the command line as a separate process for each file.
File build tools can be used to convert from a custom or app-specific file format to a file format which is understood by FlatRedBall or an external library.
FlatRedBall provides a number of integrations for file build tools, and additional tools can be added to support any file format you would like to use.
To view the file build tools window, select Settings -> File Build Tools in FRB. A window should appear displaying the existing file build tools.
This window displays the existing file build tool assications. The list box on the left displays the file types that can be used as input (such as .odf files), the tool that is being used to conver the file (such as soffice.exe), and the output file format (such as .csv).
To add a new build tool, click the Add new build tool button. A new entry is added to the list box on the left which can be customized. As you fill in the properties for the new build tool, the Example text below is updated to show FlatRedBall will call the build tool for a built file.
If you add a file to your FlatRedBall project which has an associated build tool, then a popup is shown allowing you to select which build tool to use. For example, if you add an .ods file to your project, you will see a window similar to the following image:
You can leave the default, or use the dropdown to select a different builder. If you do not want to use a builder for this particular file, you can change the dropdown to <None>.
If a file has an associated file build tool, then the destination file is displayed in the FRB Editor. For example, if an .ods file is added, the destination file type (csv) shows. At runtime the source file is completely ignored and only the destination file is loaded.
Once a file has been added you can change its BuildTool property in its Properties window.
Any time the source file changes on disk (such as an .ods file), FRB detects this change and automatically performs a build. The command is displayed in the Output window.
OpenDocument Spreadsheet files can be loaded into your game similar to .csv files. Technically, .ods files are converted to .csv files by the FlatRedBall Editor and are loaded as if they are standard CSV files.
Using .ods files offers a number of benefits over .csv files:
They can contain formulas
They can contain styling and formatting, such as cell colors or bold text
They can contain dropdowns and other formatted cell types
The .ods file format does add a small amount of complexity to your projct:
.ods files must be converted to .csv which requires installing LibreOffice
.ods file conversion to .csv is performed by the FlatRedBall Editor if the .ods file is newer than the .csv, or if the .csv is missing. This takes a short amount of time when first opening the project.
FRB creates a class for your .ods file using the same rules as .csv files. For information about the automatic generation of data for .csv files, see the .
To add a new .ods file:
Decide where to keep the .ods file. Usually game data such as .ods and .csv files are stored in Global Content Files
Right-click on the desired location (such as Global Content Files) and select Add New File
Select the ods file type
Enter a name, such as EnemyData
Click OK
Confirm the conversion of .ods to .csv in the popup window by clicking OK.
The newly-created file should appear in the tree view in FRB. Notice that the file is listed as a .csv file since it is converted from .ods to .csv.
You can confirm the original file is an .ods file by selecting the file and viewing its properties.
FlatRedBall automatically creates a backing data class for your file which matches the name of the .ods file. For example, the following screenshot shows the EnemyData class using the default contents of the .ods.
Similarly, the enemy data class is loaded in the object which contains the .ods file. Using the example from above, the EnemyData file would be loaded into GlobalContent and it can be accessed as shown in the following code:
The DestroyOnUnload value controls whether music files are destroyed when the Screen is destroyed. This value can be set to false if you want the song to continue playing into the next Screen. For this to occur, the Screen which you are transitioning into must also have a reference to the same Song file.
To add a song that plays on two screens:
Create two screens (such as GameScreen and PostGameScreen)
Drag+drop a .mp3 or .wma file into GameScreen
Drag+drop the file from the GameScreen into the PostGameScreen's Files. Be sure that the name of the file is the same in both screens
Set the "DestroyOnUnload" value to "False" on the Song you want to continue playing. If you set it on both, then you will be able to go back and forth between the two Screens and the song will continue playing.
Write custom code in your game to transition between the two Screens - notice that the song continues to play despite the transition.
Things to remember:
You do not need to manually play Songs that have been added to Screens through Glue. Doing so may make your song restart.
Wav files can be used for sound effects in FRB. Wav files, which are uncompressed, are used because compression can introduce latency (delay before the sound plays).
The FRB Editor can use .wav files to create two types of objects:
SoundEffect
SoundEffectInstance
By default .wav files are loaded as a SoundEffect, which is the simplest object to work with. The SoundEffect object allows fire-and-forget sound effects. Once a .wav file is added to FRB, the SoundEffect it creates can be used with a Play call as shown in the following code:
Once a SoundEffect Play call is made, the sound cannot be modified or stopped. It will play to completion and then stop. Therefore, to adjust the Play call, parameters can be added. For example to play a sound at half-volume, 0.5f could be passed as the first parameter:
By contrast, SoundEffectInstances are single-instance sounds which can be played, and manipulated after playing. For example, the following code plays a sound, but then adjusts its volume after 0.5 seconds:
To change whether a .wav file is loaded as a SoundEffect or SoundEffectInstance, change its RuntimeType as shown in the following image:
If you need to interrupt a sound after it has started playing, you must use a SoundEffectInstance.
To add a .wav file to FRB:
Right-click on a Screen or Entity's Files item
Select Add File->Existing File
Navigate to the location of the .wav that you would like to use and click OK
You should see the .wav file in your project:
Alternatively you can drop WAV files into your project from Windows Explorer:
Open your project in the FRB Editor
Locate the WAV file you would like to use on disk
Drag+drop the file from Windows Explorer into your project in the desired Files folder. Note that if the file is not already a child of your Content folder, the file will be copied to the desired folder and the original file will be left on disk in its original location.
Once a .wav file has been added to your FRB project, your Screen, Entity, or GlobalContent includes an instance of a SoundEffect in generated code.
The following example assumes a file named GunShotSound.wav, so the code instance is named GunShotSound. The following code can be added to CustomActivity to play the sound when the space bar is pressed:
FlatRedBall MonoGame does not require WAV files to be built and loaded from XNB files, but this is optionally supported. XNB files are built by the MonoGame content pipeline.
If using the content pipeline, then the WAV file is built into an XNB file when initially added and also whenever the WAV file ever changes.
If using the content pipeline, WAV files are added as XNB files to your Visual Studio project. For example, the following SoundEffectFile.wav is part of GameScreen:
This file is automatically added to your Visual Studio project by FlatRedBall, as shown in the following screenshot:
WAV files can be explicitly rebuilt in the FRB Editor by right-clicking on the file and selecting Rebuild Content Pipeline File (.xnb).
When the file is built, the output window displays information about the build so you can diagnose problems.
As mentioned above, the easiest way to work with wav files is to load them as SoundEffects which provide a fire-and-forget Play method. You may want to provide additional control over SoundEffect playing in which case you can use a SoundEffectInstance. If your game pre-loads content, you can add the WAV file to global content as a SoundEffect, then add individual instances to the Screens or Entities which must play them.
Note that when this occurs, a copy is created so be careful adding instances to entities which will have multiple instances alive at once.
Note that this approach does not result in the wav file being loaded multiple times - the SoundEffect in global content is reused for each instance saving time.
To do this:
Add the wav file to global content. Note, this can even be done with wildcards
Set the RuntimeType to SoundEffect
Add the same file to a Screen or Entity - you can drag+drop the file from global content, or right-click on the Files folder and select Add Existing.
Change the RuntimeType to SoundEffectInstance using the dropdown
For the full SoundEffect documentation, see the MonoGame .
For more information on SoundEffect in FlatRedBall, see the .
LoadedOnlyWhenReferenced is a property which tells Glue to not load a file until it is referenced in code. This is can be used for optionally loaded content - that is, content which will only be loaded based off of certain conditions in the game (such as the current level being played).
LoadedOnlyWhenReferenced is very useful if you have content in your game which is optionally loaded depending on the state of your game. For example, you may have a game where levels are represented by .scnx files. You may add multiple .scnx files to your Screen and mark them as LoadedOnlyWhenReferenced. This means that by default no files will be loaded when your Screen is created. However, if you access any properties created for the files in the Screen, then the corresponding file will be loaded.
Optionally Loaded Content tutorial - Basic tutorial on how to use optionally loaded content.
Optionally Loaded Scenes - Discusses how to create optionally loaded Scenes (.scnx files) to load levels dynamically.
The LoadedAtRuntime property can be used to tell FlatRedBall whether to load a particular file when its Screen or Entity is created. By default the LoadedAtRuntime property is set to true, which means that an instance of a runtime object for the given file will be created. For example, if a PNG file is added to a Screen, then that Screen will contain a Texture2D instance.
If this value is set to false, then generated code will not contain a property for that file, nor will it automatically load the file. However, the file will still be part of the project, so you can load it and work with it in custom code.
There are a number of reasons to set LoadedAtRuntime to false.
LoadedAtRuntime is often set if a file is to be used in a custom way. For example, your game may include JSON files which you want to handle in custom code. LoadedAtRuntime can be set to false in projects which load file formats which are not natively understood by FlatRedBall (such as custom audio, texture, or model formats).
You can use LoadedAtRuntime if you want to selectively load files at runtime. For example, you may add multiple files to a Screen, but only load one of them depending on the state of the game.
This approach of handling files was more popular in the past, but modern FlatRedBall games typically use derived screens (typically level screens deriving from GameScreen) to conditionally load content.
The LoadedAtRuntime and LoadedOnlyWhenReferenced properties may seem to do similar things, and you may be wondering when to use one or the other. This section will discuss why both properties exist and why to use them.
By default LoadedAtRuntime=true and LoadedOnlyWhenReferenced=false. This means that a file will always be loaded whenever its containing Screen/Entity is loaded.
LoadedOnlyWhenReferenced=true can be used to either delay the loading of a file, or not load it at all depending on certain conditions in your game. For example, a particular texture for a Sprite may not be used if the player does not pick to use that specific file type. LoadedAtRuntime=false tells FlatRedBall that you want a particular file to be added to Visual Studio, and that the file should be available to your program at runtime, but only through the file system. FlatRedBall will not generate any code to load the file at all. This means that custom code is in charge of loading the file completely, and that custom code can decide what to load the file into. For example, if FlatRedBall generates code to load a .achx file, then it must be loaded into an AnimationChainList. If LoadedAtRuntime is set to false, it can be loaded into a different type like AnimationChainListSave, or even loaded into a string or some other custom type.
FlatRedBall supports the use of localization CSV files to simplify adding text to your game, whether your game uses a single or multiple languages. The IsDatabaseForLocalizing property controls whether a CSV file is used as a localization file. When a spreadsheet is marked as IsDatabaseForLocalizing, the FlatRedBall Editor populates the LocalizationManager with the database when the CSV is loaded. For more details about how to work with localization in code, see the page.
Because of the generated code that FlatRedBall writes automatically, creating a game that supports localization requires very little manual code.
Prior to FRB Editor (gluj) file version 14, generated code would make LocalizationManager.Translate calls. This functionality was inconsistent and difficult to work with, so as of file version 14, Translate must be called manually. For more information on this change, see the .
First we'll create a spreadsheet file that will serve as a localization database. To do this:
Right-click on Global Content Files. Since most of your game probably uses text from this file, it should be in Global Content Files rather than a screen or entity.
Select Add File->New File
Select Spreadsheet (.csv) as the file type
Enter the name LocalizationDatabase for your new file. This name is not required, but recommended by convention.
Click OK
Next, set IsDatabaseForLocalizing to true:
Select the newly-created LocalizationDatabase file
Change IsDatabaseForLocalizing to True
The next step is to begin filling out the database. To do this:
Double-click the file to open it in a spreadsheet editing program such as Excel or Open Office
Change the top-left cell to read "ID (required)". Make sure "required" is not capitalized.
Change the first row in the second column to say "English", or whatever you prefer your default language to be.
Change the first row in the third column to say "Spanish" or the secondary language. You can continually add columns for any language you may want to support.
Enter a string ID under the "ID" column. You may want to use a particular prefix to differentiate between string IDs and actual text - this can help you spot bugs in development. For this tutorial, I'll use "T_" before IDs. Therefore, I'll enter "T_Hello" for my first string.
Enter the English and Spanish versions of this string
Save the spreasheet
Before any localization can happen, you must tell the game which language to use. By default, the LocalizationManager uses index 0 as its default language. This column stores the IDs. The first language (which is English in our case) begins at index 1. Therefore, to have your database translated, you must set the language index. To do this:
Open Game1.cs (or whatever your Game class is named)
Find GeneratedInitializeEarly();
and add the following before it:
Be sure that this is set before GeneratedInitializeEarly();
is called, or else the Screen will be initialized prior to the language being set.
To translate text, you can use the LocalizationManager's Translate method. For example, if you wanted to translate the string ID "T_Tutorial1" you could do so as follows:
You could then use translatedTutorialString in your game, such as by assigning the string to a Gum object's Text property.
So far we've covered static translations. Of course, you may want to have variables embedded in your text. The LocalizationManager supports this through a syntax that is very similar to the string.Format method. To support variables in your text:
Add an entry to your database spreadsheet using the { and } characters surrounding the variable index. For example, to inform the player of how many goals are left, you might enter: "You have completed {0} goals and you have {1} goals left."
In your code you can use the Translate overload which takes arguments to "format" the string. For example, your code may look like this:
Comments can be added to the ID column by using the //
syntax (similar to C#). Comments are ignored, allowing you to insert notes when creating localization files.
Games which display dialog using a dialog box may need to organize the dialog into mulitple pages. This is important to prevent sentences from being shown on multiple pages based on line wrapping. Also, games may include multiple speakers (see more info below).
Each string ID can contain multiple rows, wher each row serves as a different page. The following image shows three IDs. T_Dialog1 has 7 separate strings, beginning with the first as "Sounds like something crashed!", and ending with "Or aliens!!"
To access the strings, the TranslateMultiple method can be used, as shown in the following code:
By convention the first column in a localization file is the ID, and subsequent columns are for each language. Ofen times dialog requires additional information, such as the speaker of dialog. Keep in mind that each column can be used however you like in your game. For instance, if your game displays dialog along with the name of a speaker, you may want to have a column for the speaker.
The following shows a real-world example of a localization file which includes a column for the speaker, whether to flip the profile, and whether the text is automatically skipped. Note that these columns do not have any built-in behavior on their own. They must be read in and applied in your custom code.
The MP3 file format often used for music. All information on this page also applies to the OGG file format. FlatRedBall loads MP3 files as instances. For more information on working directly with Songs, see the .
To play an MP3 in your game:
Create or select the screen that you want to have the song
Expand the screen to see the Files item
Drag+drop the MP3 file from the explorer into a Screen's Files node.
Alternatively you can right-click on the Files tree node and select Add File->Existing File and browse to the location of the MP3
Note that by default the dropped song uses the Microsoft.Xna.Framework.Media.Song runtime type. See below for more information on this compared to other types.
The song automatically plays when the Screen starts. The song automatically stops playing when the Screen exits. You do not need write any code to play or stop the music. If a Screen contains multiple audio files, then additional settings and logic are needed to select which song should be played.
FlatRedBall provides sample songs which you can use to test song playing. To add a new song to your game:
Right-click on the Files folder in a Screen
Select Add File -> New File
Search for Song
Select one of the song types and click OK
For more information on NAudio, see below.
FlatRedBall provides simple song controls in the Song tab. To view the Song tab:
Add a song file to your game (as shown above)
Select the newly-created song
Select the Song tab
By default a Song added to a Screen plays when the Screen starts and stops when the screen is destroyed. To have songs persist between Screen transitions, check the Keep Playing After Leaving Screen checkbox. Note that if this is checked, the song continues to play only if either of the following conditions are true:
The new screen does not specify a song to play
The new screen does specify a song to play, but the song is the same as the song that was playing in the previous screen
If the new screen specifies a different song, then the new screen's song begins playing even if the old song's Keep Playing After Leaving Screen checkbox is checked.
You can add multiple songs to your Screen if you would like to select which one to play in custom code. To do this:
Create a Screen
Add any number of .mp3 files to your Screen
In custom code, play the song you would like to play. For example, if your song is called MySong, then add the following code:
FlatRedBall provides built-in support for NAudio. When a new song is added through the Add File -> New File right-click option, a window allows the selection of NAudio or (MonoGame) Songs.
Already-added songs can be changed between Song and NAudio_Song by changing the runtime type on the file's properties.
Both MonoGame/FNA Song
and NAudio_Song
share much of the same functionality. Both:
Can be managed through the Song tab in FlatRedBall
Can be played through AudioManager.PlaySong
Respond to the AudioManager's MasterSongVolume if played through AudioManager.PlaySong
NAudio provides additional functionality for playing songs, so games which need more control over music playing may want to use NAudio_Song.
IsManuallyUpdated controls whether the object created by loading a given file is manually updated. By default this value is false, indicating that objects are (by default) automatically updated by the engine. Setting this value to true can improve the runtime performance of your game, especially if your file contains a large number of objects. The downside to setting this value to true is that Velocity, Acceleration, Drag, Attachment, and Animations will not apply on any contained objects. Furthermore, any changes to objects (such as changing the position of Sprites manually) may not be reflected in rendering. This property is only available on files in Screens. Entire entities can be converted to manually updated using the method. For more information on manual vs. automatic updates, see .
The song that is played uses the method, so any properties set on the AudioManager (such as MasterSongVolume) apply to the playing of the song. For more information, see the page.
Set each of them to LoadedOnlyWhenReferenced. For more information on this property, see .
For more information on the AudioManager, see the .
The "Project Specific Files" entry allows you to create files which are specific to a project. While most FlatRedBall types can load on all platforms, your project may need certain files to only be loaded on certain platforms. Reasons for this include:
Certain platforms may not support certain file types. For example, at the time of this writing iOS does not support loading .WMA files as Songs.
Certain platforms may use different size or quality of content for performance or download reasons. For example, your game may use a larger resolution on the PC than on Windows Phone 7.
You may be using synced projects to create demo or kiosk projects with limited content. In this case you may exclude content from your data (such as reducing the number of characters available in a CSV).
UNDER CONSTRUCTION
A file's name represents its qualified location relative to the project's Content folder. By default, newly-created files will be added to a folder specific to the container Screen, Entity, or Gloabl Content Files. However, a file can exist outside of the default folder, so long as it is in the project's Content folder. For example, the following file is located in the Enemy entity, but its location on disk is <Project Content Folder>/Characters/Enemy_Shooter.achx:
Glue allows renaming of a file by changing the file's Name property. Renaming the file will perform the following actions:
Change the name of the file in the Glue project
Change the name of the file in the Visual Studio project (including all synced projects)
Change the name of the file on disk
Note that if the file is referenced by another file, Glue may not be able to update the reference. For example, changing a .PNG file which is referenced by a .TMX file may result in errors due to the .TMX file still referencing the old .PNG.
By default, files added to Glue will automatically be added to all associated Visual Studio projects. Some files, however, are only needed on some platforms. Files can be excluded from certain projects through the Platform Inclusions tab. Note that this tab will only appear when a file is selected in Glue project which has more than one code solution (added through Project Sync).
Excluding a file from a project will exclude the project from the Visual Studio .csproj or .contentproj, but the code generation currently does not consider whether the file has been excluded. This means that code generation may throw a file not found exception (or equivalent) when the project executes on a platform from which the file has been excluded. For this reason, files should only be excluded when LoadedAtRuntime is set to false.
FlatRedBall supports wildcard files in the .gluj file. Wildcard enable the automatic adding of files to your FlatRedBall project based in their location on disk. This can make managing a large number of files much easier than manually managing the files.
At the time of this writing wildcard files are only supported in Global Content, but future versions of FlatRedBall may expand this.
The easiest way to add a Wildcard entry in the FlatRedBall is to first add a single file to your project which has all of the desired settings. Once this file has been added, it can be converted to a wildcard entry. For example, consider the following project which has a single file added to Global Content Files named TextureFile.png:
Currently, wildcard entries must be manually converted by editing the FlatRedBall project (.gluj) in a text editor. To do this:
Open the folder location of the project
Open your game's .gluj file in a text editor such as Visual Studio Code
Locate the file entry of the file in your project. It should appear under the GlobalFiles section.
Change the file's Name property to be a wildcard file.
Save the file in the text editor
After you save the file .gluj the FlatRedBall Editor displays the file with a wildcard (*) icon to indicate that it is added as a wildcard file.
Now you can add new files to disk and they automatically appear in the FlatRedBall Editor (assuming they match the wildcard pattern).
Be careful - wildcard files are added automatically even if their name violates the naming convention of FlatRedBall. In other words, normally files cannot contain spaces or dashes, but FlatRedBall adds these files to your project even if the file names contain invalid characters. For example, if you copy and paste a file, Windows automatically appends " - Copy" to the name of the file, and this appears in the FlatRedBall Editor.
The code generator attempts to remove invalid characters when generating the GlobalContent code.
Of course, since characters are either removed (such as spaces) or converted to valid C# property characters (such as underscores), it is possible to have multiple properties with the same name resulting in a compile error. We recommend keeping your file names named as valid C# properties.
FlatRedBall supports a number of wildcard patterns for adding files to your projects. The following examples explain the possible wildcard patterns:
Name": "GlobalContent/*.png
- Add all files in the GlobalContent folder with the PNG extension
Name": "GlobalContent/*.*
- Add all files in the GlobalContent folder with any extension
Name": "GlobalContent/*
- Add all files in the GlobalContent folder with any extension. Note that this is the same as Name": "GlobalContent/*.*
.
Name": "GlobalContent/**/*.png
- Add all files in the GlobalContent folder and any subfolder of GlobalContent with the PNG extension
Name": "GlobalContent/**/*.*
- Add all files in the GlobalContent folder and any subfolder of GlobalContent with any extension
If a file is both included in Global Content Files explicitly and also through a wildcard, then the file appears twice in the FRB Editor and this produces an error. For example, consider a project with the file MyTexture.png added to the GlobalContent folder through a wildcard and also explicitly added. The JSON for the project might look like this:
This results in the file appearing twice in the FRB Editor, and in an error appearing in the Errors tab.
If wildcards are needed, then the explicitly-added file must be removed. It can be removed by editing the .gluj, or by removing it through the tree view in FRB. If your project needs an explicitly-added file while also using wildcards, then you must organize your content in such a way as to exclude the explicitly-added file from the wildcard pattern, such as by adding all wildcard files to a subfolder.
As mentioned above, adding the same file to Global Content Files using wildcards and explicit addition results in an error. However, adding the same file to Global Content Files using a wildcard pattern but also adding the file to a Screen or Entity explicitly is perfectly valid. This is allowed because wildcard additions behave the same as explicit additions, and FlatRedBall allows the same file to be added to both Global Content Files and a Screen or Entity.
For example, the following image shows the same file added to both an entity and Global Content Files.
The example above adds all PNGs to Global Content Files using the following entry in the .gluj file:
This approach for handling files is very useful if your game includes files which are spread out throughout the Content folder and its subfolders, yet you would like to have all files loaded up-front when the game first launches. For example, if additional files are added to an screen or entity, the files automatically appear in Global Content Files.