Home | History | Annotate | Download | only in replicaisland
      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 
     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 
     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
     44     public float getMaxX() {
     45         return mCenter.x + mRadius;
     46     }
     47 
     48     @Override
     49     public float getMinX() {
     50         return mCenter.x - mRadius;
     51     }
     52 
     53     @Override
     54     public float getMaxY() {
     55         return mCenter.y + mRadius;
     56     }
     57 
     58     @Override
     59     public float getMinY() {
     60         return mCenter.y - mRadius;
     61     }
     62 
     63     public Vector2 getCenter() {
     64         return mCenter;
     65     }
     66 
     67     public void setCenter(Vector2 center) {
     68         mCenter.set(center);
     69     }
     70 
     71     public float getRadius() {
     72         return mRadius;
     73     }
     74 
     75     public void setRadius(float radius) {
     76         mRadius = radius;
     77     }
     78 
     79     public void reset() {
     80         mCenter.zero();
     81         mRadius = 0;
     82     }
     83 
     84     @Override
     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 
    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 
    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