So I actually posted this in the C# section, but despite peoples best efforts, all all the help there, the problem is still not solved.

Background:

Im making a game in xna/c# (Who isnt these days). For collision detection, I though I would use rectangles and lists.

My thought process was:
1. Load collision map file
2. Parse file, where there is a 1, create a rectangle and add to list
3. In the player class, iterate through the list of rectangles (I called the list 'badTiles')
4. If the player intersects one of the rectangles, prevent them from moving, if not, allow them to move as normal.

The problem is, the player will only be prevented from moving into the last 'badTile' in the list. Why is this happening?

player class code:

private void TestCollResolve(Player player, Core core, Camera camera, Direction dir)
{

    foreach (Rectangle badTile in core.badTiles)
    {
        if (futurePos.Intersects(badTile))
        {
            Console.WriteLine("Collision with bad tile: " + badTile.ToString());

            // Players future position will intersect a bad tile, dont change players position vector.
            if (dir == dirUp)
            {
                player.playerVel.Z = 0; // Change velocity vector of player and camera to 0.
                camera.CameraVel.Z = 0;

            }
            else if (dir == dirDown)
            {
                player.playerVel.W = 0; // Change velocity vector of player and camera to 0.
                camera.CameraVel.W = 0;
            }
            else if (dir == dirLeft)
            {
                player.playerVel.X = 0; // Change velocity vector of player and camera to 0.
                camera.CameraVel.X = 0;
            }
            else if (dir == dirRight)
            {
                player.playerVel.Y = 0; // Change velocity vector of player and camera to 0.
                camera.CameraVel.Y = 0;
            }
        }
        else if (!futurePos.Intersects(badTile))
        {
            // Players future position will not intersect a bad tile, chenge players position vector.
            if (dir == dirUp || dir == dirDown)
            {
                // Change players yVector to tmp yVector.
                player.playerBounds.Y = futurePos.Y;

                // Restore players velocity components to origional values.
                player.playerVel.Z = 2;
                player.playerVel.W = 2;

                // Restore cameras velocity components to origional values.
                camera.CameraVel.Z = 2;
                camera.CameraVel.W = 2;

            }

            else if (dir == dirLeft || dir == dirRight)
            {
                // Change players xVector to tmp xVector.
                player.playerBounds.X = futurePos.X;

                // Restore players velocity components to origional values.
                player.playerVel.X = 2;
                player.playerVel.Y = 2;

                // Restore cameras velocity components to origional values.
                camera.CameraVel.X = 2;
                camera.CameraVel.Y = 2;

            }
        }
    }
}

Im completly stumped on this one! Ive already added in break points at the foreach statement, the if(futurePos.Intersects(core.badTile)) and even added breakpoints checking what arrow keys are being pressed. Everything appears to be working fine, it just dosent work?!

Recommended Answers

All 3 Replies

Hi there!

I'm interested in the constents of core.badTiles. How is it populated? Have you checked that there are more than just one rectangle? Could you post the code where the list is built?

Also, one thought that also came into my mind is the last else if statement (else if (dir == dirLeft || dir == dirRight)). First you test if there is an intersection between futurePos and badTile, then you test its negative. One of these will allways be true, so you will never reach your last else if-statement. I'm pretty sure that's the case anyway :)

Regards,
Emil Olofsson

Oh god I'm sorry! I completely forgot about this forum post!

Right, core.badTiles is populated by reading a text file that contains collision data for any map. The collision map takes on the form of a classic tile map:

{0,0,1,1}
{1,1,0,1}
{0,0,0,1}

You get the idea. Where 1 is an inpassable tile (badTile), and 0 is a passable tile (goodTile).

Once the collision map has been read, a method within the .core class will determin what char position within the collision doc the 1's are. When each bad tile has been accounted for, they will be added to the badTiles Rectangle list; where the x & y positions are the badTiles postion in the collision doc multiplyed by 30 (a game tiles width and height).

The list is then used in the above method to determin whether a future movement will be onto a badTile.

And to follow up on your request:

public List<Rectangle> badTiles = new List<Rectangle>(); // List of all bad tiles in game.

// Reads collision map file. Creates rectangles @ relevant coor's for each 'bad' tile.
public void LoadCollisionMap(string name)
{
    // Sets capacity to one.
    badTiles.Capacity = 1;

    string path = "C:/Users/Chris/Desktop/Documents/C# Projects/RPGEngine/Maps/" + name + ".txt";

    // Width and height of our tile array
    int width = 0;
    int height = File.ReadLines(path).Count();

    StreamReader sReader = new StreamReader(path);
    string line = sReader.ReadLine();
    string[] tileNo = line.Split(',');

    width = tileNo.Count();
    sReader.Close();

    // Re-initialising sReader
    sReader = new StreamReader(path);

    int c = 1;

    for (int y = 0; y < height; y++)
    {
        line = sReader.ReadLine();
        tileNo = line.Split(',');

        for (int x = 0; x < width; x++)
        {
            if ((Convert.ToInt32(tileNo[x])) == 1)
            {
                badTiles.Add(new Rectangle((x * TILE_WIDTH), (y * TILE_HEIGHT), 32, 32));
                badTiles.Capacity++; // Increases capacity of list for each new element.

                Console.WriteLine("New rectangle added, number: <" + x + ", " + y + ">, Count: " + c + "."); // Adds some info to the console for easy viewing.
                c++;

            }
        }
    }
    sReader.Close();
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.