SkyAphid

Tile to Circle Collision Detection/Handling

Mar 30th, 2013
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.23 KB | None | 0 0
  1.     public void applyDungeonPhysics(){
  2.         /**
  3.          *
  4.          * We detect circle collisions with square tiles.
  5.          *
  6.          * To do this, we must first detect how many tiles the circle takes up based on its radius, and then check it against
  7.          * the tiles it's currently intersecting.
  8.          *
  9.          * This is extremely useful because you can also use it in other places like spatial collision detection, which can
  10.          * really optimize your game.
  11.          *
  12.          * Anyway, let's get started.
  13.          *
  14.          */
  15.        
  16.         //Just a signal for in case we do collide with something.
  17.         boolean collided = false;
  18.        
  19.         //Your current x/y value on the tile map. In my case, I use floats so it's a direct representation.
  20.         int tileX = (int) x;
  21.         int tileY = (int) y;
  22.        
  23.         //Get the bounds of the circle as if it were a big tile.
  24.         int leftBounds = (int) Math.max(0, Math.floor(x - radius));
  25.         int rightBounds = (int) Math.min(d.getWidth(), Math.ceil(x + radius));
  26.         int upBounds = (int) Math.max(0, Math.floor(y - radius));
  27.         int bottomBounds = (int) Math.min(d.getHeight(), Math.ceil(y + radius));
  28.        
  29.         //Right collisions
  30.         for (int i = tileX + 1; i < rightBounds; i++){
  31.             if (!d.tileFilled(i, tileY, z)){
  32.                 //Move the x away from the tile, and also apply the same changes to his velocity.
  33.                 //If you don't use velocity based movement, it should still work.
  34.                 x += i - x - radius;
  35.                 vx += i - x - radius;
  36.  
  37.                 rightBounds = i - 1;
  38.                 xDir = 1f;
  39.  
  40.                 //This is just a utility for me to check for failures in collision prevention/handling
  41.                 updateLastCollision(i, tileY, z);
  42.                
  43.                 //This is the signal that we have collided with something.
  44.                 collided = true;
  45.             }
  46.         }
  47.        
  48.         //Left collisions
  49.         for (int i = tileX - 1; i >= leftBounds; i--){
  50.             if (!d.tileFilled(i, tileY, z)){
  51.                 x += radius - (x - (i + 1));
  52.                 vx += radius - (x - (i + 1));
  53.  
  54.                 leftBounds = i + 1;
  55.                 xDir = 1f;
  56.                
  57.                 updateLastCollision(i, tileY, z);
  58.                
  59.                 collided = true;
  60.             }
  61.         }
  62.        
  63.         //Up collisions
  64.         for (int j = tileY - 1; j >= upBounds; j--){
  65.             if (!d.tileFilled(tileX, j, z)){
  66.                 y += radius - (y - (j + 1));
  67.                 vy += radius - (y - (j + 1));
  68.                
  69.                 upBounds = (int) y + 1;
  70.                 yDir = 1f;
  71.                
  72.                 updateLastCollision(tileX, j, z);
  73.                
  74.                 collided = true;
  75.             }
  76.         }
  77.        
  78.         //Down collisions
  79.         for (int j = tileY + 1; j < bottomBounds; j++){
  80.             if (!d.tileFilled(tileX, j, z)){
  81.                 y += j - y - radius;
  82.                 vy += j - y - radius;
  83.  
  84.                 bottomBounds = (int) y - 1;
  85.                 yDir = 1f;
  86.                
  87.                 updateLastCollision(tileX, j, z);
  88.                
  89.                 collided = true;
  90.             }
  91.         }
  92.        
  93.         //Upper-Right of wall
  94.         for (int j = upBounds; j < tileY; j++){
  95.             for (int i = leftBounds; i < tileX; i++){
  96.                 if (!d.tileFilled(i, j, z)){
  97.                     double dx = x - (i + 1), dy = y - (j + 1);
  98.                     double distance = Math.sqrt(dx * dx + dy * dy);
  99.                    
  100.                     if (distance < radius){
  101.                         x += dx / distance * (radius - distance);
  102.                         y += dy / distance * (radius - distance);
  103.                         vx += dx / distance * (radius - distance);
  104.                         vy += dy / distance * (radius - distance);
  105.                        
  106.                         xDir = 1f;
  107.                         yDir = 1f;
  108.                        
  109.                         updateLastCollision(i, j, z);
  110.                        
  111.                         collided = true;
  112.                     }
  113.                 }
  114.             }
  115.         }
  116.        
  117.         //Upper-Left of wall
  118.         for (int j = upBounds; j < tileY; j++){
  119.             for (int i = tileX + 1; i < rightBounds; i++){
  120.                 if (!d.tileFilled(i, j, z)){
  121.                     double dx = x - i, dy = y - (j + 1);
  122.                     double distance = Math.sqrt(dx * dx + dy * dy);
  123.                    
  124.                     if (distance < radius){
  125.                         x += dx / distance * (radius - distance);
  126.                         y += dy / distance * (radius - distance);
  127.                         vx += dx / distance * (radius - distance);
  128.                         vy += dy / distance * (radius - distance);
  129.                        
  130.                         xDir = 1f;
  131.                         yDir = 1f;
  132.                        
  133.                         updateLastCollision(i, j, z);
  134.                        
  135.                         collided = true;
  136.                     }
  137.                 }
  138.             }
  139.         }
  140.        
  141.         //Bottom-right of wall
  142.         for (int j = tileY + 1; j < bottomBounds; j++){
  143.             for (int i = leftBounds; i < tileX; i++){
  144.                 if (!d.tileFilled(i, j, z)){
  145.                     double dx = x - (i + 1), dy = y - y;
  146.                     double distance = Math.sqrt(dx * dx + dy * dy);
  147.                    
  148.                     if (distance < radius){
  149.                         x += dx / distance * (radius - distance);
  150.                         y += dy / distance * (radius - distance);
  151.                         vx += dx / distance * (radius - distance);
  152.                         vy += dy / distance * (radius - distance);
  153.                        
  154.                         xDir = 1f;
  155.                         yDir = 1f;
  156.                        
  157.                         updateLastCollision(i, j, z);
  158.                        
  159.                         collided = true;
  160.                     }
  161.                 }
  162.             }
  163.         }
  164.        
  165.         //Bottom-left of wall
  166.         for (int j = tileY + 1; j < bottomBounds; j++){
  167.             for (int i = tileX + 1; i < rightBounds; i++){
  168.                 if (!d.tileFilled(i, j, z)){
  169.                     double dx = x - i, dy = y - j;
  170.                     double distance = Math.sqrt(dx * dx + dy * dy);
  171.                    
  172.                     if (distance < radius){
  173.                         x += dx / distance * (radius - distance);
  174.                         y += dy / distance * (radius - distance);
  175.                         vx += dx / distance * (radius - distance);
  176.                         vy += dy / distance * (radius - distance);
  177.                        
  178.                         xDir = 1f;
  179.                         yDir = 1f;
  180.                        
  181.                         updateLastCollision(i, j, z);
  182.                        
  183.                         collided = true;
  184.                     }
  185.                 }
  186.             }
  187.         }
  188.        
  189.         //Relay the collision signal to the entity that collided with a wall
  190.         //The method can be used in any way, for example, the player uses it for wall jumping.
  191.         if (collided) hitObstacle();
  192.     }
Advertisement
Add Comment
Please, Sign In to add comment