/** * Called after Box2D world step method, to notify FieldElements that the ball collided with. */ void processBallContacts() { for(int i=0; i<contactedBalls.size(); i++) { Ball ball = contactedBalls.get(i); Fixture f = contactedFixtures.get(i); FieldElement element = bodyToFieldElement.get(f.getBody()); if (element!=null) { element.handleCollision(ball, f.getBody(), this); if (delegate!=null) { delegate.processCollision(this, element, f.getBody(), ball); } if (element.getScore()!=0) { this.gameState.addScore(element.getScore()); audioPlayer.playScore(); } } } }
@Override public void endContact(Contact contact) { Fixture fixture = null; Ball ball = ballWithBody(contact.getFixtureA().getBody()); if (ball != null) { fixture = contact.getFixtureB(); } else { ball = ballWithBody(contact.getFixtureB().getBody()); if (ball != null) { fixture = contact.getFixtureA(); } } if (ball != null) { contactedBalls.add(ball); contactedFixtures.add(fixture); } }
/** * {@inheritDoc} */ @Override public void beginContact(Contact contact) { Fixture fixA = contact.getFixtureA(); Fixture fixB = contact.getFixtureB(); ContactHandler handler; handler = beginContactFunctions.get(fixA.getFilterData().categoryBits); if (handler != null) handler.handle(fixA, fixB); handler = beginContactFunctions.get(fixB.getFilterData().categoryBits); if (handler != null) handler.handle(fixB, fixA); }
/** * {@inheritDoc} */ @Override public void endContact(Contact contact) { Fixture fixA = contact.getFixtureA(); Fixture fixB = contact.getFixtureB(); ContactHandler handler; handler = endContactFunctions.get(fixA.getFilterData().categoryBits); if (handler != null) handler.handle(fixA, fixB); handler = endContactFunctions.get(fixB.getFilterData().categoryBits); if (handler != null) handler.handle(fixB, fixA); }
/** * Function called in the game loop, responsible for updating the fluid. */ public void step() { for (Fixture fixture : fixtures) { if (fixture.getBody().isAwake()) { /* Create clipPolygon */ List<Vector2> clipPolygon = getFixtureVertices(fixture); /* Create subjectPolygon */ List<Vector2> subjectPolygon; if (isFluidFixed) { subjectPolygon = fluidVertices; } else subjectPolygon = getFixtureVertices(fluidSensor); /* Get intersection polygon */ List<Vector2> clippedPolygon = PolygonIntersector.clipPolygons( subjectPolygon, clipPolygon); if (!clippedPolygon.isEmpty()) { applyForces(fixture, clippedPolygon.toArray(new Vector2[0])); } } } }
/** * Because the algorithm is based on vertices, and the circles do not have vertices, we create a square around it. * @param fixture Circle fixture * @return A square instead of the circle */ private static PolygonShape circleToSquare(Fixture fixture) { Vector2 position = fixture.getBody().getLocalCenter(); float x = position.x; float y = position .y; float radius = fixture.getShape().getRadius(); PolygonShape octagon = new PolygonShape(); Vector2[] vertices = new Vector2[4]; vertices[0] = new Vector2(x-radius, y+radius); vertices[1]= new Vector2(x+radius, y+radius); vertices[2]= new Vector2(x-radius, y-radius); vertices[3]= new Vector2(x+radius, y-radius); octagon.set((Vector2[]) vertices); return octagon; }
/** * Constructor that allows to specify if there is an effect of waves and splash particles. * @param waves Specifies whether the object will have waves * @param splashParticles Specifies whether the object will have splash particles */ public Water(boolean waves, boolean splashParticles) { this.waves = waves; this.splashParticles = splashParticles; this.fixturePairs = new HashSet<Pair<Fixture, Fixture>>(); this.setDebugMode(false); if (waves) { textureWater = new TextureRegion(new Texture(Gdx.files.internal("water.png"))); polyBatch = new PolygonSpriteBatch(); } if (splashParticles) { textureDrop = new Texture(Gdx.files.internal("drop.png")); spriteBatch = new SpriteBatch(); particles = new ArrayList<Particle>(); } shapeBatch = new ShapeRenderer(); shapeBatch.setColor(0, 0.5f, 1, 1); }
@Override public void endContact(Contact contact) { Fixture fixA = contact.getFixtureA(); Fixture fixB = contact.getFixtureB(); if (fixA.getUserData() == "bottom" || fixB.getUserData() == "bottom") { Fixture bottom = fixA.getUserData() == "bottom" ? fixA : fixB; Fixture object = bottom == fixA ? fixB : fixA; //resets object touched if (object.getUserData() != null && InteractiveTileObject.class.isAssignableFrom(object.getUserData().getClass())) { isObjectTouched = NoObjectionGame.DEFAULT; } } }
@Override public void endContact(Contact contact) { Fixture fixtureA = contact.getFixtureA(); Fixture fixtureB = contact.getFixtureB(); // 夹具为空时,碰撞直接返回不执行。 if (fixtureA == null || fixtureB == null) { return; } //孙悟空跳跃结束 if (fixtureA.getUserData() != null && fixtureA.getUserData().equals("foot")) { // 计数器减1 platformNum--; } if (fixtureB.getUserData() != null && fixtureB.getUserData().equals("foot")) { // 计数器减1 platformNum--; } }
private void initBall() { float radius = 26; mBall = new Circle(0.f, 0.f, radius); mBallTextureRegion = new TextureRegion(new Texture(Gdx.files.internal("ball.png"))); // create physics body BodyDef bodyDef = new BodyDef(); bodyDef.type = BodyDef.BodyType.DynamicBody; bodyDef.position.set(mBall.x, mBall.y); CircleShape ballShape = new CircleShape(); ballShape.setRadius(mBall.radius - 2.f); mBallBody = mWorld.createBody(bodyDef); mBallBody.setUserData(new BodyUserDate(BODY_USER_DATA_TYPE_BALL)); Fixture fixture = mBallBody.createFixture(ballShape, 0.5f); fixture.setFriction(BALL_FRICTION_BASE); fixture.setRestitution(0.4f); ballShape.dispose(); }
public static List<RaycastHit> raycastPoint(final Vector2 pointToTest) { final List<RaycastHit> hits = new ArrayList<RaycastHit>(); Vector2 end = pointToTest.add(new Vector2(1, 1)); //TODO move to static single object physic.physicWorld.QueryAABB(new QueryCallback() { @Override public boolean reportFixture(Fixture fixture) { if (fixture.testPoint(pointToTest)) { hits.add(new RaycastHit(fixture, pointToTest)); } return true; } }, pointToTest.x < end.x ? pointToTest.x : end.x, pointToTest.y < end.y ? pointToTest.y : end.y, pointToTest.x > end.x ? pointToTest.x : end.x, pointToTest.y > end.y ? pointToTest.y : end.y); return hits; }
public static void emptyDestroyList() { if (!world.isLocked()) { while(toDestroyList.size > 0) { if (toDestroyList.get(0).getBody() != null) { Body b = toDestroyList.get(0).getBody(); Array<Fixture> fixes = new Array<Fixture>(); world.getFixtures(fixes); if (fixes.contains(b.getFixtureList().first(), false)) { world.destroyBody(b); } } toDestroyList.get(0).finalCleanup(); toDestroyList.get(0).removeFromWorldLayers(lh); toDestroyList.removeValue(toDestroyList.get(0), true); } } }
public void die(DeathType death) { if(alive) { if (grabbed != null) { stopGrabbing(false); } gameWorld.startRespawnClock(this); Fixture f = body.getFixtureList().get(0); Filter fi = f.getFilterData(); fi.categoryBits = BodyFactory.CAT_DECEASED; fi.maskBits = BodyFactory.MASK_DECEASED; f.setFilterData(fi); body.getFixtureList().set(0, f); super.die(death); } }
public void swapWorldLayers(LayerHandler lh) { removeFromWorldLayers(lh); lh.addEntityToLayer(this, LayerHandler.ground); swapped = true; Fixture f = body.getFixtureList().get(0); Filter fi = f.getFilterData(); fi.categoryBits = BodyFactory.CAT_IMPASSABLE; fi.maskBits = BodyFactory.MASK_SHERIFF_GROUND; f.setFilterData(fi); body.getFixtureList().set(0, f); canFire = false; TimerManager.addTimer(swapTimer); }
public void testPlayerMud(GameEntity geA, GameEntity geB, Fixture fA, Fixture fB, boolean start) { if (geA instanceof Player || geB instanceof Player) { if (geA instanceof Player && fA.getDensity() == BodyFactory.HIT_BOX_DEN || geB instanceof Player && fB.getDensity() == BodyFactory.HIT_BOX_DEN) { if (geB.getType() == EntityType.MUD) { handlePlayerTerrain(geA, geB, start); } else if (geA.getType() == EntityType.MUD) { handlePlayerTerrain(geB, geA, start); } } } }
public void testPlayerWater(GameEntity geA, GameEntity geB, Fixture fA, Fixture fB, boolean start) { if (geA instanceof Player || geB instanceof Player) { if (geA instanceof Player && fA.getDensity() == BodyFactory.HIT_BOX_DEN || geB instanceof Player && fB.getDensity() == BodyFactory.HIT_BOX_DEN) { if (geB.getType() == EntityType.WATER) { handlePlayerTerrain(geA, geB, start); } else if (geA.getType() == EntityType.WATER) { handlePlayerTerrain(geB, geA, start); } } } }
public void testPlayerTower(GameEntity geA, GameEntity geB, Fixture fA, Fixture fB, boolean start) { if (geA instanceof Player || geB instanceof Player) { if (geA instanceof Player && fA.getDensity() == BodyFactory.HIT_BOX_DEN || geB instanceof Player && fB.getDensity() == BodyFactory.HIT_BOX_DEN) { if (geB.getType() == EntityType.TOWER) { handlePlayerTower(geA, geB, start); } else if (geA.getType() == EntityType.TOWER) { handlePlayerTower(geB, geA, start); } } } }
public void testPlayerBridge(GameEntity geA, GameEntity geB, Fixture fA, Fixture fB, boolean start) { if (geA instanceof Player || geB instanceof Player) { if (geA instanceof Player && fA.getDensity() == BodyFactory.BRIDGE_BOX_DEN || geB instanceof Player && fB.getDensity() == BodyFactory.BRIDGE_BOX_DEN) { if (geB.getType() == EntityType.BRIDGE) { handlePlayerBridge(geA, geB, start); } else if (geA.getType() == EntityType.BRIDGE) { handlePlayerBridge(geB, geA, start); } } } }
@Override final public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) { if ((globalFilterA != null) && !globalContactFilter(fixture)) return -1; if ((filterA != null) && !contactFilter(fixture)) return -1; if (ignoreBody && fixture.getBody() == getBody()) return -1; // if (fixture.isSensor()) // return -1; mx[m_index] = point.x; my[m_index] = point.y; f[m_index] = fraction; return fraction; }
private void handleFootContact(Contact contact, boolean onBeginContact) { Fixture footSensor = getFootSensor(); if (contact.getFixtureA() == footSensor || contact.getFixtureB() == footSensor) { Fixture otherFixture = (footSensor == contact.getFixtureA()) ? contact.getFixtureB() : contact.getFixtureA(); if (!otherFixture.isSensor()) { if (onBeginContact) { if (numFootContacts == 0) { land(); } numFootContacts++; } else { numFootContacts--; } numFootContacts = Math.max(0, numFootContacts); } } }
public void playerHitsEnemy(Fixture player, Fixture enemy) { float playerRadius = player.getShape().getRadius(); float enemyRadius = enemy.getShape().getRadius(); if (playerRadius > enemyRadius) { enemy.getShape().setRadius(0); if (l.originalLogic) player.getShape().setRadius(player.getShape().getRadius() + enemyRadius / 2); else player.getShape().setRadius(player.getShape().getRadius() - enemyRadius / 2); enemy.getFilterData().groupIndex = Advio.GROUP_COLLIDE_WITH_PLAYER; ((UserData) enemy.getUserData()).add("killer", player); } else if (enemyRadius > playerRadius) { player.getShape().setRadius(0); if (l.originalLogic) enemy.getShape().setRadius(enemy.getShape().getRadius() + enemyRadius / 2); else enemy.getShape().setRadius(enemy.getShape().getRadius() - enemyRadius / 2); player.getBody().setLinearVelocity(0, 0); l.lose(); } }
@Override public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) { Object data = fixture.getBody().getUserData(); if (data == observer) { return -1; } minFraction = fraction; if (data == observable) { observableFraction = fraction; return fraction; } return 0; }
private void setStance(Entity entity, String stance) { logger.info("set stance: " + stance); PhysicsComponent physics = Mappers.physics.get(entity); PlayerComponent player = Mappers.player.get(entity); AssetManager assetManager = Env.getGame().getAssetManager(); World world = physicsSystem.getWorld(); if (world.getBodyCount() > 0 && physics.body != null) { world.destroyBody(physics.body); } PhysicsData physicsData = assetManager.get(stance, PhysicsData.class); physics.body = physicsData.createBody(world, entity); Array<Fixture> fixtures = physics.body.getFixtureList(); player.fixture = fixtures.get(physicsData.getFixtureIdx("main")); player.feetSensor = fixtures.get(physicsData.getFixtureIdx("feet")); NodeComponent node = Mappers.node.get(entity); NodeUtils.computeWorld(entity); physics.body.setTransform(node.position, node.angle); }
@Override public void processCollision(Fixture colliderA, Fixture colliderB, boolean collisionSignal) { if (colliderA.isSensor() && !colliderB.isSensor()) { Integer indexEntityA = (Integer) colliderA.getBody().getUserData(); Integer indexEntityB = (Integer) colliderB.getBody().getUserData(); String tagSensorA = (String) colliderA.getUserData(); if (indexEntityA != null && indexEntityB != null && tagSensorA != null && tagSensorA.equals("RadarSensor")) { GameEntity entityB = Indexed.getInteractiveEntity(indexEntityB); if (entityB != null) { for (SensorEntity entity : sensorGroup.getEntities()) { RadarSensor radar = entity.getRadarSensor(); if (entityB.getTags().values.contains(radar.targetTag)) { if (collisionSignal) { Indexed.addEntityInSensor(entity, entityB); } else { Indexed.removeEntityInSensor(entity, entityB); } radar.collisionSignal = collisionSignal; } } } } } }
float reportRayFixture (RaySensor sensor, Fixture fixture){ Integer indexEntity = (Integer) fixture.getBody().getUserData(); sensor.collisionSignal = false; GameEntity entity = Indexed.getInteractiveEntity(indexEntity); if (sensor.targetTag != null && entity.getTags().values.contains(sensor.targetTag)) { sensor.rayContactList.add(indexEntity); sensor.collisionSignal = true; } else if (sensor.targetTag == null ) { sensor.rayContactList.add(indexEntity); sensor.collisionSignal = true; } if (sensor.xRayMode) return 1; else return 0; }
@Override public void beginContact(Contact contact) { // TODO Auto-generated method stub Fixture fixtureA = contact.getFixtureA(); Fixture fixtureB = contact.getFixtureB(); //logger.info("contact"); if (state == GAME_RUNNING) { if (fixtureA.getFilterData().categoryBits == CATEGORY_PLAYER && fixtureB.getFilterData().categoryBits == CATEGORY_ENEMY) { //fixtureA.getFilterData().maskBits = 0; state = GAME_OVER_SETUP; } else if (fixtureA.getFilterData().categoryBits == CATEGORY_ENEMY && fixtureB.getFilterData().categoryBits == CATEGORY_PLAYER) { //fixtureB.getFilterData().maskBits = 0; state = GAME_OVER_SETUP; } } if ((fixtureA.isSensor() == true && fixtureB.getFilterData().categoryBits == CATEGORY_PLAYER) || (fixtureB.isSensor() == true && fixtureA.getFilterData().categoryBits == CATEGORY_PLAYER)) { state = BALL_DESTROYED; } }
@Override public void endContact(Contact contact) { // End the collision. Fixture fixtureA = contact.getFixtureA(), fixtureB = contact.getFixtureB(); // This is another way for guessing which fixture are you working with. If you have // the reference to that fixture you can just check if both variable reference the // same instance. if (fixtureA == minijoeFixture && fixtureB == floorFixture) { isJumping = true; } if (fixtureA == floorFixture && fixtureB == minijoeFixture) { isJumping = true; } }
/** * @param fixtureA * @param bodyB */ public static void checkFootCollision(final Fixture fixtureA, final Body bodyB) { if ((fixtureA.getUserData() == null) || (fixtureA.getBody().getUserData() == null)) { return; } if (bodyB.getUserData() == null) { return; } final boolean bIsGround = bodyB.getUserData().equals("ground"); final Object tempData = fixtureA.getBody().getUserData(); if (fixtureA.getUserData().equals("foot") && bIsGround) { ((Player) tempData).setFooterCollidingCount(((Player) tempData).getFooterCollidingCount() + 1); // System.out.println("MyContactListener - playerIsOnGround = true"); } else if (fixtureA.getUserData().equals("outerFootRight")) { ((Player) tempData).incrOuterFootRightCount(); } else if (fixtureA.getUserData().equals("outerFootLeft")) { ((Player) tempData).incrOuterFootLeftCount(); } }
public static void checkWallCollision(final Fixture fixtureA, final Body bodyB, final boolean set) { if ((fixtureA.getUserData() == null) || (fixtureA.getBody().getUserData() == null)) { return; } if (bodyB.getUserData() == null) { return; } final Object tempData = fixtureA.getBody().getUserData(); final boolean bIsGround = bodyB.getUserData().equals("ground"); if (fixtureA.getUserData().equals("wall") && bIsGround) { if (set) { ((Player) tempData).incrWall(); } else { ((Player) tempData).decrWall(); } } }
public static void checkHeadCollision(final Fixture fixtureA, final Body bodyB, final boolean set) { if ((fixtureA.getUserData() == null) || (fixtureA.getBody().getUserData() == null)) { return; } if (bodyB.getUserData() == null) { return; } final Object tempData = fixtureA.getBody().getUserData(); final boolean bIsGround = bodyB.getUserData().equals("ground"); if (fixtureA.getUserData().equals("head") && bIsGround) { if (set) { ((Player) tempData).incrHead(); } else { ((Player) tempData).decrHead(); } } }
@Override protected void processEntity(Entity entity, float deltaTime) { PhysicsComponent physics = App.engine.mappers.physics.get(entity); BulletComponent bullet = App.engine.mappers.bullet.get(entity); ChildComponent child = App.engine.mappers.child.get(entity); //Iterate over all touching fixtures, checking to see if they have // health, and deal damage as necessary Array<Fixture> fixturesTouching = App.engine.systems.physics.getFixturesTouching(physics); for (Fixture f : fixturesTouching){ //Should have no effect on sensors if (f.isSensor()) continue; PhysicsComponent p = (PhysicsComponent) f.getBody().getUserData(); if (p == null) continue; Entity dealer = (child == null) ? entity : child.parentEntity; dealDamage(dealer,p.ownerEntity,bullet.damage,physics.getRotation()); } //disable bullet after colliding with anything if (physics.getCollisionNormal() > 0) { physics.setFilter(CollisionBits.Effects,CollisionBits.Mask_Effects); entity.remove(BulletComponent.class); //logger.debug("Entity #" + entity.getId() + ": damage disabled"); } }
private void checkBottomCollision() { float raySize = -(verticalSpeed+Gdx.graphics.getDeltaTime())*Gdx.graphics.getDeltaTime(); if(raySize < 5f) raySize = 5f; if(verticalSpeed > 0) return; final Vector2 rayFrom = new Vector2((item.getX() + item.getWidth() / 2) * PhysicsBodyLoader.SCALE, (item.getY() + item.getHeight()/2) * PhysicsBodyLoader.SCALE); final Vector2 rayTo = new Vector2((item.getX() + item.getWidth() / 2) * PhysicsBodyLoader.SCALE, (item.getY() - raySize) * PhysicsBodyLoader.SCALE); gameStage.getWorld().rayCast(new RayCastCallback(){ public float reportRayFixture(final Fixture fixture, final Vector2 point, final Vector2 normal, final float fraction){ verticalSpeed = 0; item.setY(point.y/PhysicsBodyLoader.SCALE+0.1f); return 0; } }, rayFrom, rayTo); }
public RenderOfPolyFixture(Fixture fixture, VertexBufferObjectManager pVBO) { super(fixture); PolygonShape fixtureShape = (PolygonShape) fixture.getShape(); int vSize = fixtureShape.getVertexCount(); float[] xPoints = new float[vSize]; float[] yPoints = new float[vSize]; Vector2 vertex = Vector2Pool.obtain(); for (int i = 0; i < fixtureShape.getVertexCount(); i++) { fixtureShape.getVertex(i, vertex); xPoints[i] = vertex.x * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT; yPoints[i] = vertex.y * PhysicsConnector.PIXEL_TO_METER_RATIO_DEFAULT; } Vector2Pool.recycle(vertex); mEntity = new PolyLine(0, 0, xPoints, yPoints, pVBO); }
/** * Translates b2d Fixture to appropriate color, depending on body state/type * Modify to suit your needs * @param fixture * @return */ private static Color fixtureToColor(Fixture fixture) { if (fixture.isSensor()) { return Color.PINK; } else { Body body = fixture.getBody(); if (!body.isActive()) { return Color.BLACK; } else { if (!body.isAwake()) { return Color.RED; } else { switch (body.getType()) { case StaticBody: return Color.CYAN; case KinematicBody: return Color.WHITE; case DynamicBody: default: return Color.GREEN; } } } } }
public RenderOfBody(Body pBody, VertexBufferObjectManager pVBO) { ArrayList<Fixture> fixtures = pBody.getFixtureList(); /** * Spawn all IRenderOfFixture for this body that are out there, * and bind them to this RenderOfBody */ for (Fixture fixture : fixtures) { IRenderOfFixture renderOfFixture; if (fixture.getShape().getType() == Type.Circle) { renderOfFixture = new RenderOfCircleFixture(fixture, pVBO); } else { renderOfFixture = new RenderOfPolyFixture(fixture, pVBO); } updateColor(); mRenderFixtures.add(renderOfFixture); this.attachChild(renderOfFixture.getEntity()); } }
private boolean checkMovable(Body body, Vector2 from, Vector2 to) { World b2dWorld = body.getWorld(); moveable = true; RayCastCallback rayCastCallback = new RayCastCallback() { @Override public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) { if (fixture.getFilterData().categoryBits == GameManager.INDESTRUCTIIBLE_BIT | fixture.getFilterData().categoryBits == GameManager.BREAKABLE_BIT | fixture.getFilterData().categoryBits == GameManager.BOMB_BIT | fixture.getFilterData().categoryBits == GameManager.ENEMY_BIT | fixture.getFilterData().categoryBits == GameManager.PLAYER_BIT) { moveable = false; return 0; } return 0; } }; b2dWorld.rayCast(rayCastCallback, from, to); return moveable; }
private boolean checkCanExplodeThrough(Vector2 fromV, Vector2 toV) { canExplodeThrough = true; RayCastCallback rayCastCallback = new RayCastCallback() { @Override public float reportRayFixture(Fixture fixture, Vector2 point, Vector2 normal, float fraction) { if (fixture.getFilterData().categoryBits == GameManager.INDESTRUCTIIBLE_BIT) { canExplodeThrough = false; return 0; } if (fixture.getFilterData().categoryBits == GameManager.BREAKABLE_BIT) { canExplodeThrough = false; Entity e = (Entity) fixture.getBody().getUserData(); Breakable breakable = e.getComponent(Breakable.class); breakable.state = Breakable.State.EXPLODING; return 0; } return 0; } }; b2dWorld.rayCast(rayCastCallback, fromV, toV); return canExplodeThrough; }
/** * Adds hittable contact handlers to all the hittable bodies. */ private void addHittableContactHandlers() { beginContactFunctions.put(HITTABLE_BIT, new ContactHandler() { @Override public void handle(Fixture fixA, Fixture fixB) { if (!(fixB.getBody().getUserData() instanceof EntityModel)) return; ((Hittable) fixA.getBody().getUserData()).onHit((BallModel) fixB.getBody().getUserData()); } }); }
/** * Setting the Ball's state upon begin contact with specific fixtures. * * @param ball The ball's fixture. * @param other The fixture the ball begins contact with */ private void ballBeginContact(Fixture ball, Fixture other) { switch (other.getFilterData().categoryBits) { case GROUND_BIT: ((BallModel) ball.getBody().getUserData()).setState(BallModel.State.LANDED); break; } }
/** * Setting the Ball's state upon ending contact with specific fixtures. * * @param ball The ball's fixture. * @param other The fixture the ball ends contact with */ private void ballEndContact(Fixture ball, Fixture other) { switch (other.getFilterData().categoryBits) { case GROUND_BIT: ((BallModel) ball.getBody().getUserData()).setState(BallModel.State.FLYING); break; } }