Newbie problems

May 15, 2009 at 10:11 PM

Hi guys,

I've starting program with XNA only a few weeks ago and a physic engine would be a great support in game making, i think.

But the to understand how to use Farseer is very hard for a newcomer like me and tutorials are also very hard to find.

But I've read the manual that's what comes out : (be pleasent I found no other way to post that code)

I don't know what I've done wrong, I follow each step of the manual, can someone told me my mistake? Thank you.

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.Factories;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Interfaces;
using FarseerGames.FarseerPhysics.Controllers;
using FarseerGames.FarseerPhysics.Collisions;
using FarseerGames.FarseerPhysics.Mathematics;

namespace PhysikTest
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Body rectBody;
        PhysicsSimulator _PhysicsSimulator;
        Texture2D BodyTexture;
        Vector2 _origin;
                   

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <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
            _PhysicsSimulator = new PhysicsSimulator(new Vector2(0f, 300f));                   

            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);
            BodyTexture = Content.Load<Texture2D>("Box");
            _origin = new Vector2(BodyTexture.Width / 2f, BodyTexture.Height / 2f);

            // TODO: use this.Content to load your game content here
            rectBody = BodyFactory.Instance.CreateRectangleBody(_PhysicsSimulator, 80, 60, 1);
            rectBody.Position = new Vector2(400f,300f);

            base.LoadContent();
        }

        /// <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)
        {
            // TODO: Add your update logic here
            KeyboardState input = Keyboard.GetState();

            const float forceAmount = 50;
            Vector2 force = Vector2.Zero;
            force.Y = -force.Y;

            if (input.IsKeyDown(Keys.A)) { force += new Vector2(-forceAmount, 0); }
            if (input.IsKeyDown(Keys.S)) { force += new Vector2(0, forceAmount); }
            if (input.IsKeyDown(Keys.D)) { force += new Vector2(forceAmount, 0); }
            if (input.IsKeyDown(Keys.W)) { force += new Vector2(0, -forceAmount); }

            rectBody.ApplyForce(force);

            const float torqueAmount = 1000;
            float torque = 0;

            if (input.IsKeyDown(Keys.Left)) { torque -= torqueAmount; }
            if (input.IsKeyDown(Keys.Right)) { torque += torqueAmount; }

            rectBody.ApplyTorque(torque);
           
            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);

            // TODO: Add your drawing code here
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
            spriteBatch.Draw(BodyTexture, rectBody.Position, null, Color.White, rectBody.Rotation,
                             _origin, 1, SpriteEffects.None, 0);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

Coordinator
May 15, 2009 at 10:26 PM

Physics engines by nature at not very friendly by nature :) You are not far from your goal tho, you just need to update the PhysicsSimulator object inside your Update() method. That is needed to get any physics to work.

You have also discovered the samples right? They are a great way of learning Farseer Physics and how it can be combined to make dynamic games.

May 16, 2009 at 6:39 AM
Edited May 16, 2009 at 6:48 AM

Yes, I looked at the Simple Samples, but they are very districted with the Drawing Helper class and other things like ScreenManager and PhysicsSimulatorView.

 

When I want to update my PhysicsSimulator Object : _PhysicsSimulator.Update(arguments);

It asks for a argument, but there is no description what kind of. And should I place the Update before or behind my keyboard control ?

May 16, 2009 at 8:02 AM

if you find the simple samples too confusing take a look at http://farseersimplesamples.codeplex.com/

(they can get a little complex because they tend to tell you the best way to do things rather that the absolute simplest)

 

the argument to the update method takes the time since the last update (float). most people use the total number of seconds (but i don't think it matters as long as you always use the same units)

from memory in XNA the Update method of the Game class gives you a GameTime as an argument... you can use gameTime.TotalSeconds to get a value you can pass to the physicsSimulator.Update method.

 

i hope that helps

 

p.s. @committers: it took me a bit to work out what the argument to Update was, there should probably be an XML comment on that method (i.e. /// .... )

May 16, 2009 at 11:07 AM
Edited May 16, 2009 at 12:37 PM

_PhysicsSimulator.Update(gameTime.ElapsedGameTime.TotalSeconds);

is not usable, how should I use it ?

// ErrorMessage: cannot convert from "double" to "float"

Coordinator
May 16, 2009 at 2:38 PM

I've added a code comment to the Update() method.

The samples use the following update argument:

PhysicsSimulator.Update(gameTime.ElapsedGameTime.Milliseconds * .001f);

May 17, 2009 at 6:18 PM
Edited May 17, 2009 at 6:20 PM

Okay, that helps, thank you.

 

But another problem:

I would like to kick a box (f.e.) an it flys through the screen and gets slower and slower. How should I do that? I have the command: "Geom.FrictionCoefficient = 0.5f; " but i want a general  Friction without collisions so it gets slower and slower over the time until zero. What's the command for that?

The same for the rotation, when i rotate a box once it rolls forever, how can i set a Friction here (is Friction the word of something gets slower and slower?)

Coordinator
May 17, 2009 at 6:20 PM

To make it fly slower and slower, you have to apply linear drag (air drag) to the body. This is done automatically by the engine, you only have to set a LinearDragCoefficient (Body.LinearDragCoefficient) on the body. Try experimenting a little to get the perfect slowdown of your geometry.

May 17, 2009 at 7:28 PM

Works perfect. And how is it for the rotation (with tonque applied)? I found a command: RotationalDragCoefficient  but it doesn't work.

Coordinator
May 17, 2009 at 7:29 PM

RotationalDragCoefficient is the one you are looking for. Try larger values if it does not work. Remember that it is only to "counteract" torque. If you wish no rotation at all, you need to go other ways.