com.tnf.ptm.common.MapDrawer.java Source code

Java tutorial

Introduction

Here is the source code for com.tnf.ptm.common.MapDrawer.java

Source

/*
 * Copyright 2017 TheNightForum
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.tnf.ptm.common;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.tnf.ptm.entities.Faction;
import com.tnf.ptm.entities.StarPort;
import com.tnf.ptm.gfx.PtmCam;
import com.tnf.ptm.gfx.TextureManager;
import com.tnf.ptm.entities.maze.MazeBuilder;
import com.tnf.ptm.entities.planet.Planet;
import com.tnf.ptm.entities.planet.PtmSystem;
import com.tnf.ptm.entities.planet.SystemBelt;
import com.tnf.ptm.entities.ship.FarShip;
import com.tnf.ptm.entities.ship.PtmShip;
import com.tnf.ptm.entities.maze.Maze;
import com.tnf.ptm.entities.planet.FarTileObject;
import com.tnf.ptm.entities.planet.SurfaceDirection;
import com.tnf.ptm.entities.planet.Tile;
import com.tnf.ptm.entities.planet.TileObject;
import com.tnf.ptm.handler.BeaconHandler;
import com.tnf.ptm.handler.FactionManager;
import com.tnf.ptm.handler.ObjectManager;
import com.tnf.ptm.screens.controlers.UiDrawer;

import java.util.ArrayList;
import java.util.List;

public class MapDrawer {
    public static final float MIN_ZOOM = 8f;
    public static final float MUL_FACTOR = 2f;
    public static final float MAX_ZOOM = 512f;
    public static final float ICON_RAD = .02f;
    public static final float STAR_NODE_SZ = .003f;
    public static final float INNER_ICON_PERC = .6f;
    public static final float INNER_AREA_ICON_PERC = .7f;
    public static final float GRID_SZ = 40f;
    public static final String MAP_TEX_DIR = "mapObjects/";
    public static final float MIN_ICON_RAD_PX = 16f;
    private static final float MAX_SKULL_TIME = .75f;
    private static final float MAX_AREA_SKULL_TIME = 3;
    private final TextureAtlas.AtlasRegion myAtmTex;
    private final TextureAtlas.AtlasRegion myPlanetTex;
    private final TextureAtlas.AtlasRegion myPlanetCoreTex;
    private final TextureAtlas.AtlasRegion myStarTex;
    private final TextureAtlas.AtlasRegion myMazeTex;
    private final TextureAtlas.AtlasRegion mySkullTex;
    private final TextureAtlas.AtlasRegion mySkullBigTex;
    private final TextureAtlas.AtlasRegion myStarPortTex;
    private final TextureAtlas.AtlasRegion myBeltTex;
    private final TextureAtlas.AtlasRegion myBeaconAttackTex;
    private final TextureAtlas.AtlasRegion myBeaconMoveTex;
    private final TextureAtlas.AtlasRegion myBeaconFollowTex;
    private final TextureAtlas.AtlasRegion myIconBg;
    private final TextureAtlas.AtlasRegion myWarnAreaBg;
    private final TextureAtlas.AtlasRegion myWhiteTex;
    private final TextureAtlas.AtlasRegion myLineTex;

    private final Color myAreaWarnCol;
    private final Color myAreaWarnBgCol;
    private final float myIconRad;
    private boolean myToggled;
    private float myZoom;
    private float mySkullTime;
    private float myAreaSkullTime;

    public MapDrawer(TextureManager textureManager, float screenHeight) {
        myZoom = MAX_ZOOM / MUL_FACTOR / MUL_FACTOR;
        float minIconRad = MIN_ICON_RAD_PX / screenHeight;
        myIconRad = ICON_RAD < minIconRad ? minIconRad : ICON_RAD;

        myAreaWarnCol = new Color(PtmColor.WHITE);
        myAreaWarnBgCol = new Color(PtmColor.UI_WARN);

        myWarnAreaBg = textureManager.getTexture(MAP_TEX_DIR + "warnBg");
        myAtmTex = textureManager.getTexture(MAP_TEX_DIR + "atm");
        myPlanetTex = textureManager.getTexture(MAP_TEX_DIR + "planet");
        myPlanetCoreTex = textureManager.getTexture(MAP_TEX_DIR + "planetCore");
        myStarTex = textureManager.getTexture(MAP_TEX_DIR + "star");
        myMazeTex = textureManager.getTexture(MAP_TEX_DIR + "maze");
        mySkullBigTex = textureManager.getTexture(MAP_TEX_DIR + "skullBig");
        myBeltTex = textureManager.getTexture(MAP_TEX_DIR + "asteroids");
        myBeaconAttackTex = textureManager.getTexture(MAP_TEX_DIR + "beaconAttack");
        myBeaconMoveTex = textureManager.getTexture(MAP_TEX_DIR + "beaconMove");
        myBeaconFollowTex = textureManager.getTexture(MAP_TEX_DIR + "beaconFollow");
        myWhiteTex = textureManager.getTexture(MAP_TEX_DIR + "whiteTex");
        myLineTex = textureManager.getTexture(MAP_TEX_DIR + "gridLine");

        myIconBg = textureManager.getTexture(TextureManager.HULL_ICONS_DIR + "bg");
        mySkullTex = textureManager.getTexture(TextureManager.HULL_ICONS_DIR + "skull");
        myStarPortTex = textureManager.getTexture(TextureManager.HULL_ICONS_DIR + "starPort");
    }

    public boolean isToggled() {
        return myToggled;
    }

    public void setToggled(boolean toggled) {
        myToggled = toggled;
    }

    public void draw(GameDrawer drawer, PtmGame game) {
        PtmCam cam = game.getCam();
        float iconSz = getIconRadius(cam) * 2;
        float starNodeW = cam.getViewHeight(myZoom) * STAR_NODE_SZ;
        float viewDist = cam.getViewDist(myZoom);
        FactionManager factionManager = game.getFactionMan();
        PtmShip hero = game.getHero();
        Planet np = game.getPlanetMan().getNearestPlanet();
        Vector2 camPos = cam.getPos();
        float camAngle = cam.getAngle();
        float heroDmgCap = hero == null ? Float.MAX_VALUE : HardnessCalc.getShipDmgCap(hero);

        drawer.updateMtx(game);
        game.getGridDrawer().draw(drawer, game, GRID_SZ, myLineTex);
        drawPlanets(drawer, game, viewDist, np, camPos, heroDmgCap, camAngle);
        drawMazes(drawer, game, viewDist, np, camPos, heroDmgCap, camAngle);
        drawStarNodes(drawer, game, viewDist, camPos, starNodeW);

        // using ui textures
        drawIcons(drawer, game, iconSz, viewDist, factionManager, hero, camPos, heroDmgCap);
    }

    public float getIconRadius(PtmCam cam) {
        return cam.getViewHeight(myZoom) * myIconRad;
    }

    private void drawMazes(GameDrawer drawer, PtmGame game, float viewDist, Planet np, Vector2 camPos,
            float heroDmgCap, float camAngle) {
        ArrayList<Maze> mazes = game.getPlanetMan().getMazes();
        for (int i = 0, mazesSize = mazes.size(); i < mazesSize; i++) {
            Maze maze = mazes.get(i);
            Vector2 mazePos = maze.getPos();
            float outerRad = maze.getRadius();
            float rad = outerRad - MazeBuilder.BORDER;
            if (viewDist < camPos.dst(mazePos) - rad) {
                continue;
            }
            drawer.draw(myMazeTex, 2 * rad, 2 * rad, rad, rad, mazePos.x, mazePos.y, 45, PtmColor.WHITE);
            if (HardnessCalc.isDangerous(heroDmgCap, maze.getDps())) {
                drawAreaDanger(drawer, outerRad, mazePos, 1, camAngle);
            }
        }

    }

    private void drawPlanets(GameDrawer drawer, PtmGame game, float viewDist, Planet np, Vector2 camPos,
            float heroDmgCap, float camAngle) {
        ArrayList<PtmSystem> systems = game.getPlanetMan().getSystems();
        PtmCam cam = game.getCam();
        float circleWidth = cam.getRealLineWidth() * 6;
        float vh = cam.getViewHeight(myZoom);
        for (int i3 = 0, systemsSize1 = systems.size(); i3 < systemsSize1; i3++) {
            PtmSystem sys = systems.get(i3);
            drawer.drawCircle(myLineTex, sys.getPos(), sys.getRadius(), PtmColor.UI_MED, circleWidth, vh);
        }
        for (int i2 = 0, systemsSize = systems.size(); i2 < systemsSize; i2++) {
            PtmSystem sys = systems.get(i2);
            float dangerRad = HardnessCalc.isDangerous(heroDmgCap, sys.getDps()) ? sys.getRadius() : 0;
            Vector2 sysPos = sys.getPos();
            float rad = Const.SUN_RADIUS;
            if (camPos.dst(sysPos) - rad < viewDist) {
                drawer.draw(myStarTex, 2 * rad, 2 * rad, rad, rad, sysPos.x, sysPos.y, 0, PtmColor.WHITE);
            }

            Vector2 beltIconPos = PtmMath.getVec();
            ArrayList<SystemBelt> belts = sys.getBelts();
            for (int i1 = 0, beltsSize = belts.size(); i1 < beltsSize; i1++) {
                SystemBelt belt = belts.get(i1);
                float beltRad = belt.getRadius();
                float halfWidth = belt.getHalfWidth();
                int beltIconCount = (int) (.12f * beltRad);
                for (int i = 0; i < beltIconCount; i++) {
                    float angle = 360f * i / beltIconCount;
                    PtmMath.fromAl(beltIconPos, angle, beltRad);
                    beltIconPos.add(sysPos);
                    drawer.draw(myBeltTex, 2 * halfWidth, 2 * halfWidth, halfWidth, halfWidth, beltIconPos.x,
                            beltIconPos.y, angle * 3, PtmColor.WHITE);
                }
                float outerRad = beltRad + halfWidth;
                if (dangerRad < outerRad && HardnessCalc.isDangerous(heroDmgCap, belt.getDps())) {
                    dangerRad = outerRad;
                }
            }
            PtmMath.free(beltIconPos);
            if (dangerRad < sys.getInnerRad() && HardnessCalc.isDangerous(heroDmgCap, sys.getInnerDps())) {
                dangerRad = sys.getInnerRad();
            }
            if (dangerRad > 0) {
                drawAreaDanger(drawer, dangerRad, sysPos, .5f, camAngle);
            }
        }

        ArrayList<Planet> planets = game.getPlanetMan().getPlanets();
        for (int i = 0, planetsSize = planets.size(); i < planetsSize; i++) {
            Planet planet = planets.get(i);
            Vector2 planetPos = planet.getPos();
            float fh = planet.getFullHeight();
            float dstToPlanetAtm = camPos.dst(planetPos) - fh;
            if (viewDist < dstToPlanetAtm) {
                continue;
            }
            drawer.draw(myAtmTex, 2 * fh, 2 * fh, fh, fh, planetPos.x, planetPos.y, 0, PtmColor.UI_DARK);
            float gh;
            if (dstToPlanetAtm < 0) {
                gh = planet.getMinGroundHeight() + .5f;
                drawer.draw(myPlanetCoreTex, 2 * gh, 2 * gh, gh, gh, planetPos.x, planetPos.y, planet.getAngle(),
                        PtmColor.WHITE);
                drawNpGround(drawer, game, viewDist, np, camPos);
            } else {
                gh = planet.getGroundHeight();
                drawer.draw(myPlanetTex, 2 * gh, 2 * gh, gh, gh, planetPos.x, planetPos.y, camAngle,
                        PtmColor.WHITE);
            }
            float dangerRad = HardnessCalc.isDangerous(heroDmgCap, planet.getGroundDps())
                    ? gh + Const.ATM_HEIGHT / 2
                    : 0;
            //      if (dangerRad < gh && HardnessCalc.isDangerous(heroDmgCap, planet.getGroundDps())) dangerRad = gh;
            if (dangerRad > 0) {
                drawAreaDanger(drawer, dangerRad, planetPos, 1, camAngle);
            }
        }
    }

    private void drawAreaDanger(GameDrawer drawer, float rad, Vector2 pos, float transpMul, float angle) {
        float perc = 2 * myAreaSkullTime / MAX_AREA_SKULL_TIME;
        if (perc > 1) {
            perc = 2 - perc;
        }
        perc = PtmMath.clamp((perc - .5f) * 2 + .5f);
        float a = PtmMath.clamp(perc * transpMul);
        myAreaWarnBgCol.a = a;
        myAreaWarnCol.a = a;
        drawer.draw(myWarnAreaBg, rad * 2, rad * 2, rad, rad, pos.x, pos.y, 0, myAreaWarnBgCol);
        rad *= INNER_AREA_ICON_PERC;
        drawer.draw(mySkullBigTex, rad * 2, rad * 2, rad, rad, pos.x, pos.y, angle, myAreaWarnCol);
    }

    private void drawIcons(GameDrawer drawer, PtmGame game, float iconSz, float viewDist,
            FactionManager factionManager, PtmShip hero, Vector2 camPos, float heroDmgCap) {
        List<PtmObject> objs = game.getObjMan().getObjs();
        for (int i1 = 0, objsSize = objs.size(); i1 < objsSize; i1++) {
            PtmObject o = objs.get(i1);
            Vector2 oPos = o.getPosition();
            if (viewDist < camPos.dst(oPos)) {
                continue;
            }
            if ((o instanceof PtmShip)) {
                PtmShip ship = (PtmShip) o;
                String hint = ship.getPilot().getMapHint();
                if (hint == null && !DebugOptions.DETAILED_MAP) {
                    continue;
                }
                drawObjIcon(iconSz, oPos, ship.getAngle(), factionManager, hero, ship.getPilot().getFaction(),
                        heroDmgCap, o, ship.getHull().config.getIcon(), drawer);
            }
            if ((o instanceof StarPort)) {
                StarPort sp = (StarPort) o;
                drawStarPortIcon(drawer, iconSz, sp.getFrom(), sp.getTo());
            }
            // Fix for when the player is in hyper. Hero is null and replaced in ObjMan with a StarPort.Transcendent
            if ((o instanceof StarPort.Transcendent)) {
                StarPort.Transcendent t = (StarPort.Transcendent) o;
                if (t.getShip().getPilot().isPlayer()) {
                    FarShip ship = game.getTranscendentHero().getShip();
                    drawObjIcon(iconSz, oPos, t.getAngle(), factionManager, hero, ship.getPilot().getFaction(),
                            heroDmgCap, o, ship.getHullConfig().getIcon(), drawer);
                }

            }
        }

        List<FarShip> farShips = game.getObjMan().getFarShips();
        for (int i = 0, sz = farShips.size(); i < sz; i++) {
            FarShip ship = farShips.get(i);
            Vector2 oPos = ship.getPos();
            if (viewDist < camPos.dst(oPos)) {
                continue;
            }
            String hint = ship.getPilot().getMapHint();
            if (hint == null && !DebugOptions.DETAILED_MAP) {
                continue;
            }
            drawObjIcon(iconSz, oPos, ship.getAngle(), factionManager, hero, ship.getPilot().getFaction(),
                    heroDmgCap, ship, ship.getHullConfig().getIcon(), drawer);
        }

        List<StarPort.MyFar> farPorts = game.getObjMan().getFarPorts();
        for (int i = 0, sz = farPorts.size(); i < sz; i++) {
            StarPort.MyFar sp = farPorts.get(i);
            drawStarPortIcon(drawer, iconSz, sp.getFrom(), sp.getTo());
        }
        BeaconHandler bh = game.getBeaconHandler();
        BeaconHandler.Action bhAction = bh.getCurrAction();
        if (bhAction != null) {
            Vector2 beaconPos = bh.getPos();
            TextureRegion icon = myBeaconMoveTex;
            if (bhAction == BeaconHandler.Action.ATTACK) {
                icon = myBeaconAttackTex;
            } else if (bhAction == BeaconHandler.Action.FOLLOW) {
                icon = myBeaconFollowTex;
            }
            float beaconSz = iconSz * 1.5f;
            //      drawer.draw(icon, beaconSz, beaconSz, beaconSz/2, beaconSz/2, beaconPos.x, beaconPos.y, 0, PtmColor.WHITE); interleaving
        }
    }

    public void drawStarPortIcon(GameDrawer drawer, float iconSz, Planet from, Planet to) {
        float angle = PtmMath.angle(from.getPos(), to.getPos());
        Vector2 pos = StarPort.getDesiredPos(from, to, false);
        drawObjIcon(iconSz, pos, angle, null, null, null, -1, null, myStarPortTex, drawer);
        PtmMath.free(pos);
    }

    private void drawStarNodes(GameDrawer drawer, PtmGame game, float viewDist, Vector2 camPos, float starNodeW) {
        List<PtmObject> objs = game.getObjMan().getObjs();
        for (int i1 = 0, objsSize = objs.size(); i1 < objsSize; i1++) {
            PtmObject o = objs.get(i1);
            if (!(o instanceof StarPort)) {
                continue;
            }
            Vector2 oPos = o.getPosition();
            if (viewDist < camPos.dst(oPos)) {
                continue;
            }
            StarPort sp = (StarPort) o;
            drawStarNode(drawer, sp.getFrom(), sp.getTo(), starNodeW);
        }

        List<StarPort.MyFar> farPorts = game.getObjMan().getFarPorts();
        for (int i = 0, sz = farPorts.size(); i < sz; i++) {
            StarPort.MyFar sp = farPorts.get(i);
            Vector2 oPos = sp.getPos();
            if (viewDist < camPos.dst(oPos)) {
                continue;
            }
            if (!sp.isSecondary()) {
                drawStarNode(drawer, sp.getFrom(), sp.getTo(), starNodeW);
            }
        }
    }

    private void drawStarNode(GameDrawer drawer, Planet from, Planet to, float starNodeW) {
        Vector2 pos1 = StarPort.getDesiredPos(from, to, false);
        Vector2 pos2 = StarPort.getDesiredPos(to, from, false);
        drawer.drawLine(myWhiteTex, pos1, pos2, PtmColor.UI_LIGHT, starNodeW, true);
        PtmMath.free(pos1);
        PtmMath.free(pos2);
    }

    private void drawNpGround(GameDrawer drawer, PtmGame game, float viewDist, Planet np, Vector2 camPos) {
        ObjectManager objectManager = game.getObjMan();
        List<PtmObject> objs = objectManager.getObjs();
        for (int i1 = 0, objsSize = objs.size(); i1 < objsSize; i1++) {
            PtmObject o = objs.get(i1);
            if (!(o instanceof TileObject)) {
                continue;
            }
            TileObject to = (TileObject) o;
            if (to.getPlanet() != np) {
                continue;
            }
            Vector2 oPos = o.getPosition();
            if (viewDist < camPos.dst(oPos)) {
                continue;
            }
            float sz = to.getSz();
            drawPlanetTile(to.getTile(), sz, drawer, oPos, to.getAngle());
        }

        List<FarObjData> farObjs = objectManager.getFarObjs();
        for (int i = 0, farObjsSize = farObjs.size(); i < farObjsSize; i++) {
            FarObjData fod = farObjs.get(i);
            FarObj o = fod.fo;
            if (!(o instanceof FarTileObject)) {
                continue;
            }
            FarTileObject to = (FarTileObject) o;
            if (to.getPlanet() != np) {
                continue;
            }
            Vector2 oPos = o.getPos();
            if (viewDist < camPos.dst(oPos)) {
                continue;
            }
            float sz = to.getSz();
            drawPlanetTile(to.getTile(), sz, drawer, oPos, to.getAngle());
        }
    }

    public void drawObjIcon(float iconSz, Vector2 pos, float objAngle, FactionManager factionManager, PtmShip hero,
            Faction objFac, float heroDmgCap, Object shipHack, TextureAtlas.AtlasRegion icon, Object drawerHack) {
        boolean enemy = hero != null && factionManager.areEnemies(objFac, hero.getPilot().getFaction());
        float angle = objAngle;
        if (enemy && mySkullTime > 0 && HardnessCalc.isDangerous(heroDmgCap, shipHack)) {
            icon = mySkullTex;
            angle = 0;
        }
        float innerIconSz = iconSz * INNER_ICON_PERC;

        if (drawerHack instanceof UiDrawer) {
            UiDrawer uiDrawer = (UiDrawer) drawerHack;
            uiDrawer.draw(myIconBg, iconSz, iconSz, iconSz / 2, iconSz / 2, pos.x, pos.y, 0,
                    enemy ? PtmColor.UI_WARN : PtmColor.UI_LIGHT);
            uiDrawer.draw(icon, innerIconSz, innerIconSz, innerIconSz / 2, innerIconSz / 2, pos.x, pos.y, angle,
                    PtmColor.WHITE);
        } else {
            GameDrawer gameDrawer = (GameDrawer) drawerHack;
            gameDrawer.draw(myIconBg, iconSz, iconSz, iconSz / 2, iconSz / 2, pos.x, pos.y, 0,
                    enemy ? PtmColor.UI_WARN : PtmColor.UI_LIGHT);
            gameDrawer.draw(icon, innerIconSz, innerIconSz, innerIconSz / 2, innerIconSz / 2, pos.x, pos.y, angle,
                    PtmColor.WHITE);
        }
    }

    public void changeZoom(boolean zoomIn) {
        if (zoomIn) {
            myZoom /= MUL_FACTOR;
        } else {
            myZoom *= MUL_FACTOR;
        }
        myZoom = PtmMath.clamp(myZoom, MIN_ZOOM, MAX_ZOOM);
    }

    public float getZoom() {
        return myZoom;
    }

    public void update(PtmGame game) {
        mySkullTime += game.getTimeStep();
        if (mySkullTime > MAX_SKULL_TIME) {
            mySkullTime = -MAX_SKULL_TIME;
        }
        myAreaSkullTime += game.getTimeStep();
        if (myAreaSkullTime > MAX_AREA_SKULL_TIME) {
            myAreaSkullTime = 0;
        }
    }

    private void drawPlanetTile(Tile t, float sz, GameDrawer drawer, Vector2 p, float angle) {
        float szh = .6f * sz;
        Color col = t.from == SurfaceDirection.UP && t.to == SurfaceDirection.UP ? PtmColor.WHITE
                : PtmColor.UI_OPAQUE;
        if (t.from == SurfaceDirection.FWD || t.from == SurfaceDirection.UP) {
            if (t.from == SurfaceDirection.UP) {
                drawer.draw(myWhiteTex, szh, szh, 0, 0, p.x, p.y, angle - 90, col);
            }
            drawer.draw(myWhiteTex, szh, szh, 0, 0, p.x, p.y, angle, col);
        }
        if (t.to == SurfaceDirection.FWD || t.to == SurfaceDirection.UP) {
            if (t.to == SurfaceDirection.UP) {
                drawer.draw(myWhiteTex, szh, szh, 0, 0, p.x, p.y, angle + 180, col);
            }
            drawer.draw(myWhiteTex, szh, szh, 0, 0, p.x, p.y, angle + 90, col);
        }
    }

    public TextureAtlas.AtlasRegion getStarPortTex() {
        return myStarPortTex;
    }

}