简体   繁体   中英

2D collision detection not working XNA C#

I am brand new to XNA and C# (I started 2 days ago, so please forgive the sloppy programming), and I have run into a problem with a simple game I am making. I can't seem to find the solution in any of the online tutorials. I am trying to utilize rectangle collision detection but I cannot get it to work properly. The character falls completely through the floor and it seems there is no collision ever registering in any place. I cannot find my logic error here. Below I posted a bit of my code that pertains to the collision detection. I can post more if necessary. Thank you for the help in advance!

Level.cs

//The method below is called in the initial LoadContent method in Game1.cs. 'LoadBlocks()' is supposed to read in a text file and setup the level's "blocks" (the floor or platforms in the game). 

public void LoadBlocks(int level){
    if (level == 0)
        {
            fileName = "filepath";
        }

        System.IO.StreamReader file = new System.IO.StreamReader(fileName);
        while ((line = file.ReadLine()) != null)
        {
            for (int i = 0; i < 35; i++)
            {
                rectBlock = new Rectangle((int)positionBlock.X, (int)positionBlock.Y, width / 30, height / 30);

                if (line.Substring(i, 1).Equals(","))
                {
                    positionBlock.X += (width / 100) * 24;
                }
                if (line.Substring(i, 1).Equals("#"))
                {  //block -> (bool isPassable, Texture2D texture, Rectangle rectangle, Vector2 position)
                    block = new Block(false, textureBlock, rectBlock, positionBlock);
                    blocks.Add(block);
                    positionBlock.X += (width / 100) * 24;
                }
            }


            positionBlock.Y += (height / 100) * 8;
            positionBlock.X = 0;
        }
    }

//This method below updates the character 'bob' position and velocity.
 public void UpdatePlayer()
    {
        bob.position += bob.velocity;
        bob.rectangle = new Rectangle((int)bob.position.X, (int)bob.position.Y, width / 30, height / 30);

        float i = 1;
        bob.velocity.Y += 0.15f * i;
        foreach (Block block in blocks)
        {
            if (bob.isOnTopOf(bob.rectangle, block.rectangle))
            {
                bob.velocity.Y = 0f;
                bob.hasJumped = false;
            }
        }
    }

Character.cs

//Here is my whole Character class for 'bob'

public class Character
{
    int height = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Height;
    int width = GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Width;

    int health;
    String name;
    bool gender;
    Texture2D texture;
    public Vector2 position;
    public Vector2 velocity;
    public bool hasJumped;
    public Rectangle rectangle;

    public Character(int newHealth, String newName, bool newGender, Texture2D newTexture, Vector2 newPosition)
    {
        health = newHealth;
        gender = newGender;
        name = newName;
        texture = newTexture;
        position = newPosition;
        hasJumped = true;
        rectangle = new Rectangle(0,0, width/30,height/30);
        velocity = Vector2.Zero;
    }

    public bool isOnTopOf(Rectangle r1, Rectangle r2)
    {
        const int penetrationMargin = 5;

        return (r1.Bottom >= r2.Top - penetrationMargin &&
           r1.Bottom <= r2.Top &&
           r1.Right >= r2.Left + 5 &&
           r1.Left <= r2.Right - 5);

    }


    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, rectangle,null, Color.White,0,position,SpriteEffects.None,0);
    }

}

Sorry if this is too much posted code or is confusing, but any help is greatly appreciated! Thanks!

Your test condition for intersection appears to be incorrect, at least. There might be other problems with the code (there are several just giving a quick look at it), but let's focus on this:

r1.Bottom >= r2.Top - penetrationMargin &&
r1.Bottom <= r2.Top &&
r1.Right >= r2.Left + 5 &&
r1.Left <= r2.Right - 5;

First, don't code what exists in the library for you. Xna Rectangles have an Intersects method, so scrap that code and use it instead.

We'll look at the condition anyway:

r1's Bottom is below r2's Top minus a margin AND
r1's Bottom is above r2's Top AND (...)

This is already impossible. r1.Bottom cannot be both below and above r2.Top.

Further, even if all the comparisons were correct, you are using AND everywhere (&&), which means that the condition is only true if all 4 of them are true. Basically, you are not testing for intersection, you are testing for containement, ie you are testing that r1 is entirely within r2. An intersection test would join the conditions using OR (||) not AND (&&).

But again, although you might want to code it yourself for educative purposes, the best solution from an engineering perspective is to use what the library provides, here Rectangle.Intersects.

I figured it out, but I'm not sure why this actually works. Something was wrong with my draw method. I originally had:

spriteBatch.Draw(texture, rectangle, null, Color.White, 0, position, SpriteEffects.None, 0); 

as my method but then I changed this to

spriteBatch.Draw(texture, rectangle, Color.White);

and now everything works fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM