Quantcast
Channel: Community | MonoGame - Latest topics
Viewing all articles
Browse latest Browse all 6821

Sphere-Box Collision Issue

$
0
0

@delgadobosso wrote:

Hey everyone, new to this community and I've been messing around with MonoGame. Right now I'm focusing on collision detection and action. I have a sphere that falls and stays on a platform using BoundingSphere and BoundingBox respectively, but there seems to be an issue when the sphere goes to the edge it doesn't detect the ground at certain points:

It's happening at consistent areas as well. The sphere is a 1.0 radius bound and the ground is Min(-10.0, 0.1, -10.0) to Max(10.0, 0.1, 10.0). If I place the ball at exactly 9.0 as either positive or negative in the X or Z axis, the ball will fall completely through. But if I place the ball at 10.0 in the X or Z axis, it's held up perfectly fine by the ground. It seems to fall through between 9.9~ to 9.0, and falls further down the closer to 9.0 it is. I've been trying to figure out on my own why it's doing this but I can't seem to think of any reason why. Initialize and Update code below:

Initialize:

    protected override void Initialize()
    {
        // Camera Coordinates Setup
        camPos = Vector3.Zero;
        camTarget = Vector3.Zero;

        // Mouse Setup
        Mouse.SetPosition(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
        ogMouseState = Mouse.GetState();

        // Matrix Setup
        projectionMat = Matrix.CreatePerspectiveFieldOfView(
            MathHelper.ToRadians(Constants.CAM_FOV), graphics.GraphicsDevice.Viewport.AspectRatio, 
            Constants.CAM_NEAR, Constants.CAM_FAR);
        viewMat = Matrix.CreateLookAt(camPos, camTarget, Vector3.Up);
        worldMat = Matrix.CreateWorld(Vector3.Zero, Vector3.Forward, Vector3.Up);

        // Load Models
        ground = Content.Load<Model>("Models/plane");
        basement = Content.Load<Model>("Models/plane");
        ball = Content.Load<Model>("Models/ball");

        // Setup Model Coords
        ballStart = Vector3.Up * Constants.BALL_STARTOFF + new Vector3(0.0f,0.0f,-0.0f);
        ballPos = ballStart;
        basementPos = new Vector3(0.0f, Constants.BASEMENT_OFFSETY, Constants.BASEMENT_OFFSETZ);
        camPos =  ballPos + new Vector3(0.0f, Constants.CAM_OFFSETY, -Constants.CAM_OFFSETZ);

        // Bounding Stuff
        groundBox = new BoundingBox(new Vector3(-10.0f, 0.1f, -10.0f), new Vector3(10.0f, 0.1f, 10.0f));

        basementBox = new BoundingBox(new Vector3(-10.0f, 0.1f, -10.0f) + basementPos, 
            new Vector3(10.0f, 0.1f, 10.0f) + basementPos);

        ballSphere = new BoundingSphere(ballPos, 1.0f);

        // Physics Setup
        accel = new Vector3(0.0f, -Constants.GRAV_Y, 0.0f);
        ballVel = Vector3.Zero;
        groundNormal = Vector3.Cross(new Vector3(-10.0f, 0.1f, -10.0f) - new Vector3(10.0f, 0.1f, -10.0f),
            new Vector3(-10.0f, 0.1f, -10.0f) - new Vector3(-10.0f, 0.1f, 10.0f));
        groundNormal.Normalize();

        // Dynamic Object Setup
        player = new GameObject("Player", ball, ballPos, ballSphere);

        x = 0;
        leftDown = false;
        ballHit = false;

        base.Initialize();
    }

Update:

    protected override void Update(GameTime gameTime) {
        var deltaTime = (float)gameTime.ElapsedGameTime.TotalSeconds;

        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
            Exit();

        // Collision Detection
        if (ballSphere.Intersects(groundBox)) {
            ballVel = Vector3.Zero;
            // Move ball out of ground based on overlap distance
            float groundTop = 0.0f;
            float ballButtom = ballPos.Y - ballSphere.Radius;
            float overlap = groundTop - ballButtom;
            ballPos += overlap * -groundNormal;
        } else if (ballSphere.Intersects(basementBox)) {
            ballVel = Vector3.Zero;
            // Move ball out of ground based on overlap distance
            float groundTop = basementBox.Max.Y;
            float ballButtom = ballPos.Y - ballSphere.Radius;
            float overlap = groundTop - ballButtom;
            ballPos += overlap * -groundNormal;
        } else {
            // Physics
            ballPos += deltaTime * (ballVel + deltaTime * accel / 2.0f);
            ballVel += deltaTime * accel;
        }

        if (Keyboard.GetState().IsKeyDown(Keys.Space)) {
            ballPos = ballStart;
            ballVel = Vector3.Zero;
        }

        // Hit ball in direction
        if (Mouse.GetState().LeftButton == ButtonState.Pressed && !leftDown) {
            hitDirection = rotMat.Forward;
            ballHit = true;
            leftDown = true;
        } else if (Mouse.GetState().LeftButton == ButtonState.Released) {
            leftDown = false;
        }

        // Ball Hit
        if (ballHit) {
            ballPos += Vector3.Normalize(hitDirection) * Constants.BALL_HITSPD;
        }
        if (Mouse.GetState().RightButton == ButtonState.Pressed) {
            ballHit = false;
        }

        ballSphere.Center = ballPos;

        // Orbit camera around center
        currMouseState = Mouse.GetState();
        x += (float)currMouseState.X - (float)ogMouseState.X;
        rotMat = Matrix.CreateRotationY(MathHelper.ToRadians(-Constants.CAM_ROTSPD * x));
        Mouse.SetPosition(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
        transRef = Vector3.Transform(new Vector3(0.0f, Constants.CAM_OFFSETY, -Constants.CAM_OFFSETZ), rotMat);
        camPos = transRef + ballPos;
        viewMat = Matrix.CreateLookAt(camPos, ballPos + (Vector3.Up * Constants.CAM_OFFSETVIEW), Vector3.Up);
        base.Update(gameTime);
    }

Posts: 2

Participants: 2

Read full topic


Viewing all articles
Browse latest Browse all 6821

Trending Articles