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...
Links represent a one-way path to a PositionedNode. PositionedNodes store a list of links to other PositionedNodes internally. These are used by NodeNetworks to find the shortest path between two nodes.
Links are one-way to support wider functionality with pathfinding. In other words, if Node A and B link to each other, then A stores a link to B and B stores a link to A. The reason this is important is because the cost to travel from A to B may not necessarily be the same as the cost to travel from B to A. If A is on higher ground, then traveling to B may be considered easier because the trip is downhill.
The Cost member represents the difficulty in traveling the node. Cost can be based on distance, but can also be adjusted to represent terrain difficulty or other concepts related to making decisions about which path to take. Examples include:
Difficulty in crossing due to terrain
Difficulty in crossing due to risk (enemies, thieves)
Resources required to perform a particular action (if node networks are used abstractly)
The cost property is used by the NodeNetwork to find the most efficient path from one node to the next.
The NodeLinkingTo property gets or sets the PositionedNode that the Link connects to. Notice that a link only has one NodeLinkingTo. This means that links are "one way". Therefore, if two PositionedNodes need to link to each other, then each will need a Link to the other.
This section is organized just like the engine namespaces.
PositionedNodes represent locations within a NodeNetwork which can be travelled to. PositionedNodes have a position and multiple links to other nodes.
Links can be created between any two PositionedNode objects, and can be one-way or two-way. A link has an associated value, which represents the cost of traveling across that link. Once a set of PositionedNode objects have been created, linked, and then added to a NodeNetwork object, the shortest path from one node to another can be discovered.
To create a link from one node to another, call the LinkTo method. This automatically creates a two-way link between the nodes. The LinkToOneWay method creates a one-way link from the node this method is called on, to the node that is passed on the method.
The UpdateShapes method refreshes the visible layout of the NodeNetwork. This method is internally called when a NodeNetwork is first made visible. If you are making any changes to a NodeNetwork, such as by changing existing nodes or adding new ones, you need to call UpdateShapes if you would like those changes to be reflected in the visible node network.
The FlatRedBall.AI.Pathfinding namespace provides implementation of pathfinding. Pathfinding is used in determining the best path from one location to another.
The NodeNetwork class provides the facility to group together PositionedNode items, and discover the best paths between them. Currently, only the pathfinding algorithm is implemented.
PositionedNode represents a location within the NodeNetwork.
PositionedNodes are linked to each other by Link objects. Link objects represent the cost from one PositionedNode to another.
NodeNetworks are a collection of which are linked to each other using . NodeNetworks are used for pathfinding.
The following code creates a simple NodeNetwork and a Sprite. Pressing the 1, 2, 3, or 4 keys causes the Sprite to move toward a given node on the NodeNetwork.
Add the following to your screen:
Add the following in CustomInitialize:
Add the following in CustomActivity:
The .nntx file format is a standard way to define node networks; however, there is currently no built-in .nntx creating tool supported. Therefore, apps which are interested in working with nntx will need to create their own .nntx files by using the NodeNetworkSave class.
If you have an existing .nntx you can load it from-file by adding it to the FlatRedBall Editor or to Visual Studio. If you add it directly to Visual Studio, you must manually load the file:
Add the file to your project in Visual Studio
Select the .nntx file once it's in the Solution Explorer.
Press F4 or right click and select Properties
Select "None" for the Build Action.
Select "Copy if newer" for the "Copy to Output Directory".
Add the following using statement:
Add the following code to Initialize after initializing FlatRedBall:
The VisibilityGrid can be used to quickly calculate line of sight between . The VisibilityGrid is a very efficient class when dealing with a small number of squares. For example, if each IViewer has a radius smaller than 10, visibility updates can be incredibly fast. The larger the radius (in tiles), the slower performance becomes. Visibility calculations require O(n^2) operations where N is the view radius in tiles, so be careful with larger view radii.
The VisibilityGrid can contain any number of IViewers. An IViewer is an object with a position and a view radius. The VisibilityGrid uses this information to calculate what is in view. Therefore, to use a VisibilityGrid, you must create a class that implements the IViewer interface.
The following example shows how to create a simple Sprite IViewer, move it around a grid, and view the resulting visibility.
Create the IViewer class. Normally this would be an Entity, but we're going to just whip something together quickly for this example:
Add the following using statements in your Game1.cs file:
Add the following at class scope:
Add the following to Initialize after initializing FlatRedBall:
Add the following to Update:
You can modify the code above as follows: Add the following after creating the VisibilityGrid:
AddAndLinkTiledNodeWorld adds a new node at the given position, and links it to any adjacent nodes following the DirectionalType specified in the argument call, or using the default DirectionalType specified in the TileNodeNetwork's constructor.
The following code can be added to a screen to allow the user to click the mouse and add new nodes. Newly-created nodes will be connected to adjacent nodes using the DirectionType specified in the constructor (four-way).
AddAndLinkTiledNode adds a new PositionedNode at the argument X, Y index at the argument DirectionType, or using the default DirectionType specified in the constructor if one isn't specified. This method uses indexes, where 0,0 is the bottom left of the TileNodeNetwork. Each index represents one tile, so if your TileNodeNetwork has a tile size of 16, then an X value of 1 would translate to 16 pixels further to the right than an X index of 0.
The following code adds a few nodes to a TileNodeNetwork using X,Y indexes.
The following code can be used to add nodes with the cursor when the PrimaryDown value is true (left mouse button). The following code could be added to CustomActivity of a Screen which has access to a TileNodeNetwork.
The GetPath method returns a List of which can be used to get from one point to another. The GetPath method first PositionedNode will be the closest node to the startPosition argument and the last PositionedNode will be the closest node to the endPosition.
For an example on how to use GetPath, see the .
OccupyTileWorld marks the tile at the given location (in world coordinates) as occupied. Occupied tiles can have an occupier which can be checked with the GetOccupier function. Note that occupied tiles will still be considered in pathfinding.
The following code shows how to check if a tile is occupied, and if so, to move a character to the given tile. To keep the code shorter, it only considers moving in one direction.
AreSoundEffectsEnabled can be used to make the function produce no audio. This is often set by options screens so that the game code does not need to be cluttered with if-checks surrounding all audio playing.
Setting AreSoundEffectsEnabled to false will not stop any already-playing SoundEffects.
Did this article leave any questions unanswered? Post any question in our for a rapid response.
MasterSongVolume is the default value used when calling PlaySong. This value can be null if no default is used, or a value between 0 and 1 can be assigned where 1 is full volume and 0 is silent.
Setting MasterSongVolume sets the currently playing song's volume as well if any of the following are true:
The Song is a MonoGame/FNA Song which has been played through the AudioManager's PlaySong method
The Song is a MonoGame/FNA Song which has been played through the XNA MediaPlayer
The Song is an ISong (such as an NAudio_Song) and has been played thorugh the AudioManager's PlaySong method.
Setting MasterSongVolume does not affect the volume of NAudio_Song instances which have been played through the NAudio_Song's Play method. For more information, see the NAudio_Song page.
Many games which have tile maps which also require pathfinding often include different terrain types. For example, a map may include regular terrain, water, and mountains. Terrain is important because certain units may be able to travel over certain terrain faster than other terrain. The SetCosts method allows for specifying the cost of travelling over certain terrain types quickly without modifying the cost of travelling across each Link in the NodeNetwork manually.
The SetCosts method requires the following steps:
The costs of each terrain type must be defined. These are defined in a float array
Each point on the tile which is not of the default type must have its terrain type set through the PositionedNode's PropertyField variable.
The TileNodeNetwork's SetCost method must be called with the float array containing the cost of each terrain as the argument.
The following pieces of code show how a TileNodeNetwork can be set up for different terrain types. First the terrain types must be defined. Since they will be reused in multiple places we'll use an enum:
The following code assumes that tileNodeNetworkInstance is a valid TileNodeNetwork instance which has already hadd its nodes added:
The Visible property controls whether the NodeNetwork has a visible representation. The visible representation for NodeNetworks can be useful in tools and during the development of a game.
The following code shows how to make a NodeNetwork visible in code, and how to properly clean up the NodeNetwork when the containing Screen is destroyed.
Keep in mind that you do not need to set the Visible to false if you are setting a NodeNetwork's visiblity to true in the FlatRedBall Editor - generated code handls that automatically.
PlaySong plays the argument song, optionally restarting it if it is already playing. This method is automatically called if a song file is added to the FlatRedBall Editor, but it can also be explicitly called for more control over song playing.
Microsoft.Xna.Framework.Media.Song is the default class in MonoGame and FNA for playing music. PlaySong ultimately uses the MediaPlayer.Play method to play a song, so it is inherits the limitations of MediaPlayer, including being able to play only one song at a time. MonoGame's MediaPlayer also suffers from noticeable seek time on MP3s, including looping.
The PlaySong method can also receive any class which implements ISong. The most common type of ISong implementation is the NAudio song. NAudio provides additional flexibility and better seeking/looping compared to MonoGame and FNA, so it is recommended for games which require more song playing flexibility.
For more information on loading an NAudio_Song intance, see the MP3 loading page.
The PositionedSound class is used to play a sound using the 3D audio features of XACT. This means a sound can have a position and velocity, which will be translated into volume and pitch levels on all available speakers.
A PositionedSound is a combination of a Sound class and a PositionedObject. This means that all the sound playback controls of the Sound class work the same way in the PositionedSound class, and all methods available in the PositionedObject class are also available to the PositionedSound class. This opens up some great posibilities, like this example:
Then, whenever the ship fires, a simple call to shipFireSound.Play() will play the sound in the appropriate position.
To have sounds positioned correctly, the engine must know where you want the listener to be hearing the sounds from. The AudioManager exposes a SoundListener field to control this. The SoundListener is a positioned object, so it can be placed and rotated just like other objects.
For most situations, attaching the SoundListener to the default Camera will work just fine. This line of code will do just that:
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The "absolute edge" properties returns the absolute (also known as world coordinate) value of the edge of the camera's viewable area. It is one of four properties:
AbsoluteRightXEdge
AbsoluteLeftXEdge
AbsoluteTopYEdge
AbsoluteBottomYEdge
This property is similar to calling the "At" methods, such as AbsoluteRightXEdgeAt, but it assumes a Z value of 0. These properties can be more convenient than the "At" methods, especially for games which have the Camera's Orthogonal property set to true - which is the default.
The "absolute edge" values can be used to prevent the camera from viewing outside of the Camera bounds. Note that typical games use the CameraControllingEntity for camera positioning, so setting absolute edge values only applies if the camera is not controlled by a CameraControllingEntity instance.
If the Camera's Orthogonal property is set to true, then the "absolute edge" values can be set.
For example, to move the camera so that the coordinates (0,0) appear at the bottom left of the screen, the following code can be used:
The following code can be used to prevent the Camera from viewing outside of viewable bounds:
The AddLayer method allows the addition of Camera-specific Layers.
AddLayer() instantiates a new Layer and adds it to the Camera's internal list of Layers, at the end (to be drawn on top of all other contained Layers).
AddLayer(Layer layerToAdd)
adds an existing Layer instance to the calling Camera. The argument Layer should not already already be a part of any other Cameras or this method throws an exception.
The Play method can be used to play a SoundEffect, optionally specifying the volume to play at. The Play method performs the following additional logic:
It only plays the SoundEffect if AreSoundEffectsEnabled is true.
It checks if the SoundEffect has already been played this frame, preventing the same SoundEffect from playing twice in one frame. This behavior depends on the value of SoundEffectPlayingBehavior.
It increments NumberOfSoundEffectPlays which can be used to measure how many times sound effects have played.
It checks if the argument SoundEffect has been disposed (debug only) and throws an informative exception if so.
The following assumes that Explosion is a SoundEffect. This can be created by adding a .wav file to Glue.
Sounds can be played with a custom volume:
The Sound class is used to manage and play a sound cue. It can be obtained from the AudioManager using the GetSound(CueName) method.
The following methods will modify the playback of a sound:
Play() - Plays the sound, resumes the sound (if paused), or restarts the sound (if stopped).
Stop() / StopAsAuthored() - Stops playback of the sound as authored in the XACT project.
StopImmediately() - Stops playback of the sound immediately.
Pause() - Pauses playback of the sound.
Additionally, there is a Variables field within the sound object which provides easy access to any cue instance variables. For example, if the XACT project defined a "Volume" cue instance variable, then it could be accessed using the following line:
It could be set using the following line:
For more information on setting variables in an XACT project, read the XNA Creator's Club's Advanced Audio Tutorial on controlling pitch and volume with variables.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
ClearsDepthBuffer determines whether the Camera clears the depth buffer and then writes/reads the depth buffer when performing rendering. By default this value is true, and it should be true in most cases except when a camera is used to render on top of other cameras, or for debugging purposes.
The TileNodeNetwork object is a type of NodeNetwork which is designed specifically for tile-based games. Since the TileNodeNetwork object inherits from NodeNetwork, all available methods in NodeNetwork are available in TileNodeNetwork. Therefore, you should check out the NodeNetwork page for additional information and features on the TileNodeNetwork object. Normally a TileNodeNetwork is used when creating a game which uses tile maps.
For information on creating a TileNodeNetwork in the FlatRedBall Editor (this isthe most common approach), see the FlatRedBall Editor TileNodeNetwork page.
The TileNodeNetwork offers the following benefits:
Simple addition of tiles on a grid-based system using four or eight-way movement.
Quick index based ( O(1) ) tile finding
Concept of tile occupation to prevent multiple characters moving on the same tile.
The following code creates a TileNodeNetwork that is 10X10 with has a seed (bottom left tile) at 0,0. Add the following using statement:
Add the following to Initialize after initializing FlatRedBall:
The following code can be used to create a TileNodeNetwork using a loaded TMX file:
Note that the example above uses a name (PathTile) for simplicity, but you can also use properties. You simply have to convert the properties to a list of names:
The "absolute edge" methods return the edge of the visible area at a given Z. There are four such methods:
AbsoluteRightXEdgeAt
AbsoluteLeftXEdgeAt
AbsoluteTopYEdgeAt
AbsoluteBottomYEdgeAt
The absolute functions take a single argument - the Z value where the absolute values should be calculated. The reason this is necessary is because 3D cameras (by definition) use perspective. Therefore, the edge of the Camera changes as you move further away from the Camera. If you are positioning an object along the edges of the Camera, you will most likely want to use the Z of the object you are positioning as the argument to absolute functions. For an example, see the code in the section below.
The following code creates four Circles. Each one is colored differently to help identify it.
The absolute edge values can be assigned if your Camera is 2D (Orthogonal = true). For example, the following code sets the Camera's top left corner to the origin. Keep in mind that positive Y still points up.
If your Camera's Orthogonal value is set to false, then setting any of the absolute values results in an exception being thrown.
Setting any othe absolute values ultimately assigns the Camera's X and Y properties. If your Camera is attached to another object or if you are using a CameraControllingEntity, then these position changes will be undone when updates are processed.
The edge values can be used to check if on screen. For example, the following code checks if a character's point is on screen. Since visual objects are usually larger than a single pixel, an additional buffer can be added.
Note that the buffer value above may be required if your object does not have a Width property (such as if your object is an entity). If your object has a Width and Height property, like a Sprite, you can use that value as shown in the following code:
If your Camera is attached to another object, you may need to call FlatRedBall.Camera.ForceUpdateDependencies before asking the Camera for its absolute edge values. For example:
The AspectRatio of the camera is the ratio of width to height. Usually the AspectRatio will match the aspect ratio of the displayable area. For example, if the displayable area has a width of 800 pixels and a height of 600 pixels, then the aspect ratio should be 800/600, or 1.333. The AspectRatio of a Camera is used to set how wide the field of view should be. Since it is not an absolute value, but rather a ratio, changing a Camera's property will change the resulting viewable width. Of course, the actual AspectRatio value will be the same.
Note that the AspectRatio property is typically not modified in custom code. The most common way to control aspect ratio is by assigning the desird value in the FlatRedBall Editor's .
The following code adds a then modifies the AspectRatio of the default Camera. This makes the regularly-circle graphic appear stretched out. Add the following code to Initialize after initializing FlatRedBall:
To "billboard" a Sprite means to adjust its rotation so that it is always facing the Camera. Billboarded sprites are only needed for games with a 3D camera. Note that billboarded sprites typically not used for UI because UI and HUD should be handled by Gum.
Games like Doom used a billboard effect on enemies and items. Mario 64 also used a billboard effect on its trees. This effect is evident when running around billboarded Sprites.
The DrawsWorld property controls whether the camera draws objects which are not on any and objects which are on that are not Camera-specific. Usually Cameras which are used to draw things in split-screen mode should have this property be true, while Cameras which are used to overlay things such as HUDs should usually set this to false.
The following example creates a situation where two Cameras are used. In this situation, the second Camera is used to draw HUD. The second Camera will not draw the underlying Sprite: Add the following using statement:
Add the following to Initialize after initializing FlatRedBall:
The BackgroundColor property specifies what the background color will be cleared to every frame. To prevent the background from clearing every frame, set the Alpha of the BackgroundColor to 0. See more information below on this topic.
The following changes the BackgroundColor in response to user input. Add the following to your Screen's CustomActivity:
If you would like to draw to the screen before FlatRedBall draws, you can do so, but you must do the following:
Set the Camera's Color's Alpha to 0
The Camera class inherits from the class, so it can use the AttachTo function. For general information on AttachTo, see the page.
The simplest way to have the Camera follow an object is to attach the Camera to the object. However, if you do this, you will need to make sure to have the Camera's RelativeZ be a positive value so that the Camera isn't at the same Z value as the object it is attached to. For example, the following code attaches a Camera to a PlayerInstance - which is assumed to be a PositionedObject:
Attaching a Camera to another PositionedObject (like an Entity instance) is the easiest way to have the Camera follow on object; however, it is rather limited in its movement. Most modern, professional games do not attach the Camera to the player. The reason is this results in an unnatural form of movement. Rather, most modern games will do the following:
Perform smoothing in the movement - often the Camera may lag behind player actions
Looking ahead towards where the player is facing
Adjusting to prevent the "end of the world" from being seen
Scripted movement such as zooming out or moving on game events like when entering a new environment or when a boss appears
Therefore, attaching the Camera to an object is a good initial following implementation, but you should consider replacing this with a more advanced implementation as your game moves further along.
The destination values represent the bounds that the Camera will draw to relative to the top-left of the window. By default the bounds are set to fill up the entire window. Changing these values will result in the area being drawn being smaller. These values can be used to implement a split-screen view. Since the default bounds of a Camera use the full screen, the DestinationRectangle can be used to get the resolution of your game. When setting the DestinationRectangle it is recommended that you use even values for all dimensions. In other words, the Width and Height of the rectangle should be even. Odd-sized DestinationRectangles can make pixel-perfect text render improperly.
The following code shows how changing the destination values impacts drawing. Notice that the background color of the Camera has been set to blue so that its drawn area can easily be identified.
The DrawsShapes property can be used to control whether the Camera will render any shapes (such as and ). This is on by default, and can be turned off to hide all shape rendering.
Shapes are often used for collision, and their visible representation can be useful in debugging. Shapes can be easily turned off for non-debug builds as follows:
The DrawsToScreen property controls whether what the Camera draws is shown on screen. By default this property is true. This should be set to false if you are interested in obtaining the contents of the Camera (usually as a Texture) but you do not want these contents to be drawn to the screen. This property can also be set to false if you plan on drawing the contents to the screen manually instead of using FlatRedBall.
The following code sets DrawToScreen to false, gets the resulting render as a Texture2D, then renders this Texture2D using XNA's SpriteBatch class. Add the following at class scope:
Add the following to Initialize after initializing FlatRedBall:
Modify your Draw method so it looks like this:
The IsSpriteInView method reports whether the argument Sprite is in view given the Camera's position, the Sprite's position, and the . If the is set to CameraCullMode.None then this value will always return true. If the is set to CameraCullMode.UnrotatedDownZ then this will calculate whether the Sprite is in view or not. This function is intended to be used for culling, and it favors optimization over perfect accuracy.
The AddSpriteToBillboard tells the calling Camera to hold a reference to the argument and adjust its rotation every frame so that it faces the Camera.
Billboarding is implemented by modifying the argument Rotation values. Therefore, a billboarded cannot be rotated on its X or Y axes. In other words, billboarding overwrites RotationX and RotationY values. Changing any rotation or rotation velocity values on the X or Y will not have any impact on billboarded . Billboarded Sprites can still be rotated on the Z axis.
Both billboarding and attachments modify the rotation of . To resolve this conflict, you are responsible for deciding which should take precedence. If you'd like the attachment to be dominant, you should not make a billboarded. If, on the other hand, you still want your to be billboarded, but it should have an attachment, set the property to false. For more information, see the .
When a Camera is drawn, the first thing that is done is its DestinationRectangle is painted to the background color. If you have multiple Cameras which overlap and you'd like Cameras which are on top to not write over what's already been drawn by previous Cameras, you can set the BackgroundColor to a color that has an alpha of 0. BackgroundColor for any Cameras except the default one contained in the is transparent. You will need to change the background color if you are making a split-screen game to something no-transparent.
Turn off .
Adjusts the Camera's OrthogonalWidth (if 2D) or AspectRatio (if 3D) to match the aspect ratio of the camera's DestinationRectangle.
The GetViewport method can be used to get a reference to the current Microsoft.Xna.Framework.Graphics.Viewport with the calling Camera's properties applied.
The GetViewport method does the following:
It first grabs the GraphicsDevice's Viewport
It sets the Viewport's X, Y, Width, and Height
It returns the reference to the GraphicsDevice's Viewport
Therefore, if you call GetViewport on two different Cameras, you will have the same Viewport:
Each Camera has a list of Layers which can be used to draw objects which should only appear on one Camera. This is commonly used for HUD elements such as score and health. By default each Camera has one Layer (no code necessary to add this). Therefore, if using only one Layer, then no layer instantiation is necessary. To create additional layers, see the Camera's AddLayer method.
The following code creates two Sprites, each which represents a player. The code splits the view into two screens and adds a Text object displaying which player's view is shown on the Camera layer. Notice that only one Text appears in each camera although there are two Text objects. The bool value can be changed to compare the behavior of Camera-layered Text and regular Text.
The MaximumX, MaximumY, MinimumX, and MinimumY properties can set the minimum and maximum X and Y positional values for a given Camera. These properties can be used to create boundaries beyond which the camera cannot move. These are often used in games to keep the camera viewing the playable area and keep areas beyond the playable bounds from being viewed.
If you have a Camera which is part of an Entity then the Camera will be attached to that Entity (by default). The minimum and maximum values will prevent the Camera from moving behond the values you specify, but it will not prevent the parent Entity from moving beyond the bounds. In this situation it is advised to use your own custom min and max implementation.
The following code allows the user to move the camera with the arrow keys on the keyboard, but bounds the position of the Camera to the edges of the AxisAlignedRectangle created in the Initialize method.
Add the following to your Screen's CustomInitialize:
Add the following to Update
The ForceUpdateDependencies for the Camera performs all of the same functionality as the call, but it also does a few extra things. Specifically, it updates the mins and maxes of the camera, and recalculates its View and Project matrices. For information on ForceUpdateDependencies as it relates to in general, see the page.
If you are writing a game where you need to perform logic based off of the Camera's position or edge values, then you need to call ForceUpdateDependencies prior to asking the Camera for any of these values if the Camera is attached to another object. Games often need to know a Camera's position in custom code. Consider the following examples:
You may be developing a top-down game which shows arrows on the edge of the screen to indicate where off-screen enemy units are located. The positioning of these units requires math using the Camera's position.
The calculation of the visible in a requires up-to-date Camera position values.
Your game may be a 3D game which uses a 2D for HUD. The 2D elements in your game may be based off of the 3D position of elements in the world (this is a more complex case).
If your Camera is attached to another object, you will need to call ForceUpdateDependencies to make sure that all values are up-to-date.
The order of calls matters in your game. The following code gives an example of how you would want to structure your Screen's CustomActivity if you plan on using the Camera's positioning:
As mentioned above, if you are translating between 3D and 2D coordiantes, you may still need to call ForceUpdateDepencies even if you are only updating the Camera's position manually. The reason for this is because you may end up using the Camera's matrices for calcualting the translations, and these are only updated when the Camera's dependencies are updated. Therefore, if you are experiencing unexpected behavior when translating between 3D and 2D (or 2D and 3D), then you should try calling ForceUpdateDependencies.
OrthogonalWidth and OrthogonalHeight values control the area that a 2D camera (Orthogonal = true) can see. For more information see the .
The Orthogonal setting controls whether the camera is using a perspective or orthogonal view. The following describes some differences between the two modes:
When the camera is in Orthogonal mode, the Z value of objects impacts drawing order. Objects with a larger Z value will be drawn in front of objects with a smaller Z value. Also, objects may disappear if they are moved too far away from the camera or if the objects have a Z value large enough to be placed behind the Camera. This is affected by the rotation of the camera. Camera Orthogonal can be set through the FlatRedBall Editor's Camera settings. For more information, see the .
By default the 2D camera in FlatRedBall will make objects such as sprites appear the same size on screen as the source texture. For example, the following screenshot shows the FlatRedBall icon (which is 85x88 pixels) drawn in a project with a default 2D camera:
Setting Camera.Main.Orthogonal = false results in the camera being 3D, drastically changing the size of the icon on screen:
This occurs because the size of the object now depends both on its Width and Height values, as well as the Z value of the camera. By default, the main camera has a Z value of 40. This can be changed in code. Increasing the Z value makes the camera move "backward", which allows it to see more of the sprite.
A 3D camera can be positioned so that objects at Z=0 appear the same size as on a 2D camera using GetZDistanceForPixelPerfect .
The Camera is a therefore it has a Position variable which works the same as the . The default position for Cameras is:
Projects which have been created with the Wizard will have a CameraControllingEntity instance in the GameScreen. This instance automatically adjusts the position of the camera according to its own settings.
The default (unrotated Camera) looks down the Z axis. This means that if you want the center of the screen to be at a certain coordinate, you simply need to set the Camera's X and Y value.
By default a TileMap's top-left corner will be positioned at X=0, Y=0. By default, the camera is centered at X=0, Y=0, so the top left of the map will appear in the center of the screen. For example, the following image shows how a level will appear in Tiled and in game:
One way to solve this problem is to change the Camera's X and Y values to be at the center of the tilemap. This can be adjusted by using the dimensions of the map, or arbitrarily by adding some constant value to the X and subtracting some value from the Y. For example, the following code will center on the map:
Now the Camera will be centered on the map as shown in the following image:
The RelativeXEdgeAt and RelativeYEdgeAt methods can provide the distance in world coordinates from the center of the screen to the edge of the screen at a given Z position.
If your game is using a 3D camera, then objects in the game world are viewed with a 3D perspective. The result of having a perspective view is that objects which are far from the camera will appear smaller than objects which are close to the camera. The amount that is visible in the world is controlled by the Camera's property: Notice that the further away an object is from the camera (the further to the right on the picture above) the smaller portion of the visible area it will take. In other words,observe the redball Sprite in the image above. You'll notice that it takes up very little space relative to the view height (the distance between the top and the bottom lines). But what happens if the Sprite comes closer to the Camera? At this point the Sprite is so close that it touches the top and the bottom of the view boundaries. In other words, this would result in the Sprite being as large as the entire screen. It's important to notice that in world coordinates the Sprite actually didn't change size. Instead, it just changed how close it was to the Camera, making it appear larger. We can then apply this knowledge to draw another conclusion. When far away, the Sprite was very small. So small that we could have stacked numerous Sprites on top of each other. Let's say that the Sprite has a ScaleY of 1, meaning it is 2 units tall. If we were able to stack 5 Sprites on top of each other at the original distance, then we'd be able to approximate the view height to about 10 units:
But at a closer distance to the Camera, we can only fit one Sprite. That means that in the second image, the horizontal view height is only 2 units. This relationship of having a smaller view height (and width) holds linearly. That means that at two times the distance, the view height and width double. At half the distance the view height and width are also cut in half. To take it to the limits, that also means that at an infinite number of units away, the view is also infinitely wide and tall. That's not really practical, but it can help your realize that as you move far away from the Camera, more and more can be seen. The other end of the limit is at 0 units away from the Camera. At 0 units away (the point where the lines meet in our images above, the distance between the top and bottom line is 0. That means that at 0 units from the camera nothing is visible. Since RelativeXEdgeAt and RelativeYEdgeAt measure the distance from the center of the screen to the edge of the Screen (which is half of the distance from one edge to the other) then they also linearly follow this relationship. Therefore, if the Z value that you pass to these methods is further away, you will get a greater number, while if it's closer to the Camera you'll get a smaller number. Passing a Z value that is equal to the Camera's Z value will return a value of 0.
When the Camera shows a 3D view, then the minimum and maximum visible X an Y values depend on the distance away from the Camera. The following code uses the RelativeXEdgeAt and RelativeYEdgeAt to determine the distance of the edges of the screen relative to the center of the camera. These values are used to size a Sprite so it takes up the entire screen.
In general, the edges of the camera at a given Z can be found by the following code:
The Camera class has a UpVector which is used to orient the Camera so that it is always tilted a particular way. UpVectors are very common in 3D games as they can help the player feel oriented. By default, the Camera's UpVector value is set to be the unit Y vector (0,1,0). The UpVector must be changed if you want the "up" direction to change. The most common situation this is needed is if the Camera needs to rotate on the Z axis (to change its RotationZ or RelativeRotationZ).
If you are working with the Camera class and expect modifying the Camera to rotate when you change its RotationMatrix or RotationZ, you may have been surprised to see that these properties do not modify the rotation of the Camera. As mentioned above, the reason for this is because the UpVector takes priority over the Camera's RotationMatrix. The reason for this is because in 3D games, the Camera may often end up with a rather complex RotationMatrix, and in many cases the expected behavior is to keep the Camera oriented so that it is not tilted. Simply setting the UpVector allows you to always guarantee that you will have a proper up vector without having to perform complex matrix math. In other words, if FlatRedBall were to not include an UpVector on the Camera, applying this functionality could be somewhat difficult. On the other hand, eliminating the UpVector functionality is very easy:
The Camera's View property is a matrix which contains the "view" matrix commonly used when working with shaders. The View is internally calculated using the Matrix.CreateLookAt method. The View matrix is constructed using the Camera's absolute , its , and its .
The View matrix can be used when interacting with shaders. For example the following code demonstrates how to assign a BasicEffect's View using the Camera's View property:
For information on Zooming, see the .
If your game includes a CameraControllingEntityInstance, then the Camera's position will automatically be determined by this object. If you would like to manually control the Camera, you can delete the CameraControllingEntityInstance from your game. For more information on how to use the CameraControllingEntity, see the .
Changing the Z value of the Camera will make the camera move "forward" and "backward" in the world. This is a way to simulate zooming (technically "zooming" is accomplished by changing the Camera's ). This will only work on 3D cameras. To make objects appear smaller, you will want to increase the Z value of the Camera. For example:
The UpdateViewProjectionMatrix updates the View and Projection properties according to the Camera's current state. This function is automatically called on all Cameras which are a part of FlatRedBall every frame prior to the frame being rendered, but if the View and Projection properties are needed after the Camera has been updated, then UpdateViewProjectionMatrix needs to be called.
The SetLookAtRotationMatrix method can be used to orient a camera so it is facing an object. This method of setting the rotation matrix can be easier to work with than calculating a rotation matrix yourself to accomplish a look-at.
The following code can be used to have a Camera look at a moving object called myEntity. This code assumes that myEntity is a valid Entity with a Position property.
AnimationChainListSaves are the "save" object type for AnimationChainLists. AnimatiohChainListSaves can be used to create and load .achx files. For general information on common FlatRedBall types, see the FlatRedBall File Types wiki entry.
The AnimationChainListSave class is a standardized way to save an AnimationChainList. Using the AnimationChainListSave class has the following benefits:
Requires very little code to use
Resulting files are 100% compatible with the FRBDK or any other application that can load .achx files.
You can load load a AnimationChainListSave as follows:
The following code saves a .achx file named MyAnimationChainList.achx. It assumes that animationChainList is a valid AnimationChainList.
Add the following using statements:
Assumes animationChainList is a valid AnimationChainList:
Of course, you can save a loaded AnimationChainListSave:
Of course, the code above does nothing; however, you can do things to the saveInstance between the load and save calls:
In fact, you can do pretty much anything to an AnimationChainListSave instance and it will result in a valid .achx file when saving it out. This enables you to easily create tools to create and modify .achx files.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
FileAliases is used to create aliases for files. The most common use case for FileAliases is to allow systems which expect to load files with extension to be able to access files that have been loaded by the content pipeline (which have no alias).
FileAliases can be added in code generation by the FlatRedBall Editor or manually in code.
For this example, assume that a PNG has been added to the Content directory using the content pipeline. At runtime, this file would be loaded using the following code:
Assuming that MyPngFile is built using the content pipeline, then the file MyPngFile.xnb should be included in the Content folder.
Some systems, such as Tiled or Gum, may expect that PNG files are loaded with their extension so they attempt to load the file using an extension such as "Content/MyPngFile.png". We can add a file alias to FlatRedBall to enable loading the file as shown in the following code. Note that the aliases use the FilePath type, so it's important to include the relative directory which is typically the .exe's directory:
Since Gum and Tiled both route their file loading through FlatRedBall, then the alias will be used. Also, note that each ContentManager has its own FileAliases dictionary, so this code must be applied to the proper ContentManager.
The Load method is used to obtain a reference to an object which is created from a file on disk. Common examples of are Texture2D (usually from a .png file), SoundEffect (usually from a .wav file), and AnimationChainList (usually from a .achx file). The Load method caches a file when successfully loaded, and subsequent calls to the Load method will return the cached reference.
The Load method can be used to load a Texture2D from an image file.
This exception can occur if your game is attempting to load a texture that is larger than is supported on the hardware running your game. For example, at the time of this writing many Android devices support 4096x4096 textures, but phones which only support 2048x2048 are still somewhat common. If the phone does not support loading the texture due to dimensions the app will throw a System.InvalidOperationException .
The LoadFromGlobalIfExists is a static variable in the ContentManager class which controls whether FlatRedBall will search in the Global content manager for content even if a file is being loaded from a non-global content manager. The default value is true.
As explained in this tutorial the Camera's X and Y position are the center of the screen (unless the Camera is rotated). Therefore, to keep the Camera from viewing outside of a specific area, the visible width and height must be calculated. In other words, if the Camera should not be able to see anything to the left of X = 0, then the width of the Camera needs to be calculated, and the actual minimum X becomes
The SetBordersAtZ simplifies this process by doing the calculation of cameraWidthAtSomeZ automatically, and even updating mins and maxes if the Camera moves along the Z axis. The SetBordersAtZ sets the following Camera properties:
MinimumX
MinimumY
MaximumX
MaximumY
The SetBordersAtZ calculates what the minimum and maximum values need to be set at to keep the first four argument values as the visible borders at the Z value passed (fifth argument).
The following code prevents the user from viewing behind +/- 40 on the X and Y axes. Note that bounds will be exceeded if the field of view or aspect ratio is too large for the argument values. The Keyboard moves the Camera so the bounds can be tested. Add the following using statements:
Add the following to Initialize after initializing FlatRedBall:
Add the following to Update:
Orthogonal | Perspective (non-Orthogonal) |
Moving objects further from the camera does not change their visible size | Moving objects further from the camera makes them appear smaller |
Moving the Camera forward and backward does not create a "zoom" effect | Moving the Camera forward and backward does create a "zoom" effect |
ContentLoadBatch is designed to make loading multiple assets more simple. It does this by allowing you to group together all of the resources associated with a single event (ex. all of the for a single level) to be loaded at once. ContentLoadBatch also provides a method for loading these assets in a separate thread on both the PC and Xbox360, making asynchronous loading less to worry about.
Loading and Unloading assets using ContentLoadBatch consists of four primary steps.
Add the filename of each asset to the ContentLoadBatch object.
Call the ContentLoadBatch's Load() method to load the content.
Use the object's Get method to retrieve the loaded asset.
Call ContentLoadBatch's Unload() method to unload the provided Content Manager when you are finished with the loaded assets.
The ContentLoadBatch is meant to operate in this order and will throw exceptions if you, for example, try to call Get() to retrieve an asset after calling contentLoadBatch.Unload().
Before running this example, be sure to follow the following steps to ensure the sample runs as intended.
Download this file () and then drag it into the Content section of the Solution Explorer. It's a larger version of what already exists there, so go ahead and overwrite the file that's currently in the project.
Select Frblogo.png in the Solution Explorer to view its properties. Change the Build Action to “None�, and next to Copy to Output Directory select “Copy if Newer.�
The following is an example that demonstrates how to use ContentLoadBatch for both regular and asynchronous asset loading, and demonstrates the difference between the two. Press 1 to load the logo through regular loading, and press 2 to load the logo asynchronously. Pressing 3 will simply remove the logo from the screen.
When you run this example, the result should be a blank screen with a single moving ball. Pressing 1 to load the FlatRedBall logo pauses the ball's motion while loading, and pressing 2 loads the image in a separate thread without interrupting the ball's motion.
This method works great for loading just a few assets, or for when you absolutely have to load something on the fly. However, more often than not all of the assets for a scenario will be loaded at once before the user views it. The above code could have to be repeated dozens of times to load additional textures, sounds and other assets.
The CameraSave class is a class that can store information about a which can be saved and loaded to/from disk. The CameraSave class appears in the class.
The most common use of the CameraSave class is in the class.
The following code loads a from a .scnx file and sets the default properties to match the CameraSave.
Did this article leave any questions unanswered? Post any question in our for a rapid response.
The camera uses the and properties to control the visible area.
The camera uses the property to control the visible area.
Before ContentLoadBatch, the most common way of loading assets would have been to use multiple calls to (). For example, if you wanted to simply load a and apply it in your code, you could do something like the following:
Alternatively, you can add the filenames of all assets to be loaded to a ContentLoadBatch and then load them all with one call to ContentLoadBatch.Load() or ContentLoadBatch.LoadAsync(). This allows for a more organized approach to managing content for different scenarios. All benefits of using , including content caching for previously loaded resources, are maintained as well.
Did this article leave any questions unanswered? Post any question in our for a rapid response.
The SpriteEditorScene's Camera property is a CameraSave which stores information about the FlatRedBall.Camera.
This property is by default not used when loading a .scnx file by the engine. It is primarily used to store the position of the Camera in tools like the SpriteEditor and TileEditor. However, this member can be accessed to set a Camera's properties to match what has been saved.
For information on how to use the SpriteEditorScene's Camera property, see the CameraSave page.
[subpages depth="1"]
The CommandLineWrite function can be used to append a single line to the debugger. CommandLineWrite cannot be used at the same time as Write - calling Write will clear the output, wiping out all CommandLineWrite texts. Keep in mind that any function that writes to the output may overwrite the command line buffer. Calling CommandLineWrite will append text and the text will appear on screen for subsequent frames.
A SpriteEditorScene is a "ready to save" or "just loaded" Scene. It is used to load a Scene from a .scnx file and it can be used to write .scnx files easily. The FlatRedBallServices class internally uses the SpriteEditorScene class when you use it to load Scenes.
You will not need to use the SpriteEditorScene class in most cases because you can load .scnx files through the FlatRedBallServices.Load method as shown here.
Using the SpriteEditorScene can give you additional information and control over how Scenes are created. In most cases you will want to use the FlatRedBallServices' Load method.
The following code shows how to load a .scnx file using the SpriteEditorScene instead of the FlatRedBallServices method:
Add the following using statement:
Add the following to initialize after initializing FlatRedBall:
The SpriteEditorScene.FromFile method loads and returns an instance of a SpriteEditorScene which is loaded from the argument .scnx. This SpriteEditorScene is then converted to a Scene by calling the ToScene method. The ToScene method takes a content manager name. For more information on content managers, see the FlatRedBall content manager entry.
Next, the Scene adds all of its contained objects to the appropriate managers through the AddToManagers method. Prior to calling AddToManagers all objects referenced by the Scene are stored in memory but they are not managed or drawn.
The example above which loads a .scnx into a Scene has the following compound line:
This could be broken up into:
The SpriteEditorScene is an "intermediary" type that is used to create a Scene; however there are situations where you may want to use the intermediary SpriteEditorScene in your game.
For example, consider a situation where you want to position Entities inside the SpriteEditor. Unfortunately the spriteEditor only supports the creation of .scnx files; however, you can load the .scnx into a SpriteEditorScene then instantiate Entities according to the position of Sprites in your .scnx. The following example shows what this code would look like assuming you have an Entity called Coin;
For more information on the SpriteSave class, see the SpriteSave page.
FlatRedBall provides code to save .scnx files from FlatRedBall applications. This allows the saving of .scnx files for custom scene building and debugging. Any .scnx file created with FlatRedBall will be loadable in the SpriteEditor.
To save a Scene, you must first create a SpriteEditorScene instance. You can create a SpriteEditorScene either from a Scene instance, or by manually creating the objects.
The easiest way to save a .scnx file is to first create a Scene, then use the SpriteEditorScene's static FromScene method.
For example, the following code creates and saves a .scnx file.
If you would like more control over how your .scnx is created, you can manually construct SpriteEditorScenes to be saved. To do this:
Instantiate a SpriteEditorScene
Create "Save" objects which represent FlatRedBall objects (Sprites, SpriteGrids, SpriteFrames, Texts) and set their properties and fields appropriately.
Add the "Save" objects to the SpriteEditorScene.
Save the SpriteEditorScene (which serializes it to an XML file).
The following code creates 20 Sprites and saves them to a .scnx file.
Add the following using statement:
In Initialize:
First the SpriteEditorScene instance is created. Next 20 Sprites are created. These Sprites will both appear in the application when it runs as well as saved in the SpriteEditorScene. Next, each Sprite is represented by a SpriteSave which has its properties set then is added to the SpriteEditorScene.
Once all Sprites have been created the Scene is saved to a .scnx file. Be sure to use a .scnx extension so the SpriteEditor recognizes this file as a valid scene.
The following code creates a SpriteGrid with a different Texture2D displayed by the center Sprite.
Add the following using statements:
In Initialize:
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The GetFullPerformanceInformation is a quick way to determine why your game may be experiencing poor performance. This method will not always reveal performance problems, but it's a great place to start when working on your game's performance.
This method returns a string which can be printed out to screen using the Debugger's Write. The following code can be added to your Screen's CustomActivity to see information about your game:
The Camera encapsulates functionality to simplify and control the display of a FlatRedBall application to the user. The camera controls view position, rotation, and background color. If the Camera is 3D, it can also control field of view, and viewable distance.
By default the camera in FlatRedBall looks down the negative Z axis. In other words negative Z points away from the camera. Increasing the Camera's Z moves it backwards while decreasing moves it forward. FlatRedBall uses a right handed coordinate system.
Of course, if the Camera is rotated, the forward and backward directions change. Most games can change camera properties through the . Alternatively, the Camera can be modified in code.
FlatRedBall projects automatically create a Camera which can be accessed by . The following code moves the Camera to X = 5:
For more information see the page. In most cases you will never need to create your own Camera - this one is the default camera that all single-Camera games use.
The camera inherits from the class so it shares the same interface for positioning, rotation, and attachment. Camera movement is not noticeable without something visible in the scene to compare the movement against. The following code can be added to a Screen such as an empty Screen created in the FlatRedBall Editor: Add the following using statements:
Replace CustomInitialize and CustomActivity with the following code:
FlatRedBall supports multiple cameras for different viewports (split screen). The following code creates a Sprite and views it from two different cameras. In Initialize
Every camera has a DestinationRectangle which defines where on the window it draws. When specifying the DestinationRectangle the top-left of the window is 0,0 and positive Y moves down. Assuming the window is 800 pixels wide and 600 pixels tall the following code creates a 50 pixel border around the DestinationRectangle:
Executing the code:
.scnx loaded in the SpriteEditor:
Executing the code:
.scnx loaded in the SpriteEditor:
For information about 2D coordinates and how to create 2D scenes, see the . To convert between world and pixel coordinates, see the .
For information on finding the absolute coordinates of the edges of the Camera, see the article.
For info on the see the .
For more information, see the page.
The PolygonSave class is a "save" object which corresponds to the FlatRedBall.Math.Geometry.Polygon runtime object.
For more information on the save pattern, see this page
The following code shows how to create a PolygonSave from a Polygon:
The following code shows how to create a Polygon from a PolygonSave:
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The ShapeCollectionSave class is a "save" class. Save classes are classes which allow you to load XML files to runtime objects as well as to save data contained in runtime objects to XML files. For more information on Save files, check this article.
You do not need to use the ShapeCollectionSave class in most cases since the FlatRedBallServices' Load method can load ShapeCollections. If you are simply looking to load a ShapeCollection, see this page.
You can use ShapeCollectionSave if you are making a tool that works with the .shcx file format.
You can load load a ShapeCollectionSave as follows:
Sha'eCollectionSaves can be saved through the Save method. Therefore, the process of saving an existing ShapeCollectionSave is very simple:
The more complicated process is to construct the ShapeCollectionSave. You can construct a ShapeCollectionSave by creating a ShapeCollectionSave from an existing ShapeCollection or manually (by instantiating and adding instances to it).
The following code saves a .shcxfile named MyShapeCollection.shcx. It assumes that shapeCollection is a valid .
Add the following using statements:
Assumes shapeCollection is a valid ShapeCollection:
The steps for creating a ShapeCollectionSave manually are:
Instantiate a ShapeCollectionSave
Add "save" instances to the ShapeCollectionSave (such as PolygonSave and CircleSave)
Save using the Save method.
You can convert ShapeCollectionSaves into runtime ShapeCollections: Add the following using statements:
Assumes "save" is a valid ShapeCollectionSave:
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
The FarClipPlane value determines the maximum distance from the Camera that objects will be drawn. This value is relative to the Camera. In other words, if the FarClipPlane is 1000 and the Camera's Z is 100, then the furthest the Camera will draw is -900 assuming the Camera is looking down the negative Z axis (default in FlatRedBall XNA).
The following code increases the Camera's far clip plane to 2000:
Increasing the FarClipPlane allows the Camera to see further, but it also reduces the accuracy of the Z-Buffer. The larger the distance between the Camera's NearClipPlane and FarClipPlane, the more likely Z Fighting is. Therefore, if you are experiencing Z Fighting in your game, you should consider reducing the distance between the NearClipPlane and FarClipPlane if possible. If you are not using any Z-Buffered objects in your game, then you can increase the FarClipPlane without causing any graphical problems.
The CameraCullMode property controls how the Camera culls objects such as Sprites. The process of culling is the removal of objects from rendering calls. Culling can improve your game's performance by not drawing objects which are out of view. However, culling may not be desirable if your game supports a rotated camera.
By default, CameraCullMode is set to CameraCullMode.UnrotatedDownZ, which means that the Camera will not draw objects which are outside of the calculated view of an un-rotated camera. If your game requires a rotating camera (such as a 3D game), then you may need to set CameraCullMode to None
CameraCullMode only culls objects based on their angle relative to the camera. It does not affect drawing as related to distance. For more information on distance-based culling, see the FarClipPlane page.
UnrotatedDownZ (default) - use this if your game does not support a rotated camera
None - use this if your game supports a rotated camera
Camera-based culling is performed just before rendering, which means an object can be culled in one Camera and not in another. In other words, culling will work appropriately with multiple Cameras when using split screens.
FlatRedBall XNA assumes that the current scene is being viewed directly down the negative Z axis (the default). With this assumption the engine culls out Sprites which do not fall in this visible area. The following code creates 200 Sprites which extend down the positive X axis. Because of culling only a few are visible. The camera is rotated to view into the distance. Notice that as it views to the right, sprites are not drawn.
To fix this the Camera's CameraCullMode can be changed to None:
The Debugger class provides a quick way to get real-time information in your game. It is commonly used to track down bugs which are easier to solve with real-time information, and to verify that implemented features are working as expected.
The Write method can be used to display information to the Screen. The following code example shows how to display information about the Cursor to the Screen:
Add the following to Update:
WriteAutomaticallyUpdatedObjectInformation provides information about the automatically updated objects in the FlatRedBall Engine. Including a large number of automatically updated objects can be a common performance problem in FlatRedBall games, so this method is very useful in helping you diagnose and solve these problems.
The WriteAutomaticallyUpdatedObjectInformation can be called at any point in your application. To do so, add the following line of code:
Note that if you prefer to use a different display method than the Text drawn by the Debugger, you can also call GetAutomaticallyUpdatedObjectInformation . For more information on how to use WriteAutomaticallyUpdatedObjectInformation, see .
The KeepSpriteInScreen method adjusts the absolute position of the argument Sprite so that it is fully in-view. This method makes a few assumptions:
The Camera is not rotated
The Sprite is in front of the Camera (has a smaller Z value than the Camera)
The following code creates a which is moved around the screen by the with the arrow keys. Add the following using statement:
Add the following at class scope:
Add the following to Initialize after initializing FlatRedBall:
Add the following to Update:
As of the July 2010 release of FlatRedBall, the KeepSpriteInScreen method works properly even if the argument Sprite has a parent (a common setup when using Entities).
The Layers property contains all of the specific to this Camera. Layers which belong to a camera are drawn only on this camera. Camera-speicfic layers are useful when making split-screen games which should show visuals specific to one of the screens such as a player's HUD.
Cameras will have one Layer in the Layers property by default. This can be accessed in one of two ways:
or
Notice that the first Layer in Layers is equivalent to the Layer property.
This Layer is added for convenience, but it is not automatically used unless objects are placed on this Layer explicitly. In other words, objects (such as FlatRedBall Sprites) which are added to their respective managers are drawn unlayered by default. Note that this differs from Gum, where all objects are always added to a Layer.
The PixelsPerUnit method is a method that can be used to convert between world units and screen pixels. The PixesPerUnit method can be used if pixel coordinates are desired when the 3D camera is being used.
The most common usage of PixelsPerUnit is to convert from pixels to units. In other words, the most common usage is to obtain "world units per pixel". Once the number of world units is obtained per pixel, multiplying that value can be multiplied by the desired number of pixels. To convert "pixels per unit" to "units per pixels", we simply need to take the reciprocal. If you're not familiar with this math term, taking the reciprocal of a value is the same as dividing one by the value. The code for this is as follows:
The following code example creates a and scales it to the size of the entire screen. The default resolution is 800 X 600, so scaling the to this size will make the fill up the entire screen. Add the following to Initialize after initializing FlatRedBall:
Add the PixelsToUnits method at class scope:
This example creates a row of circles, each touching end-to-end, 32 pixels apart on a 3D camera. It uses PixelsPerUnitAt to size and space the circles. The following code can be placed in a screen's CustomInitialize method:
If you are using a 3D Camera, then the FieldOfView impacts the PixelsPerUnitAt method. PixelsPerUnitAt measures the number of pixels per world unit. In other words, the formula is: PixelsPerUnit = NumberOfPixels / NumberOfWorldUnits Therefore, increasing NumberOfWorldUnits will decrease the PixelsPerUnitAt. Increasing the FieldOfView will increase the number of visible world units, but will keep the NumberOfPixels constant. Therefore, a larger FieldOfView will decrease PixelsPerUnitAt
The resolution of the game impacts the PixelsPerUnitAt value. Increasing the resolution increases the NumberOfPixels in the formula above. Therefore, if your game runs at higher resolution, then the PixelsPerUnitAt will be larger. Keep in mind that by default the FlatRedBall Camera uses the same FieldOfView. This means that if your game increases its resolution, the PixelsPerUnitAt will increase. To be more specific, the PixelsPerUnitAt uses the resolution height. Therefore, changing the width of the application will not impact the PixelsPerUnitAt, but changing the height will.
The TextRed, TextGreen, and TextBlue values control the color of the Text object used by the Debugger class. These three values range between 0 and 1, and the default value is 1,1,1 (white).
Currently the Debugger uses a single Text object for the entire "command line", meaning if you set the color, the color applies to all lines, not just the single line.
The Camera object inherits from the PositionedObject class. Therefore, it can be rotated just like any other PositionedObject. For information on using rotation values on a PositionedObject in general, see the following pages:
By default the Camera will attempt to orient itself so that "up" is the Y vector (0,1,0). For more information see the UpVector page.
The Camera can be rotated to be facing any direction. Keep in mind that many systems in FlatRedBall are designed to work in 2D, so making a game with a rotated Camera is more difficult. The following shows how to rotate the camera to simulate looking at an angle at a "floor" made up of the redball graphic. Add the following code to either Game1.cs's Initialize function, or your Screen's CustomInitialize function:
FieldOfView represents the Y angle of view from the bottom of the screen to the top. The default value for FieldOfView is:
The following diagram shows a side-view of how FieldOfView changes what is shown on screen. A smaller field of view makes the view more narrow. This narrower view results in the appearance of "zooming in". Tools such as binoculars or telescopes provide a zoomed-in view by creating a very narrow field of view. The FieldOfView property is only effective if the Camera's Orthogonal property is false (the default value).
The PositionRandomlyInView sets the Position of a PositionedObject randomly inside the view of the Camera calling the method. This can be used to quickly place one or more objects at a random position in the Camera's view and is commonly used in debugging and simple test applications.
The following code creates 100 Sprites and places them randomly in the Camera's view. All Sprites are between 20 and 60 units in front of the Camera. Add the following in Initialize after initializing FlatRedBall
The OrthogonalHeight and OrthogonalWidth values control how many units tall and wide the view of the Camera can be seen. These values apply if the camera is 2D (if the Orthogonal value is set to true). If using Glue, the default setup is for a 2D camera. Orthogonal cameras are useful for creating 2D games, or for creating menu systems which work in pixels.
By default FlatRedBall games use a 2D camera with an OrthogonalWidth of 800 and OrthogonalHeight of 600. The following diagram can help visualize this configuration:
By default, FlatRedBall games have their resolution controlled by the Display Settings in the FlatRedBall Editor.
These values can be changed by typing new values in the Width and Height boxes or by using the dropdown to change both values.
The OrthogonalHeight and OrthogonalWidth values can be used to position an object at the edge of the screen. Keep in mind that a Camera's X and Y values represent the center of the screen, so the edges of the screen can be obtained by adding or subtracting half of the OrthogonalWidth or OrthogonalHeight.
The Camera's UsePixelCoordinates method sets the calling Camera's Orthogonal property to true and adjusts the pixel coordinates to the screen's resolution. In other words, if the screen is 800X600, calling UsePixelCoordinates sets the OrthogonalWidth to 800 and the OrthogonalHeight to 600.
OrthogonalWidth and OrthogonalHeight control how much of the world can be seen. For example, consider the following game level which is 3200x3200 pixels (zoomed down to fit on screen):
If this level were viewed with a camera with OrthogonalWidth of 800 and an OrthogonalHeight of 480, the red square represents the area that might be visible at one time:
The following image shows what this might look like in a FlatRedBall game:
When using a 3D camera (Orthogonal = false) the most common way to perform a "zoom in" is to adjust the Camera's Z value. When objects move closer to the Camera in a perspective view, they become larger. This is not the case when the Camera is Orthogonal. The following code adjusts the Camera's OrthogonalHeight and OrthogonalWidth (through the FixAspectRatioYConstant method) by using the up/down keys on the keyboard. Add the following to Initialize after initializing FlatRedBall:
Add the following to your Screen's CustomActivity:
Note that the code above adjusts OrthogonalHeight, then fixes the aspect ratio keeping the Y (height) constant. This code could also be written to adjust OrthogonalWidth and call FixAspectRatioXConstant
; however it's common to have OrthogonalHeight be the dominant axis since aspect ratio can vary widely on monitors.
The UsePixelCoordinates method is an easy way to set up a traditional 2D camera. Using this method, world units can match up with pixel coordinates. Using the pixel as the unit is effective in pure 2D games where graphics are created to be drawn to-the-pixel. A camera which uses pixel coordinates is referred to as "pixel perfect". For more information on 2D games, see the article. UsePixelCoordinates is a shortcut method which does the following:
It sets to true.
It sets and to match the screen's resolution.
The following code makes the camera a pure 2D camera. A Sprite using its Texture's dimensions for its scale is added to show the resolution. Add the following to Initialize after initializing FlatRedBall:
Standard Resolution (640 X 480)
High Definition 720 (1280 X 720)
High Definition 1080 (1920 X 1080)
If you are developing a 2D game, then you may be faced with the issue of resolution on the 360. If you set your Camera to use pixel coordinates, then the size of your objects on-screen will change depending on the resolution of the game. In other words, a Sprite which takes up the entire screen in standard resolution would take up a little more than half of the screen (vertically) if the user runs the game in high definition 720. Fortunately, the UsePixelCoordinates method provides an overload for changing the coordinate dimension of the screen. This means that you can code your game the same (or very close) for all resolutions if using the overload.
The AddUnloadMethod allows you add custom logic to be executed when a ContentManager is unloaded. This is most often used to null-out static references to content contained in a particular ContentMangaer. This functionality is used heavily in Glue generated code, but it can also be used to null-out static objects in custom code.
The following code shows how to create a static Texture2D in custom code, and how to properly unload it. This code would be part of the custom code of a Screen or Entity. For this example we'll assume an Entity called Character.
When programming on Windows, you have . However, on the Xbox 360 the resolution is chosen by the user, either. Usually this is done through the switch on the video cable: Depending on the setting the user may be running the game in one of the following resolutions:
The following modifies the coordinates of the camera so that the entire redball.bmp takes up the screen. Add the following to Initialize after initializing FlatRedBall:
The IsAssetLoadedByName method returns whether a file of a given type is already loaded and stored in RAM by the given ContentManager.
The following code can be used to check if a file Background.png is loaded as a Texture2D in the current screen's content manager:
IsAssetLoadedByDetail processes the assetName parameter before checking if it has been loaded. Specifically, the following modifications are made:
If the argument is relative (such as content/background.png ), then it is converted to an absolute path (such as c:/MyGame/bin/debug/content/background.png ).
The file is standardized using the FileManager.Standardize method.
The content type is appended to the file name. This allows the same file to be loaded into multiple types.
For example, loading "content\Background.png" may result in the string "c:/folder/content/background.pngTexture2D" being stored in the ContentManager.
The SetSplitScreenViewport method is a method which can be used to set the viewport (also known as the DestinationRectangle) to a value relative to the current game window. For example, using the SplitScreenViewport.TopHalf as the argument will set the calling Camera's DestinationRectangle so that it occupies the top-half of the game window regardless of its size. Once SetSplitScreenViewport is called, the camera that called the method will automatically change its DestinationRectangle if the game window resizes. This behavior will persist until the DestinationRectangle is manually changed. By default all Cameras will have have SetSplitScreenViewport called when created using the SplitScreenViewport.FullScreen value. In other words, this means that if the game window is resized, the Camera will automatically adjust to fit the screen.
The Camera will automatically adjust according to window resizing unless the destination rectangle is manually set. This can be done by setting any of the following properties:
Calling SetSplitScreenViewport will resume the automatic destination rectangle changing behavior.
FlatRedBall supports having any number of ContentManagers living concurrently. This section will explain some situations where multiple content managers may be useful.
Multiple content managers may be used if two content managers can exist at the same time, usually for async or time-sliced loading. For example, consider a game where the user transitions from one screen to another. The content managers lay live as follows:
Content managers can also be used to provide transitions between Screens - this is typically how Loading screens operate:
Content managers can be used if you have content which has a predefined lifespan and will be removed before the current Screen is destroyed. This may look like this:
Note that deleting the object may not help much to reduce maximum memory usage - the peak will likely be hit while both content managers are alive.
If you need to load and unload individual assets, you may consider using multiple content managers. This is useful for tools. Keep in mind that if you are performing from-file content loading, you do not necessarily need to even use content managers. The ContentManager class is intended to be used as a convenient way to cache, group, and unload a collection of content, so situations where you load and unload individual files may not benefit from working with a ContentManager.
The SceneSave class is a class responsible for loading .scnx files and providing the information in a way that can be used to construct runtime objects. SceneSaves can also be used to save .scnx files easily.
SceneSave is a class that is a replacement for SpriteEditorScene. It is functionally identical, but follows the "Save" naming convention present in the rest of the engine. During this transition you can look at the SpriteEditorScene wiki page for information on how to work with SceneSave.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
UsePixelCoordinates3D adjusts the Camera's Z value so that objects at the argument Z value will render pixel-perfect. In other words, the argument Z plane will behave as if the Camera was in 2D mode. This method still keeps the Camera in 3D mode, so perspective rules still apply.
Content managers provide functionality for organizing and caching game assets. They can be thought of as a "bucket of assets". When you create an asset through the Content Manager, you give it a name (usually its file name) and decide which Content Manager it goes into. Later if the same name appears, the FlatRedBall Engine will return a reference to that asset instead of loading it from disk. Although MonoGame has a content manager class by the qualified name of Microsoft.Xna.Framework.Content.ContentManager, you do not have to ever explicitly interact with this class when using FlatRedBall. Instead, you simply work with content managers through the FlatRedBallServices class.
If you are using the FlatRedBall Editor, you may not have to directly interact with the ContentManager object. For example, if you add a .png file to the FlatRedBall Editor, it will automatically load the file in generated code using the ContentManager. However, if you would like to work with content in code, or if your game requires advanced handling of content then you may need to work with the ContentManager in custom code.
Computer memory can exist in a variety of locations: On the hard disk, in RAM, or even on the hard disks of other computers which you can access through the Internet (as you are currently doing when viewing this page). Not all types of memory can be accessed with the same speeds. Getting data through the Internet is very slow compared to data that is sitting on your local hard disk, and accessing data on the hard disk is much slower than accessing data in RAM. When the same data needs to be accessed multiple times, making a copy of it and moving it to faster memory can help improve performance. Content such as Textures and Models are copied from the hard disk to RAM to speed up future access to this memory - as well as to prevent duplicate memory in RAM.
Content managers simplify the loading of new assets as well as help organize existing assets. Content managers in FlatRedBall store references to a variety of assets. The most common type of reference held by content managers is of type Texture2D. Any FlatRedBall method which can potentially load a Texture2D works with FlatRedBall's internal content managers. Content managers are also useful for organizing data. Any data which has the same lifespan - such as textures, geometry, and sound files in a given level - should belong to the same content manager. When the level ends, simply removing that content manager unloads all memory associated with the level. Content managers make memory management and game state changes much easier.
If you have programed a FlatRedBall application which displays a texture (such as the red ball texture on a Sprite) then you have worked with content managers - although you may not realize it. Any method which takes a string file name for a Texture2D also takes a string for a content manager name. Some methods have overloads which do not require a content manager string argument, but those simply use the default "Global" content manager. You may be familiar with the SpriteManager's AddSprite method:
This method has an overload which allows the content manager to be specified. Calling the one-argument version is the same as passing "Global" as the second argument:
The Global content manager is used by default by all methods which load Texture2D's when a content manager is not explicitly supplied in the argument list. To specify a different content manager, simply provide the string of the new name - there is no need to instantiate any instances as this is all handled internally. Loading the same asset using the same content manager does not result in multiple copies of the asset in memory and the hard disk is only accessed once. The following code creates only one copy of the redball.bmp texture in memory.
While the following creates three separate copies of the redball.bmp texture and also the hard disk is accessed three times:
Or another way to look at it is:
The following code simulates the creation and destruction of 3 levels. Levels can be loaded and unloaded by pressing the 1, 2, and 3 keys. The text object which is created displays the loaded content and the Sprites themselves display the loaded Sprites.
Even if you understand the concept that content managers can be thought of as a "bucket of asset", you may be wondering which content manager to put assets in. The following lists a few conditions to help you decide.
Is your content going to live forever? You may be creating a game with a particular object (such as a Texture2D or a second Camera) that you never want to unload. If this is the case, then you may want to use the global content manager. You can use the FlatRedBallServices.GlobalContentManager property as the value passed to any method that accepts a content manager.
Are you just debugging? If you are writing code that will not ship with the final game, or if you're just testing something out, then it really doesn't matter what you use. Passing any string will create a new content manager to store the asset. Of course, creating content managers without paying attention to their names can create a buildup of assets if content managers are not cleaned up properly.
Are you creating an object which will be destroyed at some time in the future? If you are not using Screens but still want to perform your own content management (and destruction) then you should place your object in the same content manager as other objects which will be destroyed at the same time. Of course, we encourage the use of Screens as they have been created for this reason and they simplify the management of assets.
Texture caching example - Shows an example of how Content Managers cache content.
FlatRedBall.FlatRedBallServices.AddDisposable - AddDisposable can be used to add IDisposables to Content Managers.
FlatRedBall Content Manager:Multiple Content Managers - Discusses the purpose of having multiple content managers.