package vooga.fighter.model.objects; import java.awt.Dimension; import java.awt.Rectangle; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import util.Location; import util.Pixmap; import vooga.fighter.model.loaders.ObjectLoader; import vooga.fighter.model.utils.ImageDataObject; import vooga.fighter.model.utils.State; import vooga.fighter.model.utils.UpdatableLocation; /** * Represents a single object in the game. * * @author James Wei, alanni, David Le * */ public abstract class GameObject { private long myInstanceId; private ObjectLoader myLoader; private UpdatableLocation myCenter; private State myCurrentState; private String myCurrentStateKey; private State myDefaultState; private String myDefaultStateKey; private ImageDataObject myImageData; private Map<String, State> myStates; private Map<String, Integer> myProperties; private List<Integer> myImageEffects; private boolean myRemoveState; /** * Constructs a new GameObject. All fields are initially empty, and must be * populated with an ObjectLoader. */ public GameObject() { myInstanceId = System.currentTimeMillis(); myImageEffects = new ArrayList<Integer>(); myStates = new HashMap<String, State>(); myProperties = new HashMap<String, Integer>(); myLoader = null; myCurrentState = null; myCurrentStateKey = null; myDefaultState = null; myDefaultStateKey = null; myImageData = null; myRemoveState = false; try { // to prevent repetition of instance ids Thread.sleep(1); } catch (InterruptedException e) { return; } } /** * Returns the game object's instance id. This id is unique to this particular * instantiation of the object. */ public long getInstanceId() { return myInstanceId; } /** * Sets game object's center. * @param location is the new location */ public void setLocation(UpdatableLocation location) { myCenter = location; } /** * Returns game object's center. */ public UpdatableLocation getLocation() { return myCenter; } /** * Adds a property for this object. Overwrites any existing value. * @param key is the String name of the property * @param value is the int value of the property */ public void addProperty(String key, int value) { myProperties.put(key, value); } /** * Returns a property for this object. Returns -1 if property does not exist. * @param key is the property to get */ public int getProperty(String key) { if (myProperties.containsKey(key)) { return myProperties.get(key); } else { return -1; } } /** * Clears all properties. */ public void clearProperties() { myProperties.clear(); } /** * Adds a state for this object. Overwrites any existing value. * @param key is the name of the state * @param value is the actual state */ public void addState(String key, State value) { myStates.put(key, value); } /** * Returns a state for this object. Returns null if it doesn't exist. * @param key is the name of the state */ public State getState(String key) { if (myStates.containsKey(key)) { return myStates.get(key); } else { return null; } } /** * Sets the current state for this object. Resets the current state after * switching. * @param key is the state to set as current */ public void setCurrentState(String key) { myCurrentState = getState(key); myCurrentStateKey = key; myCurrentState.resetState(); } /** * Sets the current state to the default state. */ public void setToDefaultState() { setCurrentState(getDefaultStateKey()); } /** * Sets the default state for this object. * @param key is the name of the state to set at default */ public void defineDefaultState(String key) { myDefaultState = getState(key); myDefaultStateKey = key; } /** * Gets the String key of the default state. */ public String getDefaultStateKey() { return myDefaultStateKey; } /** * Gets the String key of the current state. */ public String getCurrentStateKey() { return myCurrentStateKey; } /** * Gets the current state for this object. */ public State getCurrentState() { return myCurrentState; } /** * Clears all states. */ public void clearStates() { myStates.clear(); } /** * Sets the object loader for this object. * @param loader is the object loader to set for this object */ public void setLoader(ObjectLoader loader) { myLoader = loader; } /** * Returns the object loader for this object. */ public ObjectLoader getLoader() { return myLoader; } /** * Sets image data for this object. Size, Location, and Image must not be * null for this object before calling this method, otherwise, this method * returns null. */ public void setImageData() { Pixmap myCurrentImage = myCurrentState.getCurrentImage(); Dimension myCurrentSize = myCurrentState.getCurrentSize(); Location myCurrentLocation = myCenter.getLocation(); if (!(myCurrentSize == null || myCurrentImage == null || myCenter == null)) { myImageData = new ImageDataObject(myCurrentImage, myCurrentLocation, myCurrentSize, myImageEffects); } } /** * Sets image data to the information from an ImageDataObject * @param image is the image data object to set */ public void setImageData(ImageDataObject image) { myImageData = new ImageDataObject(image.getImage(), image.getLocation(), image.getSize(), image.getImageEffect()); } /** * Returns image data for this object. */ public ImageDataObject getImageData() { return myImageData; } /** * Updates the object for the game loop. Should be overridden by subclasses if * necessary, but all overrides should first call superclass method. */ public void update() { setImageData(); if (myCenter != null) { myCenter.update(); } completeUpdate(); } /** * Updates the objects state for the game loop. States are updated separately * because all states must be updated together, either before or after other * update logic that depends on current states. */ public void updateState() { if (myCurrentState != null) { myCurrentState.update(); } if (myCurrentState.hasCompleted()) { stateCompleteUpdate(); } } /** * Determines behavior to be taken if the state has completed. Note that looping * states will automatically reset. By default this method sets the current state * to the default state. */ public void stateCompleteUpdate() { myCurrentState = myDefaultState; myCurrentStateKey = myDefaultStateKey; myCurrentState.resetState(); } /** * Returns true if this object is colliding with another. * @param other is the other game object to check collisions with */ public boolean checkCollision(GameObject other) { Rectangle thisRect = getCurrentState().getCurrentRectangle(); Rectangle otherRect = other.getCurrentState().getCurrentRectangle(); return thisRect.intersects(otherRect); } /** * Returns the map of states for this object. */ public Map<String, State> getStates() { return myStates; } /** * Indicates whether or not the object is ready to be removed. */ public boolean shouldBeRemoved() { return myRemoveState; } /** * Sets the removeState of this object * @param remove is the new remove state of the object */ public void setRemoveState(boolean remove) { myRemoveState = remove; } /** * Checks if this object is equal to another by using the instance id. * @param o is the object to check equality with */ @Override public boolean equals(Object o) { if (o == null) { return false; } GameObject other; if (o instanceof GameObject) { other = (GameObject) o; } else { return false; } return myInstanceId == other.getInstanceId(); } /** * Returns hashcode for the game object by casting instance id to int. */ public int hashCode() { return (int) myInstanceId; } /** * Handles additional update logic outside of resolving movement on the object * and setting image data. */ public abstract void completeUpdate(); }