| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| package com.replica.replicaisland; |
| |
| /** A sphere collision volume. */ |
| public class SphereCollisionVolume extends CollisionVolume { |
| private float mRadius; |
| private Vector2 mCenter; |
| private Vector2 mWorkspaceVector; |
| private Vector2 mWorkspaceVector2; |
| |
| public SphereCollisionVolume(float radius, float centerX, float centerY) { |
| super(); |
| mRadius = radius; |
| mCenter = new Vector2(centerX, centerY); |
| mWorkspaceVector = new Vector2(); |
| mWorkspaceVector2 = new Vector2(); |
| } |
| |
| public SphereCollisionVolume(float radius, float centerX, float centerY, int hit) { |
| super(hit); |
| mRadius = radius; |
| mCenter = new Vector2(centerX, centerY); |
| mWorkspaceVector = new Vector2(); |
| mWorkspaceVector2 = new Vector2(); |
| } |
| |
| @Override |
| public float getMaxX() { |
| return mCenter.x + mRadius; |
| } |
| |
| @Override |
| public float getMinX() { |
| return mCenter.x - mRadius; |
| } |
| |
| @Override |
| public float getMaxY() { |
| return mCenter.y + mRadius; |
| } |
| |
| @Override |
| public float getMinY() { |
| return mCenter.y - mRadius; |
| } |
| |
| public Vector2 getCenter() { |
| return mCenter; |
| } |
| |
| public void setCenter(Vector2 center) { |
| mCenter.set(center); |
| } |
| |
| public float getRadius() { |
| return mRadius; |
| } |
| |
| public void setRadius(float radius) { |
| mRadius = radius; |
| } |
| |
| public void reset() { |
| mCenter.zero(); |
| mRadius = 0; |
| } |
| |
| @Override |
| public boolean intersects(Vector2 position, FlipInfo flip, CollisionVolume other, |
| Vector2 otherPosition, FlipInfo otherFlip) { |
| boolean result = false; |
| |
| if (other instanceof AABoxCollisionVolume) { |
| // It's more accurate to do a sphere-as-box test than a box-as-sphere test. |
| result = other.intersects(otherPosition, otherFlip, this, position, flip); |
| } else { |
| mWorkspaceVector.set(position); |
| offsetByCenter(mWorkspaceVector, mCenter, flip); |
| |
| float otherRadius = 0; |
| if (other instanceof SphereCollisionVolume) { |
| SphereCollisionVolume sphereOther = (SphereCollisionVolume)other; |
| mWorkspaceVector2.set(otherPosition); |
| offsetByCenter(mWorkspaceVector2, sphereOther.getCenter(), otherFlip); |
| mWorkspaceVector.subtract(mWorkspaceVector2); |
| otherRadius = sphereOther.getRadius(); |
| } else { |
| // Whatever this volume is, pretend it's a sphere. |
| final float deltaX = other.getMaxXPosition(otherFlip) |
| - other.getMinXPosition(otherFlip); |
| final float deltaY = other.getMaxYPosition(otherFlip) |
| - other.getMinYPosition(otherFlip); |
| final float centerX = deltaX / 2.0f; |
| final float centerY = deltaY / 2.0f; |
| |
| mWorkspaceVector2.set(otherPosition); |
| mWorkspaceVector2.x += centerX; |
| mWorkspaceVector2.y += centerY; |
| otherRadius = Math.max(deltaX, deltaY); |
| } |
| |
| final float maxDistance = mRadius + otherRadius; |
| final float distance2 = mWorkspaceVector.length2(); |
| final float maxDistance2 = (maxDistance * maxDistance); |
| if (distance2 < maxDistance2) { |
| result = true; |
| } |
| } |
| |
| return result; |
| } |
| |
| public void growBy(CollisionVolume other) { |
| final float maxX; |
| final float minX; |
| |
| final float maxY; |
| final float minY; |
| |
| if (mRadius > 0) { |
| maxX = Math.max(getMaxX(), other.getMaxX()); |
| minX = Math.min(getMinX(), other.getMinX()); |
| maxY = Math.max(getMaxY(), other.getMaxY()); |
| minY = Math.min(getMinY(), other.getMinY()); |
| } else { |
| maxX = other.getMaxX(); |
| minX = other.getMinX(); |
| maxY = other.getMaxY(); |
| minY = other.getMinY(); |
| } |
| final float horizontalDelta = maxX - minX; |
| final float verticalDelta = maxY - minY; |
| final float diameter = Math.max(horizontalDelta, verticalDelta); |
| |
| final float newCenterX = minX + (horizontalDelta / 2.0f); |
| final float newCenterY = minY + (verticalDelta / 2.0f); |
| final float newRadius = diameter / 2.0f; |
| |
| mCenter.set(newCenterX, newCenterY); |
| mRadius = newRadius; |
| } |
| |
| private static void offsetByCenter(Vector2 position, Vector2 center, FlipInfo flip) { |
| if (flip != null && (flip.flipX || flip.flipY)) { |
| if (flip.flipX) { |
| position.x += flip.parentWidth - center.x; |
| } else { |
| position.x += center.x; |
| } |
| |
| if (flip.flipY) { |
| position.y += flip.parentHeight - center.y; |
| } else { |
| position.y += center.y; |
| } |
| } else { |
| position.add(center); |
| } |
| } |
| |
| } |