• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.replica.replicaisland;
18 
19 import java.util.Comparator;
20 
21 /**
22  * A node in the game graph that manages the activation status of its children.  The
23  * GameObjectManager moves the objects it manages in and out of the active list (that is,
24  * in and out of the game tree, causing them to be updated or ignored, respectively) each frame
25  * based on the distance of that object to the camera.  Objects may specify an "activation radius"
26  * to define an area around themselves so that the position of the camera can be used to determine
27  * which objects should receive processing time and which should be ignored.  Objects that do not
28  * move should have an activation radius that defines a sphere similar to the size of the screen;
29  * they only need processing when they are visible.  Objects that move around will probably need
30  * larger regions so that they can leave the visible area of the game world and not be immediately
31  * deactivated.
32  */
33 public class GameObjectManager extends ObjectManager {
34     private static final int MAX_GAME_OBJECTS = 384;
35     private float mMaxActivationRadius;
36     private final static HorizontalPositionComparator sGameObjectComparator
37         = new HorizontalPositionComparator();
38     private FixedSizeArray<BaseObject> mInactiveObjects;
39     private FixedSizeArray<GameObject> mMarkedForDeathObjects;
40     private GameObject mPlayer;
41     private boolean mVisitingGraph;
42     private Vector2 mCameraFocus;
43 
44 
GameObjectManager(float maxActivationRadius)45     public GameObjectManager(float maxActivationRadius) {
46         super(MAX_GAME_OBJECTS);
47         mMaxActivationRadius = maxActivationRadius;
48 
49         mInactiveObjects = new FixedSizeArray<BaseObject>(MAX_GAME_OBJECTS);
50         mInactiveObjects.setComparator(sGameObjectComparator);
51 
52         mMarkedForDeathObjects = new FixedSizeArray<GameObject>(MAX_GAME_OBJECTS);
53         mVisitingGraph = false;
54 
55         mCameraFocus = new Vector2();
56 
57     }
58 
59     @Override
commitUpdates()60     public void commitUpdates() {
61         super.commitUpdates();
62 
63         GameObjectFactory factory = sSystemRegistry.gameObjectFactory;
64         final int objectsToKillCount = mMarkedForDeathObjects.getCount();
65         if (factory != null && objectsToKillCount > 0) {
66             final Object[] deathArray = mMarkedForDeathObjects.getArray();
67             for (int x = 0; x < objectsToKillCount; x++) {
68                 factory.destroy((GameObject)deathArray[x]);
69             }
70             mMarkedForDeathObjects.clear();
71         }
72     }
73 
74     @Override
update(float timeDelta, BaseObject parent)75     public void update(float timeDelta, BaseObject parent) {
76         commitUpdates();
77 
78         CameraSystem camera = sSystemRegistry.cameraSystem;
79 
80         mCameraFocus.set(camera.getFocusPositionX(), camera.getFocusPositionY());
81         mVisitingGraph = true;
82         FixedSizeArray<BaseObject> objects = getObjects();
83         final int count = objects.getCount();
84 
85         if (count > 0) {
86             final Object[] objectArray = objects.getArray();
87             for (int i = count - 1; i >= 0; i--) {
88                 GameObject gameObject = (GameObject)objectArray[i];
89                 final float distance2 = mCameraFocus.distance2(gameObject.getPosition());
90                 if (distance2 < (gameObject.activationRadius * gameObject.activationRadius)
91                         || gameObject.activationRadius == -1) {
92                     gameObject.update(timeDelta, this);
93                 } else {
94                 	// Remove the object from the list.
95                 	// It's safe to just swap the current object with the last
96                 	// object because this list is being iterated backwards, so
97                 	// the last object in the list has already been processed.
98                 	objects.swapWithLast(i);
99                     objects.removeLast();
100                     if (gameObject.destroyOnDeactivation) {
101                         mMarkedForDeathObjects.add(gameObject);
102                     } else {
103                         mInactiveObjects.add((BaseObject)gameObject);
104                     }
105                 }
106             }
107         }
108 
109         mInactiveObjects.sort(false);
110         final int inactiveCount = mInactiveObjects.getCount();
111         if (inactiveCount > 0) {
112             final Object[] inactiveArray = mInactiveObjects.getArray();
113             for (int i = inactiveCount - 1; i >= 0; i--) {
114                 GameObject gameObject = (GameObject)inactiveArray[i];
115 
116                 final Vector2 position = gameObject.getPosition();
117                 final float distance2 = mCameraFocus.distance2(position);
118                 final float xDistance = position.x - mCameraFocus.x;
119                 if (distance2 < (gameObject.activationRadius * gameObject.activationRadius)
120                         || gameObject.activationRadius == -1) {
121                     gameObject.update(timeDelta, this);
122                     mInactiveObjects.swapWithLast(i);
123                     mInactiveObjects.removeLast();
124                     objects.add(gameObject);
125                 } else if (xDistance < -mMaxActivationRadius) {
126                     // We've passed the focus, we can stop processing now
127                     break;
128                 }
129             }
130         }
131         mVisitingGraph = false;
132     }
133 
134 
135     @Override
add(BaseObject object)136     public void add(BaseObject object) {
137         if (object instanceof GameObject) {
138             super.add(object);
139         }
140     }
141 
142     @Override
remove(BaseObject object)143     public void remove(BaseObject object) {
144         super.remove(object);
145         if (object == mPlayer) {
146             mPlayer = null;
147         }
148     }
149 
destroy(GameObject object)150     public void destroy(GameObject object) {
151         mMarkedForDeathObjects.add(object);
152         remove(object);
153     }
154 
destroyAll()155     public void destroyAll() {
156         assert mVisitingGraph == false;
157         commitUpdates();
158 
159         FixedSizeArray<BaseObject> objects = getObjects();
160         final int count = objects.getCount();
161         for (int i = count - 1; i >= 0; i--) {
162             mMarkedForDeathObjects.add((GameObject)objects.get(i));
163             objects.remove(i);
164         }
165 
166         final int inactiveObjectCount = mInactiveObjects.getCount();
167         for (int j = inactiveObjectCount - 1; j >= 0; j--) {
168             mMarkedForDeathObjects.add((GameObject)mInactiveObjects.get(j));
169             mInactiveObjects.remove(j);
170         }
171 
172         mPlayer = null;
173     }
174 
setPlayer(GameObject player)175     public void setPlayer(GameObject player) {
176         mPlayer = player;
177     }
178 
getPlayer()179     public GameObject getPlayer() {
180         return mPlayer;
181     }
182 
183     /** Comparator for game objects objects. */
184     private final static class HorizontalPositionComparator implements Comparator<BaseObject> {
compare(BaseObject object1, BaseObject object2)185         public int compare(BaseObject object1, BaseObject object2) {
186             int result = 0;
187             if (object1 == null && object2 != null) {
188                 result = 1;
189             } else if (object1 != null && object2 == null) {
190                 result = -1;
191             } else if (object1 != null && object2 != null) {
192                 float delta = ((GameObject) object1).getPosition().x
193                     - ((GameObject) object2).getPosition().x;
194                 if (delta < 0) {
195                     result = -1;
196                 } else if (delta > 0) {
197                     result = 1;
198                 }
199             }
200             return result;
201         }
202     }
203 }
204