Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1671 chris 1
package com.gebauz.bauzoid.math.collision;
2
 
3
import java.util.Vector;
4
 
5
import com.gebauz.bauzoid.game.Game;
6
import com.gebauz.bauzoid.game.GameObject;
7
import com.gebauz.bauzoid.graphics.Graphics;
8
import com.gebauz.bauzoid.graphics.sprite.SpriteTransform;
9
import com.gebauz.bauzoid.math.Vector2;
10
 
11
/** Collection of shape elements that form a complex shape. */
12
public class Shape extends GameObject
13
{
14
 
15
        // Constants========================================================================================
16
 
17
        // Embedded Types===================================================================================
18
 
19
        // Fields===========================================================================================
20
 
21
        private Vector<BaseShapeElement> mShapes = new Vector<BaseShapeElement>();
22
 
23
        private String mShapeFile = null;
24
        private boolean mIsAsync = false;
25
 
26
        public SpriteTransform transform = new SpriteTransform();
27
 
28
        private PolyElement mConvexHull = null;
29
 
30
        private AABoundingBox mBoundingBox = null;
31
        private AABoundingBox mTransformedBoundingBox = null;
32
 
33
        private int mCurrentFrame = -1;
34
 
35
        //private Vector2 mTemp = new Vector2();
36
 
37
        // Methods==========================================================================================
38
 
39
        public Shape(Game game, String shapeFile)
40
        {
41
                super(game);
42
                mShapeFile = shapeFile;
43
        }
44
 
45
        /** Clone a shape and its shape elements to new shape. */
46
        public Shape(Shape clone)
47
        {
48
                super(clone.getGame());
49
 
50
                for (int i = 0; i < clone.getShapeElementCount(); i++)
51
                {
52
                        mShapes.add(clone.getShapeElement(i).copy(this));
53
                }
54
        }
55
 
56
        public void initAsync()
57
        {
58
                mIsAsync = true;
59
 
60
                if (mShapeFile != null)
61
                {
62
                        getAssetManager().load(mShapeFile, ShapeData.class, new ShapeDataAsyncLoader.ShapeDataParameter(this));
63
                }
64
        }
65
 
66
        public void init()
67
        {
68
                if (mShapeFile != null)
69
                {
70
                        ShapeData shapeData = null;
71
                        if (!mIsAsync)
72
                        {
73
                                shapeData = ShapeUtil.createShapeFromFile(this, mShapeFile);
74
                        }
75
                        else
76
                        {
77
                                shapeData = getAssetManager().get(mShapeFile, ShapeData.class);
78
                        }
79
 
80
                        for (int i = 0; i < shapeData.getShapeElementCount(); i++)
81
                        {
82
                                mShapes.add(shapeData.getShapeElement(i).copy(this));
83
                        }
84
                }
85
 
86
                calculateConvexHull();
87
        }
88
 
89
        /** Calculate the untransformed convex hull and the axis aligned bounding box of the shape element group. */
90
        public void calculateConvexHull()
91
        {
92
                Vector<Vector2> pointCloud = new Vector<Vector2>();
93
                Vector<Vector2> hull = new Vector<Vector2>();
94
 
95
                for (int i = 0; i < getShapeElementCount(); i++)
96
                {
97
                        BaseShapeElement e = getShapeElement(i);
98
 
99
                        Vector2[] pt = e.getUntransformedPoints();
100
 
101
                        for (int j = 0; j < pt.length; j++)
102
                        {
103
                                pointCloud.add(pt[j]);
104
                        }
105
                }
106
 
107
                // find leftmost point
108
                int leftMostIndex = 0;
109
                for (int i = 1; i < pointCloud.size(); i++)
110
                {
111
                        if (pointCloud.get(i).x < pointCloud.get(leftMostIndex).x)
112
                                leftMostIndex = i;
113
                }
114
 
115
                // start from leftmost point
116
                int p = leftMostIndex;
117
                int q;
118
                do
119
                {
120
                        // search for point q such that orientation(p, i, q) is counterclockwise for all points i
121
                        q = (p + 1) % pointCloud.size();
122
                        for (int i = 0; i < pointCloud.size(); i++)
123
                        {
124
                                if (orientation(pointCloud.get(p), pointCloud.get(i), pointCloud.get(q)) == 2)
125
                                        q = i;
126
                        }
127
 
128
                        hull.add(pointCloud.get(q).copy());
129
                        p = q; // set p as q for next iteration
130
                }
131
                while (p != leftMostIndex);
132
 
133
                mBoundingBox = new AABoundingBox(hull);
134
 
135
                mTransformedBoundingBox = mBoundingBox.createFromTransformed(transform);
136
 
137
                mConvexHull = new PolyElement(this, hull);
138
        }
139
 
140
        /** To find orientation of ordered triplet (p, q, r).
141
         * The function returns following values
142
         * 0 --> p, q and r are colinear
143
         * 1 --> Clockwise
144
         * 2 --> Counterclockwise
145
         */
146
        private static int orientation(final Vector2 p, final Vector2 q, final Vector2 r)
147
        {
148
                final float x1 = (q.x - p.x) * (r.y - p.y);
149
        final float x2 = (r.x - p.x) * (q.y - p.y);
150
        final float val = x1 - x2;
151
 
152
        if (val == 0) return 0;
153
 
154
        return (val > 0) ? 1 : 2;
155
        }
156
 
157
        /** Render debug output. */
158
        public void renderDebug(Graphics graphics, SpriteTransform t)
159
        {
160
                for (int i = 0; i < getShapeElementCount(); i++)
161
                {
162
                        getShapeElement(i).renderDebug(graphics, t);
163
                }
164
 
165
                //mConvexHull.renderDebug(graphics, t);
166
        }
167
 
168
        public void addElement(BaseShapeElement shapeElement)
169
        {
170
                mShapes.add(shapeElement);
171
        }
172
 
173
 
174
        public boolean intersectsCircleSqr(float x, float y, float radiusSqr)
175
        {
176
                for (int i = 0; i < getShapeElementCount(); i++)
177
                {
178
                        if (getShapeElement(i).intersectsCircleSqr(x, y, radiusSqr))
179
                                return true;
180
                }
181
 
182
                return false;
183
        }
184
 
185
        // Getters/Setters==================================================================================
186
 
187
        public final BaseShapeElement getShapeElement(int i)
188
        {
189
                return mShapes.get(i);
190
        }
191
 
192
        public final int getShapeElementCount()
193
        {
194
                return mShapes.size();
195
        }
196
 
197
        public final PolyElement getConvexHull()
198
        {
199
                return mConvexHull;
200
        }
201
 
202
        public final AABoundingBox getBoundingBox()
203
        {
204
                return mBoundingBox;
205
        }
206
 
207
        public final AABoundingBox getTransformedBoundingBox()
208
        {
209
                mBoundingBox.transform(transform, mTransformedBoundingBox);
210
 
211
                return mTransformedBoundingBox;
212
        }
213
 
214
        public final void setCurrentFrame(int frame) { mCurrentFrame = frame; }
215
        public final int getCurrentFrame() { return mCurrentFrame; }
216
 
217
 
218
 
219
}