blob: 184536c5730fe87f4e9035f8e1f6ba04f30f4f78 [file] [log] [blame]
/*
* 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);
}
}
}