package greenfoot;

import greenfoot.collision.ColManager;
import greenfoot.collision.CollisionChecker;
import greenfoot.collision.ibsp.Rect;
import greenfoot.core.TextLabel;
import greenfoot.core.WorldHandler;
import threadchecker.OnThread;
import threadchecker.Tag;

import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;


| World is the world that Actors live in. It is a two-dimensional grid of | cells. | | <p>All Actor are associated with a World and can get access to the world object. | The size of cells can be specified at world creation time, and is constant | after creation. Simple scenarios may use large cells that entirely contain | the representations of objects in a single cell. More elaborate scenarios may | use smaller cells (down to single pixel size) to achieve fine-grained | placement and smoother animation. | | <p>The world background can be decorated with drawings or images. | | @see greenfoot.Actor | @author Poul Henriksen | @author Michael Kolling | @version 2.6 | public abstract class World { private static final greenfoot.Color DEFAULT_BACKGROUND_COLOR = greenfoot.Color.WHITE; private CollisionChecker collisionChecker = new ColManager(); private TreeActorSet objectsDisordered = new TreeActorSet(); private TreeActorSet objectsInPaintOrder; private TreeActorSet objectsInActOrder; List<TextLabel> textLabels = new ArrayList<TextLabel>();
| The size of the cell in pixels. | final int cellSize;
| Size of the world | final int width; final int height;
| Image painted in the background. | private GreenfootImage backgroundImage;
| Whether the backgroundImage is the class image | private boolean backgroundIsClassImage = true;
| Whether actors are bound to stay inside the world | private boolean isBounded;
| Construct a new world. The size of the world (in number of cells) and the | size of each cell (in pixels) must be specified. | | @param worldWidth The width of the world (in cells). | @param worldHeight The height of the world (in cells). | @param cellSize Size of a cell in pixels. | public World(int worldWidth, int worldHeight, int cellSize) { this(worldWidth, worldHeight, cellSize, true); }
| Construct a new world. The size of the world (in number of cells) and the | size of each cell (in pixels) must be specified. This constructor allows | the option of creating an unbounded world, which actors can move outside | the boundaries of. | | @param worldWidth The width of the world (in cells). | @param worldHeight The height of the world (in cells). | @param cellSize Size of a cell in pixels. | @param bounded Should actors be restricted to the world boundary? | public World(int worldWidth, int worldHeight, int cellSize, boolean bounded) { this.width = worldWidth; this.height = worldHeight; this.cellSize = cellSize; collisionChecker.initialize(worldWidth, worldHeight, cellSize, false); this.isBounded = bounded; backgroundIsClassImage = true; setBackground(getClassImage()); final WorldHandler wHandler = WorldHandler.getInstance(); if (wHandler != null) { wHandler.setInitialisingWorld(this); } }
| Set a background image for the world. If the image size is larger than | the world in pixels, it is clipped. If it is smaller than the world, it | is tiled. A pattern showing the cells can easily be shown by setting a | background image with a size equal to the cell size. | | @see #setBackground(String) | @param image The image to be shown | final public void setBackground(GreenfootImage image) { if (image != null) { int imgWidth = image.getWidth(); int imgHeight = image.getHeight(); int worldWidth = getWidthInPixels(); int worldHeight = getHeightInPixels(); boolean tile = imgWidth < worldWidth || imgHeight < worldHeight; if (tile) { backgroundIsClassImage = false; backgroundImage = new GreenfootImage(worldWidth, worldHeight); backgroundImage.setColor(DEFAULT_BACKGROUND_COLOR); backgroundImage.fill(); for (int x = 0; x < worldWidth; x += imgWidth) { for (int y = 0; y < worldHeight; y += imgHeight) { backgroundImage.drawImage(image, x, y); } } } else { backgroundImage = image; } } else { backgroundIsClassImage = false; backgroundImage = null; } }
| Set a background image for the world from an image file. Images of type | 'jpeg', 'gif' and 'png' are supported. If the image size is larger than | the world in pixels, it is clipped. A pattern showing the cells can | easily be shown by setting a background image with a size equal to the | cell size. | | @see #setBackground(GreenfootImage) | @param filename The file holding the image to be shown | @throws IllegalArgumentException If the image can not be loaded. | final public void setBackground(String filename) throws IllegalArgumentException { GreenfootImage bg = new GreenfootImage(filename); setBackground(bg); }
| Return the world's background image. The image may be used to draw onto | the world's background. | | @return The background image | public GreenfootImage getBackground() { if (backgroundImage == null) { backgroundImage = new GreenfootImage(getWidthInPixels(), getHeightInPixels()); backgroundImage.setColor(DEFAULT_BACKGROUND_COLOR); backgroundImage.fill(); backgroundIsClassImage = false; } else if (backgroundIsClassImage) { backgroundImage = backgroundImage.getCopyOnWriteClone(); backgroundIsClassImage = false; } return backgroundImage; }
| Return the color at the centre of the cell. To paint a color, you need to | get the background image for the world and paint on that. | | @param x The x coordinate of the cell. | @param y The y coordinate of the cell. | @see #getBackground() | @throws IndexOutOfBoundsException If the location is not within the world | bounds. If there is no background image at the location it | will return Color.WHITE. |
| Return the color at the centre of the cell. To paint a color, you need to | get the background image for the world and paint on that. | | @param x The x coordinate of the cell. | @param y The y coordinate of the cell. | @see #getBackground() | @throws IndexOutOfBoundsException If the location is not within the world | bounds. If there is no background image at the location it | will return Color.WHITE. | @return The color at the centre of the cell. | public greenfoot.Color getColorAt(int x, int y) { ensureWithinXBounds(x); ensureWithinYBounds(y); int xPixel = (int) Math.floor(getCellCenter(x)); int yPixel = (int) Math.floor(getCellCenter(y)); if (xPixel >= backgroundImage.getWidth()) { return DEFAULT_BACKGROUND_COLOR; } if (yPixel >= backgroundImage.getHeight()) { return DEFAULT_BACKGROUND_COLOR; } return backgroundImage.getColorAt(xPixel, yPixel); }
| Return the width of the world (in number of cells). | | @return Width of the world (in cells) | public int getWidth() { return width; }
| Return the height of the world (in number of cells). | | @return Height of the world (in cells) | public int getHeight() { return height; }
| Return the size of a cell (in pixels). | | @return Size of a cell (in pixels) | public int getCellSize() { return cellSize; }
| Set the paint order of objects in the world. Paint order is specified | by class: objects of one class will always be painted on top of objects | of some other class. The order of objects of the same class cannot be | specified. | Objects of classes listed first in the parameter list will | appear on top of all objects of classes listed later. | | Objects of a class not explicitly specified effectively inherit the paint | order from their superclass. | | Objects of classes not listed will appear below the objects whose classes | have been specified. | | @param classes The classes in desired paint order | @SuppressWarnings("unchecked") public void setPaintOrder(Class ... classes) { if (classes == null) { if (objectsInPaintOrder == objectsDisordered) { if (objectsInActOrder == null) { classes = new Class[0]; objectsDisordered.setClassOrder(true, classes); } else { objectsDisordered = objectsInActOrder; } } objectsInPaintOrder = null; return; } if (objectsInPaintOrder != null) { } else if (objectsInActOrder == objectsDisordered) { objectsInPaintOrder = new TreeActorSet(); objectsInPaintOrder.setClassOrder(true, classes); objectsInPaintOrder.addAll(objectsDisordered); return; } else { objectsInPaintOrder = objectsDisordered; } objectsInPaintOrder.setClassOrder(true, classes); }
| Set the act order of objects in the world. Act order is specified | by class: objects of one class will always act before objects | of some other class. The order of objects of the same class cannot be | specified. | | <p>Objects of classes listed first in the parameter list will | act before any objects of classes listed later. | | <p>Objects of a class not explicitly specified inherit the act | order from their superclass. | | <p>Objects of classes not listed will act after all objects whose classes | have been specified. | | @param classes | The classes in desired act order | @SuppressWarnings("unchecked") public void setActOrder(Class ... classes) { if (classes == null) { if (objectsInActOrder == objectsDisordered) { if (objectsInPaintOrder == null) { classes = new Class[0]; objectsDisordered.setClassOrder(false, classes); } else { objectsDisordered = objectsInPaintOrder; } } objectsInActOrder = null; return; } if (objectsInActOrder != null) { } else if (objectsInPaintOrder == objectsDisordered) { objectsInActOrder = new TreeActorSet(); objectsInActOrder.setClassOrder(false, classes); objectsInActOrder.addAll(objectsDisordered); return; } else { objectsInActOrder = objectsDisordered; } objectsInActOrder.setClassOrder(false, classes); }
| Add an Actor to the world. | | @param object The new object to add. | @param x The x coordinate of the location where the object is added. | @param y The y coordinate of the location where the object is added. | public void addObject(Actor object, int x, int y) { if (object.world != null) { if (object.world == this) { return; } object.world.removeObject(object); } objectsDisordered.add(object); addInPaintOrder(object); addInActOrder(object); object.addToWorld(x, y, this); collisionChecker.addObject(object); object.addedToWorld(this); WorldHandler whInstance = WorldHandler.getInstance(); if (whInstance != null) { WorldHandler.getInstance().objectAddedToWorld(object); } }
| Remove an object from the world. | | @param object the object to remove | public void removeObject(Actor object) { if (object == null || object.world != this) { return; } objectsDisordered.remove(object); collisionChecker.removeObject(object); if (objectsDisordered != objectsInActOrder && objectsInActOrder != null) { objectsInActOrder.remove(object); } else if (objectsDisordered != objectsInPaintOrder && objectsInPaintOrder != null) { objectsInPaintOrder.remove(object); } object.setWorld(null); }
| Remove a list of objects from the world. | | @param objects A list of Actors to remove. | @SuppressWarnings("unchecked") public void removeObjects(Collection<? extends Actor> objects) { for (Iterator<? extends Actor> iter = objects.iterator(); iter.hasNext();) { Actor actor = iter.next(); removeObject(actor); } }
| Get all the objects in the world, or all the objects of a particular class. | | If a class is specified as a parameter, only objects of that class (or | its subclasses) will be returned. | | @param <A> The type of objects to look for | @param cls Class of objects to look for ('null' will find all objects). | | @return A list of objects. | @SuppressWarnings({ "rawtypes", "unchecked" }) public <A> List<A> getObjects(Class<A> cls) { List result = new ArrayList(); Iterator<Actor> i = objectsDisordered.iterator(); while (i.hasNext()){ Actor actor = i.next(); if (cls == null || cls.isInstance(actor)) { result.add(actor); } } return result; }
| Get the number of actors currently in the world. | | @return The number of actors | public int numberOfObjects() { return objectsDisordered.size(); }
| Repaints the world. | public void repaint() { WorldHandler.getInstance().repaintAndWait(); }
| Act method for world. The act method is called by the greenfoot framework | at each action step in the environment. The world's act method is called | before the act method of any objects in the world.<p> | | This method does nothing. It should be overridden in subclasses to | implement an world's action. | public void act() { }
| This method is called by the Greenfoot system when the execution has | started. This method can be overridden to implement custom behaviour when | the execution is started. | | This default implementation is empty. | public void started() { }
| This method is called by the Greenfoot system when the execution has | stopped. This method can be overridden to implement custom behaviour when | the execution is stopped. | | This default implementation is empty. | public void stopped() { } | Return all objects at a given cell. | | | An object is defined to be at that cell if its graphical representation | overlaps the center of the cell. | | @param <A> The type of objects to look for | @param x X-coordinate of the cell to be checked. | @param y Y-coordinate of the cell to be checked. | @param cls Class of objects to look return ('null' will return all | objects). | @return The list of objects whose graphical representation overlaps the centre of the cell. | public <A> List<A> getObjectsAt(int x, int y, Class<A> cls) { return collisionChecker.getObjectsAt(x, y, (Class)cls); }
| Show some text centred at the given position in the world. The text will be | displayed in front of any actors. Any previous text shown at the same location will | first be removed. | | @param text The text to display; can be null to show no text | @param x X-coordinate of the text | @param y Y-coordinate of the text | public void showText(String text, int x, int y) { for (Iterator<TextLabel> i = textLabels.iterator(); i.hasNext(); ) { TextLabel label = i.next(); if (label.getX() == x && label.getY() == y) { if (label.getText().equals(text)) { return; } i.remove(); break; } } if (text != null && text.length() != 0) { textLabels.add(new TextLabel(text, x, y)); } } | Return the world's background image but without initialising it first | | @return The background image or null if not initialised yet. | GreenfootImage getBackgroundNoInit() { return backgroundImage; }
| Test whether this world is bounded. | boolean isBounded() { return isBounded; }
| Return all the objects that intersect the given object. This takes the | graphical extent of objects into consideration. | | @param actor An Actor in the world | @param cls Class of objects to look for (null or Object.class will find | all classes) | <A> List<A> getIntersectingObjects(Actor actor, Class<A> cls) { return collisionChecker.getIntersectingObjects(actor, (Class)cls); }
| Returns all objects with the logical location within the specified | circle. In other words an object A is within the range of an object B if | the distance between the centre of the two objects is less than r. | | @param x Centre of the cirle | @param y Centre of the cirle | @param r Radius of the cirle | @param cls Class of objects to look for (null or Object.class will find | all classes) | <A> List<A> getObjectsInRange(int x, int y, int r, Class<A> cls) { return collisionChecker.getObjectsInRange(x, y, r, (Class)cls); }
| Returns the neighbours to the given location. This method only looks at | the logical location and not the extent of objects. Hence it is most | useful in scenarios where objects only span one cell. | | @param actor The actor whose neighbours to locate | @param distance Distance in which to look for other objects | @param diag Is the distance also diagonal? | @param cls Class of objects to look for (null or Object.class will find | all classes) | @return A collection of all neighbours found | <A> List<A> getNeighbours(Actor actor, int distance, boolean diag, Class<A> cls) { if (distance < 0) { throw new IllegalArgumentException("Distance must not be less than 0. It was: " + distance); } return collisionChecker.getNeighbours(actor, distance, diag, (Class)cls); }
| Return all objects that intersect a straight line from the location at a | specified angle. The angle is clockwise. | | @param x x-coordinate | @param y y-coordinate | @param angle The angle relative to current rotation of the object. | (0-359) | @param length How far we want to look (in cells) | @param cls Class of objects to look for (passing 'null' will find all | objects). | <A> List<A> getObjectsInDirection(int x0, int y0, int angle, int length, Class<A> cls) { return collisionChecker.getObjectsInDirection(x0, y0, angle, length, (Class)cls); }
| Get the height of the world in pixels. | int getHeightInPixels() { return height * cellSize; }
| Get the width of the world in pixels. | int getWidthInPixels() { return width * cellSize; }
| Converts the pixel location into a cell, rounding up. | p.public int toCellCeil(int pixel) { return (int) Math.ceil((double) pixel / cellSize); }
| Converts the pixel location into a cell, rounding down. | @OnThread(Tag.Any) p.public int toCellFloor(int pixel) { return (int) Math.floor((double) pixel / cellSize); }
| Returns the centre of the cell. It should be rounded down with Math.floor() if the integer version is needed. | @param l Cell location. | @return Absolute location of the cell centre in pixels. | p.public double getCellCenter(int l) { double cellCenter = l * cellSize + cellSize / 2.; return cellCenter; } Collection<Actor> getObjectsAtPixel(int x, int y) { List<Actor> result = new LinkedList<Actor>(); TreeActorSet objects = getObjectsListInPaintOrder(); for (Actor actor : objects) { Rect bounds = actor.getBoundingRect(); if (x >= bounds.getX() && x <= bounds.getRight() && y>=bounds.getY() && y<= bounds.getTop()) { if (actor.containsPoint(x, y)) { result.add(actor); } } } return result; } p.public void updateObjectLocation(Actor object, int oldX, int oldY) { collisionChecker.updateObjectLocation(object, oldX, oldY); } p.public void updateObjectSize(Actor object) { collisionChecker.updateObjectSize(object); }
| Used to indicate the start of an animation sequence. For use in the | collision checker. | | @see greenfoot.collision.CollisionChecker#startSequence() | void startSequence() { collisionChecker.startSequence(); } p.public Actor getOneObjectAt(Actor object, int dx, int dy, Class<?> cls) { return collisionChecker.getOneObjectAt(object, dx, dy, (Class)cls); } p.public Actor getOneIntersectingObject(Actor object, Class<?> cls) { return collisionChecker.getOneIntersectingObject(object, (Class) cls); }
| Get the list of all objects in the world. This returns a live list which | should not be modified by the caller. If iterating over this list, it | should be synchronized on itself or the World to avoid concurrent | modifications. | TreeActorSet getObjectsListInPaintOrder() { if (objectsInPaintOrder != null) { return objectsInPaintOrder; } else { return objectsDisordered; } }
| Get the list of all objects in the world. This returns a live list which | should not be modified by the caller. The world lock must be held while iterating | over this list. | TreeActorSet getObjectsListInActOrder() { if (objectsInActOrder != null) { return objectsInActOrder; } else { return objectsDisordered; } } void paintDebug(@SuppressWarnings("unused") Graphics g) {
| | g.setColor(Color.BLACK); g.drawString("# of Objects: " + objects.size(), |* 50,50); */ //collisionChecker.paintDebug(g); } // ================================================= // // PRIVATE MEHTHODS // // ================================================= | |/** | Get the default image for objects of this class. May return null. | private GreenfootImage getClassImage() { Class<?> clazz = getClass(); while (clazz != null){ GreenfootImage image = null; try { image = Actor.getDelegate().getImage(clazz.getName()); } catch (Throwable e) { } if (image != null) { return image; } clazz = clazz.getSuperclass(); } return null; }
| Methods that throws an exception if the location is out of bounds. | | @throws IndexOutOfBoundsException | private void ensureWithinXBounds(int x) throws IndexOutOfBoundsException { if (x >= getWidth()) { throw new IndexOutOfBoundsException("The x-coordinate is: " + x + ". It must be smaller than: " + getWidth()); } if (x < 0) { throw new IndexOutOfBoundsException("The x-coordinate is: " + x + ". It must be larger than: 0"); } }
| Methods that throws an exception if the location is out of bounds. | | @throws IndexOutOfBoundsException | private void ensureWithinYBounds(int y) throws IndexOutOfBoundsException { if (y >= getHeight()) { throw new IndexOutOfBoundsException("The y-coordinate is: " + y + ". It must be smaller than: " + getHeight()); } if (y < 0) { throw new IndexOutOfBoundsException("The x-coordinate is: " + y + ". It must be larger than: 0"); } } private void addInActOrder(Actor object) { if (objectsInActOrder != null) { objectsInActOrder.add(object); } } private void addInPaintOrder(Actor object) { if (objectsInPaintOrder != null) { objectsInPaintOrder.add(object); } } }
top, use, map, abstract class World

.   World
.   World
.   setBackground
.   setBackground
.   getBackground
.   getColorAt
.   getWidth
.   getHeight
.   getCellSize
.   setPaintOrder
.   setActOrder
.   addObject
.   removeObject
.   removeObjects
.   numberOfObjects
.   repaint
.   act
.   started
.   stopped
.   showText
.   toCellCeil
.   toCellFloor
.   getCellCenter
.   updateObjectLocation
.   updateObjectSize
.   startSequence
.   getOneObjectAt
.   getOneIntersectingObject
.   paintDebug
.   getClassImage
.   ensureWithinXBounds
.   ensureWithinYBounds
.   addInActOrder
.   addInPaintOrder




803 neLoCode + 204 LoComm