Farseer Sensor and Parallax Foreground

Topics: Developer Forum, User Forum
Jul 30, 2010 at 7:00 AM
Edited Jul 30, 2010 at 7:07 AM

I'm new to the Farseer engine and trying to get the hang of it all. I decided to try my luck at a Worms-like physics testing environment. Since I'm trying to learn a lot about XNA, I also decided to try and implement parallax layers as well. I'm using Farseer 2.1.3 (since I couldn't find a port of Farseer 3.0 for XNA 4.0).

My parallax drawing operates with a 2d camera that calculates the necessary parallax offset by comparing the intial camera position with the current position. This lets me drag the screen around using the mouse and have the layers move in the correct fashion.

//Landscape Object
public void DrawBackground(ScreenManager screenManager, Camera2d camera)
        {
            foreach (TextureLayer layer in backgroundLayers)
            {
                screenManager.SpriteBatch.Begin(SpriteSortMode.Immediate,
                               BlendState.AlphaBlend,
                               SamplerState.LinearClamp,
                               DepthStencilState.Default,
                               RasterizerState.CullNone,
                               null,
                               camera.get_transformation(TylerGame.graphics.GraphicsDevice, layer.scrollSpeed));

                layer.Draw(screenManager.SpriteBatch);

                screenManager.SpriteBatch.End();
            }
        }
//Camera Object
public Matrix get_transformation(GraphicsDevice graphicsDevice, float scrollSpeed)
        {
            _transform =       // Thanks to o KB o for this solution
              Matrix.CreateTranslation(new Vector3((_startpos.X-_pos.X)*scrollSpeed, (_startpos.Y-_pos.Y)*scrollSpeed, 0)) *
                                         Matrix.CreateRotationZ(Rotation) *
                                         Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) *
                                         Matrix.CreateTranslation(new Vector3(graphicsDevice.Viewport.Width * 0.5f, graphicsDevice.Viewport.Height * 0.5f, 0));
            return _transform;
        }

I was glad to see that this appeared to function correctly. That is, until I turned on the PhysicsSimulatorView and noticed that all of my vertices in the view did not correspond with the positioning of the objects on screen. This makes sense since I am essentially screwing the view with the Camera. So as long as colliding objects exist in the same plane (which all will), then it would still work. In reality, the background layers didn't even need to be in the simulator as they wouldn't need to have physics applied to them. Had this been the only desired requirements I would be fine, however I also wanted foreground layers.

My goal with the foreground layers was to provide depth in front of the colliding objects as well. The only problem with this is that I didn't want the foreground objects to obstruct the view of the player. So my thought was to add the foreground layer to the simulator as a sensor, so that when triggered, I could drop the drawing opacity to 50% and then back to 100% when it wasn't colliding anymore. Thus arising my problem. I build the body and the geom from my texture then added to the simulator. But I'm not sure where to go from there. I attempted to move the physics body whenever I shifted the camera, but that caused weird behavior (all graphics disappeared).

Is there another approach I could/should be taking? Is changing the position of the body a sound idea? I know it can cause issues with collision since two objects could be "inside" each of if I'm moving the position, but since I am only using it as a sensor I thought it wouldn't cause problems. Has anyone done anything similar with Farseer? Any advice is helpful as I'm stuck as to a logical approach right now. Thanks in advance.

Jul 31, 2010 at 7:03 AM
If I were you, I wouldn't use the physics engine for your foreground layers at all. If you are looking to take advantage of how the sensor works, then why not just pick apart the code and write a custom sensor using that one as reference? That way you could pull it out of the physics altogether. That portion should really be part of your game engine, and not the physics itself. It's a clever use, and might even be able to work with right amount of finesse, but I'd do it differently. That's only my opinion. Take it for what it's worth.
Jul 31, 2010 at 9:30 PM
Edited Jul 31, 2010 at 9:31 PM
After some more work on it, I agree. I was actually able to get it to work by changing body positions based on camera movement and with some "finesse" (more like hackery). But its definitely not the cleanest solution. Collisions that are inside another geom are not quite as simple to detect using the standard Farseer implementation either, so I was going to write my own algorithm for that anyways. Thanks for the opinion, I think I'm going to pursue a path similar to what you were saying and just use Farseer for the the principal layer. And a big thanks to all the Farseer guys, this is really a great 2d physics environment for C#.