OSDN Git Service

Change collision detection in SuperKoalio test.
authorJustin Shapcott <support@mobidevelop.com>
Fri, 22 Feb 2013 13:24:25 +0000 (06:24 -0700)
committerJustin Shapcott <support@mobidevelop.com>
Fri, 22 Feb 2013 13:24:25 +0000 (06:24 -0700)
tests/gdx-tests/src/com/badlogic/gdx/tests/superkoalio/SuperKoalio.java

index b91fce0..4a0b88c 100755 (executable)
@@ -8,8 +8,6 @@ import com.badlogic.gdx.graphics.Texture;
 import com.badlogic.gdx.graphics.g2d.Animation;\r
 import com.badlogic.gdx.graphics.g2d.SpriteBatch;\r
 import com.badlogic.gdx.graphics.g2d.TextureRegion;\r
-import com.badlogic.gdx.graphics.glutils.ShapeRenderer;\r
-import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;\r
 import com.badlogic.gdx.maps.tiled.TiledMap;\r
 import com.badlogic.gdx.maps.tiled.TiledMapTile;\r
 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;\r
@@ -126,6 +124,7 @@ public class SuperKoalio extends GdxTest {
                renderKoala(deltaTime);\r
        }\r
        \r
+       private Vector2 tmp = new Vector2();\r
        private void updateKoala(float deltaTime) {\r
                koala.stateTime += deltaTime;\r
                \r
@@ -159,78 +158,98 @@ public class SuperKoalio extends GdxTest {
                // position and velocity. Collision detection will clamp the\r
                // velocity if necessary and move the koala out of tiles\r
                Rectangle koalaRect = rectPool.obtain();\r
-               System.out.println("frame");\r
-               koalaRect.set(koala.position.x, koala.position.y, Koala.WIDTH, Koala.HEIGHT);\r
+               Rectangle intersect = rectPool.obtain();\r
+               tmp.set(koala.position).add(koala.velocity);\r
                \r
-               koalaRect.y += koala.velocity.y;\r
-               for (Rectangle rect: getCollidingTiles(koala.position, 0, koala.velocity.y)) {\r
-                       if (koalaRect.overlaps(rect)) {\r
-                               System.out.println("coll y");\r
-                               if (koala.velocity.y < 0) {\r
-                                       koalaRect.y = rect.y + rect.height + 0.001f;\r
-                                       koala.grounded = true;\r
-                               } else if(koala.velocity.y > 0 ){\r
-                                       koalaRect.y = rect.y - rect.height - 0.001f;\r
-                               }\r
+               koalaRect.set(tmp.x, tmp.y, Koala.WIDTH, Koala.HEIGHT);\r
+               getSurroundingTilesForPosition(tmp.set(koala.position).add(Koala.WIDTH / 2, Koala.HEIGHT / 2), (TiledMapTileLayer) map.getLayers().getLayer(1));\r
+               \r
+               TileData item = null;\r
+               \r
+               item = surroundingTiles[UP];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {                          \r
+                               koalaRect.y -= intersect.height;\r
                                koala.velocity.y = 0;\r
                        }\r
                }\r
-               koala.position.set(koalaRect.x, koalaRect.y);\r
-\r
-               koalaRect.x += koala.velocity.x;\r
-               for (Rectangle rect: getCollidingTiles(koala.position, koala.velocity.x, 0)) {\r
-                       if (koalaRect.overlaps(rect)) {\r
-                               System.out.println("coll x");\r
-                               if (koala.velocity.x < 0) {\r
-                                       koalaRect.x = rect.x + rect.width + 0.001f;\r
-                               } else if(koala.velocity.x > 0){\r
-                                       koalaRect.x = rect.x - rect.width - 0.001f;\r
+               item = surroundingTiles[DOWN];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {\r
+                               koalaRect.y += intersect.height;\r
+                               koala.velocity.y = 0;\r
+                               koala.grounded = true;\r
+                       }       \r
+               }\r
+               item = surroundingTiles[LEFT];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {\r
+                               koalaRect.x += intersect.width;\r
+                       }\r
+               }\r
+               item = surroundingTiles[RIGHT];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {\r
+                               koalaRect.x -= intersect.width;\r
+                       }                       \r
+               }\r
+               item = surroundingTiles[UP_LEFT];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {\r
+                               if (intersect.width > intersect.height) {\r
+                                       koalaRect.y -= intersect.height;\r
+                                       koala.velocity.y = 0;\r
+                               } else {\r
+                                       koalaRect.x += intersect.width;\r
+                               }\r
+                       }                       \r
+               }\r
+               item = surroundingTiles[UP_RIGHT];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {\r
+                               if (intersect.width > intersect.height) {\r
+                                       koalaRect.y -= intersect.height;\r
+                                       koala.velocity.y = 0;\r
+                               } else {\r
+                                       koalaRect.x -= intersect.width;\r
+                               }\r
+                       }                       \r
+               }\r
+               item = surroundingTiles[DOWN_LEFT];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {\r
+                               if (intersect.width > intersect.height) {\r
+                                       koalaRect.y += intersect.height;\r
+                               } else {\r
+                                       koalaRect.x += intersect.width;\r
+                               }\r
+                       }                       \r
+               }\r
+               item = surroundingTiles[DOWN_RIGHT];\r
+               if (item.tile != null) {\r
+                       if (intersect(koalaRect, item.rectangle, intersect)) {\r
+                               if (intersect.width > intersect.height) {\r
+                                       koalaRect.y += intersect.height;\r
+                               } else {\r
+                                       koalaRect.x -= intersect.width;\r
                                }\r
-                               koala.velocity.x = 0;\r
-                               koala.state = Koala.State.Standing;\r
                        }\r
                }\r
                koala.position.set(koalaRect.x, koalaRect.y);\r
-\r
+               \r
                // unscale the velocity by the inverse delta time and set \r
                // the latest position\r
                koala.velocity.mul(1/deltaTime);\r
                \r
                // free the koala rectangle\r
                rectPool.free(koalaRect);\r
+               rectPool.free(intersect);\r
                \r
                // Apply damping to the velocity on the x-axis so we don't\r
                // walk infinitely once a key was pressed\r
                koala.velocity.x *= Koala.DAMPING;\r
        }\r
        \r
-       private Array<Rectangle> getCollidingTiles(Vector2 position, float velocityX, float velocityY) {\r
-               // figure out the tiles within which the koala is moving in the current timestep\r
-               int startX, startY, endX, endY;\r
-               if(velocityX < 0) startX = (int)(position.x + velocityX);\r
-               else startX = (int)position.x;\r
-               if(velocityY < 0) startY = (int)(position.y + velocityY);\r
-               else startY = (int)position.y;\r
-               endX = (int)(startX + Koala.WIDTH + Math.abs(velocityX));\r
-               endY = (int)(startY + Koala.HEIGHT + Math.abs(velocityY));\r
-               \r
-               // get all the tiles that overlap this area\r
-               TiledMapTileLayer layer = (TiledMapTileLayer)map.getLayers().getLayer(1);\r
-               rectPool.freeAll(tiles);\r
-               tiles.clear();\r
-               for(int y = startY; y <= endY; y++) {\r
-                       for(int x = startX; x <= endX; x++) {\r
-                               Cell cell = layer.getCell(x, y);\r
-                               if(cell.getTile() != null) {\r
-                                       Rectangle rect = rectPool.obtain();\r
-                                       rect.set(x, y, 1, 1);\r
-                                       tiles.add(rect);\r
-                               }\r
-                       }\r
-               }\r
-               return tiles;\r
-       }\r
-       \r
        private void renderKoala(float deltaTime) {\r
                // based on the koala state, get the animation frame\r
                TextureRegion frame = null;\r
@@ -256,4 +275,144 @@ public class SuperKoalio extends GdxTest {
        @Override\r
        public void dispose () {\r
        }\r
+       \r
+       public static final int UP = 1;\r
+       public static final int DOWN = 6;\r
+       public static final int LEFT = 3;\r
+       public static final int RIGHT = 4;\r
+       public static final int UP_LEFT = 0;\r
+       public static final int UP_RIGHT = 2;\r
+       public static final int DOWN_LEFT = 5;\r
+       public static final int DOWN_RIGHT = 7;\r
+       \r
+       TileData[] surroundingTiles = new TileData[] {\r
+               new TileData(), new TileData(), new TileData(),\r
+               new TileData(), /*  KOALIO  */  new TileData(),\r
+               new TileData(), new TileData(), new TileData(),\r
+       };\r
+       \r
+       public static class TileData {\r
+               TiledMapTile tile;\r
+               int tileX;\r
+               int tileY;\r
+               \r
+               Rectangle rectangle;\r
+               \r
+               public TileData() {\r
+                       tile = null;\r
+                       tileX = -1;\r
+                       tileY = -1;\r
+                       rectangle = new Rectangle();\r
+               }\r
+               \r
+               public void reset() {\r
+                       tile = null;\r
+                       tileX = -1;\r
+                       tileY = -1;\r
+                       rectangle.set(0, 0, 0, 0);\r
+               }\r
+               \r
+       }\r
+       private void getSurroundingTilesForPosition(Vector2 position, TiledMapTileLayer layer) {\r
+               int tileX = (int) position.x;\r
+               int tileY = (int) position.y;\r
+               \r
+               for (int i = 0, j = surroundingTiles.length; i < j; i++) {\r
+                       surroundingTiles[i].reset();\r
+               }\r
+               \r
+               boolean goUp = tileY > 0;\r
+               boolean goDown = tileY < layer.getHeight() - 1;\r
+               boolean goLeft = tileX > 0;\r
+               boolean goRight = tileX < layer.getWidth() - 1;\r
+\r
+               TileData item = null;\r
+               \r
+               if (goUp) {\r
+                       item = surroundingTiles[UP];\r
+                       \r
+                       item.tileX = tileX;\r
+                       item.tileY = tileY + 1;\r
+                       \r
+                       item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                       item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+                       \r
+                       if (goLeft) {\r
+                               item = surroundingTiles[UP_LEFT];\r
+                               item.tileX = tileX - 1;\r
+                               item.tileY = tileY + 1;\r
+                               item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                               item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+                       }\r
+                       if (goRight) {\r
+                               item = surroundingTiles[UP_RIGHT];\r
+                               item.tileX = tileX + 1;\r
+                               item.tileY = tileY + 1;\r
+                               item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                               item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+                       }                       \r
+               }\r
+               if (goDown) {\r
+                       item = surroundingTiles[DOWN];\r
+                       item.tileX = tileX;\r
+                       item.tileY = tileY - 1;\r
+                       item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                       item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+                       if (goLeft) {\r
+                               item = surroundingTiles[DOWN_LEFT];\r
+                               item.tileX = tileX - 1;\r
+                               item.tileY = tileY - 1;\r
+                               item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                               item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+                       }\r
+                       if (goRight) {\r
+                               item = surroundingTiles[DOWN_RIGHT];\r
+                               item.tileX = tileX + 1;\r
+                               item.tileY = tileY - 1;\r
+                               item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                               item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+                       }\r
+               }\r
+               if (goLeft) {\r
+                       item = surroundingTiles[LEFT];\r
+                       item.tileX = tileX - 1;\r
+                       item.tileY = tileY;\r
+                       item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                       item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+               }\r
+               if (goRight) {\r
+                       item = surroundingTiles[RIGHT];\r
+                       item.tileX = tileX + 1;\r
+                       item.tileY = tileY;\r
+                       item.tile = layer.getCell(item.tileX, item.tileY).getTile();\r
+                       item.rectangle.set(item.tileX, item.tileY, 1, 1);\r
+               }\r
+       }\r
+\r
+       public static boolean intersect (Rectangle r1, Rectangle r2, Rectangle out) {\r
+               final float r1L = r1.x;\r
+               final float r1T = r1.y;\r
+\r
+               final float r1R = r1.x + r1.width;\r
+               final float r1B = r1.y + r1.height;\r
+\r
+               final float r2L = r2.x;\r
+               final float r2T = r2.y;\r
+\r
+               final float r2R = r2.x + r2.width;\r
+               final float r2B = r2.y + r2.height;\r
+\r
+               if (r1L < r2R && r2L < r1R && r1T < r2B && r2T < r1B) {\r
+                       if (out != null) {\r
+                               final float outL = (r1L > r2L) ? r1L : r2L;\r
+                               final float outT = (r1T > r2T) ? r1T : r2T;\r
+                               final float outR = (r1R < r2R) ? r1R : r2R;\r
+                               final float outB = (r1B < r2B) ? r1B : r2B;\r
+\r
+                               out.set(outL, outT, outR - outL, outB - outT);\r
+                       }\r
+                       return true;\r
+               }\r
+               return false;\r
+       }\r
 }\r