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...
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...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
The Clone method can be used to make a copy of the AnimationChainList. This method is useful if your game needs to make copies of AnimationChainLists loaded from file. This is the case if the AnimationChainLists use the same texture coordinates, but simply use different Textures (such as different animation chains for characters in a game).
The following code example assumes that OriginalAnimationChainList is a valid AnimationChainList.
For more information see the AddDisposable page.
[subpages]
The RelativeX and RelativeY values in an AnimationFrame can be used to offset an animated object on a per-frame basis. This is useful if the images that are being used for the animation do not line up as desired. The relative values can be set by code or in the AnimationEditor.
Simply setting the RelativeX and RelativeY values on an AnimationFrame is not sufficient to change the position of an IAnimationChainAnimatable (such as a Sprite. The following conditions must be met:
The object (such as the Sprite) that is displaying the animation must be attached to another PositionedObject.
The UseAnimationRelativePosition property must be true.
If you are using objects created in Glue, then both of the above will usually be true.
The following code creates an AnimationFrame which displays the four quadrants of a redball.bmp graphic, then displays it in its entirety. The RelativeX and RelativeY values are used to offset the frames which display a single quadrant. Notice that the animated Sprite must be attached to an object and that the Sprite's UseAnimationRelativePosition property must be set to true.
The AnimationController class enables a game project to define animation logic using a modular approach as compared to a long chain of if/else if statements. The AnimationController was initially created to enable generated code to define animations while still allowing custom code to inject new animation behavior. Since its creation, the AnimationController has grown in capability, and it is currently the recommended way to create animation-assigning logic.
To help explain the benefit of using the AnimationController, consider the following code. It is typical code for controlling the animation for a character that can walk or stand idle in two directions (left and right)
Although the logic for setting the animationToSet is fairly simple, it suffers from not being very modular. That is, whether to assign the idle animations depends on the logic for whether to set the walking animations and whether the player is taking damage. Larger projects may want to organize logic for different types of animation assignment, or even take advantage of code generation for animation assignments. AnimationControllers provide a standard way to separate your animation code into modular pieces of code.
We can think of the code above as being organized into three layers. The top layer (the layer which has the first opportunity to set the animation) sets the taking damage animations. If it the top layer does not set an animation, then the if-check for setting the walk animations is performed. Finally if neither of the first two blocks set animations (which happens when the player is not taking damage and is walking less than 1 unit per second), then the bottom layer can set the idle animation. Games may have animations organized into multiple layers, where each layer has higher priority than layers underneath. For example the code above may would have the following layers:
TakeDamageAnimations
RunAnimations
IdleAnimations
In plain English this can be represented as:
If the player is taking damage, show damage animations. Otherwise... If the player is running, show the run animations. Otherwise... Show the Idle animations
Using an AnimationController is similar to writing a series of if/else if statements, but each layer can be independently defined in its own function, making the code more modular. For example, the above code could be rewritten using an AnimationController as shown in the following code:
The order in which the AnimationLayer instances are added controls the priority. The first layer added has the opportunity to set an animation. If its EveryFrameAction
returns a non-null value, then that layer's animation is assigned. If the layer returns null, then the next layer's EveryFrameAction
will be performed, and so on.
The code above which introduces how to add layers using AddLayer may seem similar to a similar if/else-if block. In fact, the order that AddLayer is called controls the priority of animations, so the AddLayer calls must be performed in this particular order. However, the benefit of the AnimationController is that layers can be added, removed, and reordered.
The AnimationController exposes its Layers property which can be used to perform any standard list operation. For example, consider a game where a certain type of enemy entity plays an animation when standing still and reloading. For this example we will assume that the derived enemy inherits from the base entity, and that the base animation logic should still apply. However, this derived enemy will check if it is reloading, and if so then it will play its reloading animation.
In this case the reloading animation has higher priority than the idle animations, but lower priority than walking and taking damage. To inject the animation, the following code may be added to the derived entity's CustomInitialize:
Note that this code assumes that the controller is either public or protected so that the derived entity can access it. This may be done in custom code by modifying the controller definition, or if the AnimationController is added through the FlatRedBall entity, then its ExposedInDerived property can be set to true.
Also, this code uses the Insert method with a magic number for the sake of simplicity, but a typical game may assign the Name property on layers, and find the index of the "Idle"
AnimationLayer to dynamically insert the new reload layer at the correct index.
IAnimationChainAnimatable-implementing objects should automatically update their displayed frame according to time. It is possible that a frame may last less than one frame of game time - if the game is running slowly or if the frame is of very short duration. Sprites, for example, will skip frames if the timing advances far enough. Not all frames are guaranteed to play.
The list of AnimationChains referenced by this instance.
The CurrentFrameIndex gets and sets the current frame that the IAnimationChainAnimatable is displaying. As animation plays this property will automatically increment and cycle. This value will always be between 0 and the count of the current AnimationChain minus one (inclusive).
Assuming that mSprite is a valid Sprite that has a current AnimationChain the following code will manually cycle the Frames:
Restarting the animation can be done either by setting the CurrentFrameIndex to 0 or by setting the CurrentChainName so long as the CurrentChainName differs from the set value. That means if your current animation is "DesiredAnimation" and you want to restart the animation you can either:
OR
The JustCycled property is a property which is usually false, but will be set to true when an animation either finishes or cycles. This can be used to perform logic whenever an AnimationChain ends. By default, objects (such as Sprites) which play animations will automatically loop. When this happens, the object begins displaying the first frame in the animation. When this occurs, the JustCycled property will be true. Keep in mind that when this value is set to true, the object will display the first frame of animation that frame. It is possible to prevent this by performing logic (such as destroying the object) when this is true.
The JustCycled property reports whether an object that is displaying an AnimationChain has just reached the end of an animation and has cycled to the beginning. You can perform logic in response this being set to true. The following code assumes MySprite is a valid Sprite. The if statement will trigger when the Sprite completes.
JustCycled can be used to play an animation once, then stop the animation when it's cycled. For this example we'll use an animating Sprite called MySprite:
If you are changing which animation an object is showing when JustCycled is set to true, keep in mind that JustCycled will stay true for the entire frame, regardless of whether you change chains in code. For example:
When JustCycled is true and if the displayed object has its Cycling set to true, then CurrentFrameIndex will be 0 (unless an animation is playing backwards). In a typical setup (in an unmodified FlatRedBall template), the FlatRedBall Engine will perform its logic before custom game logic is executed every frame. This means that if JustCycled is true, custom code will have an opportunity to react to the cycle before the animation visually starts over. For example, consider this code:
The BMFC file format (which stands for "bitmap font configuration") is a file that can be loaded and saved by the Bitmap Font Generator, which also produces the .fnt file format that the FlatRedBall engine natively works with. The .bmfc file format is a powerful file format because it can be saved and loaded later to make changes to an existing font. Furthermore, Glue can use the Bitmap Font Generator to automatically create a .fnt file from a .bmfc file.
A .bmfc file can be created in the Bitmap Font Generator. To create a .bmfc file:
Open the Bitmap Font Generator
Set up a bitmap font - for more information see this page
Click Options->"Save configuration as..."
Enter a name for the file and click OK
The .bmfc file is a file which must be converted into a .fnt file. This can be done by using Glue and the Bitmap Font Generator.
Note: Glue uses command line arguments to convert a .bmfc file into a .fnt file. This is not the only way to convert a .bmfc file into a .fnt. You can also manually run a command line yourself, or you can simply open the Bitmap Font Generator program, load the configuration, then manually save out the font file.
First, you must make sure Glue is set up to use the Bitmap Font Generator as a build tool. To add the Bitmap Font Generator as a build tool:
Open Glue
Select Settings->"File Build Tools"
Click "Add new build tool"
Navigate to the location of the Bitmap Font Generator. If you installed it to the default location on Windows 7, it should be located at"C:\Program Files (x86)\AngelCode\BMFont\bmfont.exe"
Set the SourceFileType to bmfc
Set the DestinationFileType to fnt
Set the SourceFileArgumentPrefix to -c
Set the DestinationFileArgumentPrefix to -o (lower-case letter 'o')
Click OK
Once you have set up the Bitmap Font Generator as a builder in Glue, you can add .bmfc files as externally built files. To do this:
Create a .bmfc file as shown above
Right-click on the Files tree item under a Screen or Entity or Global Content Files
Select "Add Externally Built File"
Select the .bmfc file. Be sure that this file is located in a subfolder of your project.
Select the bmfont.exe builder in the drop-down in the window that appears
Click OK
Enter a name for your font (or leave it as default)
Your project will now include a .fnt file which can be loaded by code into a BitmapFont, which can be used in Glue, or which can be used in a .scnx file.
The BitmapCharacterInfo contains information about a single character in a FlatRedBall.Graphics.BitmapFont. Usually BitmapCharacterInfos are not manually created - they are created automatically when loading a .fnt file into a BitmapFont; however, if you are creating custom fonts in code, you can do so by creating BitmapCharacterInfos.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
Glyphs in fonts are custom images which are typically not part of the font but which can be added through Bitmap Font Generator. This tutorial will walk you through:
How to add glyphs to a font in Bitmap Font Generator
How to use these glyphs in Text objects through code
The end result will be:
INSERT IMAGE OF GLYPH USAGE
The BitmapFont class defines the texture and rendering values used to render a bitmap font. The Text object uses BitmapFonts when drawing itself. Note that the recommended approach for displaying production-ready text to the screen (including with custom fonts) is to use Gum, which automates the creation of font files and simplifies loading these files.
The main benefit of the FRB Text object is that it can sort with other visual objects and it can have better performance than Gum text objects in some cases.
Bitmap Fonts require two files - a texture file and a .fnt file. Both can be created with AngelCode.com's Bitmap Font Generator. The following steps outline the creation of the two files used in BitmapFonts:
Click or push+drag to select the letters that you'd like included in your exported font. Selected letters will highlight.
Click Options->Font Settings
Select the font that you'd like to use in the "Font" drop down. All fonts installed on your machine will appear here.
Enter the font size that you want next to "Size (px)": The larger this is, the larger each letter will be in your game. If you are using Photoshop, you can test font sizes there (see next item)
Check the "Match char height" option. This will make the resulting font match sizes in Photoshop
Press Ok. The font display will update to the newly-selected font.
Select Options->Export Options.
Select a Bit depth of 32 (or else transparencies won't come through).
Select the texture width and height. Ideally you should select a texture size large enough to fit all characters, but small enough to minimize empty space. This may require some trial and error.
Change the "Textures:" option to "png - Portable Network Graphics"
Press Ok.
Select Options->Visualize. If you see "No Output!" then you need to select characters to export. See the above step for more information.
Return to change the width/height if necessary. Verify that your font fits on one image by seeing if View->Next Page is disabled in the preview. If everything does not fit in one page consider decreasing the size of your font or increasing the source image size. Remember to keep your texture dimension a power of 2.
Click Options->Save bitmap font as... to save your .fnt and .png files.
Copy the files to their appropriate locations for your application.
For information on how to use BitmapFonts in the FRB Editor, see the Font (.fnt) page.
BitmapFontGenerator supports adding custom images to a font file. This can be used in the following situations:
Inserting images in the middle of text, such as "Press the <A button image> to continue"
Using custom images for letters instead of having BitmapFontGenerator generate them from True Type Fonts
To add a custom image to a font:
Open Bitmap Font Generator
Select "Edit"->"Open Image Manager"
In the Image Manager window, select "Image"->"Import Image..."
Navigate to the image that you want to import and click "Open". Notice that as of BMFont 1.13 you cannot import PNGs as custom glyphs. See the "Troubleshooting BMFont"
Enter the information for the new letter
Id refers to the unicode character. A full list of unicode characters can be found here. For reference, the capital letter 'A' has an ID of 65; the lower case 'a' has an ID of 97.
X advance refers to how much horizontal space is taken up by the letter. The default of 0 means that the size of the image defines the space taken up.
BMFont 1.13 includes a number of bugs which can make glyph creation more difficult. Fortunately workarounds exist for these bugs:
BMFont will crash if a .bmcc file is saved in the same folder as a referenced image. To solve this, save the .bmfc file in a different folder, or update to the 1.14 beta build of BMFont.
BMFont will not allow .png files to be added as glyphs through the steps outlined above. To work around this, the .bmfc file can be modified manually.
Note that if you are using Glue you may not have to add fonts to your project manually, as Glue will manage the project and generate the code to load the font. However, to manually add a bitmap font to your Visual Studio project:
Create or download a .fnt file and matching image file (.png is typical)
Drag+drop the files into your project's Content folder
Mark both files as Copy if Newer in their properties
Once the files are created they need to be loaded into a BitmapFont. The following code loads a BitmapFont and assigns it to a Text object. Files used: font18arial_0.png, font18arial.fnt Add the following using statement
Add the following in your Initialize method after initializing FlatRedBall
A Text's font can also be changed after it has been created. Assuming customFont is still in scope:
The .fnt file is simply a text file which must be copied to build folder, while the referenced texture must be built through the content pipeline. Therefore, each file must be handled slightly differently. The following steps outline how to add a BitmapFont to a project through the content pipeline:
Add the following code to load the bitmapFont:
Add the following using statements:
Add the following wherever you are loading your font:
While it may not be immediately obvious, there is a difference between BitmapFonts and Texts (the FlatRedBall.Graphics.Text class). A Text contains information such as location, rotation, and the string to write out. The BitmapFont contains the texture information to use which represents the font. Specifically, it contains a Texture2D as well as the texture coordinates for each character. One notable consideration is that the properties in both the BitmapFont class as well as the Text class can contain the size of the letters in a Text object. Let's investigate why this is the case. Ultimately, there are three properties which are related to the size that a Text takes up when it is rendered:
Scale
Spacing
NewlineDistance
Information and code samples on these properties can be found here. These three properties ultimately control the absolute size and spacing of each letter in the Text object. However, a BitmapFont that has letters at a higher resolution will result in a larger Text on screen. The reason for this is because the TextManager adjusts these three values according to the current Camera setup when the AddText method is called so that the Text is drawn to-the-pixel. This means that a Text that is created through the TextManager which is displaying a large BitmapFont will have higher Scale, Spacing, and NewlineDistance values than one displaying a smaller BitmapFont. This behavior simply exists as a convenience, and it can be easily overridden if necessary by changing these values.
The RenderToTexture2D method renders a given line and instantiates a Texture2D. The Texture2D will not be part of a ContentManager; therefore, you must add it to a content manager or manually dispose it when you are finished with it to prevent accumulation errors.
The following code shows how to create a Texture and display it on screen:
Open Bitmap font generator.
Add the two font files to the Content folder. You can simply drag them into the Solution Explorer and they will be added.
Highlight the .fnt file and press F4 to bring up the Properties window. Make sure that its "Build Action" is "None" and its "Copy to Output Directory" is "Copy if newer"
The LineHeightInPixels represents the height of a line of text in pixels. A line of text includes the tallest letters (such as capital letters) as well as letters which have pixels that fall below the base of the line (such as the lower-case letters 'p', 'q', and 'y').
The LineHeightInPixels is the value used by FlatRedBall when determining the size of text in the SetPixelPerfectScale. A Text object which is drawn in 2D mode (where one unit equals one pixel) will have the following relationship to the LineHeightInPixels property of its BitmapFont:
The BlendOperation enumeration defines possible blend operations which can be used by an IColorable to modify how it draws over its background. For more information, see the IColorable wiki entry.
The following image shows how the four blend operations impact a sprite drawn on top of a gray background:
Notice that the alpha value does not result in transparency when using the Modulate2X BlendOperation. Note that the SubtractAlpha BlendOperation is not displayed above since it does not have an affect when rendering unless the object is placed on a RenderTarget.
The ColorOperation.Color option makes the drawn object completely ignore its Texture and use only the color. For objects like Sprites, this results in a colored quad (no texture). Alpha is ignored completely as well, so even if the Sprite's Texture has transparency, it will appear as a solid rectangle when using this color operation. Sprites that use .Color do not need to have a Texture. Therefore, the following code is acceptable:
The ColorOperation enumeration defines possible color operations which can be used by an IColorable to modify its appearance. For more information, see the IColorable wiki entry.
The following table lists color operations and supported platforms:
Images which are grayscale can be colored using the Modulate color operation. This is a fast way to create variety for entities such as enemies or equipment. The following animation shows tinting using the FlatRedBall Editor on a Sprite with Modulate color operation.
The following code creates 10 bears, starting with a color of pure black (0,0,0) and ending with white (1,1,1). The bears start dark (as if in shadow), then become progressively brighter.
Whenever a property is changed on the GraphicsOptions, the FlatRedBall Engine attempts to implement the changes immediately. However, this can cause problems when properties are changed on a GraphicsOptions instance prior to the initialization of FlatRedBall. If this occurs, the graphics device is not yet created so the setting of the property will raise an exception. This exception can be avoided by suspending device resets. If device resetting is suspended then the properties of a GraphicsOptions instance will be updated, but the device will not be reset. If the changed instance is then used to initialize FlatRedBall then the changed properties will be applied to the graphics device when it is first created. The following code tells the engine to initialize the engine in full-screen:
ColorOperation | PC (DesktopGL) | iOS | Android |
---|---|---|---|
The ColorOperation.Modulate option makes the drawn object "multiply" all of its texture color values by the Red, Green, and Blue of the IColorable. Setting a Modulate with Red, Green, Blue values of 1,1,1 will result in the object drawn regularly. Setting the values to .5, .5, .5 will result in the object being drawn at half-brightness. Setting values to 1,0,0 will result in only red values being drawn. Blue and green will draw as black. The following code example renders the Bear.png graphic with no Modulate operation, then with 3 different values to show how Modulate works. Image used:
The GraphicsOptions class provides high-level control over the graphical presentation of FlatRedBall. As a user you do not need to create an instance of GraphicsOptions, it is done automatically when the engine is created. It is exposed through the class. However, you can explicitly instantiate a GraphicsOptions to make changes prior to the initialization of FlatRedBall. This is useful for setting resolution or fixing compatibility issues. Of course, if this is done you need to suspend and resume the device resets, as explained below.
X
X
X
X
X
X
X
X
X
ColorTextureAlpha
X
X
X
Add
X
Subtract
X
InverseTexture
X
Modulate2X
X
Modulate4X
X
X
The IsFullScreen property can be set to make your game run in full screen mode or windowed mode. Keep in mind that only certain resolutions are supported in full screen, so you should make sure that your desired resolution is supported before setting full screen to avoid crashes.
An excellent feature of The GIMP is that the eyedropper tool gives you both the color of the current pixel considering alpha and also ignoring trancparency. This allows you to easily see the color of pixels which are transparent and helps identify problems related to halo filtering. To fix the filtering, first, identify the location which is causing problems using the eyedropper. Once you have spotted a point where a fully transparent pixel is touching a fully opaque pixel but their colors do not match, use the eyedropper to select the color of the neighboring opaque pixel. Next, simply paint the transparent pixel the color of the opaque pixel - this will make the transparent pixel opaque. Finally, erase the newly-painted pixel so that it is transparent once again. Notice that if you select the pixel with the eyedropper, the color matches the opaque pixel. One way to do this a little faster is to use the "Fuzzy Select" (also known as the magic wand in Photoshop) to select the transparent area and paint multiple pixels at once without modifying the transparent pixels.
Filtering is a process to reduce the pixellated look of textures when viewed from up close. Without filtering, each pixel represents a rectangular area of a solid color on a Sprite. For example, the following image shows the redball.bmp graphic without filtering. Here is a black and white checkered image. It has been enlarged so that the checkered image is clearly visible: With filtering, each pixel represents a color at just one point. When a texture is displayed on the screen, the color for each pixel on the screen is determined through an interpolation between the nearest pixels. The following image shows the redball.bmp graphic with filtering. Here is another example of how filtering affects a 16X16 black and white checkered image (again, enlarged to show detail): Filtering not only "blurs" the color of each pixel from the source image, but also the transparency. Therefore, rather than having a solid edge, the edge pixels will gradient to transparency. Filtering can be a beneficial technique for reducing visible pixels, but can cause problems as explained in the following section.
For more information on how to enable and disable Filtering in your FlatRedBall project, see:
Although Filtering can greatly improve the appearance of a Sprite, it can also cause problems. Consider the following situation. You are interested in creating a white sphere. You create a .png with the center white and fully opaque and the borders transparent. In your image editing program, everything looks great. However, when you load the white sphere in the SpriteEditor or other FlatRedBall application with filtering turned on, you notice a dark border around your white Sprite. The following image shows some simple colored shapes with a dark filtering halo over a white background. The reason this occurs is because the color of the transparent pixels are "averaged" or interpolated at points which display the Sprite. That is, the edge point on a Sprite may have an RGB value of (255,255,255) - white. Its alpha may also be 255 - fully opaque. Its neighboring pixel may have an alpha of 0 - fully transparent. However, its color value still exists. In the image shown above, the transparent pixels have an RGB value of (0,0,0) - black. Therefore, any point that is "between" the fully transparent and fully opaque pixels will have an averaged color. That is, the point on the screen which is halfway between the opaque and transparent pixel will have an alpha value of around 127 - half transparent; however, its color value will be the average of (0,0,0) and (255, 255, 255) which is around (127, 127, 127) - gray. This is often a problem which arises when games use transparent pixels and filtering. This can be solved manually by coloring the transparent pixels the same color as any opaque pixels. For example, consider the white ball presented previously. To solve the filtering halo, all transparent pixels should be white. After the change, the only difference between the transparent pixels and the white pixels should be the alpha value.
Kao Martin provided a wonderful tool for removing filtering halo from files. It can be found .
The ResolutionWidth and ResolutionHeight members can be used to get and set the resolution of the game. If you are setting both ResolutionWidth and ResolutionHeight, consider using SetResolution instead of setting each value independently to avoid a double-resize.
The SetResolution method sets the resolution (number of pixels wide and tall) of your game. This method can be called at any time after FlatRedBall is initialized.
The following code resizes the screen to display a resolution of 320X240.
Resolutions can be changed by calling SetResolution multiple times. For example, the following code allows the user to press the 1 or 2 keys to change between two resolutions:
By default if SetResolution is called, the Camera will adjust its DestinationRectangle according to the changed resolution. This automatic adjustment depends on the Camera's split screen viewport settings. For more information, see the SetSplitScreenViewport page.
One common piece of code that people use (incorrectly) to set the game resolution to the entire display's resolution is:
While this may seem fine, let's investigate what happens. The SetResolution method sets the resolution to the monitor's width/height; however, it can't actually set it to the full height. The reason for this is because Windows prevents the game window from being much taller than your current resolution. In other words, Windows resizes your game window's height to allow for the title bar and window borders. Here's a screen shot from Visual Studio showing the variables being different: Notice that the code above sets the resolution to the GraphicsDevice.DisplayMode.Height which clearly shows up as 768 on my monitor; however, the FlatRedBallServices.GraphicsOptions.ResolutionHeight (stored in a height variable) is only 752. The moral of the story is - when in windowed mode, don't set your resolution to the monitor's full-screen resolution.
SetFullScreen sets the game to run in full screen. This function can change the current resolution of the desktop. Graphics cards only support a certain number of resolution configurations. If SetFullScreen is called with a value not supported by the graphics device, an exception will be thrown.
The following code sets the game to run in full screen, using the current display resolution.
The Alpha property represents the transparency (or opacity) of a given object. The default value is 1 (full opacity), and setting the value to 0 will make the object fully transparent.
For FRB MDX users: Color and alpha values range from 0 to 255 in FlatRedBall MDX.
The following code shows how to use the Alpha property on Text objects to control their transparency.
The GraphicsOptions' TextureLoadingColorKey allows you to set the color to ignore when loading .bmp graphics. The TextureLoadingColorKey value is only applied to .bmp images and not to other images. The reason for this is because other image formats either:
Have lossy compression so exact colors are not preserved and color keys are not an effective way to create transparency.
Include an alpha channel which include the ability to have partial transparency.
You may be wondering why the above tutorial requires a recompile and a change of the bool instead of simply creating two Sprites with a change in the TextureLoadingColorKey between the creation of the two Sprites. The reason for this is because FlatRedBallServices caches. Therefore an actual load is only performed the first time that the redball.bmp graphic is referenced. Every subsequent time, the texture reference to the cached texture data is returned. The exception to this is if different content managers are used.
The following code creates a Sprite from a graphic which has a magenta background. The bool ifUsingColorKey controls whether the color key is set to Magenta or not - the default color is Black. Files used: Add the following to Initialize after initializing FlatRedBall:
Setting the ifUsingColorKey to false will result in a magenta box being drawn around the redball graphic.
Filtering is the process of modifying how a texture is drawn to reduce the effect of pixellation when viewing a texture at a large size on screen. For a more in-depth (conceptual) discussion about filtering, see the Filtering page. The default value is Linear. The GraphicsOptions.TextureFilter property can be used to control the default project-wide texture filter. Individual Sprites can overwrite this value. For more information, see the Sprite TextureFilter page.
Filtering can be controlled through the GraphicsOptions class. The following code creates a large Sprite which takes up the entire screen. Pressing the space key toggles the filtering between Linear (on) and Point (off). Add the following using statement:
Add the following in Initialize after initializing FlatRedBall:
Add the following to Update:
If you are using tile maps (such as loading a .tmx file) then you will most likely need to set the texture filter to point. Otherwise you may see lines between your tiles:
The TextureFilter enumeration is an XNA enumeration. More information on the enumeration can be found here. More information on Filtering can be found in the filtering wiki entry.
TextureFilter.Linear: TextureFilter.Point:
The IColorable interface defines properties for interacting with an object which can have its color dynamically modified and which can specify how it "blends" with objects behind it. Common objects which implement the IColorable interface include the Sprite and Text object.
ColorOperations can be used to change the color of a IColorable at runtime. ColorOperations require two pieces of information: the color specified by three values (Red, Green, and Blue) and the operation to perform with the specified color.
The default ColorOperation for most IColorables (like Sprites) is ColorOperation.None. Unless the ColorOperation is changed, the Red, Green, and Blue properties will have no effect on way the IColorable is rendered. The default ColorOperation for Texts is Modulate.
The Red, Green, and Blue properties provide access to the components of the color which is used to change the IColorable's color. The ColorOperation property specifies how to modify the color.
Color values range between 0 and 1 and are all set to 0 by default.
The exception is the Text object. The Text object has its Red, Green, and Blue color values set to 1 so that the text appears as white. Furthermore, the ColorOperation defaults to ColorOperation.Modulate for the Text object.
The following code will create five Sprites, each with a different ColorOperation.
For more information on specific ColorOperation values, see the ColorOperation page.
Color rates are values which change the Red, Green, and Blue values over time. The rates, just like all velocity values, indicate units changed per second. The following code creates 80 Sprites and randomly varies their colors using a SpriteCustomBehavior.
The Alpha and BlendOperation properties are related just as the components of color and ColorOperation properties. The Alpha property is used to control the transparency of an IColorable.
Unlike the color components, modifying the Alpha value will affect the appearance of an IColorable with its default BlendOperation.
BlendOperations control how IColorables blend with objects behind them. The following code shows two rows of Sprites - the first with the default BlendOperation.Regular and the second with BlendOperation.Add;
The AlphaRate property modifies the Alpha property similar to the ColorRate properties. AlphaRate can be used to fade an IColorable in and out.
Most IColorables are created with an Alpha value of 1. This generally represents full opacity. AlphaRate can change this value over time. A positive AlphaRate value will increase the Alpha property over time, and a negative AlphaRate value will decrease the Alpha property over time. The formula (which is generally applied automatically for managed objects) is:
Therefore, a fully opaque object with an AlphaRate of -1 will disappear in 1 second. Increasing the absolute value of the AlphaRate makes the object disappear faster. That is, an AlphaRate of -2 (twice as large in absolute value terms) will make an object disappear after .5 seconds (half as long). The formula is:
Therefore, we can see that an AlphaRate value of -2 will cause an object to disappear in
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The Red, Green, and Blue values in an IColorable represent the three color components used when applying the ColorOperation. Since the ColorOperation impacts how color is applied, then the color represented by Red, Green, and Blue may not necessarily describe the color of the object on-screen.
The ColorOperation value controls how the color values in an IColoable (Red, Green, Blue) are applied to the IColorable to determine the resulting color. The ColorOperation variable is of type FlatRedBall.Graphics.ColorOperation. For more information see the ColorOperation page.
The Sprite's default ColorOperation is:
The SizeOrOrientationChanged event is an event which is raised whenever the resolution of the screen is changed, or if the orientation changes. This allows your game to react to the resolution change as necessary. For example, Windows 8 applications can be docked, and when this occurs the screen space for the application changes. This event is not raised when a Windows Desktop app's restore button is clicked (after being maximized), so Windows Desktop apps should use the
In this example you may detect if the user has docked the game, and if the aspect ratio is smaller than some value (indicating that the dock is narrow), then you may want to pause the game.
Although the feature set for FlatRedBall is rapidly expanding, it is impossible for the engine to handle every graphical possibility. DrawableBatches are a solution to this problem as they allow custom rendering in the engine. A DrawableBatch is a class that implements the IDrawableBatch interface, which allows user-specified rendering through XNA/MonoGame. For a full API reference of MonoGame, see the MonoGame Class Reference.
The following code shows how to create a class that implements IDrawableBatch . This class draws a triangle which uses vertex colors - each point on the triangle is a different color.
The following code shows how the DrawableBatchExample can be used in a screen:
The code above produces the following when the game runs:
MonoGame's SpriteBatch can be used to draw sprites in FlatRedBall coordinates. For example, the following code considers the Camera's position, resolution, zoom, and the object's position:
The IDrawableBatch interface provides considerable freedom in custom drawing. However, the IDrawableBatch's Draw method is a method which is executed during FlatRedBall's Draw call. This means that it is possible to change the state of the graphics device in such a way that will cause FlatRedBall to render incorrectly or even crash. The following lists actions which should not be performed.
The GraphicsDevice's Viewport should not be changed. IDrawableBatches can be added to Layers - including Camera-specific Layers which inherit the containing Camera's viewport. In other words, to render to a portion of the Screen, add the IDrawableBatch to the desired Camera using the SpriteManager's AddToLayer method.
FlatRedBall handles render targets under the hood. Changing the RenderTarget can result in unexpected behavior or crashing. For control over render targets, use the Camera's RenderOrder property. If you are interested in performing something not currently supported by one of the render modes, please post on the forums.
SpriteManager.AddToLayer - This method can be used to put DrawableBatches on layers for additional sorting control.
Boolean get-only Property that specifies whether or not the Update() method will be called on this drawable batch. If you don't need to do any updating logic, just return false. For example:
This is where any updating logic goes. This could include updating positions, moving particles, or anything else that your drawable batch might need to do outside of drawing. This method is actually called inside the FlatRedBallServices' Draw method, so you should not be doing any RenderTarget setting here.
Executes your drawing code. The camera parameter represents the currently drawing camera, and may be used to retrieve camera settings (the SetDeviceViewAndProjection will work with both the BasicEffect and Effect classes, and will set the variables View, Projection, ViewProj, and any variables that have the semantics VIEW or PROJECTION). Any XNA drawing code may be used in this section. However, please note that RenderState is not preserved, so you will need to set any RenderState variables at the beginning of this method. This includes anything on the graphics device, such as a vertex declaration. For more information, read the Render State article.
Here is where you destroy any assets that won't be automatically destroyed when they go out of scope (for example, some types of buffers), and do any other cleanup you might need to perform (removing the batch from some lists, for example).
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The IVisible interface is an interface which defines that an object must have a Visible property. Setting Visible to true or false will make the object appear or disappear visually. Most visual FlatRedBall types implement the IVisible property including:
The following code shows how to toggle a Sprite's visibility when the mouse is clicked:
The Visible property on an IVisible controls whether an object will be drawn, but it also controls whether all of its children will be drawn. Therefore, if an object (such as a Glue Entity) implements IVisible, and if its Visible is set to false, then all attached objects will also be invisible. This behavior simplifies making UI objects (such as Pause menus) which many be made up of multiple levels of UI elements.
This behavior can be modified through the IgnoresParentVisibility property.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
Layers can be used to control the order of visual objects on screen. Typically objects with a larger Z value appear on top of objects with smaller Z values, but this relationship is only true if the objects are on the same layer.
Layers take priority over the Z value of objects when performing rendering. Typically Layers are used to force groups of visual objects to draw on top of other objects. For example, a HUD layer can be used to force HUD UI such as score and health bars to appear on top of everything else in a game regardless of Z value.
Layers can be added in the FlatRedBall Editor or in code through the SpriteManager. For information on how to use Layers in the FRB Editor, see this article.
To create a new Layer:
Expand the Screen which should contain a layer. Note that layers are usually added to GameScreen and not Level screens unless you need to have a layer specific to a level.
Right-click on the Objects folder and select Add Object
Find the Layer type
Enter a name for the Layer
Click OK
The following types can be added to Layers:
Additionally, Entities can be added to shapes through the FlatRedBall Editor, or through their MoveToLayer method.
Layers are used only to control the drawing order of objects. This means that layers have nothing to do with the position of the objects that they contain. For example, objects in an entity which are attached to the root entity can span multiple layers despite having their positions controlled by the parent/child relationship. For example we can consider a typical entity which is made up of three (3) objects:
The Entity itself
The visible representation which is attached to the Entity, such as a Sprite
The collision object which is also attached to the Entity, such as an AxisAlignedRectangle
Of these three, only the visible representation needs to be layered. You can add the collision to a Layer, but this does not have any impact on the behavior of your collision. The only reason you might want to add the collision object to a layer is so it will be drawn if on the same layer as the visible representation if you desire to have it drawn for debugging reasons. To clarify, adding the collision to a Layer does not impact collision. Two entities on different Layers will still be able to have their collision objects collide. The collision objects do not consider Layers when performing collision.
In code, layers are created through the SpriteManager. The following code creates a layer and two Sprites. Although the Sprite named nearSprite is closer than the Sprite named farSprite, farSprite is not hidden by nearSprite.
SpriteManager.AddToLayer - Responsible for adding SpriteFrames, Sprites, and IDrawableBatches to Layers.
TextManager.AddToLayer - Responsible for adding Texts to Layers.
Similar to Sprite and Texts, PositionedModels can also be layered. The following code creates a PositionedModel and adds it to a layer.
There are two ways to remove objects from Layers:
Completely remove the object from the engine and its Layer(s)
Remove the object just from the Layer but keep it in the engine
For reference, let's use the following setup to discuss this point:
This is the most common method of removing an object. It's usually what you'll do if you're manually handling the removal of your objects (as opposed to letting Glue do it for you). To do this, simply use the manager removal methods:
In other words, remove your objects just like normal - they'll automatically get removed from their Layers too.
Objects can be removed from Layers through the Remove method.
Now the Sprite and Text object are no longer on the layer, so they will not be drawn. However, the two objects have not been removed from their respective managers so they are still in memory and still managed every frame!
Multiple layers can exist at a given time. Calling AddLayer multiple times creates multiple layers. The newest layer is always on top while the oldest is on bottom.
This section discusses sorting objects (such as Sprites within a Layer. For information on how to control the order that Layers are drawn, see the SpriteManager MoveToBack and MoveToFront page. While Layers represent Lists in some ways, they cannot sort objects that they hold (like SpriteLists or PositionedObjectLists). The reason for this is because the internal SpriteList that a Layer references is used directly by the engine to draw the Layer. The engine may perform sorting on this list to ensure proper overlapping and to improve runtime performance so user-controlled sorting of the SpriteList may disrupt this behavior. If objects in a Layer need to be sorted they should be added to a separate SpriteList and sorted there.
If you are using Glue then you can add an Entity to a Layer. See this article for information on this.
Layers will render to the full screen by default. Layers can be adjusted to only render to part of the Screen. For more information see the LayerCameraSettings destination coordinate page.
For more information, see the Adding Gum Components to Layers page.
Most rendering APIs (including XNA and DirectX) have what are called "render states". While there are RenderState classes, the term "render state" is a general term which is a variable that can be set before rendering to impact the rendering of objects. When rendering objects, there are many (dozens upon dozens) of states that can be set to control how objects appear. For example, The XNA GraphicsDevice.RenderState.DestinationBlend partly controls how a drawn pixel will blend with the underlying pixel.
FlatRedBall internally sets a variety of render states to achieve certain effects according to user variables. For example, a property can potentially change the RenderState's GraphicsDevice.RenderState.SourceBlend and DestinationBlend when being rendered. Therefore, any render state that you rely on in your IDrawableBatch's Draw method must be set in the Draw method. If it is set only in the IDrawableBatch's constructor or elsewhere in the code, your render state may be overwritten by FlatRedBall's rendering code.
Unfortunately, FlatRedBall cannot predict the type of render states you will need in your IDrawableBatch code. Therefore, it's impossible for the engine to adjust its render states to fit your needs. However, FlatRedBall does require certain render states to be set in its rendering code. For performance reasons, FlatRedBall generally sets render states only when switching between categories of objects being rendered (such as and ) or when an object calls for it (such as when one has a different than the previously-drawn . Since IDrawableBatches are drawn in the same section of code as ordered and , render states must be preserved. This means that if you change a render state at the beginning of your IDrawableBatch's Draw method, be sure to set it back to the previous value or else you may encounter unexpected rendering behavior.
The LayerCameraSettings property is of type FlatRedBall.Graphics.LayerCameraSettings which can be used to override the settings of the Camera when rendering the particular Layer. For more information on how to use this, see the LayerCameraSettings page.
If a Camera is unrotated, then the default SortType (Z) will work well. However, if your game uses a camera which can be rotated, then the default SortType may no longer produce desired results. For example, in a typical 3D game the Camera can face in any direction. When this occurs, objects with larger Z values are not guaranteed to be closer to the Camera than objects with smaller Z values. This is very noticeable when working with UI elements which are attached to the Camera. This is the main reason for the DistanceAlongForwardVector SortType. In most you can resolve ordering issues on UI/HUD elements which are attached to a rotated Camera by setting the Layer's SortType to DistanceAlongForwardVector:
Each Layer can have its own SortType which controls how , , and sort. This property allows each Layer to have its own Sort type. By default objects on Layers will be sorted by their Z values - objects with smaller Z values (which are in the distance) will draw behind objects which have larger Z values (which are closer to the Camera).
For general information abou tthe SortTypes property, see the . This article will discuss how sorting can be modified. Keep in mind that the SpriteManager article linked here discusses object sorting and uses the SpriteManager's OrderedSortType property which only controls how unlayered objects sort. In other words, changing the SpriteManager's OrderedSortType will not impact how Layers sort. Unlayered objects can sort differently than Layered objects, and each Layer can specify its own SortType.
Layers provide a way to force a particular order of drawing on a single Camera. While the concept is fairly straight-forward, things can become more complicated when objects are moved from being layered to unlayered, or when objects have presence on multiple layers. Since there are a variety of ways to layer and unlayer objects, this article will present a number of small code blocks and explain what each one does.
First, let's start with some common code that all samples below will use. Consider the following line of code:
Okay, so far we have two layers that have been added to the SpriteManager. Keep in mind that secondLayer will actually be drawn on top of firstLayer - they are drawn in the order that they are created, so first is drawn first, then second is drawn on top of first.
Here's a very common setup (of course, assuming the lines above are still in the code).
As you may have guessed, the above code creates a Sprite which is managed and drawn, but not layered. We can show the membership as follows:
This table is just another way of showing what we mentioned before.
There are two ways to make a layered Sprite. The first is to use the AddToLayer method:
The AddToLayer method in the SpriteManager as well as all other Managers does two things:
Adds the Sprite (or other object) to the argument Layer
Removes the Sprite (or other object) from unlayered drawing
The result:
The SpriteManager provides a shortcut method for adding a Sprite directly to a Layer:
This code does the exact same thing if used instead of the two lines of code above. That is, this method both adds the Sprite for membership as well as adds it to the firstLayer but not to unlayered drawing.
The AddToLayer method does remove the argument Sprite from unlayered drawing, but it does not remove the argument Sprite from any other Layers that it belongs to. Therefore, a Sprite can be added to two Layers simply by calling AddToLayer twice:
The result:
To remove a Sprite (or any other object) from a Layer, simply call the Remove method. Keep in mind that calling Remove will not re-add the object to unlayered drawing.
As shown below, this makes the Sprite managed, but it will not be drawn.
Having an object be drawn layered an unlayered is not something supported by the FlatRedBall Engine. One reason for this is that in most cases, this is an undesirable behavior. It can hurt performance, as well as result in unexpected graphical behavior. But we're going to cover this anyway because it may help expose bugs that you are experiencing if you've tried this (or stumbled across it unintentionally).
This code needs some explanation. The first line makes the Sprite managed and drawn unlayered. The second line makes the Sprite layered, but removes it from unlayered drawing. Now, you may be thinking "Ok, the last line just re-adds the Sprite to the SpriteManager so it is drawn unlayered." Well, you're half right. The second AddSprite call does add the Sprite to be drawn, but it also has a nasty side-effect. The Sprite will actually be added to the SpriteManager twice. It was added once on the first line, and once again on the third line. This means that the Sprite will have its every-frame management performed twice. Not only does this hurt performance, but it results in properties like Velocity and Acceleration applied twice. In other words, you may get very unexpected behavior if you do this.
The AddToLayer method has a little bit of inconsistent behavior. Let's explore it a little bit. FlatRedBall assumes that in most cases whenever you want an object drawn, you also want it managed. So, let's look at the following code:
So it's a safe bet that the Sprite will be drawn on the firstLayer, but what about management? Is it managed by the SpriteManager? We never called AddSprite. Drum roll please...
The SpriteManager actually added the object both to the layer as well as to itself for management. This behavior is present because it's assumed that drawn objects should be managed. There is one exception, however. The ShapeManager's AddToLayer method. Shapes have somewhat unique behavior in that they are most often used for collision, and many times they can exist and be used, but not be managed by the ShapeManager for performance reasons. Therefore, the ShapeManager does not add a shape for management unless you explicitly tell it to do so. In other words, adding a shape to a layer, but not to the ShapeManager results in the shape being drawn, but not managed. For more information on the reasoning behind this type of behavior, see the "Why Limit Shape Management" section of the ShapeManager page.
Category
Is a member
Managed by SpriteManager
X
Drawn unlayered
X
Drawn on firstLayer
Drawn on secondLayer
Category
Is a member
Managed by SpriteManager
X
Drawn unlayered
Drawn on firstLayer
X
Drawn on secondLayer
Category
Is a member
Managed by SpriteManager
X
Drawn unlayered
Drawn on firstLayer
X
Drawn on secondLayer
Category
Is a member
Managed by SpriteManager
X
Drawn unlayered
Drawn on firstLayer
X
Drawn on secondLayer
X
Category
Is a member
Managed by SpriteManager
X
Drawn unlayered
Drawn on firstLayer
Drawn on secondLayer
Category
Is a member
Managed by SpriteManager
X X
Drawn unlayered
X
Drawn on firstLayer
X
Drawn on secondLayer
Category
Is a member
Managed by SpriteManager
X
Drawn unlayered
Drawn on firstLayer
X
Drawn on secondLayer
The Sprites collection provides access to all ordered Sprites stored within this layer. This is a read-only collection so it cannot be directly modified through the layer. Note that this list only contains ordered sprites. Z-buffered sprites are stored in the Layer's ZBufferedSprites property.
The Sprites property can be used to check if a Sprite is being displayed on a layer. The following code shows how to check if a Sprite is on a Layer.
The Remove method is responsible for removing the argument object from the calling Layer. Remove has the following signatures:
Calling Remove is usually not necessary. The reason is because the internal list that Layers use to keep track of objects is a two-way list. In other words, consider the following code:
Therefore, you will not need to call Remove to take a Sprite off of a Layer if you are using the SpriteManager to remove it. However, Remove can be useful if you would like to move a Sprite from one Layer to another:
The OrthogonalWidth and OrthogonalHeight of a LayerCameraSettings object controls the number of units wide and high that the Layer will display. The LayerCameraSettings' Orthogonal value must be true for the OrthogonalWidth and OrthogonalHeight properties to apply.
This example was initially constructed in Glue. To reproduce this:
Create a Screen
Add a Sprite to the Screen
Create a 2D Layer
Place the Sprite on the 2D Layer
You can match the LayerCameraSettings to match the Camera by setting the OrthogonalWidth/OrthogonalHeight of the LayerCameraSettings to the Camera's OrthogonalWidth/OrthogonalHeight. This assumes that both the Layer and Camera are using orthogonal values.
Orthogonal values can be used to determine the width and height in world coordinates of the area that a Layer displays. Usually these coordinates happen to match the pixel display area as well, but it is possible for this to not be the case if destination rectangle values are set differently from orthogonal values. The following code will size a Sprite so that it is the same size as the displayed area of a Layer:
The following example shows a situation where a Camera which is 3D (default) draws a 2D layer which contains some text. Add the following using statement:
Add the following to Initialize after initializing FlatRedBall:
The code above creates two different coordinate systems; however, if the Camera is moved, then the Text that is on the 2D layer will also be affected. Usually when creating 2D HUD and UI elements, they should also be attached to the Camera. If an object is attached to the Camera, it will always stay in the same place on-screen even if the Camera moves or rotates. Therefore, the positioning code could be modified as follows:
Set its Texture (I used )
If you run the game you should now see the Sprite rendering on the Layer: We can now zoom in on this Sprite simply by adjusting the orthogonal values on the LayerCameraSettings. Since I'm using Glue I'll add the following code to my CustomInitialize for my Screen that contains the Layer:
Now the Sprite (and anything on the same Layer) will appear at 8x zoom:
The UsePixelCoordinates can be used to easily create a 2D Layer. This method is often used in combination with attaching Entities to a Camera so that they can be placed in screen space. This method is used by if a given Layer's "Is 2D" property is set true.
The TopDestination, BottomDestination, LeftDestination, and RightDestination properties of the LayerCameraSettings class allow Layers to render to only a portion of the Screen (also known as creating a mask). These coordinates are measured in pixel units in screen space. In other words, 0 is the left side of the screen for LeftDestination and RightDestination, and it increases to the right. The value of 0 is the top of the screen for TopDestination and BottomDestination, and it increases downward. The destination values are not necessarily used when a given Layer is rendered. The default value for TopDestination, BottomDestination, LeftDestination, and RightDestination is -1. If -1 is used, then the Camera's DestinationRectangle values are used.
The following code creates a LayerCameraSetting which has a 200 pixel border around the edges of the screen. The Layer draws a large Sprite which is masked by the destination values of the LayerCameraSettings. Add the following using statement:
Add the following to Initialize after initializing FlatRedBall:
If you are explicitly setting the destination rectangle of a LayerCameraSettings object, then you may encounter an exception. If FlatRedBall detects that the BottomDestination is too large, you may get an error as follows:
Similarly you may get a message about the width, which might read:
You can fix this in one of the following ways:
Prevent resizing of your game window
Adjust the LayerCameraSettings for your Layer to fit within the bounds of the display
Set the LayerCameraSettings' destination values to -1, which will result it in automatically adjusting to its contained Camera destination.
The RenderBreak struct is a struct used internally by the engine to identify when to switch rendering states during a vertex buffer rendering pass. Vertex buffers are used to render most FRB types including Sprites, Texts, and Shapes. You will likely not need to interact with RenderBreak if you are writing game-level code. This class is only used in rendering code.
LastFrameRenderBreakList is a list of RenderBreaks which were created last frame. For this to be a non-null list, the Renderer's RecordRenderBreaks value must be set to true. This is by default false for performance reasons.
This member can be used to get detailed information about the last frame's render breaks. To simply count the number of render breaks, use the RenderBreaksAllocatedThisFrame property. This property is always valid.
The following code will measure the render breaks.
The RenderBreaksAllocatedThisFrame property returns how many render breaks have been created and applied during the last rendering pass. Render breaks can significantly slow down the performance of your game, and reducing the number of render breaks occurring in each render pass can provide big performance boosts without requiring you to reduce the number of objects in your game.
For a detailed discussion of render breaks, see this page.
The Draw function is responsible for looping through all Cameras in FlatRedBall and performing rendering for each one. This method is automatically called for you in a default template, so most games do not require manually calling this method. The Renderer's Draw method is usually called by the FlatRedBallServices object. You can modify the game code where FlatRedBallServices.Draw is called to customize how rendering occurs (such as to do custom render targets). For more information, see this page
The GetWidth method returns the width of a piece of text. The GetWidth method returns the width of text, and can accept a variety of arguments. The overloads provide flexibility depending on how much information is needed.
The following code creates a Text object and a Line which can be moved between letters with the left and right arrows on the keyboard:
Add the following using statements:
Add the following to your Game or Screen's class scope:
Add the following to your Game's Initialize or Screen's CustomInitialize:
Add the following to your Game's Update or Screen's CustomActivity:
Add the following function at class scope:
The DisplayText property controls what a Text object will write to the Screen. The DisplayText property can be set to initially set what the Text will display, and it can be changed at any time. The DisplayText property should be used to change a Text's display instead of re-creating a new Text every frame or whenever the Text changes.
The following code shows how to display how much time has been running since the start of the game:
Add the following using statement:
Add the following at class scope:
Add the following to Initialize after initializing FlatRedBall:
Add the following to Update:
The Font property gets and sets the BitmapFont that the Text will use when it's drawn. This property can be set at any time to change the BitmapFont that the Text object uses.
For more information, see the BitmapFont page
HorizontalAlignment determines how the text aligns itself according to the Text's X position. By default text is left justified, so the left side of the first letter will be placed at the Text's X value.
The Text object's X value marks the left side of the text object by default - that is, text is left justified by default. This justification or alignment can be changed. The following code creates three text objects with different HorizontalAlignment.
The dotted line above shows the X position of the Text objects.
The NumberOfLines property returns the number of lines that the Text object will occupy when rendering. this value corresponds to the number of newline characters in the text object ('\n'). Newline characters can be added manually to the DisplayText property, by calling FlatRedBall.Graphics.Text.InsertNewLines, or automatically according to the Text's FlatRedBall.Graphics.Text.MaxWidthBehavior.
VerticalAlignment determines how the text aligns itself according to the Text's Y position. By default text uses VerticalAlignment.Center, so the center of Y value of the Text will represent its center vertically.
The Text object's Y value determines the position of the Text along with the Text's VerticalAlignment. Changing the VerticalAlignment will change the visible Y position of the text even though the Y value will be the same. The following code creates three Text objects with different VerticalAlignments.
The TextManager is a static class which handles Text object addition, removal, and common behavior. The TextManager has many of the same methods (in concept) as the SpriteManager. The TextManager is automatically instantiated by FlatRedBall so you do not need to create an instance yourself.
The TextManager provides numerous methods for for working with the Text object. The following sections provide code samples for working with Text-related methods.
Most AddText methods both instantiate a new Text object as well as add it to TextManager for management. The following methods instantiate and add a Text object to the SpriteManager:
Custom BitmapFonts can be used when creating Text objects as well.
For information see the BitmapFont wiki entry.
Adding Text and Layers
Text objects can also be added to Layers.
For more information, see the Layer wiki entry and the AddToLayer method.
The RemoveText methods remove Text objects from the engine as well as any two-way AttachableLists (such as PositionedObjectList) that the Text object belong to. For more information, see the RemoveText page.
[subpages depth="1"]
The AddManuallyUpdated method adds the argument Text to the TextManager to be drawn. A manually updated Text does not have any of its ever-frame behavior performed by the TextManager, so changes to the Text must be manually applied. Manually updated Texts can be used in situations where a Text does not change after it has been created, or where only a small subset of properties change every frame, so manual updating can selectively update these variables for a performance boost.
The following code shows how to create 1000 manually updated Texts. It uses a large number of Text instances to show the performance benefit of using manually updated Texts.
On an i7 (in 2018) this code renders at around 464 frames per second, as shown in the following screenshot:
By contrast, calling AddText instead of AddManuallyUpdated results in a framerate of around 150 frames per second.
The ForceUpdateDependencies call is required to update a Text object according to its properties so that it renders properly. Normally this call is not needed because the engine calls it automatically, but in the code above we must call it after setting all properties to apply the values to the Text object. Notice that any changes made to the Text object after calling ForceUpdateDependencies will not apply on manually-updated Text instances. For example, changing the DisplayText after calling ForceUpdateDependencies will not change the string that the Text object is displaying.
FlatRedBall introduced a new method to the Text object: UpdateInternalRenderingVariables . This function will update the internal rendering values just like ForceUpdateDependencies without also updating the object according to its parent's position and rotation. Using UpdateInternalRenderingVariables can be slightly faster if the Text being updated is not attached to another object (such as an entity).
Width returns the distance in absolute world coordinates from the left side of the Text instance to the right. This value reacts to font size, word wrapping, and the Text's DisplayText property.
The following code creates a Text object and adds it to a layer.
Alternatively the Text can be added to a Layer after AddText is called. The following code can also be used:
The FilterTexts property controls whether Texts are rendered. The TextManager can set this value and it will override the value set in the GraphicsOption's TextureFilter property.
The default for TextManager.FilterTexts is false, while the default value for the GraphicsOption's TextureFilter is on (technically it's an enumeration, but for simplicity we'll say that filtering does occur). The reason for this is because Text which is drawn to-the-pixel does not need to be filtered. Filtering text that is drawn to-the-pixel will make it look fuzzier than normal.
However, you may want to turn FilterTexts to true if you plan on drawing Texts at larger-than-pixel-perfect to reduce their pixellated look.
AnimationChains represent a series of AnimationFrames which can be used to animate objects which implement the IAnimationChainAnimatable interface such as Sprites. AnimationChains can be created in code, or they can be created using the AnimationEditor. The AnimationEditor is installed when running the FlatRedBall installer which can be found on the downloads page. The IAnimationChainAnimatable page has more information on how to use AnimationChains, so please check it out after finishing up this page.
The following statement will help reduce code when working with AnimationChains.
AnimationChains can be created manually by creating the frames individually through code, by loading a .achx file, or through the content pipeline.
Notice that the .1f is the frame length in seconds. For from-file and content pipeline loading, see the AnimationChainList wiki entry.
Note: The AnimationFrame class is used to define individual frames in an AnimationChain. For more information on how to modify your animations, including how to create animations by using parts of a single Texture, see the AnimationFrame page.
For information on loading an AnimationChainList from a .achx file, see this page.
AnimationChains are also Lists of AnimationFrames. Therefore the AnimationChain provides the same interface as a list for accessing frames, such as indexing ( [index] ), properties like Count, and methods like Add. For example, the following code can be used to change the referenced texture of all frames in an animation chain to NewTexture :
FlatRedBall.Graphics.Animation.AnimationFrame - AnimationChains represent a list of AnimationFrames. When an AnimationChain is applied to an object, the object flips through and uses the AnimationFrames to modify its appearance.
FlatRedBall.Graphics.Animation.AnimationChainList - AnimationChainLists are lists of AnimationChains. Objects such as Sprites store AnimationChainLists, simplifying the process of setting which AnimationChain is currently used.
FlatRedBall.Content.AnimationChain.AnimationChainListSave - The "save" file for AnimationChainList files. This can be saved to and loaded from .achx files, and can also be converted to and from AnimationChainLists. For more information, see the FlatRedBall File Types wiki entry.
FlatRedBall.Graphics.Animation.IAnimationChainAnimatable - The interface that defines properties and members for objects which can be animated by AnimationChains. See this article for information on how to set animations on objects such as Sprites.
FlatRedBall.Sprite.PixelSize - PixelSize can be used to reactively set scale based off of a changed Texture resulting from playing an AnimationChain.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The FrameToFrame method returns the shortest absolute distance between two frame indexes. This value may be negative and considers looping. Example Assuming you have created an AnimationChain named "ac" with 6 AnimationFrames (the last at index 5), FrameToFrame returns the following values:
Call | Result | Explanation |
ac.FrameToFrame(1, 2) | 1 | The closest distance from 1 to 2 is 1 frame. |
ac.FrameToFrame(2, 1) | -1 | The closest distance from 2 to 1 is -1. This value is negative because you must move "backward" to get from 2 to 1 |
ac.FrameToFrame(1, 5) | -2 | The closest distance considering looping to get from 1 to 5 is -2. That is first going from 1 to 0, then 0 to 5 (the last frame) |
ac.FrameToFrame(0, 3) | 3 | Although 0 is both 3 and -3 frames away from index 3, FrameToFrame doesn't wrap if the direct difference is equally short as the wrapped. |
Represents a list of AnimationChains. This object can be loaded from file and saved to file as well. This object is associated with the .achx file. For information on how to use AnimationChainLists in Glue, see this article. AnimationChains can be displayed by IAnimationChainAnimatables such as Sprites and SpriteFrames. For more information on how to work with AnimationChains in code, see the IAnimationChainAnimatables page.
AnimationChains can be loaded from .achx files which are created in the AnimationEditor. The following code creates an AnimationChain and assigns it to a Sprite. Add the following using statements to reduce code:
In Initialize after FlatRedBallServices.InitializeFlatRedBall:
For information on loading through the Content Pipeline, see the FlatRedBall XNA Content Pipeline wiki entry.
To save an AnimationChainList to file, you can use the AnimationChainListSave object. For more information, see this page.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
AnimationFrames represent the state of an IAnimationChainAnimatable. The following properties can be set by an AnimationFrame:
Texture
RelativeX/Y Position
Texture Coordinates
Horizontal/Vertical Flipping
AnimationFrames usually exist inside AnimationChains.
AnimationFrame instances are typically contained in AnimationChains, and are created by loading a .achx file. AnimationFrames can be constructed in code, and can be added to AnimationChains (see below).
Although .achx files are the most common way to create AnimationFrames and AnimationChains, AnimationFrames can also be constructed in code. The following code shows how to construct an AnimationChain and AnimationFrame in code, assign it to an existing Sprite, and update the Sprite to the AnimationChain:
The FrameLength property defines how long an AnimationFrame is displayed. Adding the FrameLengths of all AnimationFrames in an AnimationChain results in the length of the entire animation. FrameLength - like all timing in FlatRedBall - is performed in seconds. Therefore, if an AnimationFrame has a FrameLength of 1, the AnimationFrame will show for 1 second. If you are familiar with working in milliseconds, then simply divide the desired value by 1,000. For example, to set the FrameLength to 600 millseconds, simply divide 600 by 1,000 and set that value to your FrameLength:
A ShapeCollectionSave instance which can be used to apply a frame's collision to an entity. By default this is null.
The most common usage is to add shapes to an AnimationChainListSave file (.achx) and to apply animations to a collidable Entity. The following example assumes that shapes have been added to a frame in the AnimationEditor.
The code performs null checks (through the null coalescing operator), since a frame may not have collision data. If a frame does not have collision data, then the collision will not be modified. Note that if one frame does have collision, but subsequent frames do not, then the collision will remain unchanged when the later frames are played. Therefore, if one frame has collision, other frames should as well to avoid confusing behavior.
The Texture property is a reference to the Texture2D referenced by an AnimationFrame. This is the Texture that it will apply when the animation is being displayed. This is automatically set when loading a .achx file (such as in Glue), but it can be changed at runtime, or can be set when creating a new frame.
The IAnimationChainAnimatable interface defines methods and properties for objects which can be animated by AnimationChains (which are stored in a AnimationChainList). Examples of classes which implement the IAnimationChainAnimatable interface include the Sprite and SpriteFrame.
The following shows various ways to set a Sprite's current AnimationChain. The reason there are so many examples is because Sprites and AnimationChains can be created many different ways. What follows are examples which cover the most common scenarios. For information on how to create AnimationChains, see the Creating AnimationChains wiki Entry.
Normally the Sprite's AnimationChains can be set in Glue; however, to set them manually in code:
IAnimationChainAnimatables like Sprites can also have their AnimationChains set after they are created:
If the Sprite has had its AnimationChains value set, either in code or in Glue, then you can simply select which animation to play:
Calling SetAnimationChain or setting the CurrentChainName needs to only be called when the AnimationChain is changing or being set. It does not need to be called every frame to keep the animation going.
See FlatRedBall.Graphics.Animation.IAnimationChainAnimatable.CurrentFrameIndex.
When an IAnimationChainAnimatable changes the AnimationFrame that it is displaying, its JustChangedFrame property is true for that frame.
Walk North
Walk South
Walk West
Walk East
Attack (likely also has directions, but not included to save space)
Die
Since these behaviors share many similarities they should be put in a base class. However, setting AnimationChains becomes a problem. If each type of object (human peasant, orc peasant, ogre) references different AnimationChains the the code cannot fully be standardized if references are used to set the current animation. That is, if methods are called when a state change occurs, there will need to be virtual methods that can be called by the base class to set the current AnimationChain to the appropriate reference. While this will work, it is not very convenient or readable - for a new user to understand the behavior he will have to traverse multiple files and follow the execution path up and down the inheritance tree. The alternative is to recognize early on that this similarity between objects exists and design for this standard behavior both in content and in code. In other words, if the behaviors previously listed in bullet points are recognized early on before content creation begins, then this pattern can be used when all AnimationChainLists are created. Once the textures for all animations are created, the .achx file created in the AnimationEditor can use the same names for their AnimationChains. Therefore, the humanPeasant.achx file and the orc.achx file will both reference different textures, and can even have a different number of textures or frame times, but they should include a set of same-named AnimationChains. What the AnimationChain holds internally is insignificant from the programmer's point of view, just the name. Once these AnimationChains are created, the code simply loads the appropriate .achx file in the derived class' constructor. The base class can set the current AnimationChains using the Name property. As an example, the following code would work for all objects which have walking and dying animations:
So long as all objects which inherit from the class containing this code have AnimationChains named WalkNorth, WalkSouth, WalkWest, WalkEast, Attack, and Die, this code will handle all AnimationChain setting with no regard to the actual contents of the AnimationChain being set.
The previous section discusses how to set AnimationChains on an IAnimationChainAnimatable. Of course, for the CurrentChainName property to work, the IAnimationChainAnimatable must have a reference to an AnimationChain with a matching name. Another way of looking at it is that if you are going to toggle between AnimationChains, then the object that is going to have its AnimationChain set must have references to multiple AnimationChains. How can this be done? The most common and data-driven approach is to load a .achx file created in the AnimationEditor or some other tool. The .achx file can contain multiple AnimationChains so this greatly simplifies the process. However, it's also possible to set up your IAnimationChainAnimatable to use multiple AnimationChains if you are creating the AnimationChains by hand. To do this, you can simply add each AnimationChain to the AnimationChains property. For example, assuming that animationChain1, animationChain2, and animationChain3 are valid AnimationChains:
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
Objects which implement the IAnimationChainAnimatable interface hold an AnimationChainList reference internally. This AnimationChainList is referenced by IAnimationChainAnimatables to standardize the setting of AnimationChains according to state or behavior. The game Warcraft 2 will be used as an example of how the internal storage of AnimationChains can standardize code and simplify development. Warcraft 2 has numerous characters which share similar behavior. All ground units have the following behavior:
The total length obtained by adding the of all contained .
The Animate property returns whether the IAnimationChainAnimatable is performing animation (cycling through AnimationFrames). This property does not reflect whether the IAnimationChainAnimatable has a CurrentChain. If it does not, this value may still be true indicating that the IAnimationChainAnimatable will animate once a CurrentChain is set.
The IAnimationChainAnimatable interface only requires that the Animate property returns a value - it doesn't require a setter; however, common IAnimationChainAnimatable-implementing classes like Sprite and SpriteFrame provide a setter. If the specific implementing class allows, setting this value to false will prevent animation from occurring, and will stop any existing animation. For example, the following code can be used to toggle whether a Sprite is animating:
The AnimationSpeed property controls the speed at which an Animation is playing. The default value for AnimationSpeed is 1, which means the amount of time that each AnimationFrame displays is equal to its FrameLength property.
Increasing this value above 1 will make animations play faster.
Setting this value between 0 and 1 will make animations play slower.
Setting this value to 0 will make animations stop (similar to setting Animate to false).
Setting this value to a negative number will make animations play in reverse.
A Sprite's AnimationSpeed can be changed in the FlatRedBall Editor in the Variables tab.
The UseAnimationRelativePosition property controls whether the IAnimationChainAnimatable sets its relative values when the current AnimationChain changes its displayed frame. This value is true by default for the Sprite object. If you are applying relative values to an object such as a Sprite and do not want the AnimationChain to interfere, then set this value to false in code:
The Texture color operation results in an object being drawn with its unmodified texture. Color values (red, green and blue) on the IColorable are completely ignored, unless the object has no texture. The Texture color operation is the default color operation for FlatRedBall types like Sprite and Text.
Texture color operation can be assigned on any IColorable, such as Sprite:
As mentioned above, the Red, Green, and Blue values have no impact on an object which uses the Texture color operation.
The Add color operation allows the addition of the Color (Red, Green, Blue) values to the texture drawn by an object. This can be used to "lighten", or simulate light shining on an object.
The following code can be used to set a Sprite's color operation to Add when the space bar is pressed.
BlendOperation can control how an IColorable (such as a Sprite) will render on top of objects under it. The default ColorOperation for most renderable objects is BlendOperation.Regular. For examples on how BlendOperation is applied, see the BlendOperation page here: https://flatredball.com/documentation/api/flatredball/flatredball-graphics/flatredball-graphics-blendoperation/
The Z value controls the ordering of the batch relative to other batches, z-ordered sprites and text objects. Since the rendering performed in IDrawableBatches may be preceded and followed by other FlatRedBall rendeing calls, render states are not preserved between DrawableBatch Draw calls.
The IgnoresParentVisibility property controls whether an IVisible instance's visibility is impacted by its parent's visibility. If an IVisible doesn't have a parent, then the IgnoresParentVisibility property has no impact. IgnoresParentVisibility defaults to false, meaning that parent visibility impacts a child's visibility. Setting this value to true makes an IVisible's Visible property ultimately determine whether it appears on screen.
The following example creates four Sprites. Two of the Sprites are parents, two are children of their respective parent. spriteChildB has its IgnoresParentVisibility set to true, meaning it will still be visible desipite its parent being invisible. Since spriteParentA is invisible, spriteChildA will also be invisible.
The CurrentChainName property gets and sets the name of the AnimationChain currently played by the owner of the property. Setting this property is the most common way to change between different animations at runtime, and it can also be set in Glue to control the animation displayed by an IAnimationChainAnimatable (such as a Sprite).
The CurrentChainName property is a string, so code can assign animation chains in a way that is not tied to the underlying content. The following code shows how to set the animation of an object according to pressed keys.
Changing CurrentChainName does a number of things:
Sets the displayed animation to the animation matching the set name.
Restarts the animation from the very beginning.
Immediately updates the IAnimationChainAnimatable's textures and texture coordinates to reflect the first frame in the animation.
Note that these actions are only taken if the CurrentChainName *changes. *Assigning CurrentChainName to the same value performs no logic, so it can be safely set every frame without restarting the animation from the beginning. To restart the animation from the beginning, set CurrentFrameIndex to 0.
Keep in mind that some properties will not change in response to CurrentChainName being set:
JustCycled
JustChangedFrame
The Emitter class is part of FlatRedBall to support old projects, but its use is no longer recommended. It is not maintained, likely has bugs, and the genera patterns do not align with modern FlatRedBall programming.
The RenderTarget property can be set so a given Layer renders to the RenderTarget rather than to screen. The RenderTarget property can be used for a number of reasons:
To create textures used in a multi-pass rendering system, such as to apply layer-wide effects like color tinting or bloom
To improve the performance of complicated, static visuals on a Layer by eliminating the management of multiple objects and multiple draw calls with a single object and draw call (for a collection of objects which do not require every-frame activity)
If a Layer's RenderTarget is set, then the Layer will does render directly to the screen. The contents of the Layer are rendered to the RenderTarget which must then be rendered to the screen using another graphical object such as a FlatRedBall Sprite, a Gum Sprite, or SpriteBatch.
To set a RenderTarget in the FRB Editor:
Create a RenderTarget object
Create a Layer instance
Set the RenderTarget property on the layer to the previously-created RenderTarget
As mentioned above, the contents of the Layer are rendered to its RenderTarget instead of the screen. The easiest way to see the contents of the RenderTarget is to add a Sprite and use the RenderTarget as its Texture.
The following code shows how a RenderTarget2D can be created and assigned to the Layer.RenderTarget property. This Layer contains a single Circle which is drawn with a separate unlayered Sprite:
Note that the above code creates a Layer in code instead of creating one in the FRB editor. This is done purely to keep the example short - Layer instances created in the FRB editor can be used as well.
RenderTarget instances can be updated every-frame, or can be rendered just one time (if the contents of the render target never change). The following code example shows how to create a RenderTarget which is used as the target only one time. This example differs in the following ways compared to the previous example:
The layer is only needed temporarily until the render is done.
The Renderer needs a temporary camera to perform rendering. While this example only uses a single Layer, multiple layers could be used to sort objects.
Any rendered objects (such as entities, sprites, or shapes) are only needed for the Draw call and can be destroyed afterwards.
The example above shows how to render an AxisAlignedRectangle using a one-time render to a RenderTarget. If entities (or other objects which have PositionedObject attachments) are rendered to a one-time render target, then dependencies (aka attachments) must be updated prior to rendering the render target. For example, the following snippet shows how multiple Ship instances might be rendered to a RenderTarget:
The RenderTarget2D constructor takes width and height parameters. These values can be as large as the current game's resolution, but they can also be smaller. If a smaller resolution is used, the Layer will be rendered at lower resolution, but the entire layer will still be drawn. For example, first we will modify the example above to no longer squash the Sprite:
We can adjust the RenderTarget2D constructor so the RenderTarget is 1/4 the resolution, as shown in the following code snippet:
Since the Sprite uses a TextureScale of 1, shrinking the RenderTarget2D will also shrink the Sprite:
To compensate for this, the Sprite.TextureScale property can be changed to 4. This will result in the RenderTarget2D being drawn at the same size as before, but it will be 1/4 the resolution, so it will appear pixellated (or blurred due to linear filtering):
Rendering to a RenderTarget2D which is smaller than the game's resolution can improve performance, especially if the RenderTarget2D is used with effects which do not need full-resolution images, such as blurring.
Adding a 2D layer when the main Camera is 3D
Adding a 3D layer when the main Camera is 2D
Adjusting the field of view on a 3D layer when the Camera is 3D
Adjusting the orthogonal width and height values on a 2D layer when the Camera is 2D
Add the following to Initialize after initializing FlatRedBall:
If a Layer is added through Glue, the generated code for the layer will instantiate a new LayerCameraSettings and add it to the Layer. By default these settings will match the camera at the time of Layer creation.
The LayerCameraSettings class is a class which can be used to override the settings of a on a by basis. LayerCameraSettings can be used to achieve the following:
The following code creates a which renders in 2D even though the camera is rendering in 3D: Add the following using statement:
The PixelSize property determines the value which is set on Sprites. For more information on PixelSize, see the .
EmissionSettings stores information about how individual Sprite particles will behave after they are created by an Emitter. Each contains an EmissionSettings instance which controls how particles emit.
Did this article leave any questions unanswered? Post any question in our for a rapid response.
The AdjustPositionForPixelPerfectDrawing method tells the FlatRedBall Engine to attempt to offset Text objects so that they do not render in-between pixels. This value defaults to true, and in most cases you do not need to adjust it.
AdjustPositionForPixelPerfectDrawing should be turned off if FlatRedBall is not properly adjusting your Text objects to be pixel perfect. One common scenario for this is if a Text object is on a camera other than the default Camera.
The following assumes that "TextInstance" is a valid Text object:
For information on using FlatRedBall with render targets, see .
The Text class implements the interface. This gives the Text object lots of flexibility in controlling how it will appear.
For information that is general to all , see the
By default the Text class has the following properties:
Property | Value |
---|
Notice that the is "ColorTextureAlpha". This means that the Texture will control the transparency (of course, also considering the Text's Alpha property), but the color is controlled purely by the Red, Green, and Blue properties.
This can be easily changed, of course. If you want to set the color of your text from its source texture (as might be the case when doing outlined text), consider changing the to Texture or Modulate depending on the effect you are interested in achieving.
ColorTextureAlpha |
Red | 1 (255 in FRB MDX) |
Green | 1 (255 in FRB MDX) |
Blue | 1 (255 in FRB MDX) |
The Text object provides functionality for drawing bitmap fonts in 2D and 3D space. It inherits from the PositionedObject class and shares many similarities with the Sprite class. Just as the Sprite class is associated with the SpriteManager, the Text object is associated with the TextManager. Note that most games which use Text do so through Gum instead of using the FlatRedBall Text object.
The FlatRedBall engine stores a default BitmapFont internally. Any Text object created will use this default BitmapFont. To create a Text object in code, add the following to your Screen's CustomInitialize, or Game1.cs Initialize after initializing FlatRedBall:
The Text object behaves the same as other FlatRedBall objects which have been added to their respective managers. This means that when you add a Text object, it will be drawn and updated automatically for you until it is removed.
A common mistake is to add and remove text every frame to change what it displays. Instead of doing this, you should set a text's DisplayText property to change what it says. For example:
For more information on the persistence of objects, see this article. For code example comparing the approach of creating a new text vs. setting the DisplayText, see the DisplayText page.
The DisplayText property allows for changing the string that a Text object renders. The following code sets the text depending on whether the user has a gamepad connected: Add the following include statements:
Add the following to the Initialize method after initializing FlatRedBallServices:
Text objects can be positioned just like any PositionedObject. For example, a text object's X and Y values can be set:
For more information on PositionedObject fields and properties, see the PositionedObject entry.
By default Text objects added through the FRB editor are sized to be pixel perfect given the game's resolution. The Text object provides a number of properties for changing size.
TextureScale controls the size of the text relative to its source texture. A TextureScale of 1 results in the text drawing pixel perfect if the game is running at 100% scale. If the game runs at larger scale, then Text using a fixed TextureScale will drawn larger.
The SetPixelPerfectScale function sets the text size to be pixel perfect given the argument camera or layer. The following code sets the Text to be pixel perfect to the main camera:
Note that pixel-perfect text will not appear zoomed if the game settings are zoomed.
The Text object provides three different variables for changing the size of text. These properties are:
Scale
Spacing
NewLineDistance
The following code creates three text objects which have non-default values for these three properties.
FlatRedBall.Graphics.IColorable - Properties for changing a Text's color.
IAttachable Wiki Entry - Text implements the IAttachable interface.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The MaxWidthBehavior controls how the Text object displays its DisplayText when it is longer than the MaxWidth. MaxWidthBehavior is an enumeration. Available values are:
Chop
Wrap
The default behavior is Chop.
The following code creates 2 Text objects. It assumes a 3D camera.
The NewlineDistance property sets the amount of spacing between lines on a Text object. This value is set according to the Camera/Layer settings automatically when the Text is added to managers, but it can be modified after the fact to adjust spacing.
The default setup for FlatRedBall is to be in 2D coordinates. If so, then NewlineDistance will be measured in pixels. The following code creates two Text objects and shows how to adjust their NewlineDistance:
The following code creates two Text objects and shows how to adjust their NewlineDistance. Note that this example was made with a 3D camera.
Text object are designed to work in 2D coordinates by default. Therefore, NewlineDistance will round to the nearest integer value. To change this, you can set the Texts' AdjustPositionForPixelPerfectDrawing to false. The reason this happens is because if you are dealing with Text that has multiple lines and it is going to scroll vertically (like on a credits screen), then individual lines may appear to jitter when the text scrolls. If you are using 3D text, then you most likely do not want it to be adjusted for pixel perfect drawing anyway, so setting AdjustPositionForPixelPerfectDrawing to false will both resolve this issue and potential other issues with rendering te a Text object on a 3D Camera/Layer.
The InsertNewLines method modifies the Text's DisplayText property by inserting the newline character ('\n') to prevent the text from exceeding the argument maxWidth. The maxWidth property is in absolute world units.
Add the following using statements:
Add the following to Initialize after initializing FlatRedBall:
FlatRedBall.Graphics.BitmapFont - See the BitmapFont class for determining the unit-size of your text.
SetPixelPerfectScale is a method which will adjust a Text object so that it renders pixel-perfect on the argument Camera. This method is automatically called on Text objects when added to the FlatRedBall.Graphics.TextManager. For more information on this behavior, see the AddText page. In the simplest situations this function will automatically be called for you and you won't need to do anything to have Text appear properly. For more information on when to call this function, see the next section. SetPixelPerfectScale sets the following properties on the Text instance that calls it:
You will not need to use SetPixelPerfectScale if you create a Text and do not adjust the Text object or the Camera after the Text object has been instantiated. However, you will need to call this method if any of the following modifications are made:
The Camera's Z value is changed (assuming the Camera is 3D)
The Camera's Orthogonal values are changed (assuming the Camera is Orthogonal)
The Text's Z is changed (assuming the Camera is 3D)
The Text is attached to an object with a different Z value than the Text (assuming the Camera is 3D)
The Text is added to a Layer that uses a custom coordinate system (such as 2D Layers in Glue)
Glue assumes that Text objects should be drawn pixel-perfect, so it calls SetPixelPerfectScale on Text objects after they are initialized in generated code. This means that you don't have to call SetPixelPerfectScale on Texts which are added through Glue, unless modifications are made after the generated code has executed.
The following code shows how to use SetPixelPerfectScale:
Text objects are true 3D objects - they can be scaled, rotated, and positioned in 3D space. Similarly, they are affected by their distance from the camera. If a Text object moves closer to a 3D Camera, or similarly if a 3D Camera moves closer to a Text object, it will apparently change size. This is often undesirable. Therefore, to "counter" the size change of a Text object when a 3D Camera changes its distance (often Z value), the Text's Scale, Spacing, and NewLineDistance must change. The SetPixelPerfectScale greatly simplifies this process. The following code creates 3 Text objects and sets the Camera's velocity so that it is slowly moving forward. One Text object remains unchanged while the other changes its size every frame by calling SetPixelPerfectScale. Add the following to a Screen's CustomInitialize Initialize method:
Add the following to the same Screens' CustomActivity:
The SetColor method can be used to set all 3 components of a Text's color values. The end result of calling this function is the same as setting the individual components. In other words:
is the same as:
For more information on how the Red, Green, and Blue colors impact rendering, see the IColorable page.
The MaxWidth value controls the available area that the Text object can render text inside. The Text object will either wrap or clamp text according to its MaxWidthBehavior.
The ScaleX and ScaleY properties are read-only properties in the Text class. You may be familiar with these properties through classes such as Sprite or AxisAlignedRectangle. Unlike those classes, the Text class's ScaleX and ScaleY properties are only used to read the dimensions of the Text object, not to set it. To set the size of your Text, you need to use the Scale, Spacing, and NewlineDistance properties. You can find out more about them here.
If you've read about the IScalable interface, then you're likely familiar with the concept of Scale. To help you remember, Scale is the measure from the center of an object to its edge. Another way to put it is ScaleX is half of an object's width and ScaleY is half of an object's height. In most cases, the center of an object is the same as its Position. Therefore, adding or subtracting Scale from an object's position will give you its edges. This is not the case with Text objects because of the HorizontalAlignment and VerticalAlignment properties. Therefore, to find the center of your Text object, you should use the HorizontalCenter and VerticalCenter properties.
The following code creates two Text objects. It then creates two AxisAlignedRectangles which show the bounds of the Text object using ScaleX/ScaleY and HorizontalCenter/VerticalCenter properties. Add the following include statements:
Add the following to the Initialize method after initializing FlatRedBallServices: