обнаружение столкновений в физическом движке Farseer 3.3 - PullRequest
1 голос
/ 05 сентября 2011

для тех из вас, кто знаком с дальнобойщиком, у меня есть вопрос относительно обнаружения столкновений.Я много читаю и смотрю отличный видеоурок по XNAtutorial от Джорана Омара.К сожалению, он использовал более старую версию farseer (версия 2006 года), поэтому мне пришлось немного подправить, чтобы заставить мою работать.Теперь все работает, кроме моего обнаружения столкновений.Я просто не могу заставить их работать.Я решил пойти на подход к управлению экранами и поэтому создать хорошие отдельные классы.

Мой GameplayScreen выглядит следующим образом

   public class GamePlayScreen : GameScreen
{
    Texture2D stewieTexture;
    Texture2D floorTexture;
    Sprite stewie;
    Sprite floor;
    World world;

    public GamePlayScreen()
    {
        world = new World(new Vector2(0, 9.81F));
        EnabledGestures = GestureType.Flick;
    }

    public override void LoadContent()
    {
        stewieTexture = ScreenManager.Game.Content.Load<Texture2D>("playerStewie");
        floorTexture = ScreenManager.Game.Content.Load<Texture2D>("Floor");

        this.stewie = new Sprite();
        this.floor = new Sprite();
        this.stewie.LoadGraphicsContent(ScreenManager.SpriteBatch, this.stewieTexture, world);
        this.floor.LoadGraphicsContent(ScreenManager.SpriteBatch, this.floorTexture, world);
       // very ugly unfortunately for now like this.. We need Textures for our sprite that's why
        this.stewie.Initialize(world, BodyType.Dynamic ,new Vector2(16000,1500));
        this.floor.Initialize(world, BodyType.Static, new Vector2(1500, 16000));
    }

    public override void HandleInput(InputState input)
    {
        foreach (GestureSample gesture in input.Gestures)
        {
            if (gesture.GestureType == GestureType.Flick)
            {
                stewie.PhysicsBody.ApplyForce(Vector2.Divide(gesture.Delta, 0.5f));
            }
        }
    }

    public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
    {
        world.Step((float)gameTime.ElapsedGameTime.TotalSeconds);
        this.stewie.Update(gameTime, world);
        this.floor.Update(gameTime, world);
        base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
    }

    public override void Draw(GameTime gameTime)
    {
        // TODO: Add your drawing code here
        ScreenManager.SpriteBatch.Begin();

        this.stewie.Draw(gameTime);
        this.floor.Draw(gameTime);
        ScreenManager.SpriteBatch.End();

        base.Draw(gameTime);
    }
}

И мой класс Sprite

    public class Sprite
{
    private Animation graphicsImage;
    private Body physicsBody;
    //Fixture test  
    //private Fixture fixtureBody;
    private Vector2 _screenCenter;

    private float pixelsPerMeter = 50;  //needed to convert pixels per meter , because the gesture.position is in meters
    public Body PhysicsBody { get { return physicsBody; } }

    public Sprite()
    {
        this.graphicsImage = new Animation();
    }
    /// <summary>
    /// Initialize the sprite sets up position , creates rectangle from bodyfactory 
    /// </summary>
    /// <param name="world"> takes a reference to the worldobject</param>
    public void Initialize(World world, BodyType bodyType,Vector2 position)
    {
        this.graphicsImage.Initialize();

        this.physicsBody = BodyFactory.CreateRectangle(world, this.graphicsImage.Size.X / pixelsPerMeter, this.graphicsImage.Size.Y / pixelsPerMeter, 1f);
        this.graphicsImage.Position = position / pixelsPerMeter;
        this.physicsBody.Position = this.graphicsImage.Position;
        this.physicsBody.BodyType = bodyType;
     //   this.fixtureBody = FixtureFactory.AttachRectangle(this.physicsBody.Position.X / pixelsPerMeter, this.physicsBody.Position.Y / pixelsPerMeter, 3f, new Vector2(100, 100), this.physicsBody);

        //this.physicsBody.Restitution = 0.7f;
        Debug.WriteLine("Initialize Sprite");
        Debug.WriteLine(this.graphicsImage.Position);
    }

    /// <summary>
    /// LoadGraphicsContent for the sprite    call this function in the LoadContent ( initialize also works ) 
    /// </summary>
    /// <param name="spriteBatch">takes a reference to a spritebatch</param>
    /// <param name="texture">takes a reference to texture2D</param>
    public void LoadGraphicsContent(SpriteBatch spriteBatch, Texture2D texture, World world)
    {
        this.graphicsImage.LoadGraphicsContent(spriteBatch, texture);
    }


    /// <summary>
    /// Update sprite for graphicsImage position , and rotation  needs to be called in the main Update function of the game 
    /// </summary>
    /// <param name="gameTime">reference to gameTime</param>
    /// <param name="world">reference to worldobject</param>
    public void Update(GameTime gameTime, World world)
    {
        this.graphicsImage.Update(gameTime);
        this.graphicsImage.Position = this.physicsBody.Position;
        this.graphicsImage.Rotation = this.physicsBody.Rotation;

    }

    /// <summary>
    ///  Draw sprite method needs to be called in the main Draw function of the game
    /// </summary>
    /// <param name="gameTime"></param>
    public void Draw(GameTime gameTime)
    {
        this.graphicsImage.Draw(gameTime);
    } 
}

}

Как я уже говорил, мое столкновение неНе работает.Я посмотрел на текущие образцы, которые используют Farseer 3.3 (так же, как я делаю).Например, здесь http://farseerphysics.codeplex.com/releases/view/64108, а затем пример HelloWorld.Я читал материал о GeomFactory, который использовался в предыдущих версиях для столкновения.Однако это изменилось с новой версией Farseer, где фабрика по производству кузовов может обрабатывать целую кучу вещей.Так кто-нибудь знает, почему мое столкновение не работает?

1 Ответ

0 голосов
/ 17 сентября 2011

Да, ваше позиционирование отключено, потому что из того, что я получил от игры с двигателем, он использует координаты экрана в метрах.Это означает, что ваш экран может быть только 10x16 (ish) метров (480x800 пикселей), потому что это то, что Microsoft имеет ограниченное разрешение экрана.Таким образом, когда вы передаете позиции 16000, 1500 пикселей и делите его на 50, вы действительно помещаете тела на 320 и 30 м, что далеко от экрана для тел, но на экране для функции Draw, потому что она считает эти значенияв пикселях.

Также из того, что я видел в примере HelloWorld на их сайте, вы должны использовать 64, чтобы разделить на не 50. Я не уверен, почему это именно так, но я могу догадаться, что это потому64 - это коэффициент 2, а компьютерам нравится коэффициент 2, поэтому если вы используете 50, вы можете столкнуться с некоторыми столкновениями.

...