How do I get farseer to work with a map file?

Topics: Developer Forum, Project Management Forum, User Forum
Jul 30, 2009 at 6:04 AM

I have a single image as my map.

Do I need to have some kind of data file so the physics engine knows were to collide and how much power was absorbed?

If so what kind of data file whould I use?

 

Thanks

 

Aug 3, 2009 at 5:05 AM

So I am geussing nobody uses a solid bmp as a map and creates walls with collision to create like a pinball game.

How else can you create collision with this software

Aug 3, 2009 at 1:02 PM

I guess no one understood what are you getting to, as Farseer is a physics engine and how will you set physical properties to bodies it is up to you, engine just provides possibility to do so.

But, as you mentioned pinball game now, I would do it like this:

- have pinball table background as pure image without any moving part

- have all the moving stuff (and also walls or any static collision objects) as separate images together with (another file) information where to place it on pinball table and other physical properties (friction, restitution, ... ), you can also define restrictions (angle restr.) for stuff that should be controlled by player, etc.

Aug 3, 2009 at 3:34 PM
Edited Aug 3, 2009 at 3:40 PM

the way I am trying to do it is have only two images the level and the player.

So the best way to ask this then I belive. Is there a way to create a bunch of vertices and have them be a polygon in the physics engine so the ball can react to them?

Aug 3, 2009 at 7:01 PM

You'll prolly have to tile it, as detailed  http://farseerphysics.codeplex.com/Thread/View.aspx?ThreadId=63543 <<<here. i did the same thing with mine, and i actually wrote up a class for it...

 

 


 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using FarseerGames.FarseerPhysics.Collisions;
using Microsoft.Xna.Framework;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Factories;
using FarseerGames.FarseerPhysics;

namespace Hyperinflation
{
    class LevelTile
    {
        public Texture2D Texture;
        public int xOffset;
        public int yOffset;
        public uint[] Data;
        public Vertices Verts;
        public Vector2 Origin;
        public Body Body;

        public LevelTile(Texture2D loadedTexture, int _xOffset, int _yOffset)
        {
            Texture = loadedTexture;
            xOffset = _xOffset;
            yOffset = _yOffset;
            Data = new uint[loadedTexture.Width * loadedTexture.Height];
            Texture.GetData(Data);
            Verts = Vertices.CreatePolygon(Data, loadedTexture.Width, loadedTexture.Height);
            Origin = new Vector2(0,0);
        }
    }
}


(you'll want to copy and paste that into a new class and replace "Hyperinflation" with whatever your game is called)

 

it's fairly easy to use. you'll just want to cut up your level into any number of "tiles." make sure you keep track of the position of these tiles in your bigger picture. also, make sure you have the parts of the image where the ball will be set as alpha channels (if you don't know how to do that, ask). when you cut it up, try to avoid concave angles (like corners) because they wont work perfectly. just try to put them in two tiles. it doesn't matter if they intersect. it's a little hard to explain.

when you've got it tiled up right, put the following at the top of your code (where you define stuff)

 


 

 

        // LevelTiles
        const int NumberOfTiles = 11;
        LevelTile[] TileArray;


obviously, your NumberOfTiles won't necessarily be 11. change that to whatever your number is.

now initialization...

TileArray = new LevelTile[NumberOfTiles];

            TileArray[0] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile1x1"), 0, 0);
            TileArray[1] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile2x1"), 666, 0);
            TileArray[2] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile3x1"), 1332, 0);
            TileArray[3] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile1x2"), 0, 666);
            TileArray[4] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile2x2"), 666, 666);
            TileArray[5] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile3x2"), 1332, 666);
            TileArray[6] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile1x3"), 0, 1332);
            TileArray[7] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile2x3"), 666, 1332);
            TileArray[8] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile3x3x1"), 1332, 1332);
            TileArray[9] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile3x3x2"), 1665, 1332);
            TileArray[10] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile3x3x3"), 1332, 1665);

this is mine. since i have 11, i go from 0 to 10. the argument for leveltile is (Texture, xOffset, yOffset). the offsets start from the top left corner.

now load content... (now that i think of it i probably should have put this in initialization, whatever.)

            // LevelTiles
            foreach (LevelTile Tile in TileArray)
            {
                Tile.Body = BodyFactory.Instance.CreatePolygonBody(physicsSimulator, Tile.Verts, 5);
                Tile.Body.IsStatic = true;
                Tile.Body.Position = new Vector2(Tile.xOffset, Tile.yOffset);
                GeomFactory.Instance.CreatePolygonGeom(physicsSimulator, Tile.Body, Tile.Verts, Tile.Verts.GetCentroid(), 0, 0);
                Tile.Body.Position -= TileArray[0].Verts.GetCentroid();
            }

i don't think you have to change this. basically it just creates the geometry for each tile in the array.

now draw it....

foreach (LevelTile Tile in TileArray)
            {
                spriteBatch.Draw(
                    Tile.Texture,
                    Tile.Body.Position,
                    null,
                    Color.White,
                    Tile.Body.Rotation,
                    Tile.Origin,
                    1,
                    SpriteEffects.None,
                    0);
            }

that should be it. ask if you have any questions about it.
Aug 4, 2009 at 4:40 AM

I am not sure how drawing square tiles I will be able to find the curved walls on every tile. Also I dont see why I coudnt just make some kind of grid and test if the player is in that grid then test it aginst an array of vertices in that grid. instead of cutting up the whole image and drawing them and then placing the walls on top of that. It just seams like so much extra work instead of just doing this

 

genbox wrote:

If you have hundreds of levels, it might be better to code your way out of it, but Farseer Physics does not have any such tools.

 

which I do have a tool in gimp that you can draw the path wich are just an array of vertices. which if I can just tell the physics api

to do something like this

TileArray[10] = new LevelTile(Content.Load<Texture2D>("LevelTiles//LevelTile3x3x3"), 1332, 1665);

but instead of an texture I just set the vertices for that tile location

what do you thinck?

Aug 4, 2009 at 5:41 AM
Well actually, the "tile system" calculates the vertices from your
texture, so having a seperate vertices data file is a bit unneccesary.