package greenfoot.collision;

import greenfoot.Actor;
import greenfoot.collision.ibsp.IBSPColChecker;

import java.awt.Graphics;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;


| This class manages collision checkers. It doesn't do any collision checking | itself but optimises the collision checking by deciding how to delegate | collision checking to other collision checkers. | | @author Poul Henriksen | public class ColManager implements CollisionChecker{
| Map from classes to objects that are not part of the collision checking (yet). | private Map<Class<? extends Actor>, LinkedList<Actor>> freeObjects = new HashMap<Class<? extends Actor>, LinkedList>();
| Classes that are part of the collision checking. | private Set<Class<? extends Actor>> collisionClasses = new HashSet<Class<? extends Actor>>();
| The actual collision checker. | private CollisionChecker collisionChecker = new IBSPColChecker();
| Ensures that objects of this class are in the collision checker | private void makeCollisionObjects(Class<? extends Actor> cls, boolean includeSubclasses) { if (cls == null) { Set<Entry<Class<? extends Actor>, LinkedList<Actor>>> entries = freeObjects.entrySet(); for (Entry<Class<? extends Actor>, LinkedList<Actor>> entry : entries) { for (Actor actor : entry.getValue()) { collisionChecker.addObject(actor); } collisionClasses.add(entry.getKey()); } freeObjects.clear(); } else if (collisionClasses.contains(cls)) { } else { List<? extends Actor> classSet = freeObjects.remove(cls); if ( classSet != null) { collisionClasses.add(cls); for (Actor actor : classSet) { collisionChecker.addObject(actor); } } } if (includeSubclasses) { Set<Entry<Class<? extends Actor>, LinkedList<Actor>>> entries = new HashSet<Entry<Class<? extends Actor>, LinkedList>>(freeObjects.entrySet()); for (Entry<Class<? extends Actor>, LinkedList<Actor>> entry : entries) { if (cls.isAssignableFrom(entry.getKey())) { makeCollisionObjects(entry.getKey(), false); } } } }
| Ensure that objects of the actors class and all objects of 'cls' or a | subclass is part of the collision detection. | private <T extends Actor> void prepareForCollision(Actor actor, Class<T> cls) { makeCollisionObjects(actor.getClass(), false); makeCollisionObjects(cls, true); } public void addObject(Actor actor) { Class<? extends Actor> cls = actor.getClass(); if (collisionClasses.contains(cls)) { collisionChecker.addObject(actor); } else { LinkedList<Actor> classSet = freeObjects.get(cls); if (classSet == null) { classSet = new LinkedList<Actor>(); freeObjects.put(cls, classSet); } classSet.add(actor); } } public <T extends Actor> List getIntersectingObjects(Actor actor, Class<T> cls) { prepareForCollision(actor, cls); return collisionChecker.getIntersectingObjects(actor, cls); } public <T extends Actor> List getNeighbours(Actor actor, int distance, boolean diag, Class<T> cls) { prepareForCollision(actor, cls); return collisionChecker.getNeighbours(actor, distance, diag, cls); } @SuppressWarnings("unchecked") public <T extends Actor> List getObjects(Class<T> cls) { List<T> result = collisionChecker.getObjects(cls); Set<Entry<Class<? extends Actor>, LinkedList<Actor>>> entries = freeObjects.entrySet(); for (Entry<Class<? extends Actor>, LinkedList<Actor>> entry : entries) { if (cls == null || cls.isAssignableFrom(entry.getKey())) { result.addAll((Collection<? extends T>) entry.getValue()); } } return result; } public <T extends Actor> List getObjectsAt(int x, int y, Class<T> cls) { makeCollisionObjects(cls, true); return collisionChecker.getObjectsAt(x, y, cls); } public <T extends Actor> List getObjectsInDirection(int x, int y, int angle, int length, Class<T> cls) { makeCollisionObjects(cls, true); return collisionChecker.getObjectsInDirection(x, y, angle, length, cls); } public <T extends Actor> List getObjectsInRange(int x, int y, int r, Class<T> cls) { makeCollisionObjects(cls, true); return collisionChecker.getObjectsInRange(x, y, r, cls); } public List getObjectsList() { return getObjects(null); } public <T extends Actor> T getOneIntersectingObject(Actor object, Class<T> cls) { prepareForCollision(object, cls); return collisionChecker.getOneIntersectingObject(object, cls); } public <T extends Actor> T getOneObjectAt(Actor object, int dx, int dy, Class<T> cls) { prepareForCollision(object, cls); return collisionChecker.getOneObjectAt(object, dx, dy, cls); } public void initialize(int width, int height, int cellSize, boolean wrap) { collisionChecker.initialize(width, height, cellSize, wrap); } public void paintDebug(Graphics g) { collisionChecker.paintDebug(g); } public void removeObject(Actor object) { LinkedList<Actor> classSet = freeObjects.get(object.getClass()); if (classSet != null) { classSet.remove(object); } else { collisionChecker.removeObject(object); } } public void startSequence() { collisionChecker.startSequence(); } public void updateObjectLocation(Actor object, int oldX, int oldY) { if (!freeObjects.containsKey(object.getClass())) { collisionChecker.updateObjectLocation(object, oldX, oldY); } } public void updateObjectSize(Actor object) { if (!freeObjects.containsKey(object.getClass())) { collisionChecker.updateObjectSize(object); } } }
top, use, map, class ColManager

.   LinkedList>
.   Actor>>
.   makeCollisionObjects
.   LinkedList>>
.   prepareForCollision
.   addObject
.   getIntersectingObjects
.   getNeighbours
.   getObjects
.   entry.getValue
.   getObjectsAt
.   getObjectsInDirection
.   getObjectsInRange
.   getObjectsList
.   getOneIntersectingObject
.   getOneObjectAt
.   initialize
.   paintDebug
.   removeObject
.   startSequence
.   updateObjectLocation
.   updateObjectSize




242 neLoCode + 10 LoComm