* *
* * In addition, modify the velocity to cause a bounce in the opposite direction. */ private void makeIrisInBounds(float simulationRate) { float irisOffsetX = mIrisPosition.x - mEyePosition.x; float irisOffsetY = mIrisPosition.y - mEyePosition.y; float maxDistance = mEyeRadius - mIrisRadius; float distance = (float) Math.sqrt(Math.pow(irisOffsetX, 2) + Math.pow(irisOffsetY, 2)); if (distance <= maxDistance) { // The iris is in bounds, so no correction is necessary. mConsecutiveBounces = 0; return; } // Accumulate a consecutive bounce count, in order to dampen the momentum of a quickly // moving iris. Two or more bounces in a row indicates that the iris is moving so fast that // it doesn't even travel inside the eye. We progressively slow the velocity using this // count until this is no longer the case. mConsecutiveBounces++; // Move the iris back to where it would have been when it would have contacted the side of // the eye. float ratio = maxDistance / distance; float x = mEyePosition.x + (ratio * irisOffsetX); float y = mEyePosition.y + (ratio * irisOffsetY); // Update the velocity direction and magnitude to cause a bounce. float dx = x - mIrisPosition.x; vx = applyBounce(vx, dx, simulationRate) / mConsecutiveBounces; float dy = y - mIrisPosition.y; vy = applyBounce(vy, dy, simulationRate) / mConsecutiveBounces; mIrisPosition = new PointF(x, y); } /** * Update velocity in response to bouncing off the sides of the eye (i.e., when iris hits the * bottom or the eye moves quickly). This is the only way to gain horizontal velocity, since * there is no other horizontal force. */ private float applyBounce(float velocity, float distOutOfBounds, float simulationRate) { if (isZero(distOutOfBounds)) { // No bounce needed, since we are still in bounds along this dimension. return velocity; } // Reverse velocity to create a bounce in the opposite direction. velocity *= -1; // If distOutOfBounds was large, this indicates that the iris was whacked against the side // of the eye quickly. Add an additional velocity factor to account for the force gained by // this quick movement, based upon how much it was out of bounds. float bounce = BOUNCE_MULTIPLIER * Math.abs(distOutOfBounds / mIrisRadius); if (velocity > 0) { velocity += bounce * simulationRate; } else { velocity -= bounce * simulationRate; } return velocity; } /** * The iris is stopped if it is at the bottom of the eye and its velocity is zero. */ private boolean isStopped() { if (mEyePosition.y >= mIrisPosition.y) { return false; } float irisOffsetY = mIrisPosition.y - mEyePosition.y; float maxDistance = mEyeRadius - mIrisRadius; if (irisOffsetY < maxDistance) { return false; } return (isZero(vx) && isZero(vy)); } /** * Allow for a small tolerance in floating point values in considering whether a value is zero. */ private boolean isZero(float num) { return ((num < ZERO_TOLERANCE) && (num > -1 * ZERO_TOLERANCE)); } }