Aether.Physics2D - Release v 1.0 - 1.7

Yes, that’s the right approach.

By using the physics systeme you always need to take care of the simulation-units-to-display-units-ratio or at least it’s helpful to know what this is meaning.

Basically (regarding to the defaults) you can say that 64 pixels on your screen should be 1 meter in the physical world. This is espacially helpful if you want to create realistic simulations.

Use the following helper functions to make your life as a game dev simpler:

public Vector2 ConvertWorldToScreen(Vector2 position)
{
    Vector3 temp = GraphicsDevice.Viewport.Project(new Vector3(position, 0), Projection, View, Matrix.Identity);
      
    return new Vector2(temp.X, temp.Y);
}
     
public Vector2 ConvertScreenToWorld(int x, int y)
{
    Vector3 temp = GraphicsDevice.Viewport.Unproject(new Vector3(x, y, 0), Projection, View, Matrix.Identity);
      
    return new Vector2(temp.X, temp.Y);      
}

For that you just need to set up a Projection and View matrix.

The old Farseer Physics Engine did it with a seperate class. Take a look at it here:

This is of course just to help you with your game development.

For the first just play around with the values from the HelloWorld sample and you should get a good feeling for everything.

Okay, I think I’ve got it.

The first problem I had is I wasn’t setting my environment up properly to that +y was up.

I’ll be writing a tutorial shortly that will spawn a static image in the centre of the screen, but the main focus will be setting up the world, and view.

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Collections.Generic;
using tainicom.Aether.Physics2D.Dynamics;

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

    private BasicEffect _spriteBatchEffect;

    private World _world;

    private Matrix _projection;

    private Texture2D _texture;

    private Vector2 _origin;

    private Vector2 _scale;

    private Body _body;

    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

      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);

      _spriteBatchEffect = new BasicEffect(graphics.GraphicsDevice);
      _spriteBatchEffect.TextureEnabled = true;

      _world = new World();

      _texture = Content.Load<Texture2D>("Square");

      _origin = new Vector2(_texture.Width / 2, _texture.Height / 2);

      _scale = new Vector2(1f, 1f);

      _body = _world.CreateRectangle(_scale.X, _scale.Y, 0.1f, new Vector2(0f, 0f));
      _body.BodyType = BodyType.Static;
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// game-specific 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)
    {
      // update camera View Projection
      var vp = GraphicsDevice.Viewport;
      var cameraZoomFactor = 12.5f / vp.Width; // zoom out to about ~12.5 meters wide
      _projection = Matrix.CreateOrthographic(vp.Width * cameraZoomFactor, vp.Height * cameraZoomFactor, 0f, -1f);

      _world.Step((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);

      _spriteBatchEffect.Projection = _projection;
      spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, RasterizerState.CullClockwise, _spriteBatchEffect);

      spriteBatch.Draw(_texture, _body.Position, null, Color.White, _body.Rotation, _origin, _scale / new Vector2(_texture.Width, _texture.Height), SpriteEffects.FlipVertically, 0f);

      spriteBatch.End();

      base.Draw(gameTime);
    }
  }
}

I think the above is about as basic as I can get it. I’m going to debug it over the weekend to see if I can understand it more.

With everything being rotated, and using the smaller values for positions and such, my brain is a little mumbled right now!

1 Like

Hey, thats realy cool. But one question, why not merge that into the new release of the Farseer Physics Engine? https://github.com/VelcroPhysics/VelcroPhysics

One way to move is to set Body.LinearVelosity. This will override the current velocity of the body.
Another idea is to set Body.LinearDamping at 1 and apply a force on every step().

Of course the preferred.way is to use forces if you want your sprite to interact with other objects and set LinearDamping to a value that feels like air resistance. In that case you have to read the current LinearVelosity. and apply only the required force needed to have a max velocity.
The difference between ApplyLinearImpulse() and ApplyForce() is that force dependence on the mass of the object. Double the mass requires double the force to get equal acceleration. ApplyLinearImpulse() will multiply the impulse with invMass , so you get more or less the same result and you don’t have to care about the mass.

In the worst case, you can have a kinematic body where you are responsible for moving your sprite however you want, and you can still make use of the collision system (Body.ContactList).

The simulation works in KMS (kilo-Meters-seconds) and the coordinates system is Right: [+1;0], Up: [0,+1], Rotation: (CounterClockWise). It’s best to use realistic values and then everything will just work. Rendering the world is another issue. The samples use SpriteBatch for simplicity but it’s not the best choice because SpriteBatch works in ScreenSpace. In a real game you will probably replace SpriteBatch with your own batching, translation and effects or 3D models.

So, in order to work with spriteBatch I use a customEffect to override the default projection with my own View/Projection.
Additionally I had to Flip the sprites Vertically and CullClockwise.

Hey, this looks like a pretty great evolution of Farseer! I have a quick question:

While Farseer is not technically deterministic, it is very close and is possible to make determinstic (assuming run on the same runtime/CPU-architecture) with only a handful of simple changes. And so my question is, does the addition of multithreading break the near-determinism of the physics simulation? (Which, if not easy to fix, would make Aether unusable for my purposes since my game relies on determinism for its multiplayer.)


And unrelated to the above question, here’s an idea for a possible optimization that I just want to throw out there. It’s one that I’ve implemented in my own fork of Farseer to great effect in my particular game, with the caveat that my use case stresses Farseer in a pretty unusual and extreme way.

Basically, in my game it is common to have hundreds (or in extreme cases, thousands) of fixtures attached to a single body. Here’s an example of what I mean, with a debug layer turned on that shows all of the fixtures (there’s 380 of them):

The problem is that Farseer is not optimized for an extremely high ratio of fixtures to bodies. There are a couple problems with Farseer’s implementation:

  1. The broad phase needlessly queries for and finds overlaps between fixture AABBs in the same body, only to throw them out before creating the contacts. When you have so many fixtures constantly in close proximity constantly getting flagged for overlaps, this is a ton of wasted work.

  2. When a body moves, all of its fixtures also move, which requires updating the AABB of every single one of them in the broad phase’s DynamicTree. When you have so many fixtures, this is just really expensive.

My solution to these problems was to modify the broad phase so that it stores bodies instead of fixtures and to give each body its own DynamicTree of fixtures stored in body-relative coordinates. Only when the AABBs of two bodies overlap do the fixtures in the two bodies get queried for overlaps with each other, and fixtures within the same body never even get queried against each other. Additionally, since fixtures are stored in body-relative coordinates, the DynamicTree containing them doesn’t need to get updated continuously as the body moves.

The upside of this is that the performance improvement when there is a high ratio of fixtures to bodies is dramatic, in my case a couple orders of magnitude improvement. The downside is that in the case where there are only a few fixtures per body, the engine is likely slowed by the additional overhead of having to do body overlap queries and then fixture queries, plus the overhead of having to translate AABBs between coordinate systems on-the-fly during the fixture overlap queries (since fixtures are stored in body-relative coordinates). But I suspect most of the downside can be ameliorated by having some threshold under which bodies with only a few fixtures simply have their individual fixtures inserted into the broad phase and bodies over the threshold get optimized as above.

Anyway, just an idea. :slight_smile:

Hi @holyfuzz.

That’s true. It’s not deterministic which contact will get processed first. The multi-threading solvers locks the two bodies in a contact during processing.
Multi-threading is off by default. To turn it on you specify a threshold which is the number of active contacts. It’s unnecessary to set up threads when you have a small number contacts. You can set thresholds for PositionConstrainsSolver, VelocityConstrainsSolver and Contacts, individually.
It’s possible that the contacts does not update the bodies (It doesn’t alter position/velocity/etc), but that’s something I have to double check, I can’t say for sure right now. Although callback events like OnCollision/OnSeperation will fire from different threads. You have to buffer and change object states on the next update.

Farseer has a couple of triangulation tools, maybe you can find an algorithm that reduces the number of fixtures from what you have now.

In most engines you use a simplified approximation for collisions.

You can setup a body with a few fixtures that cover your sprite and subscribe to Body.OnCollision where you can perform a per-pixel collision. If you return false from OnCollision() the collision is ignored. For a generic solution you can listen to World.ContactManager.BeginContact and implement a IPixelPerfectCollision interface or something similar on some of your bodies.

Another idea:
Have you tried to add a reference to the body in FixtureProxy?
You could then quickly discard the pair inside .AddPair() without having to get the bodies through fixture, which probably cause a cache-miss.

Hey guys!

I tried to port my game from the good old FarseerPhysics to this engine. Unfortunately I have some problems with it.
First, where is the IgnoreCollisionWith-method? Is there any replacement for it? Same goes for the ConvertUnits-class.
An other issue is that the collision not working any more. If my player collides with a edge, it bounced back ~50px and sometimes he walk through it. I have attached a sample clip: https://www.dropbox.com/s/66eypwcat3uljpz/collisionbug.mp4?dl=0
But the strangest issue is, that I can not work right any more. left, up and down works well…
I have nothing changed to the code, just only replaced FarseerPhysics-parts with Aether. So why ist that?

The ConvertUnits was removed. An orthographic camera (View&Projection) is preferred for rendering your Physics world.
You can find ConvertUnits here and copy it in your project if you find it useful.

IgnoreCollisionWith was removed as well.
Depending on your scenario you can use some other collision mechanism like Fixture.BeforeCollision, ContactManager.ContactFilter, Fixture.OnCollision or ContactManager.BeginContact.

Maybe your step time is to long and/or the force is too big (tunneling). Try to set your sprite as a Bullet.

That’s strange. You have to narrow it down to a short simulation/test to reproduce it.
What version of Farseer were you using?

EDIT
In the last second of the video you break into the code and I see that you have a newPosition variable.
Did you update the position of the sprite directly on each frame? By forcing a position it’s like teleporting a body into another one. If that’s the case then the simulation sees two bodies overlapping and tries to break the collision by throwing them apart, that’s why your sprite is jumping away from either side of the edge.
You need to move the sprite by applying a force, where then the simulation has knowledge about the sprite position/movement and can correctly resolve collision and move the body to the new position.
Read on Forces and impulses - Box2D tutorials - iforce2d about force, impulse and ‘teleporting’.

Hi,

you brought me the right idea. The jump comes from my dynamic-body which have an kinematic-body as his hull.
The code you see is for the inital position I set to my characters.
I’m only sync the two bodies after the world step. I use that two bodies to prevent to shove the other characters if they collide. And that is the issue here to. In FarseerPhysics I use the IgnoreCollisionWith method on both bodies, but now its gone and the collision works again… I think its a dirty work around, but I dont have any idea how to fix it either. If you know how I could prevent shoving, without that, let me hear :smiley:

You mean something like restitution/inelastic collision?
http://www.iforce2d.net/b2dtut/fixtures
“Restitution measures how ‘bouncy’ a fixture is. Like friction, it is given a value between 0 and 1, where zero means that the fixture will not bounce at all, and one means that all the energy of the bounce will be conserved. When two fixtures collide with each other, the resulting restitution tends toward the higher of their restitution values.”

Hi,

I have set it already to 0. Here 2 clips to show what I mean (shove/push):
No-Shove https://www.dropbox.com/s/rxyhehvvnaknu1i/noshove.mp4?dl=0
Shove: https://www.dropbox.com/s/voencbmzx7d75fe/shove.mp4?dl=0

Oh, I see. Your workaround sounds about right. I don’t see a simpler way to do that.

No way :smiley: I hoped you say something like “Hey you did it all wrong, use … instead”

2 Likes

Is it possible to rotate a body relative to its LocalCenter? I want the player to look towards the mouse so I have set FixedRotation = true and I’m setting Body.Rotation but its rotating around the corner.

You have a couple of options here,

  1. offset all your fixtures so that the center of mass is at the center of the body. you will now have body.LocalCenter = [0,0] and body.WorldCenter = body.Position. This will throw off other code like drawing, etc.

  2. Update both body.Rotation and body.Position in respect of body.WorldCenter. You need to rotate body.Position from the point of referent of body.WorldCenter.
    I think you need to do something like that,

var rotDiff = targetRot - body.Rotation;
var posFromCenter = body.WorldCenter - body.Position;
var newPosFromCenter = Complex.Multiply(posFromCenter, Complex.FromAngle(rotDiff));
body.Position =  body.WorldCenter - newPosFromCenter;
body.Rotation = body.Rotation + rotDiff;

  1. Remove FixedRotation and use one of ApplyAngularForce(),ApplyTorque(), use a MotorJoint or a custom Joint to correct the rotation on each step. Or use the code from 2) but set body velocities instead. This might cause your sprite to occasionally oscillate around targetRotation when colliding with other objects. Increasing the mass or inertia to reduce the influence of other bodies. Keep in mind that if you explicitly set rotation/position (aka “Transporting”) the engine doesn’t know which way to resolve collisions and can cause overshoot or unexpected behavior.

Thanks alot,

I have used Solution 1) since it was pretty easy to shift the drawn picture as well.

I’m curious if anyone has used this engine for commercial games? Has it worked out well? Seems like a great tool.

Hi @holyfuzz, what you’re describing sounds very similar to some performance issues I’ve found in my testing. Would you be willing to share your modified BroadPhase code? I’m very interested in testing it out and seeing if it optimizes my game as you’re saying it did yours. You can check out my thread on the matter here: https://github.com/tainicom/Aether.Physics2D/issues/61

Thank you!

Andrew

Happy to share! (With the caveat that my fork of Farseer has a bunch of other changes to it as well that I’ve made over many years and don’t remember very well, so isolating the broad-phase changes may or may not be easy.)

Send me an email and I’ll send you a zip of my Farseer code. (Unfortunately my Farseer code is part of my closed-source engine, so I don’t have a Git repo I can easily share with you.)

It was definitely tricky to get the broad-phase changes working, what with all the coordinate system conversions that need to happen with all the collisions and raycasts, but I think it’s working very well now. I’ve had this code live in my game for about half a year now with no reported issues, and the performance improvements for my particular game were enormous.

Hi,

is it possible to configure gravity dynamically? So that you have more gravity further down, for example, or that the bodies are not pulled in one direction, but to a point?