package vooga.scroller.level_editor.model; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; import vooga.scroller.level_editor.ILevelEditor; import vooga.scroller.level_editor.LevelEditing; import vooga.scroller.level_editor.commands.Command; import vooga.scroller.level_editor.commands.CommandLibrary; import vooga.scroller.sprites.Sprite; import vooga.scroller.util.IBackgroundView; import vooga.scroller.util.mvc.IController; /** * LevelEditor is the Model side of the Level Editor as a whole. It processes * commands received by the controller on an Editable Grid also handed from * the controller * * @author Danny Goodman, Deo Fagnisse */ public class LevelEditor implements ILevelEditor { private static final String SPACE = " "; private static final String NO_METHOD_COMMAND_ERROR = "Command does not exist"; private static final String PARAM_COMMAND_ERROR = "Incorrect Parameters"; private static final String DEFAULT_COMMAND_ERROR = "Incorrect Command"; private static final String COPY_ERROR = "Cannot copy Sprite. Missing default constructor"; private static final String INVOKE_COMMAND_ERROR = "Sprite does not exist in Sprite Map"; private EditableGrid myGrid; private Map<Integer, Sprite> mySpriteMap; private Map<Integer, IBackgroundView> myBackgrounds; private IController<LevelEditing> myController; /** * Constructor sets value of myController. * * @param con - Controller parameter that contains LevelEditor */ public LevelEditor (IController<LevelEditing> con) { myController = con; } /** * Takes in the command name and parameters all as one String to be processed. * and processes it on the Editable given by the LEController. * * @param m - Editable to process command on. * @param cmd - the input from the LEView. */ @Override public void processCommand (EditableGrid m, String cmd) { myGrid = m; processCommand(cmd); } @Override public void setSpriteMap (Map<Integer, Sprite> spriteMap) { mySpriteMap = spriteMap; } @Override public void setBackgroundMap (Map<Integer, IBackgroundView> map) { myBackgrounds = map; } /** * Method to create a sprite uses the @command annotation to be called * through reflection by the processCommand method. * * @param x - position in pixels * @param y - position in pixels * @param id - Sprite ID */ @Command public void createSprite (int x, int y, int id) { if (id == START_ID) { addStartPoint(x, y); } if (id < START_ID) { addDoor(x, y, id); } else { Sprite sprite = getSpriteFromMap(id); try { myGrid.addSprite(sprite, x, y); } catch (NullPointerException e) { myController.showErrorMsg(COPY_ERROR); } } } /** * Method to delete a sprite uses the @command annotation to be called * through reflection by the processCommand method. * * @param x - position in pixels * @param y - position in pixels */ @Command public void deleteSprite (int x, int y) { myGrid.deleteSprite(x, y); } /** * Method to change the background image uses the @command annotation * to be called through reflection by the processCommand method. * * @param id - Background ID */ @Command public void changeBackground (int id) { myGrid.changeBackground(myBackgrounds.get(id)); } /** * Method to change the grid size. Uses the @command annotation * to be called through reflection by the processCommand method. * * @param width - number of SpriteBoxes in horizontal direction * @param height - number of SpriteBoxes in vertical direction */ @Command public void changeGridSize (int width, int height) { myGrid.changeGridSize(width, height); } private Sprite getSpriteFromMap (int id) { Sprite sprite = mySpriteMap.get(id); sprite = sprite.copy(); return sprite; } private void addStartPoint (int x, int y) { myGrid.addStartPoint(x, y); } private void addDoor (int x, int y, int id) { myGrid.addDoor(getSpriteFromMap(id), x, y); } /** * Splits the string by White Space and obtains name and parameters from String. * Calls @Command method through reflection. * * @param command as one String. */ private void processCommand (String command) { String[] splitCommand = command.split(SPACE); String name = splitCommand[0]; Object[] params = getParams(splitCommand); try { Method m = CommandLibrary.get(name); m.invoke(this, params); } catch (NullPointerException e) { myController.showErrorMsg(NO_METHOD_COMMAND_ERROR); } catch (IllegalAccessException e) { myController.showErrorMsg(DEFAULT_COMMAND_ERROR); } catch (IllegalArgumentException e) { myController.showErrorMsg(PARAM_COMMAND_ERROR); } catch (InvocationTargetException e) { myController.showErrorMsg(INVOKE_COMMAND_ERROR); } } /** * Takes in the command as a Sting[] and returns the parameters as an Integer[]. * The output is used by the processCommand method to invoke the command method. * * @param splitCommand - command as a String[] with name followed by params. * @return Integer[] of parameters */ private Integer[] getParams (String[] splitCommand) { Integer[] params = new Integer[splitCommand.length - 1]; for (int i = 0; i < params.length; i++) { params[i] = Integer.parseInt(splitCommand[i + 1]); } return params; } }