/* * Copyright (c) 2012. HappyDroids LLC, All rights reserved. */ package com.happydroids.droidtowers.entities; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.*; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Pools; import com.happydroids.droidtowers.TowerAssetManager; import com.happydroids.droidtowers.TowerConsts; import com.happydroids.droidtowers.actions.Action; import com.happydroids.droidtowers.controllers.AvatarSteeringManager; import com.happydroids.droidtowers.events.ElevatorHeightChangeEvent; import com.happydroids.droidtowers.events.GridObjectBoundsChangeEvent; import com.happydroids.droidtowers.grid.GameGrid; import com.happydroids.droidtowers.gui.ElevatorPopOver; import com.happydroids.droidtowers.gui.FontManager; import com.happydroids.droidtowers.gui.GridObjectPopOver; import com.happydroids.droidtowers.input.InputSystem; import com.happydroids.droidtowers.input.PlacementTool; import com.happydroids.droidtowers.math.GridPoint; import com.happydroids.droidtowers.types.ElevatorType; import com.happydroids.droidtowers.types.ResizeHandle; import static com.happydroids.droidtowers.types.ResizeHandle.TOP; public class Elevator extends Transit { public static final int MAX_NUMBER_OF_CARS = 10; private Sprite topSprite; private Sprite shaftSprite; private Sprite emptyShaftSprite; private Sprite bottomSprite; private ResizeHandle selectedResizeHandle; private boolean drawShaft; private Action onResizeAction; static TextureAtlas elevatorAtlas; private GridPoint anchorPoint; private int numCars; private final Array<ElevatorCar> elevatorCars; private final BitmapFontCache floorLabelCache; private int numFloorsSinceLabelCacheBuilt; private final Vector2 tmpVector; public Elevator(ElevatorType elevatorType, final GameGrid gameGrid) { super(elevatorType, gameGrid); if (elevatorAtlas == null) { elevatorAtlas = TowerAssetManager.textureAtlas(elevatorType.getAtlasFilename()); } floorLabelCache = new BitmapFontCache(FontManager.BankGothic32.getFont(), true); size.set(1, 3); topSprite = elevatorAtlas.createSprite("elevator/top"); topSprite.setScale(getGridScale()); bottomSprite = elevatorAtlas.createSprite("elevator/bottom"); bottomSprite.setScale(getGridScale()); shaftSprite = TowerAssetManager.sprite("elevator/shaft.png"); shaftSprite.setScale(getGridScale()); emptyShaftSprite = TowerAssetManager.sprite("elevator/empty.png"); emptyShaftSprite.setScale(getGridScale()); drawShaft = true; numCars = 1; elevatorCars = new Array<ElevatorCar>(numCars); elevatorCars.add(new ElevatorCar(this, elevatorAtlas)); tmpVector = new Vector2(); } @Override public Sprite getSprite() { return shaftSprite; } @Override public void update(float deltaTime) { super.update(deltaTime); for (ElevatorCar elevatorCar : elevatorCars) { elevatorCar.update(deltaTime); } if (numFloorsSinceLabelCacheBuilt != size.y) { rebuildFloorLabelCache(); } } @Override public float getDesirability() { return 0; } @Override public boolean shouldUseSpriteCache() { return false; } @Override public void render(SpriteBatch spriteBatch, SpriteCache spriteCache, Color renderTintColor) { tmpVector.set(worldPosition); if (selectedResizeHandle == ResizeHandle.BOTTOM) { bottomSprite.setColor(Color.CYAN); } else { bottomSprite.setColor(renderColor); } bottomSprite.setPosition(tmpVector.x, tmpVector.y); bottomSprite.draw(spriteBatch); Sprite shaftToRender; if (drawShaft && !(InputSystem.instance().getCurrentTool() instanceof PlacementTool)) { shaftToRender = shaftSprite; } else { shaftToRender = emptyShaftSprite; } tmpVector.add(0, scaledGridUnit()); shaftToRender.setColor(renderColor); shaftToRender.setPosition(tmpVector.x, tmpVector.y); shaftToRender.setSize(worldSize.x, worldSize.y - scaledGridUnit()); setWrap(shaftToRender); shaftToRender.draw(spriteBatch); floorLabelCache.setColor(1, 1, 1, 0.5f); floorLabelCache.draw(spriteBatch, renderColor.a); if (isPlaced() && selectedResizeHandle == null && !(InputSystem.instance() .getCurrentTool() instanceof PlacementTool)) { for (ElevatorCar elevatorCar : elevatorCars) { elevatorCar.setColor(renderColor); elevatorCar.draw(spriteBatch); } } if (selectedResizeHandle == TOP) { topSprite.setColor(Color.CYAN); } else { topSprite.setColor(renderColor); } topSprite.setPosition(getWorldPosition().x, getWorldTop().y - scaledGridUnit()); topSprite.draw(spriteBatch); } protected float scaledGridUnit() { return TowerConsts.GRID_UNIT_SIZE * getGridScale(); } @Override public boolean tap(GridPoint gridPointAtFinger, int count) { if (count >= 2) { drawShaft = !drawShaft; return true; } return super.tap(gridPointAtFinger, count); } @Override public boolean touchDown(GridPoint gameGridPoint, Vector2 worldPoint, int pointer) { if (topSprite.getBoundingRectangle().contains(worldPoint.x, worldPoint.y)) { selectedResizeHandle = TOP; anchorPoint = position.cpy(); return true; } else if (bottomSprite.getBoundingRectangle().contains(worldPoint.x, worldPoint.y)) { selectedResizeHandle = ResizeHandle.BOTTOM; anchorPoint = position.cpy().add(size); return true; } else { selectedResizeHandle = null; } return super.touchDown(gameGridPoint, worldPoint, pointer); } @Override public boolean touchUp() { if (selectedResizeHandle != null) { selectedResizeHandle = null; ElevatorHeightChangeEvent event = Pools.obtain(ElevatorHeightChangeEvent.class); event.setGridObject(this); broadcastEvent(event); Pools.free(event); return true; } return super.touchUp(); } private void rebuildFloorLabelCache() { StringBuilder floors = new StringBuilder(size.y * 3); for (int localFloorNum = 1; localFloorNum < size.y - 1; localFloorNum++) { int worldFloorNum = position.y + localFloorNum; int normalizedWorldFloor = worldFloorNum - TowerConsts.LOBBY_FLOOR; String labelText = String.valueOf(normalizedWorldFloor); if (worldFloorNum == TowerConsts.LOBBY_FLOOR) { labelText = "L"; } else if (worldFloorNum < TowerConsts.LOBBY_FLOOR) { labelText = "B" + (TowerConsts.LOBBY_FLOOR - worldFloorNum); } floors.insert(0, labelText + "\n"); } floorLabelCache.setMultiLineText(floors, getWorldCenterBottom().x, getWorldCenterBottom().y, 0f, BitmapFont.HAlignment.CENTER); floorLabelCache.setPosition(0, floorLabelCache.getBounds().height + (TowerConsts.GRID_UNIT_SIZE * 1.25f)); numFloorsSinceLabelCacheBuilt = size.y; } @Override public boolean pan(GridPoint gridPointAtFinger, GridPoint gridPointDelta) { if (selectedResizeHandle == null) { return false; } GridObjectBoundsChangeEvent event = Pools.obtain(GridObjectBoundsChangeEvent.class); event.setGridObject(this); switch (selectedResizeHandle) { case BOTTOM: position.y = gridPointAtFinger.y; size.y = anchorPoint.y - position.y + 1; checkSize(); position.y = anchorPoint.y - size.y; break; case TOP: size.y = gridPointAtFinger.y - anchorPoint.y; checkSize(); break; } clampPosition(); updateWorldCoordinates(); broadcastEvent(event); Pools.free(event); return true; } private void checkSize() { size.y = Math.max(size.y, 3); size.y = Math.min(size.y, 20); } public boolean servicesFloor(int floorNumber) { float minFloor = getPosition().y + 1; float maxFloor = minFloor + getSize().y - 3; return minFloor <= floorNumber && floorNumber <= maxFloor; } public void setWrap(Sprite shaftSprite) { Texture texture = shaftSprite.getTexture(); shaftSprite.setV(0f); shaftSprite.setV2(shaftSprite.getHeight() / texture.getHeight()); texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat); } @Override public void adjustToNewLandSize() { for (ElevatorCar elevatorCar : elevatorCars) { elevatorCar.clearQueue(); } rebuildFloorLabelCache(); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof Elevator)) { return false; } Elevator elevator = (Elevator) o; return !(elevatorCars != null ? !elevatorCars.equals(elevator.elevatorCars) : elevator.elevatorCars != null); } @Override public int hashCode() { return elevatorCars != null ? elevatorCars.hashCode() : 0; } @Override public GridObjectPopOver makePopOver() { return new ElevatorPopOver(this); } @Override protected boolean hasPopOver() { return true; } public boolean addPassenger(AvatarSteeringManager avatarSteeringManager, int currentFloor, int destinationFloor, Runnable uponArrivalRunnable) { if (elevatorCars.size == 0) { return false; } for (ElevatorCar elevatorCar : elevatorCars) { if (!elevatorCar.isInUse()) { return elevatorCar.addPassenger(avatarSteeringManager, currentFloor, destinationFloor, uponArrivalRunnable); } } ElevatorCar elevatorCar = elevatorCars.get(MathUtils.random(0, elevatorCars.size - 1)); return elevatorCar.addPassenger(avatarSteeringManager, currentFloor, destinationFloor, uponArrivalRunnable); } public void removePassenger(AvatarSteeringManager avatarSteeringManager) { for (ElevatorCar elevatorCar : elevatorCars) { elevatorCar.removePassenger(avatarSteeringManager); } } public int getNumRiders() { int totalRiders = 0; for (ElevatorCar elevatorCar : elevatorCars) { totalRiders += elevatorCar.getNumRiders(); } return totalRiders; } public int getNumPassengersWaiting() { int totalRiders = 0; for (ElevatorCar elevatorCar : elevatorCars) { totalRiders += elevatorCar.getNumPassengersWaiting(); } return totalRiders; } public void addCar() { numCars = MathUtils.clamp(numCars + 1, 0, MAX_NUMBER_OF_CARS); elevatorCars.add(new ElevatorCar(this, elevatorAtlas)); } public int getNumElevatorCars() { return elevatorCars.size; } public void setNumElevatorCars(int numberOfElevatorCars) { for (int i = numCars; i < numberOfElevatorCars; i++) { addCar(); } } @Override public int getUpkeepCost() { return super.getUpkeepCost() + (gridObjectType.getCoins() / 20 * numCars); } public void removeCar() { numCars = MathUtils.clamp(numCars - 1, 0, MAX_NUMBER_OF_CARS); if (elevatorCars.size > 0) { ElevatorCar car = elevatorCars.removeIndex(0); car.resetToBottomOfShaft(); } } public boolean canAddElevatorCar() { return elevatorCars.size < MAX_NUMBER_OF_CARS; } }