Question

Hello I am new to XNA and trying to develop a game prototype where the character moves from one location to another using mouse clicks.

I have a Rectangle representing the current position. I get the target location as a Vector2 using player mouse input. I extract the direction vector from the source to the target by Vector2 subtraction.

//the cursor's coordinates should be the center of the target position
float x = mouseState.X - this.position.Width / 2;
float y = mouseState.Y - this.position.Height / 2;
Vector2 targetVector = new Vector2(x, y);
Vector2 dir = (targetVector - this.Center); //vector from source center to target
                                            //center

I represent the world using a tile map, every cell is 32x32 pixels.

int tileMap[,];

What I want to do is check whether the direction vector above passes through any blue tiles on the map. A blue tile is equal 1 on the map.

I am not sure how to do this. I thought about using linear line equation and trigonometric formulas but I'm finding it hard to implement. I've tried normalizing the vector and multiplying by 32 to get 32 pixel length intervals along the path of the vector but it doesn't seem to work. Can anyone tell me if there's anything wrong in it, or another way to solve this problem? Thanks

//collision with blue wall. Returns point of impact
    private bool CheckCollisionWithBlue(Vector2 dir)
    {
        int num = Worldmap.size; //32
        int i = 0;
        int intervals = (int)(dir.Length() / num + 1);  //the number of 32-pixel length 
                                                        //inervals on the vector, with an edge
        Vector2 unit = Vector2.Normalize(dir) * num;    //a vector of length 32 in the same 
                                                        //direction as dir.
        Vector2 v = unit;
        while (i <= intervals & false)
        {
            int x = (int)(v.X / num);
            int y = (int)(v.Y / num);
            int type = Worldmap.getType(y, x);
            if (type == 1) //blue tile
            {
                return true;
            }
            else
            {
                i++;
                v = unit * i;
            }
        }
        return false;
    }
Was it helpful?

Solution

  1. You need the initial postion too, not only direction
  2. Maybe you need more resolution
  3. ¿what? remove the "false" evaluation
  4. The calcs for next pos are a bit complicated

 private bool CheckCollisionWithBlue(Vector2 source, Vector2 dir)
 {
    int num = 8; // pixel blocks of 8
    int i = 0;
    int intervals = (int)(dir.Length() / num);   

    Vector2 step = Vector2.Normalize(dir)*num;

    while (i <= intervals)
    {
        int x = (int)(source.X);
        int y = (int)(source.Y);
        int type = Worldmap.getType(y, x);
        if (type == 1) //blue tile
        {
            return true;
        }
        else
        {
            i++;
            source+=step;
        }
    }
    return false;
}

This will improve something your code, but maybe innacurate... it depends on what are you trying to do...

You maybe can find interesting the bresenham's line algorithm http://en.wikipedia.org/wiki/Bresenham's_line_algorithm

You should realize that you are not doing a volume collision but a line collision, if the ship or character or whatever that is at source position maybe you have to add more calcs

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top