Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public void applyDungeonPhysics(){
- /**
- *
- * We detect circle collisions with square tiles.
- *
- * To do this, we must first detect how many tiles the circle takes up based on its radius, and then check it against
- * the tiles it's currently intersecting.
- *
- * This is extremely useful because you can also use it in other places like spatial collision detection, which can
- * really optimize your game.
- *
- * Anyway, let's get started.
- *
- */
- //Just a signal for in case we do collide with something.
- boolean collided = false;
- //Your current x/y value on the tile map. In my case, I use floats so it's a direct representation.
- int tileX = (int) x;
- int tileY = (int) y;
- //Get the bounds of the circle as if it were a big tile.
- int leftBounds = (int) Math.max(0, Math.floor(x - radius));
- int rightBounds = (int) Math.min(d.getWidth(), Math.ceil(x + radius));
- int upBounds = (int) Math.max(0, Math.floor(y - radius));
- int bottomBounds = (int) Math.min(d.getHeight(), Math.ceil(y + radius));
- //Right collisions
- for (int i = tileX + 1; i < rightBounds; i++){
- if (!d.tileFilled(i, tileY, z)){
- //Move the x away from the tile, and also apply the same changes to his velocity.
- //If you don't use velocity based movement, it should still work.
- x += i - x - radius;
- vx += i - x - radius;
- rightBounds = i - 1;
- xDir = 1f;
- //This is just a utility for me to check for failures in collision prevention/handling
- updateLastCollision(i, tileY, z);
- //This is the signal that we have collided with something.
- collided = true;
- }
- }
- //Left collisions
- for (int i = tileX - 1; i >= leftBounds; i--){
- if (!d.tileFilled(i, tileY, z)){
- x += radius - (x - (i + 1));
- vx += radius - (x - (i + 1));
- leftBounds = i + 1;
- xDir = 1f;
- updateLastCollision(i, tileY, z);
- collided = true;
- }
- }
- //Up collisions
- for (int j = tileY - 1; j >= upBounds; j--){
- if (!d.tileFilled(tileX, j, z)){
- y += radius - (y - (j + 1));
- vy += radius - (y - (j + 1));
- upBounds = (int) y + 1;
- yDir = 1f;
- updateLastCollision(tileX, j, z);
- collided = true;
- }
- }
- //Down collisions
- for (int j = tileY + 1; j < bottomBounds; j++){
- if (!d.tileFilled(tileX, j, z)){
- y += j - y - radius;
- vy += j - y - radius;
- bottomBounds = (int) y - 1;
- yDir = 1f;
- updateLastCollision(tileX, j, z);
- collided = true;
- }
- }
- //Upper-Right of wall
- for (int j = upBounds; j < tileY; j++){
- for (int i = leftBounds; i < tileX; i++){
- if (!d.tileFilled(i, j, z)){
- double dx = x - (i + 1), dy = y - (j + 1);
- double distance = Math.sqrt(dx * dx + dy * dy);
- if (distance < radius){
- x += dx / distance * (radius - distance);
- y += dy / distance * (radius - distance);
- vx += dx / distance * (radius - distance);
- vy += dy / distance * (radius - distance);
- xDir = 1f;
- yDir = 1f;
- updateLastCollision(i, j, z);
- collided = true;
- }
- }
- }
- }
- //Upper-Left of wall
- for (int j = upBounds; j < tileY; j++){
- for (int i = tileX + 1; i < rightBounds; i++){
- if (!d.tileFilled(i, j, z)){
- double dx = x - i, dy = y - (j + 1);
- double distance = Math.sqrt(dx * dx + dy * dy);
- if (distance < radius){
- x += dx / distance * (radius - distance);
- y += dy / distance * (radius - distance);
- vx += dx / distance * (radius - distance);
- vy += dy / distance * (radius - distance);
- xDir = 1f;
- yDir = 1f;
- updateLastCollision(i, j, z);
- collided = true;
- }
- }
- }
- }
- //Bottom-right of wall
- for (int j = tileY + 1; j < bottomBounds; j++){
- for (int i = leftBounds; i < tileX; i++){
- if (!d.tileFilled(i, j, z)){
- double dx = x - (i + 1), dy = y - y;
- double distance = Math.sqrt(dx * dx + dy * dy);
- if (distance < radius){
- x += dx / distance * (radius - distance);
- y += dy / distance * (radius - distance);
- vx += dx / distance * (radius - distance);
- vy += dy / distance * (radius - distance);
- xDir = 1f;
- yDir = 1f;
- updateLastCollision(i, j, z);
- collided = true;
- }
- }
- }
- }
- //Bottom-left of wall
- for (int j = tileY + 1; j < bottomBounds; j++){
- for (int i = tileX + 1; i < rightBounds; i++){
- if (!d.tileFilled(i, j, z)){
- double dx = x - i, dy = y - j;
- double distance = Math.sqrt(dx * dx + dy * dy);
- if (distance < radius){
- x += dx / distance * (radius - distance);
- y += dy / distance * (radius - distance);
- vx += dx / distance * (radius - distance);
- vy += dy / distance * (radius - distance);
- xDir = 1f;
- yDir = 1f;
- updateLastCollision(i, j, z);
- collided = true;
- }
- }
- }
- }
- //Relay the collision signal to the entity that collided with a wall
- //The method can be used in any way, for example, the player uses it for wall jumping.
- if (collided) hitObstacle();
- }
Advertisement
Add Comment
Please, Sign In to add comment