Search code examples
c++sdlcollision-detectioncollision

How would I write a for loop to check each pixel for collision?


I'm trying to write a for loop in my enemy class to check collision with the player...What I'm trying to do specifically is have it check each pixel in every row, so it should check all in a row then go to the next row. I'm having trouble figuring out how to write it so it checks every row...How would I do this? Here is what I've written...I'm pretty sure I need to have another for loop in there to go down each row, but I'm not sure how to implement it.

bool Enemy::checkCollision()
{
    for(i = 0; i < postion.w; i++)
    {
        if(position.x + i == player.position.x)
        {
            return true;
        }
        else if(position.y + i == player.position.y)
        {
            return true;
        }
        else
        { 
            return false; 
        }
    }
}

Solution

  • Waaaay to complicated. Have a free function which takes in two positions and two collision boxes and just use a simple check (concise version at the bottom, this one explains how it works):

    // y ^
    //   |
    //   +----> x
    struct SDL_Rect{
        unsigned x, y;
        int w, h;
    };
    
    bool collides(SDL_Rect const& o1, SDL_Rect const& o2){
      /* y_max -> +------------+
       *          |            |
       *          |            |
       *          +------------+ <- x_max
       *    |-----^------|
       *     y_min, x_min        
       */
      unsigned o1_x_min = o1.x, o1_x_max = o1.x + o1.w;
      unsigned o2_x_min = o2.x, o2_x_max = o2.x + o2.w;
    
      /* Collision on X axis: o1_x_max > o2_x_min && o1_x_min < o2_x_max
       * o1_x_min -> +-----------+ <- o1_x_max
       *     o2_x_min -> +-------------+ <- o2_x_max
       *
       * No collision 1: o1_x_max < o2_x_min
       * o1_x_min -> +-----------+ <- o1_x_max
       *                  o2_x_min -> +-------------+ <- o2_x_max
       *
       * No collision 2: o1_x_min > o2_x_max
       *                  o1_x_min -> +-------------+ <- o1_x_max
       * o2_x_min -> +-----------+ <- o2_x_max
       */
      if(o1_x_max >= o2_x_min && o1_x_min <= o2_x_max)
      { // collision on X, check Y
        /* Collision on Y axis: o1_y_max > o2_y_min && o1_y_min < o2_y_max
         * o1_y_max -> +
         *             |  + <- o2_y_max
         *             |  |
         * o1_y_min -> +  |
         *                + <- o2_y_min
         * No collision: o1_y_min > o2_y_max
         * o1_y_max -> +
         *             | 
         *             | 
         * o1_y_min -> +
         *                + <- o2_y_max
         *                |
         *                |
         *                + <- o2_y_min
         */
        unsigned o1_y_min = o1.y, o1_y_max = o1.y + o1.h;
        unsigned o2_y_min = o2.y, o2_y_max = o2.y + o2.h;
        return o1_y_max >= o2_y_min && o1_y_min <= o2_y_max;
      }
      return false;
    }
    

    Concise version of collides:

    bool collides(SDL_Rect const& o1, SDL_Rect const& o2){
      unsigned o1_x_min = o1.x, o1_x_max = o1.x + o1.w;
      unsigned o2_x_min = o2.x, o2_x_max = o2.x + o2.w;
    
      if(o1_x_max >= o2_x_min && o1_x_min <= o2_x_max)
      { // collision on X, check Y
        unsigned o1_y_min = o1.y, o1_y_max = o1.y + o1.h;
        unsigned o2_y_min = o2.y, o2_y_max = o2.y + o2.h;
        return o1_y_max >= o2_y_min && o1_y_min <= o2_y_max;
      }
      return false;
    }