Coverage Summary for Class: World (io.github.unisim.world)

Class Class, % Method, % Branch, % Line, %
World 0% (0/1) 0% (0/37) 0% (0/76) 0% (0/198)


 package io.github.unisim.world;
 
 import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.graphics.OrthographicCamera;
 import com.badlogic.gdx.graphics.Texture;
 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
 import com.badlogic.gdx.maps.tiled.TiledMap;
 import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
 import com.badlogic.gdx.maps.tiled.TmxMapLoader;
 import com.badlogic.gdx.maps.tiled.renderers.IsometricTiledMapRenderer;
 import com.badlogic.gdx.math.Matrix4;
 import com.badlogic.gdx.math.Vector2;
 import com.badlogic.gdx.math.Vector3;
 import com.badlogic.gdx.utils.ScreenUtils;
 import com.badlogic.gdx.utils.viewport.ScreenViewport;
 import com.badlogic.gdx.utils.viewport.Viewport;
 
 import io.github.unisim.AchievementManager;
 import io.github.unisim.GameState;
 import io.github.unisim.Point;
 import io.github.unisim.Settings.Difficulty;
 import io.github.unisim.building.Building;
 import io.github.unisim.building.BuildingManager;
 import io.github.unisim.building.BuildingType;
 import io.github.unisim.ui.GameScreen;
 
 /**
  * A class that holds all the gameplay elements of the game UniSim.
  * It has the ablity to render the game and update the state of the game
  */
 public class World {
     private OrthographicCamera camera = new OrthographicCamera();
     private Viewport viewport = new ScreenViewport(camera);
     private TiledMap map = new TmxMapLoader().load("map/medium_map.tmx");
     private float unitScale = 1f / 16f;
     private IsometricTiledMapRenderer renderer = new IsometricTiledMapRenderer(map, unitScale);
     private Vector2 camPosition = new Vector2(150f, 0f);
     private Vector2 panVelocity = new Vector2(0f, 0f);
     private float zoomVelocity = 0f;
     private final float timeStepSize = 0.001f;
     private float panDt = 0f;
     private float zoomDt = 0f;
     private float minZoom;
     private float maxZoom;
     private SpriteBatch tileHighlightBatch = new SpriteBatch();
     private SpriteBatch buildingBatch = new SpriteBatch();
     private Texture tileHighlight = new Texture(Gdx.files.internal("map/tileHighlight.png"));
     private Texture errTileHighlight = new Texture(Gdx.files.internal("map/errTileHighlight.png"));
     private Matrix4 isoTransform;
     private Matrix4 invIsoTransform;
     public BuildingManager buildingManager;
     public boolean canBuild;
     public Point mousePosInWorld;
     public Point btmLeft;
     public Point topRight;
     public Building selectedBuilding;
     public boolean selectedBuildingUpdated;
     private Point lastLocation;
     private GameScreen gameScreen;
     private int camX = 0;
     private int camY = 0;
     private String popupStatus = "null";
     private float multiplier = 1f;
     private boolean placedBuild = false;
     private boolean flipped;
     private Point lastSize = new Point();
 
     /**
      * Create a new World.
      */
     public World(GameScreen gameScreen) {
         this.gameScreen = gameScreen;
 
         camera.zoom = 0.05f;
         initIsometricTransform();
         buildingManager = new BuildingManager(isoTransform);
         selectedBuilding = null;
     }
 
     public void setDifficulty(Difficulty difficulty) {
         if (difficulty == Difficulty.HARD) {
             this.multiplier = 0.4f;
         } else if (difficulty == Difficulty.MEDIUM) {
             this.multiplier = 1f;
         } else {
             this.multiplier = 1.5f;
         }
     }
 
     /**
      * Releases all resources of this object.
      * Should be called when the World object is no longer needed
      */
     public void dispose() {
         map.dispose();
     }
 
     /**
      * Steps the world forward by delta time and renders the world.
      */
     public void render() {
         viewport.apply();
 
         ScreenUtils.clear(0.59f, 0.72f, 1f, 1f);
 
         updatePan();
         updateZoom();
 
         // Render the map tiles
         // Render the map 0.0624 units lower than the rest of the world to account for
         // the extra pixel at the bottom of each tile. (The pixel is used to prevent
         // tiny gaps between the tiles caused by floating point errors)
         camera.position.set(camPosition.x, camPosition.y + 0.0624f, 0);
         camera.update();
         renderer.setView((OrthographicCamera) viewport.getCamera());
         renderer.render();
 
         // Reset the camera position to the correct value for the rest of the world
         camera.position.set(camPosition.x, camPosition.y, 0);
         camera.update();
 
         pan(camX, camY);
 
         // Deselect the selected building if the game is over
         if (GameState.gameOver) {
             selectedBuilding = null;
             selectedBuildingUpdated = true;
         }
 
         // Update the mouse grid pos and the buildable flag
         Point mouseGridPos = getCursorGridPos();
         if ((!mouseGridPos.equals(mousePosInWorld) || selectedBuildingUpdated)) {
             mousePosInWorld = mouseGridPos;
             btmLeft = mousePosInWorld;
             Point buildingSize = selectedBuilding == null ? new Point(1, 1) : selectedBuilding.size;
             btmLeft.x -= buildingSize.x / 2;
             btmLeft.y -= buildingSize.y / 2;
             topRight = new Point(btmLeft.x + buildingSize.x - 1, btmLeft.y + buildingSize.y - 1);
             canBuild = buildingManager.isBuildable(btmLeft, topRight, getMapTiles());
             if (selectedBuilding != null) {
                 selectedBuilding.location = btmLeft;
             }
             buildingManager.setPreviewBuilding(selectedBuilding);
         }
 
         // Render the tile highlight
         if (selectedBuilding != null) {
             tileHighlightBatch.setProjectionMatrix(camera.combined);
             tileHighlightBatch.begin();
             highlightRegion(btmLeft, topRight, canBuild ? tileHighlight : errTileHighlight);
             tileHighlightBatch.end();
         }
 
         // render buildings after all map related rendering
         buildingBatch.setProjectionMatrix(camera.combined);
         buildingBatch.begin();
         buildingManager.render(buildingBatch);
         buildingBatch.end();
     }
 
     public void addDir(int x, int y) {
         this.camX += x;
         this.camY += y;
     }
 
     /**
      * Resizes the gameplay (usually to fit the size of the window)
      * This is mostly done by resizing the relevant viewports.
      *
      * @param width  - The new width of the window
      * @param height - The new height of the window
      */
     public void resize(int width, int height) {
         if (camera.viewportHeight > 0) {
             camera.zoom *= (float) camera.viewportHeight / height;
         }
         viewport.update(width, height);
         minZoom = 10f / camera.viewportHeight;
         maxZoom = 100f / camera.viewportHeight;
     }
 
     /**
      * Pans the view of the game by translating the camera by a multiple of the
      * vector (x, y).
      * The view will continue to move in the same direction for a short period
      * afterwards
      * Camera bounded to the dimensions of the map
      * 
      * @param x - The distance to pan horizontally
      * @param y - The distance to pan vertically
      */
     public void pan(float x, float y) {
         camPosition.add(x * camera.zoom, y * camera.zoom);
         if (camPosition.x < 0) {
             camPosition.x = 0;
         }
         if (camPosition.y < -75) {
             camPosition.y = -75;
         }
         if (camPosition.x > 300) {
             camPosition.x = 300;
         }
         if (camPosition.y > 75) {
             camPosition.y = 75;
         }
         if (Gdx.input.isButtonPressed(0) || Gdx.input.isButtonPressed(1)
                 || Gdx.input.isButtonPressed(2)) {
             panVelocity.set(x * timeStepSize / Gdx.graphics.getDeltaTime(),
                     y * timeStepSize / Gdx.graphics.getDeltaTime());
         }
     }
 
     /**
      * Pans the view of the game by translating the camera by a multiple of the
      * vector (x, y).
      *
      * @param x - The distance to pan horizontally
      * @param y - The distance to pan vertically
      */
     public void panWithoutInertia(float x, float y) {
         camPosition.add(x * camera.zoom, y * camera.zoom);
     }
 
     /**
      * Tell the game to zoom in or out by a certain amount.
      *
      * @param amount - The speed to zoom at; negative to zoom in and positive to
      *               zoom out
      */
     public void zoom(float amount) {
         final float zoomAcceleration = 0.0003f;
         zoomVelocity += amount * zoomAcceleration;
     }
 
     /**
      * Adjusts the zoom of the camera based on the zoomVelocity.
      * Also slightly reduces the zoomVelocity to prevent infinite zooming
      * Limits the zoom of the camera to be between minZoom and maxZoom
      */
     private void updateZoom() {
         zoomDt += Gdx.graphics.getDeltaTime();
         while (zoomDt > timeStepSize) {
             zoomDt -= timeStepSize;
             zoomVelocity *= 0.987f;
             float scaleFactor = (1f + zoomVelocity * (float) Math.sqrt(camera.zoom) / camera.zoom);
             if (camera.zoom * scaleFactor < minZoom) {
                 scaleFactor = minZoom / camera.zoom;
             }
             if (camera.zoom * scaleFactor > maxZoom) {
                 scaleFactor = maxZoom / camera.zoom;
             }
             panWithoutInertia(
                     Gdx.input.getX() - camera.viewportWidth / 2, camera.viewportHeight / 2 - Gdx.input.getY());
             camera.zoom *= scaleFactor;
             panWithoutInertia(
                     camera.viewportWidth / 2 - Gdx.input.getX(), Gdx.input.getY() - camera.viewportHeight / 2);
         }
     }
 
     /**
      * Adjusts the panning of the camera based on the panVelocity.
      * Also slightly reduces the panVelocity to prevent infinite panning
      */
     private void updatePan() {
         panDt += Gdx.graphics.getDeltaTime();
         while (panDt > timeStepSize) {
             panDt -= timeStepSize;
             panVelocity.scl(0.987f);
             if (!(Gdx.input.isButtonPressed(0) || Gdx.input.isButtonPressed(1)
                     || Gdx.input.isButtonPressed(2))) {
                 panWithoutInertia(panVelocity.x, panVelocity.y);
             }
         }
     }
 
     /**
      * Returns the maximum allowed zoom level.
      *
      * @return - A float holding the mazimum allowed zoom level
      */
     public float getMaxZoom() {
         return maxZoom;
     }
 
     /**
      * Returns the current zoom level.
      *
      * @return - A float holding the current zoom level
      */
     public float getZoom() {
         return camera.zoom;
     }
 
     /**
      * Return the (x, y) co-ordinates of the grid cell that the mouse pointer
      * is currently within.
      *
      * @return - A Vector2 containing the position of the cursor in grid space
      */
     public Point getCursorGridPos() {
         Vector3 unprojected = camera.unproject(
                 new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0)).mul(invIsoTransform);
         unprojected.add(0.45f, -0.45f, 0f);
         return new Point((int) Math.floor(unprojected.x), (int) Math.floor(unprojected.y));
     }
 
     /**
      * Highlight a rectangular region about the cursor with a given highlight
      * texture.
      *
      * @param btmLeft          - The bottom left edge of the region
      * @param topRight         - The top right edge of the region
      * @param highlightTexture - The texture to highlight the squares with
      */
     public void highlightRegion(Point btmLeft, Point topRight, Texture highlightTexture) {
         Point tilePos = new Point();
         for (tilePos.x = btmLeft.x; tilePos.x <= topRight.x; tilePos.x++) {
             for (tilePos.y = btmLeft.y; tilePos.y <= topRight.y; tilePos.y++) {
                 Vector3 worldPos = gridPosToWorldPos(tilePos);
                 tileHighlightBatch.draw(highlightTexture, worldPos.x, worldPos.y, 1, 1);
             }
         }
     }
 
     /**
      * Gets the camera position as a 2D vector.
      *
      * @return a Vector2 holding the position of the camera
      */
     public Vector2 getCameraPos() {
         return new Vector2(camera.position.x, camera.position.y);
     }
 
     /**
      * Transforms a point from grid space to world space.
      *
      * @param gridPos - The coordinates of the point in grid space
      * @return - The coordinates of the point in world space
      */
     private Vector3 gridPosToWorldPos(Point gridPos) {
         return new Vector3(
                 (float) Math.floor(gridPos.x), (float) Math.floor(gridPos.y), 0f).mul(isoTransform);
     }
 
     /**
      * Calculates the matrices needed to transform a point into and outof isometric
      * world space.
      */
     private void initIsometricTransform() {
         // create the isometric transform
         isoTransform = new Matrix4();
         isoTransform.idt();
 
         // isoTransform.translate(0, 32, 0);
         isoTransform.scale((float) (Math.sqrt(2.0) / 2.0), (float) (Math.sqrt(2.0) / 4.0), 1.0f);
         isoTransform.rotate(0.0f, 0.0f, 1.0f, -45);
 
         // ... and the inverse matrix
         invIsoTransform = new Matrix4(isoTransform);
         invIsoTransform.inv();
     }
 
     public TiledMapTileLayer getMapTiles() {
         return (TiledMapTileLayer) map.getLayers().get(0);
     }
 
     /**
      * Place a building onto the map, called when a tile is clicked and building
      * mode is enabled.
      *
      * @return - True if building could be done successfully, false otherwise.
      */
     public boolean placeBuilding() {
         if (!canBuild) {
             popupStatus = "invalid";
             return false;
         }
 
         if (!gameScreen.buildCheck()) {
             return false;
         }
         buildingManager.placeBuilding(
                 new Building(
                         selectedBuilding.texture, selectedBuilding.textureScale, selectedBuilding.textureOffset,
                         selectedBuilding.location.getNewPoint(), selectedBuilding.size.getNewPoint(),
                         selectedBuilding.flipped, selectedBuilding.type, selectedBuilding.name, selectedBuilding.cost,
                         selectedBuilding.rep));
         gameScreen.calcBuild(selectedBuilding.texture.toString(), true);
         if (AchievementManager.getInstance().getAchievements().get(0).isUnlocked() == false) {
             gameScreen.addMoneyRep(1500, 0);
             String reward = "<html><p>Achievement: First building placed</p><p>You have received $1500</p></html>";
             AchievementManager.getInstance().setReward(reward);
             AchievementManager.getInstance().checkAchievement("FIRST_BUILDING_PLACED");
             popupStatus = "reward";
         }
         selectedBuilding = null;
 
         return true;
 
     }
 
     public boolean placeBuildingOld() {
         if (!canBuild) {
             setBuildingNull(lastLocation, flipped, lastSize);
             popupStatus = "invalid";
             return false;
         }
 
         if (!gameScreen.buildCheckOld()) {
             setBuildingNull(lastLocation, flipped, lastSize);
             return false;
         }
         buildingManager.placeBuilding(
                 new Building(
                         selectedBuilding.texture, selectedBuilding.textureScale, selectedBuilding.textureOffset,
                         selectedBuilding.location.getNewPoint(), selectedBuilding.size.getNewPoint(),
                         selectedBuilding.flipped, selectedBuilding.type, selectedBuilding.name, selectedBuilding.cost,
                         selectedBuilding.rep));
         gameScreen.calcBuild(selectedBuilding.texture.toString(), false);
 
         selectedBuilding = null;
 
         return true;
     }
 
     public void setPlaced(boolean placed) {
         this.placedBuild = placed;
     }
 
     public boolean getPlaced() {
         return this.placedBuild;
     }
 
     /**
      * Returns the number of buildings of a certain type that have been placed
      * in the world.
      *
      * @param type - The type of building
      * @return - An int holding the number of that building that have been placed
      */
     public int getBuildingCount(BuildingType type) {
         return buildingManager.getBuildingCount(type);
     }
 
     public void setBuildingNull(Point location, boolean flip, Point size) {
         if (selectedBuilding != null && getPlaced() == true) {
             placeBuilding(location, flip, size);
             setPlaced(false);
         } else {
             selectedBuilding = null;
         }
     }
 
     public void setPopup(String option) {
         this.popupStatus = option;
     }
 
     public String getPopup() {
         return this.popupStatus;
     }
 
     private boolean placeBuilding(Point location, boolean flip, Point size) {
         buildingManager.placeBuilding(
                 new Building(
                         selectedBuilding.texture, selectedBuilding.textureScale, selectedBuilding.textureOffset,
                         location, size, flip, selectedBuilding.type, selectedBuilding.name, selectedBuilding.cost,
                         selectedBuilding.rep));
 
         selectedBuilding = null;
 
         return true;
     }
 
     public void setLocation(Point location) {
         this.lastLocation = location;
     }
 
     public Point getLocation() {
         return this.lastLocation;
     }
 
     public Boolean getFlipped() {
         return this.flipped;
     }
 
     public void setFlipped(Boolean flipped) {
         this.flipped = flipped;
     }
 
     public Point getSize() {
         return this.lastSize;
     }
 
     public void setSize(Point size) {
         this.lastSize = size;
     }
 
     /**
      * Set the camera position to the starting point, rebuild the isometry matrices
      * and deselect the selected building.
      */
     public void reset() {
         camPosition = new Vector2(150f, 0f);
         panVelocity = new Vector2(0f, 0f);
         zoomVelocity = 0f;
         panDt = 0f;
         zoomDt = 0f;
         camera.zoom = 0.05f;
         initIsometricTransform();
         buildingManager = new BuildingManager(isoTransform);
         selectedBuilding = null;
     }
 
     public Building getBuildingAt(Point gridPos) {
         for (Building building : buildingManager.getBuildings()) {
             Point btmLeft = building.location;
             Point topRight = new Point(btmLeft.x + building.size.x - 1, btmLeft.y + building.size.y - 1);
             if (gridPos.x >= btmLeft.x && gridPos.x <= topRight.x &&
                     gridPos.y >= btmLeft.y && gridPos.y <= topRight.y) {
 
                 return building;
             }
         }
         return null;
     }
 
     public float getMultiplier() {
         return this.multiplier;
     }
 }