1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package com.replica.replicaisland; 19 20 /** A sphere collision volume. */ 21 public class SphereCollisionVolume extends CollisionVolume { 22 private float mRadius; 23 private Vector2 mCenter; 24 private Vector2 mWorkspaceVector; 25 private Vector2 mWorkspaceVector2; 26 SphereCollisionVolume(float radius, float centerX, float centerY)27 public SphereCollisionVolume(float radius, float centerX, float centerY) { 28 super(); 29 mRadius = radius; 30 mCenter = new Vector2(centerX, centerY); 31 mWorkspaceVector = new Vector2(); 32 mWorkspaceVector2 = new Vector2(); 33 } 34 SphereCollisionVolume(float radius, float centerX, float centerY, int hit)35 public SphereCollisionVolume(float radius, float centerX, float centerY, int hit) { 36 super(hit); 37 mRadius = radius; 38 mCenter = new Vector2(centerX, centerY); 39 mWorkspaceVector = new Vector2(); 40 mWorkspaceVector2 = new Vector2(); 41 } 42 43 @Override getMaxX()44 public float getMaxX() { 45 return mCenter.x + mRadius; 46 } 47 48 @Override getMinX()49 public float getMinX() { 50 return mCenter.x - mRadius; 51 } 52 53 @Override getMaxY()54 public float getMaxY() { 55 return mCenter.y + mRadius; 56 } 57 58 @Override getMinY()59 public float getMinY() { 60 return mCenter.y - mRadius; 61 } 62 getCenter()63 public Vector2 getCenter() { 64 return mCenter; 65 } 66 setCenter(Vector2 center)67 public void setCenter(Vector2 center) { 68 mCenter.set(center); 69 } 70 getRadius()71 public float getRadius() { 72 return mRadius; 73 } 74 setRadius(float radius)75 public void setRadius(float radius) { 76 mRadius = radius; 77 } 78 reset()79 public void reset() { 80 mCenter.zero(); 81 mRadius = 0; 82 } 83 84 @Override intersects(Vector2 position, FlipInfo flip, CollisionVolume other, Vector2 otherPosition, FlipInfo otherFlip)85 public boolean intersects(Vector2 position, FlipInfo flip, CollisionVolume other, 86 Vector2 otherPosition, FlipInfo otherFlip) { 87 boolean result = false; 88 89 if (other instanceof AABoxCollisionVolume) { 90 // It's more accurate to do a sphere-as-box test than a box-as-sphere test. 91 result = other.intersects(otherPosition, otherFlip, this, position, flip); 92 } else { 93 mWorkspaceVector.set(position); 94 offsetByCenter(mWorkspaceVector, mCenter, flip); 95 96 float otherRadius = 0; 97 if (other instanceof SphereCollisionVolume) { 98 SphereCollisionVolume sphereOther = (SphereCollisionVolume)other; 99 mWorkspaceVector2.set(otherPosition); 100 offsetByCenter(mWorkspaceVector2, sphereOther.getCenter(), otherFlip); 101 mWorkspaceVector.subtract(mWorkspaceVector2); 102 otherRadius = sphereOther.getRadius(); 103 } else { 104 // Whatever this volume is, pretend it's a sphere. 105 final float deltaX = other.getMaxXPosition(otherFlip) 106 - other.getMinXPosition(otherFlip); 107 final float deltaY = other.getMaxYPosition(otherFlip) 108 - other.getMinYPosition(otherFlip); 109 final float centerX = deltaX / 2.0f; 110 final float centerY = deltaY / 2.0f; 111 112 mWorkspaceVector2.set(otherPosition); 113 mWorkspaceVector2.x += centerX; 114 mWorkspaceVector2.y += centerY; 115 otherRadius = Math.max(deltaX, deltaY); 116 } 117 118 final float maxDistance = mRadius + otherRadius; 119 final float distance2 = mWorkspaceVector.length2(); 120 final float maxDistance2 = (maxDistance * maxDistance); 121 if (distance2 < maxDistance2) { 122 result = true; 123 } 124 } 125 126 return result; 127 } 128 growBy(CollisionVolume other)129 public void growBy(CollisionVolume other) { 130 final float maxX; 131 final float minX; 132 133 final float maxY; 134 final float minY; 135 136 if (mRadius > 0) { 137 maxX = Math.max(getMaxX(), other.getMaxX()); 138 minX = Math.min(getMinX(), other.getMinX()); 139 maxY = Math.max(getMaxY(), other.getMaxY()); 140 minY = Math.min(getMinY(), other.getMinY()); 141 } else { 142 maxX = other.getMaxX(); 143 minX = other.getMinX(); 144 maxY = other.getMaxY(); 145 minY = other.getMinY(); 146 } 147 final float horizontalDelta = maxX - minX; 148 final float verticalDelta = maxY - minY; 149 final float diameter = Math.max(horizontalDelta, verticalDelta); 150 151 final float newCenterX = minX + (horizontalDelta / 2.0f); 152 final float newCenterY = minY + (verticalDelta / 2.0f); 153 final float newRadius = diameter / 2.0f; 154 155 mCenter.set(newCenterX, newCenterY); 156 mRadius = newRadius; 157 } 158 offsetByCenter(Vector2 position, Vector2 center, FlipInfo flip)159 private static void offsetByCenter(Vector2 position, Vector2 center, FlipInfo flip) { 160 if (flip != null && (flip.flipX || flip.flipY)) { 161 if (flip.flipX) { 162 position.x += flip.parentWidth - center.x; 163 } else { 164 position.x += center.x; 165 } 166 167 if (flip.flipY) { 168 position.y += flip.parentHeight - center.y; 169 } else { 170 position.y += center.y; 171 } 172 } else { 173 position.add(center); 174 } 175 } 176 177 } 178