Farseer tutorial for the absolute beginners
Posted
by Bil Simser
on ASP.net Weblogs
See other posts from ASP.net Weblogs
or by Bil Simser
Published on Fri, 13 Apr 2012 23:38:08 GMT
Indexed on
2012/04/14
11:30 UTC
Read the original article
Hit count: 289
This post is inspired (and somewhat a direct copy) of a couple of posts Emanuele Feronato wrote back in 2009 about Box2D (his tutorial was ActionScript 3 based for Box2D, this is C# XNA for the Farseer Physics Engine).
Here’s what we’re building:
What is Farseer
The Farseer Physics Engine is a collision detection system with realistic physics responses to help you easily create simple hobby games or complex simulation systems. Farseer was built as a .NET version of Box2D (based on the Box2D.XNA port of Box2D). While the constructs and syntax has changed over the years, the principles remain the same.
This tutorial will walk you through exactly what Emanuele create for Flash but we’ll be doing it using C#, XNA and the Windows Phone platform.
The first step is to download the library from its home on CodePlex. If you have NuGet installed, you can install the library itself using the NuGet package that but we’ll also be using some code from the Samples source that can only be obtained by downloading the library.
Once you download and unpacked the zip file into a folder and open the solution, this is what you will get:
The Samples XNA WP7 project (and content) have all the demos for Farseer. There’s a wealth of info here and great examples to look at to learn. The Farseer Physics XNA WP7 project contains the core libraries that do all the work. DebugView XNA contains an XNA-ready class to let you view debug data and information in the game draw loop (which you can copy into your project or build the source and reference the assembly).
The downloaded version has to be compiled as it’s only available in source format so you can do that now if you want (open the solution file and rebuild everything). If you’re using the NuGet package you can just install that. We only need the core library and we’ll be copying in some code from the samples later.
Your first Farseer experiment
Start Visual Studio and create a new project using the Windows Phone template can call it whatever you want.
It’s time to edit Game1.cs
1 public class Game1 : Game 2 { 3 private readonly GraphicsDeviceManager _graphics; 4 private DebugViewXNA _debugView; 5 private Body _floor; 6 private SpriteBatch _spriteBatch; 7 private float _timer; 8 private World _world; 9 10 public Game1() 11 { 12 _graphics = new GraphicsDeviceManager(this) 13 { 14 PreferredBackBufferHeight = 800, 15 PreferredBackBufferWidth = 480, 16 IsFullScreen = true 17 }; 18 19 Content.RootDirectory = "Content"; 20 21 // Frame rate is 30 fps by default for Windows Phone. 22 TargetElapsedTime = TimeSpan.FromTicks(333333); 23 24 // Extend battery life under lock. 25 InactiveSleepTime = TimeSpan.FromSeconds(1); 26 } 27 28 protected override void LoadContent() 29 { 30 // Create a new SpriteBatch, which can be used to draw textures. 31 _spriteBatch = new SpriteBatch(_graphics.GraphicsDevice); 32 33 // Load our font (DebugViewXNA needs it for the DebugPanel) 34 Content.Load<SpriteFont>("font"); 35 36 // Create our World with a gravity of 10 vertical units 37 if (_world == null) 38 { 39 _world = new World(Vector2.UnitY*10); 40 } 41 else 42 { 43 _world.Clear(); 44 } 45 46 if (_debugView == null) 47 { 48 _debugView = new DebugViewXNA(_world); 49 50 // default is shape, controller, joints 51 // we just want shapes to display 52 _debugView.RemoveFlags(DebugViewFlags.Controllers); 53 _debugView.RemoveFlags(DebugViewFlags.Joint); 54 55 _debugView.LoadContent(GraphicsDevice, Content); 56 } 57 58 // Create and position our floor 59 _floor = BodyFactory.CreateRectangle( 60 _world, 61 ConvertUnits.ToSimUnits(480), 62 ConvertUnits.ToSimUnits(50), 63 10f); 64 _floor.Position = ConvertUnits.ToSimUnits(240, 775); 65 _floor.IsStatic = true; 66 _floor.Restitution = 0.2f; 67 _floor.Friction = 0.2f; 68 } 69 70 protected override void Update(GameTime gameTime) 71 { 72 // Allows the game to exit 73 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 74 Exit(); 75 76 // Create a random box every second 77 _timer += (float) gameTime.ElapsedGameTime.TotalSeconds; 78 if (_timer >= 1.0f) 79 { 80 // Reset our timer 81 _timer = 0f; 82 83 // Determine a random size for each box 84 var random = new Random(); 85 var width = random.Next(20, 100); 86 var height = random.Next(20, 100); 87 88 // Create it and store the size in the user data 89 var box = BodyFactory.CreateRectangle( 90 _world, 91 ConvertUnits.ToSimUnits(width), 92 ConvertUnits.ToSimUnits(height), 93 10f, 94 new Point(width, height)); 95 96 box.BodyType = BodyType.Dynamic; 97 box.Restitution = 0.2f; 98 box.Friction = 0.2f; 99 100 // Randomly pick a location along the top to drop it from 101 box.Position = ConvertUnits.ToSimUnits(random.Next(50, 400), 0); 102 } 103 104 // Advance all the elements in the world 105 _world.Step(Math.Min((float) gameTime.ElapsedGameTime.TotalMilliseconds*0.001f, (1f/30f))); 106 107 // Clean up any boxes that have fallen offscreen 108 foreach (var box in from box in _world.BodyList 109 let pos = ConvertUnits.ToDisplayUnits(box.Position) 110 where pos.Y > _graphics.GraphicsDevice.Viewport.Height 111 select box) 112 { 113 _world.RemoveBody(box); 114 } 115 116 base.Update(gameTime); 117 } 118 119 protected override void Draw(GameTime gameTime) 120 { 121 GraphicsDevice.Clear(Color.FromNonPremultiplied(51, 51, 51, 255)); 122 123 _spriteBatch.Begin(); 124 125 var projection = Matrix.CreateOrthographicOffCenter( 126 0f, 127 ConvertUnits.ToSimUnits(_graphics.GraphicsDevice.Viewport.Width), 128 ConvertUnits.ToSimUnits(_graphics.GraphicsDevice.Viewport.Height), 0f, 0f, 129 1f); 130 _debugView.RenderDebugData(ref projection); 131 132 _spriteBatch.End(); 133 134 base.Draw(gameTime); 135 } 136 } 137
Lines 4: Declare the debug view we’ll use for rendering (more on that later).
Lines 8: Declare _world variable of type class World. World is the main object to interact with the Farseer engine. It stores all the joints and bodies, and is responsible for stepping through the simulation.
Lines 12-17: Create the graphics device we’ll be rendering on. This is an XNA component and we’re just setting it to be the same size as the phone and toggling it to be full screen (no system tray).
Lines 34: We create a SpriteFont here by adding it to the project. It’s called “font” because that’s what the DebugView uses but you can name it whatever you want (and if you’re not using DebugView for your production app you might have several fonts).
Lines 37-44: We create the physics environment that Farseer uses to contain all the objects by specifying it here. We’re using Vector2.UnitY*10 to represent the gravity to be used in the environment. In other words, 10 units going in a downward motion.
Lines 46-56: We create the DebugViewXNA here. This is copied from the […] from the code you downloaded and provides the ability to render all entities onto the screen. In a production release you’ll be doing the rendering yourself of each object but we cheat a bit for the demo and let the DebugView do it for us. The other thing it can provide is to render out a panel of debugging information while the simulation is going on. This is useful in tracking down objects, figuring out how something works, or just keeping track of what’s in the engine.
Lines 49-67: Here we create a rigid body (Farseer only supports rigid bodies) to represent the floor that we’ll drop objects onto. We create it by using one of the Farseer factories and specifying the width and height. The ConvertUnits class is copied from the samples code as-is and lets us toggle between display units (pixels) and simulation units (usually metres). We’re creating a floor that’s 480 pixels wide and 50 pixels high (converting them to SimUnits for the engine to understand). We also position it near the bottom of the screen. Values are in metres and when specifying values they refer to the centre of the body object.
Lines 77-78: The game Update method fires 30 times a second, too fast to be creating objects this quickly. So we use a variable to track the elapsed seconds since the last update, accumulate that value, then create a new box to drop when 1 second has passed.
Lines 89-94: We create a box the same way we created our floor (coming up with a random width and height for the box).
Lines 96-101: We set the box to be Dynamic (rather than Static like the floor object) and position it somewhere along the top of the screen.
And now you created the world. Gravity does the rest and the boxes fall to the ground. Here’s the result:
Lines 105: We must update the world at every frame. We do this with the Step method which takes in the time interval. [more]
Lines 108-114: Body objects are added to the world but never automatically removed (because Farseer doesn’t know about the display world, it has no idea if an item is on the screen or not). Here we just loop through all the entities and anything that’s dropped off the screen (below the bottom) gets removed from the World. This keeps our entity count down (the simulation never has more than 30 or 40 objects in the world no matter how long you run it for). Too many entities and the app will grind to a halt.
Lines 125-130: Farseer knows nothing about the UI so that’s entirely up to you as to how to draw things. Farseer is just tracking the objects and moving them around using the physics engine and it’s rules. You’ll still use XNA to draw items (using the SpriteBatch.Draw method) so you can load up your usual textures and draw items and pirates and dancing zombies all over the screen. Instead in this demo we’re going to cheat a little. In the sample code for Farseer you can download there’s a project called DebugView XNA. This project contains the DebugViewXNA class which just handles iterating through all the bodies in the world and drawing the shapes. So we call the RenderDebugData method here of that class to draw everything correctly. In the case of this demo, we just want to draw Shapes so take a look at the source code for the DebugViewXNA class as to how it extracts all the vertices for the shapes created (in this case simple boxes) and draws them. You’ll learn a *lot* about how Farseer works just by looking at this class.
That’s it, that’s all. Simple huh?
Hope you enjoy the code and library. Physics is hard and requires some math skills to really grok. The Farseer Physics Engine makes it pretty easy to get up and running and start building games. In future posts we’ll get more in-depth with things you can do with the engine so this is just the beginning.
Enjoy!
© ASP.net Weblogs or respective owner