package vooga.rts.map; import java.awt.Graphics2D; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Observable; import java.util.Observer; import java.util.TreeMap; import vooga.rts.IGameLoop; import vooga.rts.gamedesign.sprite.gamesprites.GameEntity; import vooga.rts.gamedesign.sprite.gamesprites.GameSprite; import vooga.rts.state.GameState; import vooga.rts.util.Location3D; /** * This class is a basic manager for Game Sprites that will go on the map. * These will be things such as Terrains and Resources. * * This class uses generics in order to store multiple types of specific GameSprites * * @author Jonathan Schmidt * */ public class GameSpriteManager<T extends GameSprite> implements IGameLoop, Observer { private List<T> myGameSprites; private Iterator<T> myRemoval; /** * Creates a new GameSpriteMananger */ public GameSpriteManager () { myGameSprites = new ArrayList<T>(); } @Override public void update (double elapsedTime) { for (T t : myGameSprites) { t.update(elapsedTime); } } @Override public void paint (Graphics2D pen) { } /** * Adds items to the manager. These items will then be observed by the NodeMap * and will be updated and painted every cycle. * * @param gs The item to add */ public void add (T gs) { gs.addObserver(GameState.getMap().getNodeMap()); gs.setChanged(); gs.notifyObservers(gs.getWorldLocation()); myGameSprites.add(gs); } /** * Removes a particular item from the manager. This will stop it from being updated or painted. * * @param gs The Terrain to remove */ public void remove (T gs) { if (gs == null) { return; } myGameSprites.remove(gs); gs.setChanged(); gs.notifyObservers("remove"); } private void removeIterator (T gs) { myRemoval.remove(); gs.setChanged(); gs.notifyObservers("remove"); } /** * Returns the first item at the provided world location * * @param world The world location to look at * @return The Game Sprite at that position */ public T getItem (Location3D world) { for (T t : myGameSprites) { if (t.intersects(world)) { return t; } } return null; } /** * Returns a list of all the items in this manager that are within a certain radius * of the provided location. * * @param center The location to search from * @param radius The distance away from the location to select items * @return List of items that are in the area */ public List<T> getInArea (Location3D center, double radius) { Map<Double, T> sortedItems = new TreeMap<Double, T>(); for (T single : myGameSprites) { if (!single.isVisible()) { continue; } // Do basic test first if (single.getWorldLocation().getManhattanDistance(center) < radius) { // Do accurate test second double distance = single.getWorldLocation().getDistance(center); if (distance < radius) { sortedItems.put(distance, single); } } } return new ArrayList<T>(sortedItems.values()); } @Override public void update (Observable arg0, Object arg1) { if (arg0 instanceof GameEntity) { if (((GameEntity) arg0).isDead()) { remove((T) arg0); } } } /** * Returns the number of entities in the manager. */ public int getSize () { return myGameSprites.size(); } /** * Returns the contents of the Game Sprite Manager */ public List<T> getContents() { return myGameSprites; } public void clearAll() { myRemoval = myGameSprites.iterator(); while (myRemoval.hasNext()) { removeIterator(myRemoval.next()); } } public List<T> getMySprites () { return myGameSprites; } }