Raycasting not finding object?

Topics: Developer Forum
Mar 20, 2011 at 1:27 AM
Edited Mar 20, 2011 at 1:30 AM

I'm trying to do a platformer, where a player can "vault" over an object (parkour style). To detect if the player is in range, I raycast in the direction they're heading, and grab the first one with the appropriate user data.

I'm having a problem with raycasting not finding the object when the player is sufficiently close to it.

Code speaks 1000 words, so here's a demo app. Hit the spacebar to start moving the "player" back and forth, and look at the trace (output) window. You'll see a list of found objects in the raycast, followed by "found" or "not found". Since the block and ray never move, it should always be able to find it.

Any way around this? Or is there a better method for finding "in range" fixtures?

Edit: I'm aware I'm not moving my raycast to match the player position... That's not terribly important - this is just a code sample. The real thing raycasts from the appropriate location


using System.Collections.Generic;
using FarseerPhysics.DebugViews;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Diagnostics;

namespace FreeRunnerPrototype
{
    public class TestGame : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;

        DebugViewXNA _debugView;
        Body player;
        World world;

        public TestGame()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.PreferredBackBufferHeight = 600;
            graphics.PreferredBackBufferWidth = 800;
        }

        protected override void Initialize()
        {
            world = new FarseerPhysics.Dynamics.World(-20f * Vector2.UnitY);

            List<Fixture> capsule = FixtureFactory.CreateCapsule(world, 1f, 0.4f, 1);
            player = capsule[0].Body;
            player.BodyType = BodyType.Dynamic;
            player.Position = new Vector2(2f, 0.95f);
            player.FixedRotation = true;
            foreach (var f in capsule)
            {
                f.Friction = 0;
                f.UserData = "Player";
            }

            Fixture block = FixtureFactory.CreateRectangle(world, 1f, 1.0f, 1);
            block.Body.BodyType = BodyType.Static;
            block.Body.Position = new Vector2(5f, 0.5f);
            block.Friction = 0;
            block.Restitution = 1;
            block.UserData = "Block";

            Fixture stopper = FixtureFactory.CreateRectangle(world, 1f, 1.0f, 1);
            stopper.Body.BodyType = BodyType.Static;
            stopper.Body.Position = new Vector2(0f, 0.5f);
            stopper.Friction = 0;
            stopper.Restitution = 1;
            stopper.UserData = "Stopper";

            Fixture ground = FarseerPhysics.Factories.FixtureFactory.CreateRectangle(world, 50, 1, 1);
            ground.Body.Position = new Vector2(0, -0.5f);
            ground.UserData = "Ground";


            base.Initialize();
        }

        public string FindObject()
        {
            // Raycast to find potential object
            Vector2 raycastStart = new Vector2(2, 0.95f);
            Vector2 raycastEnd = raycastStart + 5 * Vector2.UnitX;
            string found = null;
            world.RayCast((f, pt, n, fr) =>
            {
                string target = f.UserData as string;

                Trace.Write((target ?? "== NULL ==") + "  ");
                if (target == "Block")
                {
                    found = target;
                    return 1;
                }
                return fr;

            }, raycastStart, raycastEnd);
            Trace.WriteLine(found == null ? "Not found" : "Found");
            return found;
        }

        protected override void LoadContent()
        {
            _debugView = new DebugViewXNA(world);
            _debugView.LoadContent(GraphicsDevice, Content);
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            KeyboardState state = Keyboard.GetState();
            if (state.IsKeyDown(Keys.Escape)) Exit();

            if (state.IsKeyDown(Keys.Space))
            {
                player.LinearVelocity = new Vector2(5, 0);
            }

            // Pretty much check for raycast success

            float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
            world.Step(dt);

            string s = FindObject();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            Matrix proj = Matrix.Identity;
            Matrix view = Matrix.CreateOrthographicOffCenter(0, 8, -1, 5, -1, 1);
            _debugView.RenderDebugData(ref proj, ref view);

            base.Draw(gameTime);
        }
    }
}


Thanks!