package rts.core.engine; import java.awt.Point; import java.util.ArrayList; import org.newdawn.slick.Animation; import org.newdawn.slick.Color; import org.newdawn.slick.GameContainer; import org.newdawn.slick.Graphics; import org.newdawn.slick.Image; import org.newdawn.slick.Input; import org.newdawn.slick.SlickException; import org.newdawn.slick.SpriteSheet; import rts.core.engine.layers.entities.ActiveEntity; import rts.core.engine.layers.entities.MoveableEntity; import rts.core.engine.layers.entities.buildings.Building; import rts.core.engine.layers.entities.buildings.BuildingECreator; import rts.utils.ResourceManager; public class PlayerInput { public static final int CURSOR_NO_ACTION = 0; public static final int CURSOR_MOVE = 1; public static final int CURSOR_ATTACK = 2; public static final int CURSOR_SPECIAL_ACTION = 3; public static final int CURSOR_SELL = 4; public static final int CURSOR_REPAIR = 5; private static final int SINGLE_SELECTION_LIMIT = 20; private static final int TIME_BETWEEN_CURSOR_FRAME = 200; private int pressedX; private int pressedY; private boolean pressedLeft; private ArrayList<MoveableEntity> movers; private ArrayList<ActiveEntity> selected; private Engine engine; // Cursors private Image cursor; private Animation[] cursors; public PlayerInput(Engine engine) { this.engine = engine; this.movers = new ArrayList<MoveableEntity>(); this.selected = new ArrayList<ActiveEntity>(); } public void init() { cursor = ResourceManager.getImage("cursor"); SpriteSheet cursorSheet = ResourceManager.getSpriteSheet("cursors"); cursors = new Animation[6]; for (int i = 0; i < 6; i++) cursors[i] = new Animation(); for (int i = 0; i < 6; i++) { for (int j = 0; j < 4; j++) { cursors[i].addFrame(cursorSheet.getSprite(j, i), TIME_BETWEEN_CURSOR_FRAME); } } } // mx and my determine where the mouse is on the current screen // decX and decY determine where the screen is relative to the game map public void update(GameContainer container, boolean onGui, int mx, int my, int decX, int decY) throws SlickException { // Get Selected selected.clear(); selected.addAll(engine.getPlayerSelectedEntities()); // Get movers movers.clear(); movers.addAll(engine.getSelectedMoveableEntities((mx + decX) / engine.getTileW(), (my + decY) / engine.getTileH())); updateKey(container); updateMouse(container, onGui, mx, my, decX, decY); } // here might allow us to select items or move them // CURRENTLY IN LUA WARS, NO WAY TO SELL OR REPAIR BUILDINGS // IF YOU WANT TO ADD MOUSE PRESSES BACK UNCOMMENT OUT THESE private void updateMouse(GameContainer container, boolean onGui, int mx, int my, int decX, int decY) { if (engine.isMouseRightPressed() && !onGui) { if (engine.getGui().isSellMod()) { //sellBuilding(mx + decX, my + decY); // note i changed the structure of these if/else statements // to be less confusing } else if (engine.getGui().isRepairMod()) { //repairBuilding(mx + decX, my + decY); } else { //moveOrSpecialAction(mx + decX, my + decY); } } else { selectAction(container, onGui, mx, my, decX, decY); } } private void repairBuilding(int x, int y) { ActiveEntity ae = engine.getEntityAt(null, x, y); if (ae != null && ae instanceof Building && engine.isPlayerEntity(ae.getPlayerId())) { ((Building) ae).repair(); } } private void sellBuilding(int x, int y) { ActiveEntity ae = engine.getEntityAt(null, x, y); if (ae != null && ae instanceof Building && engine.isPlayerEntity(ae.getPlayerId())) { ((Building) ae).sell(); } } /*New function to attack or move all units*/ public void moveOrAttackAction(int x, int y) { ArrayList<ActiveEntity> selectedAllUnits = engine.selectAllUnits(x,y); ArrayList<ActiveEntity> selectedAllEnemies = engine.selectAllEnemies(x,y); moveOrSpecialAction(x, y); for(ActiveEntity ae1 : selectedAllUnits) { for(ActiveEntity ae2 : selectedAllEnemies) { if(engine.DistanceOfUnit(ae1,ae2)) { ae1.target((ActiveEntity) ae2, (int)ae2.getX(), (int)ae2.getY()); } } } } public void moveOrSpecialAction(int mx, int my) { ActiveEntity e = engine.getEntityAt(null, mx, my); // this is our enemy unit if (e != null && !(engine.getMap().isEnableFow() && engine.getMap().fogOn(mx / engine.getTileW(), my / engine.getTileH()))) { if (!selected.isEmpty() && e instanceof ActiveEntity) { // attack enemy // target() is the attack function if (selected.size() == 1) { selected.get(0).target((ActiveEntity) e, mx / engine.getTileW(), my / engine.getTileH()); } else { // All entity target ! ArrayList<Point> points = Utils.getCloserPoints(engine.getMap(), movers, mx / engine.getTileW(), my / engine.getTileH()); int counter = 0; for (int i = 0; i < selected.size(); i++) { if (selected.get(i) instanceof Building) { selected.get(i).target((ActiveEntity) e, 0, 0); } else { if (counter < points.size()) { selected.get(i).target((ActiveEntity) e, points.get(counter).x, points.get(counter).y); counter++; } } } } } } else { if (!movers.isEmpty()) { if (movers.size() == 1) { if (engine.getMap().blocked(movers.get(0), mx / engine.getTileW(), my / engine.getTileH())) { Point p = Utils.getCloserPoint(engine.getMap(), movers.get(0), mx / engine.getTileW(), my / engine.getTileH()); movers.get(0).moveFromPlayerAction(p.x * engine.getTileW(), p.y * engine.getTileH()); } else movers.get(0).moveFromPlayerAction(mx, my); } else { // Plusieurs entit�s, il faut regrouper des points � // proximit� //this is how it determines how to move unit ArrayList<Point> points = Utils.getCloserPoints(engine.getMap(), movers, mx / engine.getTileW(), my / engine.getTileH()); for (int i = 0; i < movers.size(); i++) { movers.get(i).moveFromPlayerAction(points.get(i).x * engine.getTileW(), points.get(i).y * engine.getTileH()); } } } } if (!selected.isEmpty() && selected.get(0) instanceof BuildingECreator) { ((BuildingECreator) selected.get(0)).changeRallyingPoint(mx, my); } } // used to select units private void selectAction(GameContainer container, boolean onGui, int mx, int my, int decX, int decY) { // first mouse click, after this, player can drag to select units with select box if (container.getInput().isMouseButtonDown(Input.MOUSE_LEFT_BUTTON)) { if (!pressedLeft) { pressedX = mx; pressedY = my; pressedLeft = true; } // when player releases the mouse, it selects the units inside select box // changed the if statement, but it's pretty much the same } else if (pressedLeft) { if (Math.abs(pressedX - mx) < SINGLE_SELECTION_LIMIT && Math.abs(pressedY - my) < SINGLE_SELECTION_LIMIT && !onGui) { ActiveEntity e = engine.getEntityAt(null, mx + decX, my + decY); if (e != null) { if (!e.isSelected()) engine.deselectAllEntities(); e.selected(); } else { engine.deselectAllEntities(); } } else { engine.deselectAllEntities(); // Select severals entities engine.selectEntitiesBetween(pressedX, pressedY, mx, my); } pressedLeft = false; } } // TRUNG NGUYEN'S SELECT ACTION FOR LUA public ArrayList<ActiveEntity> selectUnitsAt(int tileX, int tileY, float radius, int numUnits, String unitType) { // NOTE I DON'T WANT TO DESELECT UNITS. THIS WAY I CAN ADD DIFFERENT TYPES OF UNITS TO THE ONES SELECTED //engine.deselectAllEntities(); // Select several entities ArrayList<ActiveEntity> selectedUnits = engine.selectClosestEntities(tileX, tileY, radius, numUnits, unitType); // add a way to select specific type of unit selected.addAll(selectedUnits); for(ActiveEntity e : selectedUnits) { if(e instanceof MoveableEntity) { movers.add((MoveableEntity) e); } } return selectedUnits; } public void deselectUnits() { for(ActiveEntity ae : selected) { ae.deselected(); } } public void setUpBase() { ArrayList<ActiveEntity> selectedUnits = selectUnitsAt(0, 0, 10000, 1, "Builder"); // add a way to select specific type of unit if(selectedUnits.size() > 0) { moveOrSpecialAction((int)selectedUnits.get(0).getX(), (int)selectedUnits.get(0).getY()); } } private void updateKey(GameContainer container) { if (container.getInput().isKeyPressed(Input.KEY_TAB)) engine.getGui().hideOrShow(); } public void render(GameContainer container, Graphics g) throws SlickException { int mx = container.getInput().getMouseX(); int my = container.getInput().getMouseY(); if (pressedLeft) { g.setColor(Color.white); g.drawRect((pressedX <= mx) ? pressedX : mx, (pressedY <= my) ? pressedY : my, Math.abs(pressedX - mx), Math.abs(pressedY - my)); } } // looks important too public void renderCursor(GameContainer container, Graphics g, boolean onGui) { int mx = container.getInput().getMouseX(); int my = container.getInput().getMouseY(); if (engine.getGui().isSellMod() || engine.getGui().isRepairMod()) { ActiveEntity ae = engine.getEntityAt(null, engine.getMouseX(), engine.getMouseY()); if (ae != null && ae instanceof Building && engine.isPlayerEntity(ae.getPlayerId())) { g.drawAnimation(cursors[engine.getGui().isSellMod() ? CURSOR_SELL : CURSOR_REPAIR], mx - 10, my - 10); } else { g.drawAnimation(cursors[CURSOR_NO_ACTION], mx - 10, my - 10); } } else { if (!selected.isEmpty() && !onGui) { int cursor = selectCursor(selected.get(0), engine.getMouseX(), engine.getMouseY()); g.drawAnimation(cursors[cursor], mx - 10, my - 10); } else { g.drawImage(cursor, mx, my); } } } // looks pretty important private int selectCursor(ActiveEntity firstSelected, int mx, int my) { for (int i = 0; i < selected.size(); i++) { int c = selected.get(i).getTargetCursor(engine.getEntityAt(null, mx, my), mx, my); if (c != CURSOR_NO_ACTION) { return c; } } return CURSOR_NO_ACTION; } public boolean isPressedLeft() { return pressedLeft; } }