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...
FlatRedBall provides a built-in synchronization context enabling the use of async and await keywords while keeping logic on the primary thread. This document discusses common usage of these keywords.
For a general discussion of async and await, see the Microsoft Asynchronous Programming page. The most common FlatRedBall usage of asynchronous programming is to delay the execution of some action. For example, consider a player entity which can shoot a bullet. After shooting a bullet the player must reload. The following code could be used to implement shooting and reloading:
In this example, if the player is not reloading, pressing the space bar shoots a bullet and immediately sets the IsReloading variable to true. The remainder of the code (the line setting IsReloading back to false) will not execute until some time passes, as specified in ReloadTimeInSeconds. The example above shows how using async/await can reduce the amount of code needed to perform time-based logic. By contrast, implementing the code above without using the async
and await
keywords would require additional variables for timing.
Programmers who have performed async programming may be familiar with the Task.Delay method. For example, the following code creates a Circle, then destroy it after 3 seconds:
While the code above is functional, it does suffer from a few problems:
The removal of the circle executes after 3 seconds, even if the game is paused.
The delay of 3 seconds runs in real-world time, and does not respect slow-motion or fast-forward.
The Task is not cancelled when the Screen exits. If additional creation logic were performed after Task.Delay, this may result in objects being added to a different screen.
These limitations make sense - the Task.Delay
method doesn't know about game-specific considerations like pausing or slow motion. By contrast, the TimeManager.DelaySeconds
method can take all of these concepts into consideration. Therefore, in most cases your game should use TimeManager.DelaySeconds
instead of Task.Delay
. Of course, if you are performing logic which should run on a timer regardless of pausing or slow motion, then Task.Delay
should be used.
For more information about Screen destruction, see the next section.
FlatRedBall eliminates any FlatRedBall async calls which have yet to execute when transitioning a screen. This allows code to fire-and-forget async calls without needing to consider whether screens have switched since the last call. For example, consider the following code which adds text objects to a stacking Gum container, one each second:
This code might produce the following result:
Notice that although the code has a while(true) statement, the code does not block the execution of the normal game loop. In other words, the button still shows its hover state in response to cursor movement.
However, a loop like this would normally never end, but if we move to the next screen the loop will end. In short, code can be safely written without considering whether the screen has changed when using await calls.
All async FlatRedBall calls automatically cancel when the Screen, but if you are making calls to non-FlatRedBall async calls which should cancel when the Screen is destroyed, you can use the current Screen's CancellationTokenSource.
For example, consider a situation where a sound effect is played after 1 second of actual real-world time. The following code could be used to properly handle the Screen exiting:
Culling is the process of determining that an object or a part of an object does not need to be drawn, then skipping the drawing logic because of this determination. This is an effective way to improve performance if the process of detecting whether an object should be drawn is significantly faster than just performing the drawing itself, or if it is slightly faster but most objects will fail the draw test.
Some types of culling are performed at the hardware level. XNA and MDX have some options which allow you to cull objects depending on their position or orientation.
Other types of culling are performed at the engine level. FlatRedBall by default culls Sprites and PositionedModels which are not in view. SpriteGrids perform an even more efficient culling than draw culling. By default SpriteGrids remove Sprites which are not in view from the engine's memory. This not only saves draw time, but also management time and memory usage.
FlatRedBall automatically culls the "back faces" of models by setting the RenderState's CullMode to CullMode.CullCounterClockwiseFace. This eliminates the drawing of back-facign polygons which are part of PositionedModels. In some cases this can double rendering speed.
This behavior happens automatically and requires no special implementation or management.
FlatRedBall uses the depth buffer (also known as the Z-buffer) to both create realistic-looking sorting as well as to improve performance.
The depth buffer is used in the following cases:
When drawing PositionedModels.
When drawing Z Buffered Sprites.
Depth buffered culling is performed on a per-pixel basis. If a depth buffer check fails, then the renderer does not need to perform the pixel shader code for that pixel.
PositionedModels automatically perform depth buffer culling so there is no need for any special implementation or management. Sprites perform depth buffer culling if added as Z Buffered Sprites.
Manually updated objects are objects which are removed from the FlatRedBall engine's automatic managed lists. In other words, manually updated objects will not have behavior such as velocity or attachments automatically applied. The following set of articles discuss what automatic vs. manual udpates are and why they are important for performance.
Bouncing collision is a common behavior which has been implemented in the earliest of games including the ball bouncing off paddles and walls in Pong, the ball bouncing off of blocks in Breakout, and the fireballs bouncing off of terrain in Super Mario Bros. http://www.ordiworld.com/jargon/fig/pong.gif http://www.consoleclassix.com/info_img/Breakout_2600_ScreenShot2.jpg http://img67.photobucket.com/albums/v205/LBoogie82583/Screenshots/SMB1.jpg While this behavior appeared early in video games it can present some challenges. Collision jitter is one of these challenges which often appears when first implementing bouncing collision behavior. This article discusses what collision jitter is and common solutions.
The first step to understanding collision jitter is to understand bouncing collision code. I will use a simple ball vs. axis aligned rectangle example and ignore the possibility of the ball hitting the corners. I will assume that I have a method which returns the side on which the collision has occurred.
This code seems like it should work but it is possible that it will result in collision jitter especially if the game is not running at a fixed frame rate.
The most obvious solution to collision jitter is to have a constant frame rate. While the default FlatRedBall XNA template does provide a constant frame rate which reduces the likelihood that this will occur, it is not a 100% solution. Due to floating point inaccuracies it is still possible to trigger a collision.
The CLR Profier was a common way to measure memory usage for games. It is no longer maintained by Microsoft and now memory profiling is performed through Visual Studio. This document is kept here for older games which may still benefit from its usage if they are still on .NET Framework 4.X.
The CLR Profiler (CLR meaning Common Language Runtime) is a program created by Microsoft which gives detailed information about memory allocation and method calls. It is an invaluable tool for identifying areas of code which allocate too much memory. The CLR Profiler can give you information about where your project is allocating memory, which is the first step in cleaning up the allocation. Memory allocation can cause performance problems because the allocation increases the frequency in which the garbage collector runs. The best way to prevent the garbage collector from running (or to reduce its impact) is to reduce memory allocations. Fewer allocations means that ram needs to be "cleaned" less frequently, so the user will not experience as many pops in frame rate as the garbage collector freezes execution.
Visual Studio 2015 and later includes a built-in profiler which can help you diagnose performance and memory problems. To measure memory allocations in Visual Studio, the profiler can take snapshots of the heap which can be compared to see what allocation is happening in a call. While this is useful if you suspect that a particular call is allocating memory, snapshots are not as useful when measuring memory allocation across multiple frames in a game. Therefore, even though the CLR Profiler is no longer maintained at the time of this writing, it is still a very valuable tool for improving your game's performance, and it can provide more insight into allocations compared to the Visual Studio memory profiler.
The allocation of memory itself isn't necessarily the problem. The problem is the clean-up (called garbage collection) that is triggered due to allocations. The .NET framework provides extremely fast memory allocation due to the way it eliminates memory fragmentation. However, the clean-up of unused objects is another story. During the time of garbage collection (at least as of the .NET Framework 3.5) the program execution must stop. Garbage collection can take enough time that your game will experience a noticeable stop in execution. This "pop" can disrupt game play and appear annoying to the user. Since suppressing the garbage collector is not an option, the solution is to eliminate or reduce memory allocation. Less memory allocation means less frequent cleanup by the garbage collector. Memory can be reduced enough that the garbage collector can run very infrequently. This, coupled with intelligent forced garbage collections by Screens can essentially eliminate pops in frame rate.
To install the CLR Profiler:
Download CLRProfiler45Binaries at: https://github.com/MicrosoftArchive/clrprofiler/releases
Unzip the CLRProfiler45Binaries.zip file
It is recommended that you leave the default unzip folder c:\CLRProfiler
Open the 64 or 32 folders depending on whether your application is 64 or 32 bit. At the time of this writing all FRB apps default to 32 bit.
Double-click CLRProfiler.exe to run the CLR Profiler.
If you get a "Waiting for application to start common language runtime" message in Vista, try running the CLR Profiler as an administrator.
One of the best ways to test out the CLR Profiler is to use it on an application that you have written. That makes the results a little easier to understand because you can compare the CLR Profiler's log to the code that you've written. To create a sample program, create a new project using a FlatRedBall template, then add the following code: Add the following at class scope:
Add the following to Update:
The CLR Profiler can now be used to test the application that you've created. To test the application:
Open the CLR Profiler.
Make sure Calls is unchecked (we'll only look at memory allocations in this tutorial)
Make sure Allocations is checked. This must be checked before the program starts (it seems to be a bug)
Optionally - uncheck Profiling active, so you can check it later exactly when you want profiling to start
Click Start Desktop App...
Navigate to the folder where your .exe was built.
Select your .exe and click the "Open" button. If Profiling active is checked profiling will begin immediately. Otherwise, navigate to where you want the profiling to start, then check Profiling active.
Let your application run for a few seconds or minutes. The longer it runs the more allocations you'll have. It's good to let the application run for a while because the initialization of the engine causes some allocations to happen, and running for too short of a time period will result in the initialization being the majority of your allocations.
Once you're finished, simply close your application, or click the "Kill application" button.
Once the application ends, the CLR Profiler will generate a log. A window will appear which provides access to the information in the log.
Cache off the Texture2D for "redball.bmp" and use that as an argument instead of calling Load.
Try calling AddParticleSprite instead of AddSprite.
Try creating your own pool of Sprites which you add and remove from the SpriteManager.
You can find more performance-enhancing solutions in the Performance Tutorials section.
Sometimes the CLR Profiler is a little tricky to get running. If you're having problems with the CLR profiler, try the following:
Copy the CLR Profiler binary files (exes and dlls) to the location where your game's EXE is located and then try running the CLR Profiler
Right-click on each .dll and each .pdb used by the CLR Profiler, select "Properties", then click the "Unblock" button
Run the CLR Profiler as administrator
Turn Memory Allocations on, but turn profiling off, then turn profiling back on when the app is running.
The default FlatRedBall camera presents a 3D view - the further an object is from the camera the smaller it appears. However, the camera looks down the Z axis and its default settings assume that this is the view for performance reasons. The camera can be modified so that it doesn't have to view down the Z axis.
The following code creates sets the camera to look down the Y axis rather than Z axis. It is common in 3D applications using FlatRedBall to have the ground lie on the XY axis and Z be height. Add the following in Initialize after initializing FlatRedBall:
FlatRedBall can be added to any MonoGame/XNA project with only three lines of code. This tutorial describes the process of adding FlatRedBall to a project created from a MonoGame/XNA template.
First we'll download the FlatRedBall .dll files. Note that FlatRedBall provides different files depending on the platform you are targeting.
Go to the prebuilt file location.
Select your platform
Select Debug or Release. You may want to start with Debug, then grab the release .dlls when you are ready to test your game for release.
Download the .dll for FlatRedBall, and the associated .pdb file if you would like additional debugging information.
Note that the folder will include other files, which may be needed if you would like to add FlatRedBall.Forms to your project. However if you are interested in only the core FlatRedBall functionality, you will only need the single .dll.
Most FlatRedBall platforms only require a single - the engine .dll. Add this file to your existing game project's references.
Open your project in Visual Studio
Expand the game project in the Solution Explorer
Right-click on the References item
Select Add Reference...
Select the Browse category
Click the Browse... button
Navigate to where you have downloaded the .dll in the previous steps and select it to add it to your project.
Now that your project is referencing FlatRedBall, add the following code: In Game1.Initialize:
In Game1.Update:
In Game1.Draw:
The default template includes code for clearing the screen in the Draw method. FlatRedBall automatically clears the screen for you, so having the call outside of FlatRedBall is redundant. You can choose if you want FlatRedBall to clear the screen, or if you want your own code to clear the screen.
FlatRedBall automatically clears the screen, so you can remove any code that performs clearing for you, such as:
If you want to clear the screen in your own code, you can tell FlatRedBall to not clear the screen by setting the main camera's background color to transparent:
WPF controls can be added to any FlatRedBall PC game. This walkthrough shows how to add a floating control which will both display runtime information and also be used to add new entity instances.
This tutorial uses a Glue project named "FrbAndWpf" as the starting point. This Glue project will contain the following:
An entity called "CircleEntity"
CircleEntity will contain a single Circle named CircleInstance
A screen called GameScreen
GameScreen will contain a PositionedObjectList of CircleEntities named CircleEntityList
By default the game will not display anything since the CircleEntityList will be empty.
Before adding any code or XAML to the project you'll need to add a few library references. To do this:
Open your project in Visual Studio
Right-click on "References" under your project
Select "Add Reference..."
In the dialog that appears select the "Assemblies" option
Check the following assemblies:
PresentationCore
PresentationFramework
System.Xaml
Click OK
To create a window:
Right-click on your project
Select "Add" -> "New Folder"
Name the folder "Wpf"
Right-click on the newly-created folder
Select "Add" -> "New Item..."
Select "User Control (WPF)"
Enter the name "DiagnosticWindow"
Click "Add"
For this tutorial we actually want DiagnosticWindow to be a Window and not a UserControl. We can change this by opening up the XAML for this and changing "UserControl" to "Window". The XAML should look like this:
The inheritance code in the codebehind needs to be modified to inherit Window as well. Modify the codebehind to look like this:
Now that we have a Window called DiagnosticWindow we can instantiate and show it in Game1.cs. To do this:
Open Game1.cs in Visual Studio
Find the Initialize method
Modify the Initialize function to instantiate and show the DiagnosticWindow so it looks like:
Also the use of WPF requires that the Main function has the STAThread attribute. To add this:
Open Program.cs
Add the STAThread to the Main method so it looks like:
The DiagnosticWindow will have two elements:
A Label that will display how many PositionedObjects are in the engine
A button used to create entities
Modify the DiagnosticWindow XAML so it is as follows:
Note: WPF is typically implemented with binding and MVVM. For brevity we won't use these patterns in this tutorial, but you should consider doing so as you expand your FRB/WPF application.
Of course you'll need to add a Button_Click event to the DiagnosticWindow codebehind:
First we'll add logic for the button to be able to create entities when clicked. First we'll tell Glue to create a factory for us:
Switch to Glue
Select CreatedByOtherEntities to True
Next we'll use the factory to instantiate a CircleEntity whenever the button is clicked. To do this:
Switch to Visual Studio
Navigate to the Button_Click method in the DiagnosticWindow
Modify Button_Click so it looks like:
For a more complicated game we might update the label on a timer, or by using a view model. In this case we'll simply update the label whenever the user clicks the button. We can do this by modifying the Button_Click method so it looks like:
Now clicking the button will instantiate an Entity and update the label to show how many objects are in the engine:
For information on this problem, see this post.
This tutorial showed how to add a WPF window to an existing FlatRedBall (Glue) project. It shows how to both display information as well as drive behavior using the UI. Of course, it implements the bare minimum for a working example but WPF can be added to games to create very powerful diagnostics and behavior.
Enums are a very common type of object used in dictionaries. Unfortunately there is a hidden behavior in dictionaries that use enums as their keys which can cause performance problems - usually resulting from memory allocation.
Consider the following simple example:
The easiest way to fix this problem is to simply use ints and cast your enums as follows:
This will completely eliminate any allocation that will occur in your ContainsKey call.
Windows RT supports a custom cursor. This article discusses how to modify the cursor to use custom visuals.
This project assumes a working Windows RT project. It also assumes that the cursor is visible. For more information on making the cursor visible, see .
Unfortunately to create a resource to hold the Cursor graphic you must create a C++ project. Don't worry, we won't do any C++ programming, but Visual Studio requires this project to create the proper resource files. To do this:
Open your project in Visual Studio
Right-click on the solution
Select Add->"New Project"
On the left select the category "Visual C++"->"Store Apps"->"Windows Apps"
Select the "DLL (Windows)" project type
Enter the name "ProjectForCursor"
Click OK
Next we'll add a resource file to contain our cursor resource. To do this:
Right-click on the newly-created project (ProjectForCursor)
Select Add->"Resource..."
Select "Cursor" when the popup appears and click "New"
First we need to build the C++ project to create the compiled resource file. To do this:
Right-click on the ProjectForCursor project
Select "Build"
Navigate to the build folder, which should be
Look for a .res file (mine was ProjectForCursor1.res)
We will now add this file to our game project. To do this:
Right click on the game project and select Add->"Existing Item..."
Navigate to the .res file mentioned above and select it. Notice that the file will be copied unless you explicitly select to link it.
Select File->"Save All" to save the addition of the resource file to the project
We must now modify the Visual Studio (C#) project by-hand. To do this:
Navigate to your game project's .csproj file
Open it in a text editor
Find the first PropertyGroup tab, which might appear as follows:
And add the Win32Resource tag inside of the PropertyGroup as follows:
Once finished save the file in the text editor.
Finally we can set the cursor in code. Unfortunately this must be done after the Game's Initialize method is called. We can do this in Update, but we only need to do it once so we will create a bool to keep track of whether the cursor has been set. First, add this bool outside of any function in Game1.cs:
Next, modify Game1.Update so it has the following code:
Windows Desktop games can display custom cursors. The default XNA window is a Windows Forms window, so customization of the cursor visuals is done the same as for any other Windows Forms app.
MonoGame 3.6 and newer introduces a method for changing the Windows cursor. The cursor can be set from a Texture2D. Assuming CursorTexture is a valid Texture2D:
For more information, see the following links:
The following code loads a .cur file and sets the window's default cursor:
.cur files have a 32x32 pixel size limit. This can be bypassed by loading a .png into a Bitmap object, then using that object to construct a Cursor, as shown in the following code:
So you're working on a FlatRedBall game and you're having performance problems? Don't worry, it happens to almost everyone. Performance issues can happen at any point throughout the development process. Fortunately, many methods exist for diagnosing. If you're having any problems with performance, or if you'd like to take some preventative measures in making sure your game runs quickly, then this is a great place to start.
The first step in solving performance problems is to identify which type of performance problem you're having. Let's look at the most common:
My game takes a long time to load
My game runs smoothly, but then seems to freeze or drop frames every once in a while
My game constantly runs slowly in a particular situation (such as in a particular level, or when lots of enemies are on screen)
Let's look at each one individually and explain what may be happening:
If your game takes a long time to load, it may be one of the following:
If your game takes a long time to load before anything shows on-screen, then it may be related to how much content is in your Global Content Files. <under construction>
If your game loads fine initially, but it takes a long time to transition between screens then your screen may suffer from either long load times or a long CustomInitialize function. For more information, see .
If your game seems to run slow, but the slowdown is no consistent then it is likely that you are experiencing slowdown from the garbage collector. Visual Studio offers a tool for measuring memory allocation. For more information, see the Visual Studio documentation for analyzing memory usage: https://learn.microsoft.com/en-us/visualstudio/profiling/dotnet-alloc-tool?view=vs-2022
If your game is constantly running slowly, the reason may be one of the following:
Rendering (the process of displaying graphics on screen) can be a source of performance problems. If you're not familiar with rendering you may ask "Why do we differentiate between rendering and other areas of code which may slow performance?" A few reasons for this are:
Computers often have dedicated hardware for rendering.
Rendering is often "async". In other words, a particular call may begin the process of rendering, and the code flow can continue while the rendering happens in the background. While this means that rendering can be fast, it also means that it can be difficult to measure exactly where the slowdown occurs.
Rendering is often handled internally by FlatRedBall, so unless you are building against source you may not know exactly what is happening in the rendering code.
Special software exists to help diagnose rendering problems.
Rendering slowdowns can occur due to a number of problems:
Render State changes - for more information see
Fill rate/vertex count - for more information see the
This section discusses CustomActivity and its potential impact on performance. Although CustomActivity can have an impact on performance, more often than not performance problems are a result of having too many managed objects in the engine. Therefore, you should always check this first before looking at your custom code for performance problems. For information on checking the number of objects, see .
If your game runs slow because of your code, this could be code which is located in a variety of places in custom code. It may not actually be part of the CustomActivity of your screen because the slowdown could be in an entity, event handler, async method, or instruction. Therefore, finding your slowdown may not be a simple matter of adding timing code around your Screen's CustomActivity. Visual Studio offers a powerful profiler which can be used to measure where your game's slowdown occurs.
Your game may be experiencing performance problems only in a particular screen or a particular situation. Therefore, you will want to have your game in the "slow" state before beginning profiling so that the profiler returns the most relevant information. Once you have this situation set up, place a breakpoint at the beginning of your Screen's CustomActivity method. Once your game hits the breakpoint, open Debug -> Windows -> Show Diagnostic Tools
Enable CPU profiling. Remove the breakpoint. Run your game. After enough time has passed, re-add the breakpoint. Once you hit this breakpoint, Visual Studio should show you which code is responsible for time spent since you started profiling.
z fighting is a term which describes an artifact which occurs when two surfaces are parallel (or near parallel) and are close enough to one another that the depth buffer resolution cannot accurately resolve overlapping. This is often seen as a striped or zig-zag pattern. Often this effect can flicker if the camera or objects are moving.
The following image shows two Sprites which are very close to each other - one blue and one white - rotated on the X axis so that they lie flat. The z fighting causes the white and blue bands.
Since z fighting occurs because there isn't enough resolution in the depth buffer to handle the proximity of the surfaces accurately, there are two solutions:
1. Increase the distance between the surfaces 2. Increase the resolution
The first option is fairly simple. For example, if the Y value of Sprite2 were changed to -3.999400f, then there is no more z fighting (at least for this particular camera setup).
Notice that this is a fairly small change of .000599f;, which is less than 0.02% (that's two-hundredths of a percent).
Increasing the resolution of the depth buffer can be done in one of two ways. One is to increase the bit depth of the z buffer. Just as a number stored as a double has more precision than a float, a 64-bit depth buffer has more resolution than a 32-bit depth buffer. Unfortunately at the time of this 64 bit depth buffers are not very common and FlatRedBall does not support this format.
The other way to increase the resolution is to reduce the near and far clip planes of the FlatRedBall Camera. In the above example, the default near and far clip planes for the Camera were used. If the far clip plane is pulled in from the default value of 1000 to 240 (to contain the Sprite extending 200 units into the distance centered 40 units away from the camera), then the necessary separation value becomes -3.999600f instead of -3.999400f. In this case it may not seem like a huge difference, but intelligently setting the far clip plane can help you avoid having to fine-tune your positions.
If you have a screen which seems to take a long time to load then this can be the cause of either long load times in generated code or a slow CustomInitialize function. The first step in fixing the problem is to identify whether it is custom or generated code.
CustomInitialize can be measured easily by using the property along with the function. For this example, let's assume a simple CustomInitialize which looks like this:
The actual contents of CustomInitialize don't really matter - this is just some sample code that we can use to show how to measure CustomInitialize time. To measure and output the time, we'll need to do 3 things:
Record the current time at the start of the function
Record the current time at the end of the function
Print out how long the initialize took by subtracting the beginning time from the end time
CustomInitialize can be modified to do this as follows:
The example above tells us how long CustomInitialize takes, but it doesn't tell us how long generated code took to execute. This is important if your CustomInitialize code is fast (like less than 1 second) but the Screen still takes a long time to load. We can ask Glue to give us more detailed information to solve this. The steps to solve this are:
Turning on detailed performance logging in Glue
Modifying your code to output load times
To do this:
Switch to glue
Select "Settings"->"Performance Settings"
Set "RecordInitializeSegments" to "True"
Click "Done"
Now Glue will generate code to measure Screen initialization time. Next we'll output this information on-screen.
To do this:
Switch to Visual Studio
Open your Screen that you want to measure the initialization times on
Go to CustomActivity (not CustomInitialize)
Add the following code in CustomActivity:
So far we've discussed how to measure where slowdowns are occurring.
Collision jitter occurs when a moving object bounces off of another object, but it is either not repositioned after the collision or the following frame is not long enough to move the moving object outside of the other object. This results in another collision the following frame which inverts the velocities so that the moving object is once again moving towards the other object. Scenario A and B show two situations in which the collision code works successfully. In scenario A the ball moves inside the rectangle, its velocity is inverted, and the following frame is long enough to move the ball back out of the rectangle. Scenario B is almost the same. The only difference is that the second frame is longer than the first frame. This is not a problem because the ball is again moved out far enough to not trigger another collision next frame. Scenario C shows how jitter occurs. The first frame moves the ball into the object and its YVelocity is inverted. Unlike scenarios A and B, the next frame happens too quickly for the ball to move out of the square (C1). This results in collision triggering the next frame which again inverts the velocity (C2). Depending on the frame times the ball may jitter for a short amount of time or it may become permanently stuck in the rectangle. Regardless this can be disruptive to gameplay and can even result in the ball passing through the rectangle.
One common solution to jitter is to reposition the moving object after collision so that there is no overlap. The code for this would be as follows:
Another solution is to invert velocity only when appropriate. Although this doesn't stop two consecutive collisions from being triggered it does prevent the jittering motion. Conceptually velocity should only be inverted if the moving object is moving into the other object. The following guarantees that the resulting velocity will move the circle out of the rectangle:
The information in the log is interesting, but the most useful information can be found in the Histograms. First, click on the first "Histogram" button - the one to the right of "Allocated bytes:". You'll see a window appear: According to the graph above, the most-allocated object by size is the Sprite class. This is expected as the example code written above was intentionally written to be heavy on allocations. We have a pretty good sense of where this allocation is happening by looking at our code...but what about the second most-allocated object? According to the graph above, it's the string object. But where is this happening? Fortunately, we can see exactly where our allocations happen.
To see where objects are being allocated , close the "Histogram by Size for Allocated Objects" window, then click the "Allocation Graph" to the right of the "Histogram" to the right of "Allocated bytes:". This will bring up a window that shows the allocation by method call. You can easily trace where your allocations are happening using this. On the very left side you should see a rectangle tyat says
This indicates that 100% of your allocations are originating from <root> which is basically the very bottom of the call stack. Since <root> is around as long as your program is running, it makes sense why it is responsible for all of the allocations in your program. The next method to the right is Main, where virtually all of my allocations were from (99.80%). You may be wondering where the other .2% went - well, you can actually find out if you increase the detail. While it might be interesting to see how the insides of how a .NET application runs, it's not very useful for profiling. In general, we're interested in knocking out the biggest allocators first, and keeping the detail to the default value of 1 helps eliminate some of the noise so we can focus on the most important calls. Scrolling to the very right shows the most allocated objects by type. The most-allocated by memory are on the top. You'll notice that just like the previous graph, the Sprite class sits at the very top, then next is System.String, then Graphics.SpriteVertex, then Graphics.VertexPositionColorTexture, and so on. What's interesting is that we can actually start to trace where these calls are coming from. If you click a rectangle, then anything that allocated it and anything that it allocates will be easily traceable because the curved lines will become a diamond pattern. You should use this graph to see exactly what methods are allocating the most memory. If a method that you didn't write is allocating memory (such as a FlatRedBall or .NET call), then you should look at the method that calls that one and see if you can reduce the number of times that the allocating method is being called
A large portion of initialization comes from the initialization of FlatRedBall. For example, FlatRedBall pre-allocates a pool of Sprites which it uses for particles. Not only can this allocation introduce noise in the results if you are focused on your every-frame execution, but since you can't impact the FlatRedBall initialization there's really no benefit to including the initialization in your report. To skip initialization, uncheck the "Profiling active" check box, then begin running your application. Once your application has started running for a second, check the "Profiling active" check box so that the CLR Profiler begins measuring. If you do this you will avoid recording the initialization allocations. Also, you'll notice that the Allocation Graph gives a much clearer picture of where your allocations are occurring. It's clear from this graph that almost all allocations (98.23%) occur from calling AddSprite. This gives you a strong direction on where allocations could be improved. In this case, there are a number of options for reducing the memory footprint. As an exercise, consider some of the following:
At this point you'll want to make sure to save your project. You can do this by build/running it, or by using the "File" -> "Save All" menu item. Running the game shows the WPF window next to the FRB window:
If you run the game now and click the button you'll see that you can create entities:
While that may seem like code that shouldn't case problems, unfortunately under the hood .NET casts the enum to an object to perform the equality check. This cast takes far more time than an integer comparison, and it also creates garbage, which can be fatal on the Xbox 360. If you'd like to read more, check .
Visual Studio creates a .cur file which contains the visuals for a cursor. This can be edited in many image editors. Users of Paint.NET can install a plugin to edit .cur files .
Number of objects in the engine. This one is fairly easy to diagnose. We can find out if the problem is related to the number of objects in your engine simply by asking the engine to tell us how many objects it is managing. To identify if this is the problem, you should start with teh Profiling tab in the FlatRedBall Editor. For more information, see the page.
Complicated logic in Custom code. This means that your CustomActivity code is causing problems. It could be in your Screen or it could be in your entities. For information on detecting and fixing complicated logic in custom code, see
Rendering issues. This means that you have too many graphical objects on screen. This is possible, however it is not as common of a problem as the first two, so you should look here only after you have eliminated the first two options. For information on detecting and fixing complicated logic in custom code, see
Your game should now output information about initialization time: Notice that this output method uses exponential notation for very small values. For example in the image above GameScreenPooled PostInitialize took "4E-07". This is the equivalent of 4 * 10^(-7), or in other words 0.0000004. Typically if you see exponential notation you are dealing with time values which are so small that they will not have much if any of an impact on performance, so they can be treated as if they're 0. If the output from ToStringVerbose is too large to view on screen you can also output this to the Visual Studio output window as follows:
If the slowdown is in CustomLoadStaticContent or LoadStaticContent (notice the name of your screen will be prefixed), then you can solve the problem either by loading less content or by using a loading screen. For more information on using loading screens, see .
Particles may require a large number of FlatRedBall Sprite instances. This guide shows how to create an incredibly efficient particle system using manual particle sprites.
Manual sprites are sprites which the engine does not automatically update every frame. Manual sprites are an efficient alternative to automatically-updates sprites (the default) if:
The sprite does not change often (such as a static background object)
The sprite changes frequently, but only uses a subset of variables that change every frame
The term "particle sprite" implies it is used for particle effects, but technically a particle sprite is pooled - supporting rapid addition and removal without any memory allocation.
The following code is written in a screen which has access to a Texture2D called Texture. Notice that it creates sprites very quickly (60 per second), and even at large numbers the game will run at a reasonable speed:
Automatic updates can take a significant amount of time every frame if your game includes a large number of automatically updated objects. The first step in improving the performance of your game is measure the number of objects your game contains. This article will discuss how to do this.
This article assumes that you already have a working project in FlatRedBall - preferably one with a variety of automatically updated objects (Sprites, Shapes, Entities, Text objects, etc).
The FlatRedBall Engine includes a class called Debugger which can help you debug and diagnose problems in your project. In this case we'll be using a function called WriteAutomaticallyUpdatedObjectInformation. This method will print the number of managed objects to the screen in real time. It's a very simple method to use which provides a lot of useful information. To use it:
Open your project in Visual Studio
Navigate to your Game class (which is by default called Game1 in Game1.cs)
Navigate to the Update method
Add the following code *after* FlatRedBallServices.Update:
Run your game
Now you should see information about the objects that are present in your game. The top-left of your screen may look similar to:
The information printed out gives you an idea of what the engine is spending its time updating. In the picture above you can see that the game has a total of 50 automatically updated objects. The lines show the breakdown - the majority of the objects are Sprites, then PositionedObjects (which are usually Entities if using Glue) make up the second largest category.
This question can be difficult to answer. The short answer is "it depends". Here are some considerations to keep in mind when working on a game:
Numbers greater than 1000 are usually bad.
Games with fewer than 100 are unlikely to have performance problems from managed objects.
Platforms without as much processing power (such as mobile platforms) can have performance problems with as few as 500 managed objects.
Fewer objects is always better on mobile platforms even if no performance problems are visible. Fewer objects means less processing needed per-frame, which means your game won't run down batteries as quickly.
For the most part the cost of each type of object is equal. In other words, managing one Text takes just as much time as managing one Sprite. Therefore, when looking to improve the performance of your game, you likely want to tackle the largest number first.
If you are using Glue then it's likely that a large number of your automatically updated PositionedObjects are Entities. For more information on making these manually updated, see the ConvertToManuallyUpdated page.
For information on how to improve the performance of your game if it has a large number of Sprites, see this page.
This section will walk you through identifying how many Sprites you have in your game, and how you can reduce this number to improve performance. If you haven't yet, you should first read the article about measuring all PositionedObjects. This article can be found here.
If you've used WriteAutomaticallyUpdatedObjectInformation and have identified that Sprites are causing performance issues, then the next step is to figure out where your Sprites are coming from. Of course, if your game is simple, or if your Sprites do not come from diverse sources, then you may already know where your Sprites are coming from. For example, if you have a level with a very large Scene (.scnx file) then it's likely that many of your Sprites are coming from this file. However, let's assume that you're not sure where your Sprites are coming from.
Just like in the general PositionedObject measuring tutorial, the FlatRedBall Debugger provides functions that can help us identify where our Sprites are coming from. To use this function:
Open your project in Visual Studio
Navigate to your Game class (which is by default called Game1 in Game1.cs)
Navigate to the Update method
Add the following code *after* FlatRedBallServices.Update:
Run your game
Here is an example of what output might look like:
The image shown above was taken from Baron when it was late in its development. At this point a considerable amount of optimization had already been performed. The first line tells us the total number of Sprites which are automatically updated by the engine. In this case, the engine is managing 111 Sprites. Assuming you want to reduce this number, the next step is to identify where all of your Sprites are being used. What follows are lines indicating how many Sprites are being used by which entity, or marked as Unparented if the Sprites are not associated with any entities. For example, we can see that in this screen shot 51 of the Sprites are being used in the OverworldLevel entity. This represents almost half of our updated Sprites. If we were to try to reduce the number of Sprites here, then OverworldLevel would be a good place to start.
Even if you've used FlatRedBall for a while you may not be familiar with exactly what a "manually updated" object is. The reason for this is because the option to make things manually updated exists almost exclusively for performance reasons. Technically one might want to manually update objects to achieve custom behavior as well, but generally this is not encouraged because it can lead to bugs and often this type of implementation duplicates functionality already present in automatically updated objects. In short, you can designate objects as manually updated to make your game run faster, and that's usually the only reason this is done.
To answer the question of what a manually updated object is, let's look at a very common piece of code:
If you've used FlatRedBall you probably know that the code above will create a Sprite, then start the Sprite's movement to the right at 5 units per second. As mentioned in one of the introductory tutorials, the Velocity property changes the Position property based off of elapsed time. This is done "automatically". This "automatic" application of velocity is what it means to be "automatically updated". So, then you might be guessing that something which is manually updated does not have Velocity applied to it every frame - and if so you're right! If an object is manually updated, then it means that the FlatRedBall Engine is not performing every-frame automatic updates on it.
The following is a list of properties which are applied for automatically updated objects. Not all properties apply to every automatically updated object. For example, the ScaleXVelocity property doesn't apply to Scale on the PositionedObject class because the PositionedObject class doesn't have the ScaleX or ScaleXVelocity properties. However, looking below can give you an idea of what kind of things are done for you by the engine:
So, if you have a group of objects which do not have any of the above properties then that group of objects is a good candidate for being made manually updated. That is, an object can safely be made manually updated if it doesn't have:
Movement
Color rate changes
Attachments
Scale velocities
Animations
Instructions
The answer is "it depends". It depends on how much of your game time is actually spent on updates. Converting to manually updated helps the most when your game has a large number of objects (such as Sprites or PositionedModels) which are going to be static - such as part of a level. It's common to have games which have hundreds or even thousands of such objects - most of which aren't even on screen. In these situations the engine may be spending a considerable amount of time updating these objects unnecessarily. Grabbing a reference to these objects (perhaps through some naming convention if using Scenes) and converting them to be manually updated can greatly improve performance. The process is fairly straight-forward so if you suspect that you may be experiencing update-related performance issues, give it a try. For an example of how this works in a very simple scenario, see the SpriteManager's AddManualSprite wiki entry.
PIX is a program for debugging the graphical side of DirectX applications on the desktop. Since it works with desktop executables, it cannot be used to directly debug the graphics of non-desktop platforms such as iOS or Android. Despite this limitation PIX can be used on synced FlatRedBall projects to identify performance and memory problems common to all platforms.
PIX can be found in the start menu. To debug an existing FlatRedBall app:
Select File->New Experiment
Use the "..." button to select the "Program path"
Click the "Start Experiment" button
Your program will begin running. PIX will add some information to your project to notify you that it is running:
PIX can be found in the DirectX SDK: http://www.microsoft.com/en-us/download/details.aspx?id=6812 A walkthrough of PIX can be found here: http://blogs.msdn.com/b/manders/archive/2006/12/15/a-painless-introduction-to-pix-for-windows.aspx
Note - this documentation uses the SpriteGrid class which is now obsolete. The concepts of movement still apply, but the backing SpriteGrid is not recommended.
Tile based movement is a control system common in classic RPGs like Dragon Warrior and many of the early Final Fantasy games. While it was used in some very early games, tile based movement is not as simple as free movement which can be applied as follows:
Tile based movement can be applied in a variety of ways, but the most common is using instructions. The following code creates a tile map and a keyboard-controlled which moves using tile based movement.
Add the following using statements:
Add the following code in initialize:
Add the following at class scope:
Many games require to overlap to create realistic scenes. FlatRedBall offers a number of ways to control sorting. This article will discuss and link to various methods of controlling how (and other objects) overlap.
There are a number of methods of controlling overlapping . Keep in mind that these methods are not just used for , but for as well. and also use many of the methods mentioned below. These methods are:
Setting Z value
Using the depth buffer (also known as the z buffer)
Using
Using multiple
Setting the Z value of objects is an easy way to control sorting of objects. Of course, this method is mostly used when the is in its default, unrotated state. and are, by default, created as "ordered" objects. This means that FlatRedBall sorts these objects by their Z values every frame, then draws them "back-to-front" so that objects in back are overlapped by objects in front. This method of sorting is very common and is acceptable for many games. Often if the is not , then the Z value can also be used to place objects in the distance, making them smaller due to the natural perspective of a 3D . In this case, the Z value has the dual purpose of making objects seem like they are in the distance due to on-screen size changes as well as controlling the sorting. If the is (also known as a 2D ), then the Z value won't impact the on-screen size of an object, but it will still impact its sorting. In these cases, the Z value is used purely to control sorting. It is also common when using a 3D to use very small differences in the Z value between objects to force a particular sorting. For example, if you are making a 2D platformer which has a player and grass both on the ground, you may set the player's Z to 0 and the grass to -.0001 so that they are drawn in front of the player.
If two objects have the same Z value, their sorting priority is undefined. While there technically is a method to how FlatRedBall picks the order, this order is subject to performance optimizations and can vary between different versions of the engine. The bottom line is, you should never rely on the particular sorting order that you see for two objects that have the same Z value. If you require a particular sorting order, enforce it by explicitly setting different Z values, or by using one of the other sorting methods mentioned below.
Many top-down games have objects that should overlap each other depending on their Y positions. This functionality is built-in to FlatRedBall. For more information see the .
The following diagram shows the order in which objects are drawn. Categories in the same vertical space will sort with each other (such as Depth Buffer and Coordinate Sorting) while categories which appear above will draw on top of categories below. For example, layered objects will always draw on top of unlayered objects.
Sprite appearance can be modified through a number of properties including Texture, ColorOperation, and BlendOperation. Full rendering control can be achieved by using custom shaders, applied through an IDrawableBatch. This guide covers how to render a Sprite using a custom IDrawableBatch.
Before writing any code, we’ll add a few files to our project. This requires an existing FlatRedBall project with at least one Screen.
To add a shader file:
Download this file:
Add the file to your FlatRedBall screen (such as GameScreen)
To add an Image file:
Right-click on your FlatRedBall screen's Files folder (such as GameScreen)
Select Add File -> New File
Select Texture (.png)
Both files should now be in your Screen so that we can reference them in the code below.
Next we’ll create a IDrawableBatch which will handle our rendering. To do this:
Add a new file to your project in Visual Studio
Name the file CustomShaderSprite
Replace your file with the following (you may need to change the namespace to match your project’s namespace:
To add an instance of CustomShaderSprite to your screen, modify your Screen’s code so its methods are as shown in the following code:
Running the project will result in the following being shown on screen:
Velocity, another term for movement, is an essential element of nearly all video games. Understanding how to work with velocity is one of the first steps in successfully creating video games. This tutorial will discuss how to use velocity to control the movement of your objects on screen.
Similar to movies and television, the display of video games is broken up into frames. Unlike physical movement, objects which move in video games will actually perform small "hops" from one position to the next every frame. For example, the following image shows the positions of a red ball that is moving along the X axis.
As you can tell there are distinct positions that the red ball falls on every frame. While this may appear to be jarring, when played at a high frame rate the animation appears smooth to the user.
The frame-style movement is relevant for a number of reasons, but perhaps most importantly that when an object moves it will not always touch every position along the way. That is, if an object has a positive X velocity, and it starts at 0, there is no guarantee that it will ever be positioned at 1 during a given frame. Its position may be:
Consider this code:
If our numbers above show the movement of the object frame-by-frame, then the the DoSomething() will never be called. This is because the object skips from .99 to 1.02, and it's never actually positioned at 1.0 (or any number between .99 and 1.02).
To guarantee that the code gets hit when the object moves past 1.0, the following code would work:
Since implementing velocity is nothing more than the continual changing of position over time, we can implement velocity rather easily.
In this code if your frame rate changes, then SecondDifference will automatically be different to reflect this change. The result is that your objects will move at the same apparent speed regardless of the frame rate.
As mentioned at the beginning of this article, velocity is an essential element of nearly all video games. So what kind of game engine would FlatRedBall be if it didn't provide you with support for one of the most common behaviors in game development? Surprisingly enough, there are many engines which do not even handle velocity for the user. But before this turns into a full commercial, let's get to the point.
XVelocity
YVelocity
ZVelocity
All three are also available in a Vector3:
Velocity
Either can be used, and modifying one automatically modifies the other.
or:
Keep in mind that velocity persists from frame to frame. That means that you do not need to set an object's velocity every frame. Once you set the velocity, it will remain the same - of course unless something else modifies the velocity.
Add the following to Initialize after initializing FlatRedBall:
KABOOM!
The depth buffer can be used when more complex sorting is needed. Simple sorting by Z values always results in an object being drawn in full over all objects which are behind it. It is impossible to have two objects which intersect each other draw properly without using the depth buffer. The depth buffer is automatically used on , and objects which are ordered by their Z values sort properly with objects that modify the depth buffer. can optionally modify the depth buffer as well. For information on this, see the article. The object cannot modify the depth buffer - but objects that modify the depth buffer will sort properly with . can use and modify the depth buffer depending on the state values that are set in their Draw method.
can be used to sort all types of objects. Objects on will always draw on top of objects that are not on any layers, or objects that are on lower (unless multiple are used, which we'll get to in the next section). Objects within a will use Z ordering and the depth buffer to sort, so the provides a hierarchical form of ordering. are also effective in situations where you want to override the natural sorting performed by Z position or the Depth Buffer. For example, you may want a game's HUD to always appear on top of other objects, but you may also have a game where objects move freely towards the camera (if your game is 3D, or if you are using 3D particles). In this situation, Layers can guarantee that the HUD will never be covered by any other objects. The article includes a considerable amount of information on how it can be used to perform sorting, so for more information, .
FlatRedBall supports multiple Cameras. These cameras can be used to create split-screen views, or can be overlapped to result in one drawing over another. Camera order is the highest-level form of controlling now objects sort. That is, an object on a second will always draw on top of an another object that is drawn by a first regardless of Z position, depth buffering, or layer membership. For more information on how to use multiple , see the .
This diagram can best be read bottom-up. The very bottom section (Camera 0, Unlayered) is where objects are added by default when added through managers like the or . added to the are added as world . are specific to the they are added to. To move objects to specific , call AddToLayer on the appropriate manager for the objectt to be moved.
However, there is one thing to keep in mind when implementing movement: frame time may not be constant! In some cases, it may be constant if you are . However, even if your game is running at a fixed frame rate, you should not depend on this to move your object. In other words, don't do this:
You may at some time in the future decide to turn off the fixed frame rate, or you may want to change it. If that happens you will suddenly find that your objects are moving at a different rate - and this rate may even fluctuate as you play your game. Instead, use the SecondDifference property to move your objects:
The is a class that is used for many common FlatRedBall objects such as , , and even custom types like . This object has the following members available:
Any object which is managed by one of the FlatRedBall Managers will automatically have its position be modified by its Velocity every frame using time-based movement (using the SecondDifference property). Therefore, to reproduce the above code where myObject is moving along the X axis by 5 units/second, the following code would be used:
The following code creates 30 and sets their velocities to random values. Keep in mind that the following code is placed in the Initialize method. That is, it's called only once. Even though you never explicitly touch the Sprite's positions, and even though velocity is never set again, the objects continue to move.
Property that modifies
Modified property
Notes
Velocity
Position
Acceleration
Velocity/Position
Position
If KeepTrackOfReal is true.
Position/RealVelocity
If KeepTrackOfReal is true.
RotationXVelocity/RotationYVelocity/ RotationZVelocity
RotationX/RotationY/RotationZ RotationMatrix
Drag
Velocity
RelativeVelocity
RelativePosition
RelativeAcceleration
RelativeVelocity/RelativePosition
RelativeRotationXVelocity RelativeRotationYVelocity RelativeRotationZVelocity
RelativeRotationX/RelativeRotationY/ RelativeRotationZ/ RelativeRotationMatrix
Relative values
Matching absolute values
If Parent is not null.
AnimationSpeed/CurrentChain
CurrentChainIndex/Texture/Texture coordinates
ScaleXVelocity/ScaleYVelocity
ScaleX/ScaleY
Instructions
Potentially anything
The engine calls Instructions on any IInstructable that it manages.
RedRate/GreenRate/BlueRate/ AlphaRate
Red/Green/Blue/Alpha
This tutorial will explain how to implement FRB on a windows form (also known as WinForms). There are a few noticeable differences between the normal FRB template and using FRB in a form.
The requirements for this example are:
A form with 1 panel control
A class inheriting from Microsoft.Xna.Framework.Game
PeekMessage API call.
There are currently a few known issues regarding using FRB in a windows form.
This tutorial is written for FlatRedBall XNA. It has not been tested and will probably not work with modern versions of FlatRedBall (MonoGame or FNA).
Mouse position also updates outside the form.
Method FlatRedBall.Input.Mouse.IsInGameWindow() can incorrectly return true whilst the cursor is outside the window.
The first step is to create a new Windows Forms Application project. To do this:
Open Visual Studio
Go to File->New Project...
Select "Windows Forms Application" under Visual Studio installed templates. You may need to select the "C#" category as "XNA Game Studio VERSION NUMBER" might be selected by default.
Enter a Name and press OK.
FlatRedBall needs to be added to the project. To do this:
Right-click on your project
Select Add->New Folder
Rename the new folder "Libraries"
Locate the FlatRedBall.dll file. If you downloaded the template, then it'll be located inside the .zipped template file on your computer. On Windows Vista, it's probably:
If you're not sure, you can always re-run the installer and see the folder location where it's saved.
You'll probably need to unzip the template to get access to the .dll. Remember, you'll still need the .zipped folder in the same location if you decide to make a FRB application at a later time. Remember to unzip the XNA template.
Once you've unipped the folder, navigate to its Libraries directory.
Drag the FlatRedBall.dll file from the unzipped Libraries folder into the Libraries folder in your project in the Solution Explorer.
For Intellisense support, drag the FlatRedBall.XML file into your project's Libraries folder. Right-click it and select "Exclude From Project".
Right-click on the References item under your project and select "Add Reference...".
Select the Browse tab.
Navigate to your Libraries folder.
Select FlatRedBall.dll and click OK.
Just like FlatRedBall, your project needs to reference XNA. To add the necessary references:
Right-click on your project's References item and select "Add Reference...".
Click on the .NET tab.
Scroll down and select Microsoft.Xna.Framework.
Click "OK"
Repeat the above steps to add "Microsoft.Xna.Framework.Game" to your project as well.
To implement this feature we'll need a piece of code that is familiar to those that worked with the MDX version of FRB.
We'll implement this in a new class called NativeMethods. To do this:
Right-click on your project in the Solution Explorer
Select Add->Class...
Name your class NativeMethods
Add the following code:
Add the following using statement:
Copy the following code as your class:
Next we'll create our Game class. Basically this class can be copied from the template and modified; For this example however I'll discuss all the necessary bits and pieces that we need to add to get a working application.
To create a game class:
Right-click on your project
Select Add->Class...
Name your class RenderClass
Add the code to your class as follows:
Add the following using statement:
Create the class:
Here start the differences with the normal template code. We apply a small hack to force XNA to recreate the device context. Also note that the constructor ends with the Initialize() method due to the form being the messagepump parser.
Create the following method:
Next on the list is the Initialize() method. Here as well we are applying a small hack to let XNA get into the right execution context.
Create the following method:
Next are the usual methods that you'll also find in the FRB template with one exception. The dispose() override.
Create the following methods:
Once those are pasted into your class, you can declare the game class in the form code.
Most samples on the FlatRedBall website use the redball.bmp image. If you made a new project then it likely doesn't have this file. So, be sure to add the redball.bmp graphic to the project as follows:
Navigate to this location on your computer.
Drag the redball.bmp image into your Project.
Select the redball.bmp item and press F4 to bring up the properties window.
Select the "Build Action" as "None" and the "Copy to Output Directory" to "Copy if newer".
In this application, your form is the primary window. Usually in XNA applications the Game class window is the primary window. We need to make a few modifications to the form to ensure proper execution. To do this:
Right-click on your Form1.cs item in the Solution Explorer.
Select "View Code"
Make the following modifications:
Add the following using statement:
Start off by adding the XNA Game class to the top of the form.
Add the following to class scope::
To prepare for using the game class, add the following methods to perform the messageloop for the game. These methods mimic the messagepump and only render if there are no messages in the queue for the window to handle.
Add the following methods to your Form1 Class:
Since the game code can't maintain its own disposal, an override method in the form is required to dispose the game window when the application exits. It's possible you will get an error regarding Dispose() which that it already exists. If so; delete the Dispose() from the <formname>.Designer.cs file.
Create the following method:
Normally when Visual Studio creates a form for you, the constructor will only contain a call to the components initialisation. For example, yours probably looks like:
We'll need to modify the constructor, but before we do we need to add a panel. To do so:
Double-click your Form1.cs item in the Solution Explorer. This will take you to the Design View.
Open the Toolbox and select a "Panel". This can be found under the "Containers" category or the "All Windows Forms" category.
Click and drag to draw the new Panel on your form.
Name the panel "Viewport".
Modify the constructor method:
And you are done. Press F5 and if FRB initialised the panel will now be black with the red ball in the middle.
In case you wish to resize your form, please add the following to the ResizeEnd event of the form. This enforces FRB to use the new ClientSize.
Congratulations. You just implemented FRB on a windows form.
Did this article leave any questions unanswered? Post any question in our forums for a rapid response.
Save the redball.bmp image somewhere on your computer: