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 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 
     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
     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
     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
    136     public void add(BaseObject object) {
    137         if (object instanceof GameObject) {
    138             super.add(object);
    139         }
    140     }
    141 
    142     @Override
    143     public void remove(BaseObject object) {
    144         super.remove(object);
    145         if (object == mPlayer) {
    146             mPlayer = null;
    147         }
    148     }
    149 
    150     public void destroy(GameObject object) {
    151         mMarkedForDeathObjects.add(object);
    152         remove(object);
    153     }
    154 
    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 
    175     public void setPlayer(GameObject player) {
    176         mPlayer = player;
    177     }
    178 
    179     public GameObject getPlayer() {
    180         return mPlayer;
    181     }
    182 
    183     /** Comparator for game objects objects. */
    184     private final static class HorizontalPositionComparator implements Comparator<BaseObject> {
    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