Simple XNA example with a PhysicsSimulatorView but no ScreenSystem?

Topics: Developer Forum, User Forum
May 17, 2009 at 11:42 AM
Edited May 17, 2009 at 2:13 PM

Hi All,

Firstly I'd just like to thank the Farseer team for providing us all with such an amazing physics engine, especially as it's completely free! It's very generous of them and I'm very grateful.

I've read quite a few threads on the forum and it looks like there's a very helpful and friendly user/dev community here, so I hope someone can help me out. I'm trying to learn how to use Farseer for my 2d game with the XNA framework but I'm struggling to get to grips with how it works. I've read the manual and I've looked at the simple examples, but I'm still finding it somewhat difficult. The examples with the menu system are great, but I'm finding find the ScreenSystem set of classes and the way the PhysicsSimulatorView is implemented is making it more complex for me to learn.

Personally I'd find it very helpful to see a simple example Solution containing an XNA Windows game project and Farseer Physics. The example game project could have a couple of Texture2Ds with bodies and geoms attached (e.g. one controlled by player and one not) showing how to manage movement, collision detection and collision response/reaction. I'd like to see the PhysicsSimulatorView implemented but no ScreenSystem. 

Does anybody have a simple project like this they could show me? It would really help me a lot.

Many thanks!

Matt

 

Coordinator
May 17, 2009 at 11:59 AM
Edited May 17, 2009 at 1:07 PM

Hi Matt.

Thanks for the very kind words about our engine and our team. The community means a lot to us and we really appreciate people taking their time to help out and contribute to the project.

I have some plans to make Farseer Physics Engine even easier. To accomplish this I'm including the simplest samples you can imagine (much like you describe). I remember the first time I stepped into the world of game physics, I was as much lost by the clutter as you are now. Sometimes we just need a place to start - get the fundamentas right and begin from there.

When the features for Farseer Physics 2.1 are done and we are close to a release, I'm going to make some improvements to the manual. I have a lot of requests from our users and even examples on what the changes might look like. I aim to create a fully documented physics engine that is easy to use and learn. It's not an easy task, but it can be done. If you have any suggestions other than what you already have, you are welcome to tell us and we will take it up to consideration.

As for the sample itself, I do hope someone here can brew a quick sample for you, I don't have the time right now as I have exams tomorrow and need to study. However, I can tell you the very basic setup of a sample:

1. Create new XNA game
2. Create a PhysicsSimulator object. - This object is in charge of updating bodies and geometries.
3. Create 2 objects:
   3.a A Body object for dynamics (force and impulse) - Use BodyFactory class to create a body. Also, remember to position the body.
   3.b A Geom object for collision detection (it consists of vertices that makes up an shape) - Use GeomFactory class to create a Geom.
4. If you used the factories that use a PhysicsSimulator argument, you can skip this step. But else you need to add both the Body and Geom object to the PhysicsSimulator object (Example: PhysicsSimulator.Add(Body) )
5. Make sure to have PhysicsSimulator.Update() called inside your update loop.

That is it. If you have done it right, you now have a geometry (geom) that supports collisions with other geometries. To see them, you will need to draw them on the screen. In the samples, the DrawingSystem folder has some classes that can create textures (rectangles, polygons, circles).

May 17, 2009 at 2:27 PM
Edited May 17, 2009 at 3:40 PM

Hi genbox,

Thanks for your quick reply. Good luck with your exams tomorrow, hope it all goes well!

I'll have a go at creating a simple project as you've suggested in your post. I need to get the PhysicsSimulatorView working as well so that I can actually see what's happening with the (invisible) bodies/geoms that I'm creating...

If anybody can help me out I'd really appreciate it!

Anyway you'd better go and study so I'll leave you in peace for now!

Thanks again.

Matt   

May 20, 2009 at 8:25 PM

Is anybody able to help me out with this please?

Coordinator
May 20, 2009 at 8:37 PM

To use the PhysicsSimulatorView, you need to move the PhysicsSimulatorView.cs file and dependencies (everything in DrawingSystem folder) into your own project.

Then you need to instanciate the PhysicsSimulatorView and remember to give it the reference to your physics simulator object. (PhysicsSimulatorView view = new PhysicsSimulatorView(physicsSimulator); )

Then you call view.LoadContent(graphicsDevice, contentManager); to make it initialize all the graphics and stuff. And finally, you just call view.Draw(spriteBatch); to make it draw to screen.

That should be it. You can not see geometries, bodies, joints and the internals of the engine. Remember that you can turn off and on the different features.

May 21, 2009 at 3:37 PM

Here is a bare bones sample like the one described. It just has circle body and a static rectangle that it falls onto. I went a little crazy with the using statements lol. The one thing I had problems with was that the default template in visual studio adds a Content.RootDirectory = "Content", which won't work if you pass this content manager to the PhysicsSimulatorView. Just comment that line out and let it use the default root directory.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Factories;
using FarseerGames.FarseerPhysics.Interfaces;
using FarseerGames.FarseerPhysics.Mathematics;
using FarseerGames.FarseerPhysics.Controllers;

using FarseerGames.AdvancedSamples;
using FarseerGames.AdvancedSamples.DrawingSystem;

namespace SimpleTest
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        PhysicsSimulator physicsSimulator;
        Body player;
        Geom playerGeom;
        Body platform;
        Geom platformGeom;

        PhysicsSimulatorView simView;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content = new ContentManager(Services);
            //Content.RootDirectory = "Content"; // commented out so PhysicsSimulatorView can find its stuff in the default directory

            // setup the physics sim
            physicsSimulator = new PhysicsSimulator(new Vector2(0.0f, 300f));

            // setup the player body and geom
            float playerRadius = 10.0f;
            player = BodyFactory.Instance.CreateCircleBody(physicsSimulator, playerRadius, 1.0f);
            playerGeom = GeomFactory.Instance.CreateCircleGeom(physicsSimulator, player, playerRadius,
                10,  // number of edges
                new Vector2(0.0f, 0.0f), // position
                0.0f); // rotational offset

            player.Position = new Vector2(300.0f, 300.0f);


            //// setup the platform
            platform = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, 40f, 100f, 100f);
            platformGeom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, platform, 100, 100f);
            platform.Position = new Vector2(300.0f, 310.0f);
            platform.IsStatic = true;

            create the simView, but don't load resources yet
            simView = new PhysicsSimulatorView(physicsSimulator);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // now load the simView's content
            simView.LoadContent(GraphicsDevice, Content);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // ----- apply any game logic forces first -----

            // in a real game this will be some force you calculate from user input, or more than one force
            Vector2 someForceFromInput = new Vector2(100.0f, 0.0f);

            // apply force for user input
            player.ApplyForce(new Vector2(someForceFromInput);

            // ----- now update the physics simulator -----
            physicsSimulator.Update((float)gameTime.ElapsedGameTime.TotalSeconds);

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

 

            // ----- draw your game textures first -----

           spriteBatch.Begin();

           // draw everything in your game

           spriteBatch.End();

          // ----- now draw the simView in a separate Begin/End section, so the PhysicsSimulatorView draws on top of everything you drew earlier

            spriteBatch.Begin();

            // this draws the simview
            simView.Draw(spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}