summaryrefslogtreecommitdiff
path: root/src/com/replica/replicaisland/AABoxCollisionVolume.java
blob: f0f33c4fe1cef57195dce68aa60f17b73087c34a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * Copyright (C) 2008 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;

/**
 * An Axis-Aligned rectangular collision volume.  This code treats other volumes as if they are
 * also rectangles when calculating intersections.  Therefore certain types of intersections, such
 * as sphere vs rectangle, may not be absolutely precise (in the case of a sphere vs a rectangle,
 * for example, a new rectangle that fits the sphere is used to perform the intersection test, so
 * there is some potential for false-positives at the corners).  However, for our purposes absolute
 * precision isn't necessary, so this simple implementation is sufficient.
 */
public class AABoxCollisionVolume extends CollisionVolume {
    private Vector2 mWidthHeight;
    private Vector2 mBottomLeft;
    
    public AABoxCollisionVolume(float offsetX, float offsetY, float width, float height) {
        super();
        mBottomLeft = new Vector2(offsetX, offsetY);
        mWidthHeight = new Vector2(width, height); 
    }
    
    public AABoxCollisionVolume(float offsetX, float offsetY, float width, float height, 
            int hit) {
        super(hit);
        mBottomLeft = new Vector2(offsetX, offsetY);
        mWidthHeight = new Vector2(width, height);
    }
    
    @Override
    public final float getMaxX() {
        return mBottomLeft.x + mWidthHeight.x;
    }

    @Override
    public final float getMinX() {
        return mBottomLeft.x;
    }
    
    @Override
    public final float getMaxY() {
        return mBottomLeft.y + mWidthHeight.y;
    }

    @Override
    public final float getMinY() {
        return mBottomLeft.y;
    }
    
    /**
     * Calculates the intersection of this volume and another, and returns true if the
     * volumes intersect.  This test treats the other volume as an AABox.
     * @param position The world position of this volume.
     * @param other The volume to test for intersections.
     * @param otherPosition The world position of the other volume.
     * @return true if the volumes overlap, false otherwise.
     */
    @Override
    public boolean intersects(Vector2 position, FlipInfo flip, CollisionVolume other, 
            Vector2 otherPosition, FlipInfo otherFlip) {
        final float left = getMinXPosition(flip) + position.x;
        final float right = getMaxXPosition(flip) + position.x;
        final float bottom = getMinYPosition(flip) + position.y;
        final float top = getMaxYPosition(flip) + position.y;
        
        final float otherLeft = other.getMinXPosition(otherFlip) + otherPosition.x;
        final float otherRight = other.getMaxXPosition(otherFlip) + otherPosition.x;
        final float otherBottom = other.getMinYPosition(otherFlip) + otherPosition.y;
        final float otherTop = other.getMaxYPosition(otherFlip) + otherPosition.y;
       
        final boolean result = boxIntersect(left, right, top, bottom, 
                    otherLeft, otherRight, otherTop, otherBottom) 
                || boxIntersect(otherLeft, otherRight, otherTop, otherBottom, 
                    left, right, top, bottom);
        
        return result;
    }
    
    /** Tests two axis-aligned boxes for overlap. */
    private boolean boxIntersect(float left1, float right1, float top1, float bottom1, 
            float left2, float right2, float top2, float bottom2) {
        final boolean horizontalIntersection = left1 < right2 && left2 < right1;
        final boolean verticalIntersection = top1 > bottom2 && top2 > bottom1;
        final boolean intersecting = horizontalIntersection && verticalIntersection;
        return intersecting;
    }
    
    /** Increases the size of this volume as necessary to fit the passed volume. */
    public void growBy(CollisionVolume other) {
        final float maxX;
        final float minX;
        
        final float maxY;
        final float minY;
        
        if (mWidthHeight.length2() > 0) {
            maxX = Math.max(getMaxX(), other.getMaxX());
            minX = Math.max(getMinX(), other.getMinX());
            maxY = Math.max(getMaxY(), other.getMaxY());
            minY = Math.max(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;
        mBottomLeft.set(minX, minY);
        mWidthHeight.set(horizontalDelta, verticalDelta);
    }

}