Platform-Style Slope Collision

Hey, I’ve finally created a method to handle sprite -> tile collisions but there is one little problem: It doesn’t handle going up sloped surfaces very well. Perhaps someone has some insight on this? Here is my current code:


      private int collisionHoriz(int x, int y)
      {
            TileSystem tilesys = GameGlobals.getTileSystem();

            int w = (int)getWidth();

            for(int i = x; i < (x + w); i++)
            {
                  if(tilesys.tileCollide(i, y))
                        return i;
            }
            return -1;
      }

      private int collisionVerti(int x, int y)
      {
            TileSystem tilesys = GameGlobals.getTileSystem();

            int h = (int)getHeight();

            for(int i = y; i < (y + h); i++)
            {
                  if(tilesys.tileCollide(x, i))
                        return i;
            }
            return -1;
      }

      public void think()
      {
            double vx = getPhysics().getLinearVelocity().getX() * GameGlobals.getStep();
            double vy = getPhysics().getLinearVelocity().getY() * GameGlobals.getStep();
            double px = getX();
            double py = getY();
            double npx = px + vx;
            double npy = py + vy;
            Vector2D size = getSize();
            double w = size.getX() - 1;
            double h = size.getY() - 1;
            TileSystem tilesys = GameGlobals.getTileSystem();
            int tmp;

            if(vy < 0) //Moving Up
            {
                  tmp = collisionHoriz((int)px, (int)npy);
                  if(tmp != -1)
                  {
                        for(int i = (int)npy;; i++)
                        {
                              if(!tilesys.tileCollide((int)px, i))
                              {
                                    setY(i);
                                    break;
                              }
                              else
                                    continue;
                        }
                        getPhysics().getLinearVelocity().setY(0);
                  }
                  else
                  {
                        getPhysics().applyGravity();
                        onGround = false;
                  }
            }
            else //Moving Down or On Ground
            {
                  tmp = collisionHoriz((int)px, (int)(npy + h));
                  if(tmp != -1) //On Ground
                  {
                        if(tmp > (npx + (w + npx)) / 2)
                              tmp = (int)(px + w);
                        else if(tmp < (npx + (w + npx)) / 2)
                              tmp = (int)px;
                        for(int i = (int)(npy + h);; i--)
                        {
                              if(!tilesys.tileCollide((int)tmp, i))
                              {
                                    setY(i - h);
                                    break;
                              }
                              else
                                    continue;
                        }
                        getPhysics().getLinearVelocity().setY(0);
                        onGround = true;
                        return;
                  }
                  else //Moving Down, Falling, In Air
                  {
                        tmp = collisionHoriz((int)px, (int)(npy + h + 1));
                        if(tmp != -1)
                        {
                              onGround = true;
                        }
                        else
                        {
                              if(vy > TileSystem.TILESIZE)
                                    getPhysics().getLinearVelocity().setY(TileSystem.TILESIZE);
                              getPhysics().applyGravity();
                              onGround = false;
                        }
                  }
            }

            vx = getPhysics().getLinearVelocity().getX() * GameGlobals.getStep();
            vy = getPhysics().getLinearVelocity().getY() * GameGlobals.getStep();
            px = getX();
            py = getY();
            npx = px + vx;
            npy = py + vy;
            if(vx > 0)
            {
                  //collision on the right side
                  tmp = collisionVerti((int)(npx + w), (int)py);
                  if(tmp != -1)
                  {
                        for(int i = (int)(npx + w);; i--)
                        {
                              if(!tilesys.tileCollide(i, (int)py))
                              {
                                    setX(i - w);
                                    break;
                              }
                              else
                                    continue;
                        }
                        getPhysics().getLinearVelocity().setX(-1 * vx);
                  }
            }
            else if(vx < 0)
            {
                  //collision on the left side
                  tmp = collisionVerti((int)npx, (int)py);
                  if(tmp != -1)
                  {
                        for(int i = (int)npx;; i++)
                        {
                              if(!tilesys.tileCollide(i, (int)py))
                              {
                                    setX(i);
                                    break;
                              }
                              else
                                    continue;
                        }
                        getPhysics().getLinearVelocity().setX(-1 * vx);
                  }
            }

            getPhysics().updateTick();
      }

Sample Image:

http://modx.ath.cx:1337/collision.jpg

someone else asked about this a little while ago:

http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=2D;action=display;num=1112789789

Mmm, ok thanks for the link. However, what if I’m using images and not able to store a slope for each of the tiles… ? I saw something about Area, and that it might be able to get the slope?

Well, I just made a simple modification to the code above:

            if(vy < 0) //Moving Up
            {
                  ...
            }
            else //Moving Down or On Ground
            {
                  tmp = collisionHoriz((int)px, (int)(npy + h));
                  if(tmp != -1) //On Ground
                  {
                              int f = collisionHoriz((int)px, i);
                              if(f == -1)
                              {
                                    setY(i - h);
                                    break;
                              }
                              else
                                    continue;
                        ...
                  }

Seems to work pretty well, now I just need to get my animations to be consistent with the movement…

Hope someone can use it.