com.tm4rkus.screens.MapScreenOld.java Source code

Java tutorial

Introduction

Here is the source code for com.tm4rkus.screens.MapScreenOld.java

Source

package com.tm4rkus.screens;

/**
 *   Copyright 2011 David Kirchner dpk@dpk.net
 *
 *   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.
 *   
 * TiledMapHelper can simplify your game's tiled map operations. You can find
 * some sample code using this class at my blog:
 * 
 * http://dpk.net/2011/05/08/libgdx-box2d-tiled-maps-full-working-example-part-2/
 * 
 * Note: This code does have some limitations. It only supports single-layered
 * maps.
 * 
 * This code is based on TiledMapTest.java found at:
 * http://code.google.com/p/libgdx/
 */

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Plane;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.Ray;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.tm4rkus.conquertheempire.Game;
import com.tm4rkus.conquertheempire.Tile;
import com.tm4rkus.helperclasses.InteractiveObjectHandler;
import com.tm4rkus.helperclasses.MyFPSLogger;
import com.tm4rkus.helperclasses.MyGrid;
import com.tm4rkus.helperclasses.MyGrid3D;
import com.tm4rkus.helperclasses.MyTextureRegion;
import com.tm4rkus.objects.Interactive3DObject;
import com.tm4rkus.objects.MovableI3DO;

public class MapScreenOld extends Stage {

    public final static int MAPSIZE_SMALL = 50;
    public final static int MAPSIZE_MEDIUM = 75;
    public final static int MAPSIZE_BIG = 100;
    public final static int MAPSIZE_HUGE = 125;
    public final static int MAPSIZE_GIANT = 200;

    public static int tiles;
    protected TextureRegion[] grasses, stones, leaves, sands, grassesStones, grassesLeaves, grassesSands,
            stonesLeaves, stonesSands, leavesSands;
    protected TextureRegion backgroundImage;
    protected Texture scene2dTexture;
    protected OrthographicCamera cam;
    protected Sprite[][] tilesBackground;
    protected MyGrid tilesForeground;
    protected MyGrid3D tilesForeground3D;
    protected Image topLine;
    protected boolean touchDragged = false;
    protected InteractiveObjectHandler interactiveObjectHandler;

    private static int tilesOnSight = 10;
    private Texture texture;
    private TextureRegion grassRegion, stoneRegion, leavesRegion, sandRegion, grassStoneRegion, grassLeavesRegion,
            grassSandRegion, stoneLeavesRegion, stoneSandRegion, leavesSandRegion;
    private SpriteBatch batch;
    private ModelBatch modelBatch;
    private final Matrix4 matrix = new Matrix4();
    private MyFPSLogger logger = new MyFPSLogger();
    private int tilesInView[] = new int[4];
    private Label fps;
    public ScrollPane scrollPane;
    public boolean creativeMode;

    public MapScreenOld(int size) {
        //super(Game.stageWidth, Game.stageHeight, true);

        tiles = size;
        tilesBackground = new Sprite[tiles * 2][tiles * 2];
        tilesForeground = new MyGrid(tiles);
        tilesForeground3D = new MyGrid3D(tiles);
        interactiveObjectHandler = new InteractiveObjectHandler();

        texture = new Texture(Gdx.files.internal("data/packer/texture.png"));

        int tWidth = texture.getWidth();

        //pure grass, stone, leaves
        grassRegion = new TextureRegion(texture, 0, 0, tWidth, 32);
        grasses = new TextureRegion[tWidth / 32];

        stoneRegion = new TextureRegion(texture, 0, 32, tWidth, 32);
        stones = new TextureRegion[tWidth / 32];

        leavesRegion = new TextureRegion(texture, 0, 64, tWidth, 32);
        leaves = new TextureRegion[tWidth / 32];

        sandRegion = new TextureRegion(texture, 0, 96, tWidth, 32);
        sands = new TextureRegion[tWidth / 32];

        //merge regions
        grassStoneRegion = new TextureRegion(texture, 0, 128, tWidth, 32);
        grassesStones = new TextureRegion[tWidth / 32];

        grassLeavesRegion = new TextureRegion(texture, 0, 160, tWidth, 32);
        grassesLeaves = new TextureRegion[tWidth / 32];

        grassSandRegion = new TextureRegion(texture, 0, 192, tWidth, 32);
        grassesSands = new TextureRegion[tWidth / 32];

        stoneLeavesRegion = new TextureRegion(texture, 0, 224, tWidth, 32);
        stonesLeaves = new TextureRegion[tWidth / 32];

        stoneSandRegion = new TextureRegion(texture, 0, 256, tWidth, 32);
        stonesSands = new TextureRegion[tWidth / 32];

        leavesSandRegion = new TextureRegion(texture, 0, 288, tWidth, 32);
        leavesSands = new TextureRegion[tWidth / 32];

        for (int x = 0; x < 16; x++) {
            grasses[x] = new MyTextureRegion(grassRegion, x * 32, 0, 32, 32, MyTextureRegion.GRASS);
            stones[x] = new MyTextureRegion(stoneRegion, x * 32, 0, 32, 32, MyTextureRegion.STONE);
            leaves[x] = new MyTextureRegion(leavesRegion, x * 32, 0, 32, 32, MyTextureRegion.LEAVES);
            sands[x] = new MyTextureRegion(sandRegion, x * 32, 0, 32, 32, MyTextureRegion.SAND);
        }
        //cam = new PerspectiveCamera(10, tilesOnSight, tilesOnSight * (Gdx.graphics.getHeight() / (float)Gdx.graphics.getWidth()) );   
        cam = new OrthographicCamera(tilesOnSight,
                tilesOnSight * (Gdx.graphics.getHeight() / (float) Gdx.graphics.getWidth()));
        cam.direction.set((float) -0.0002, -1, 0);
        cam.position.set((float) ((tiles / 2) - cam.direction.x * 10), (float) (10), (float) (tiles / 2));

        //cam.zoom = 3;
        cam.near = 1;
        cam.far = 100;
        matrix.setToRotation(new Vector3(1, 0, 0), 90);

        //create the map
        for (int z = 0; z < tiles; z++) {
            for (int x = 0; x < tiles; x++) {
                int tileNumber = (int) (Math.random() * 16);
                if ((x + z) % 2 == 0)
                    tilesBackground[x][z] = new Tile((MyTextureRegion) grasses[tileNumber]);
                else
                    tilesBackground[x][z] = new Tile((MyTextureRegion) stones[tileNumber]);
                tilesBackground[x][z].setPosition(x, z);
                tilesBackground[x][z].setSize(1, 1);

            }
        }
        batch = new SpriteBatch();
        modelBatch = new ModelBatch();
        setTilesInView();

        createOverlay();
    }

    private void createOverlay() {

        scene2dTexture = new Texture(Gdx.files.internal("data/packer/scene2d.png"));
        backgroundImage = new TextureRegion(scene2dTexture, 0, 0, 400, 240);

        //Unit unit = new Unit();

        topLine = new Image(new TextureRegionDrawable(backgroundImage));
        topLine.setHeight(42);
        topLine.setWidth(820);
        topLine.setX(-10);
        topLine.setY(440);

        fps = new Label("fps: 0", Game.skin);
        fps.setX(Game.stageWidth - 100);
        fps.setY(Game.stageHeight - 35);

        addActor(topLine);
        addActor(fps);
        //addActor(unit);

    }

    int frame = 0;
    long deltaTime = 0;
    long oldTime = System.currentTimeMillis();
    long newTime = System.currentTimeMillis();

    public void draw() {
        if (Game.objectManager.isLoading() && Game.objectManager.update()) {
            Game.objectManager.getModels();
            for (int i = 0; i < 2; i++) {
                //   tilesForeground3D.add(new MovableI3DO(Game.objectManager.villager, (float)Math.random()*4+98, (float)Math.random()*4+98, cam));
            }
        }
        if (!Game.objectManager.isLoading()) {
            frame++;
            fps.setText(logger.log());
            oldTime = System.currentTimeMillis();
            deltaTime = oldTime - newTime;
            newTime = System.currentTimeMillis();
            act(); // do not forget this one!!

            Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

            cam.update();
            batch.setProjectionMatrix(cam.combined);
            batch.setTransformMatrix(matrix);
            batch.begin();

            //tilesInView stores, which tiles are visible to the user, so there is no unnecessary rendering of other tiles

            //rendering background
            //disable blending, because background doesn't need to merge with other pixels
            batch.disableBlending();

            for (int z = tilesInView[2]; z <= tilesInView[3]; z++) {
                for (int x = tilesInView[0]; x <= tilesInView[1]; x++) {
                    if (tilesBackground[x][z].getTexture() != null)
                        tilesBackground[x][z].draw(batch);
                }
            }

            //rendering Foreground
            //enable blending, because foreground needs to merge with background
            batch.enableBlending();
            for (int z = tilesInView[2]; z <= tilesInView[3]; z++) {
                for (int x = tilesInView[0]; x <= tilesInView[1]; x++) {
                    if (tilesForeground.get(x, z) != null) {
                        tilesForeground.act(x, z, (float) 0.01);
                        tilesForeground.draw(x, z, batch);
                    }
                }
            }

            batch.end();
            cam.apply(Gdx.gl10);
            modelBatch.begin(cam);
            for (int z = tilesInView[2] - 1 >= 0 ? tilesInView[2] - 1 : 0; z <= tilesInView[3]; z++) {
                for (int x = tilesInView[0] - 4 >= 0 ? tilesInView[0] - 4 : 0; x <= tilesInView[1] + 1; x++) {
                    if (tilesForeground3D.get(x, z).size() != 0) {
                        tilesForeground3D.draw(x, z, modelBatch);
                    }
                }
            }
            modelBatch.end();

            if (!stop) {
                tilesForeground3D.calcPositions();
                tilesForeground3D.checkCollisions();
            }
            super.draw();
        }
    }

    private static boolean stop = false;

    public static void stop() {
        stop = true;
    }

    public static void run() {
        stop = false;
    }

    final Plane xzPlane = new Plane(new Vector3(0, 1, 0), 0);
    final Vector3 intersection = new Vector3();
    Sprite lastSelectedTile = null;

    private void setTilesInView() {

        //smallest X
        tilesInView[0] = getIntersectedTiles(0, 0, xzPlane)[0];
        //biggest X
        tilesInView[1] = getIntersectedTiles(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), xzPlane)[0];
        //smallest Z
        tilesInView[2] = getIntersectedTiles(Gdx.graphics.getWidth(), 0, xzPlane)[1];
        //biggest Z
        tilesInView[3] = getIntersectedTiles(0, 0, xzPlane)[1];

        for (int i = 0; i < 4; i++) {
            if (tilesInView[i] < 0)
                tilesInView[i] = 0;
            else if (tilesInView[i] >= tiles)
                tilesInView[i] = tiles - 1;
        }
    }

    @Override
    public boolean touchDragged(int x, int y, int pointer) {
        //move the camera
        Boolean isTouchDragged = super.touchDragged(x, y, pointer);

        if (!isTouchDragged && numberOfFingers == 1) {
            singleTapDragged(x, y);
        }

        // pinch to zoom
        // for pinch-to-zoom
        if (numberOfFingers == 2) {
            twoFingersDragged(x, y, pointer);
        }
        cam.update();
        return false;
    }

    //get intersected tiles on the xzPlane
    //x, y: place on the screen, where to detect the intersected tile
    //return intersectedTiles: Array with two entries, storing the x and z coordinate of the intersected tile
    private int[] getIntersectedTiles(int x, int y, Plane plane) {
        cam.update();
        Ray ray = cam.getPickRay(x, y);
        Vector3 myintersection = new Vector3();
        int intersectedTiles[] = new int[2];

        Intersector.intersectRayPlane(ray, plane, myintersection);
        intersectedTiles[0] = (int) myintersection.x;
        intersectedTiles[1] = (int) myintersection.z;

        return intersectedTiles;
    }

    /**
     * If no object selected: Select object (or add object to the already selected objects).
     * If object(s) selected: Send object to touched point on the map (or attack hostile object at that point)
     * @param x x-coordinate on the map
     * @param z z-coordinate on the map
     */
    private void singleTap(float x, float z) {

        // TODO: select object
        // TODO: send object
    }

    /**
     * if object is touched: select all objects of that type within the viewport (delete all others from selected list)
     * @param x x-coordinate on the map
     * @param z z-coordinate on the map
     */
    private void doubleTap(float x, float z) {
        // TODO: select all objects of that type
    } //end doubleTap

    /** 
     * Move the camera to scroll over the map
     * @param x x-coordinate of the finger on screen
     * @param y y-coordinate of the finger on screen
     */
    final Vector3 currentSingleTapDrag = new Vector3();
    final Vector3 lastSingleTapDrag = new Vector3(-1, -1, -1);
    final Vector3 deltaSingleTapDrag = new Vector3();

    private void singleTapDragged(int x, int y) {
        //System.out.println(batch.maxSpritesInBatch);
        Ray pickRay = cam.getPickRay(x, y);
        Intersector.intersectRayPlane(pickRay, xzPlane, currentSingleTapDrag);

        if (!(lastSingleTapDrag.x == -1 && lastSingleTapDrag.y == -1 && lastSingleTapDrag.z == -1)) {
            pickRay = cam.getPickRay(lastSingleTapDrag.x, lastSingleTapDrag.y);
            Intersector.intersectRayPlane(pickRay, xzPlane, deltaSingleTapDrag);
            deltaSingleTapDrag.sub(currentSingleTapDrag);

            cam.position.add(deltaSingleTapDrag.x, 0, deltaSingleTapDrag.z);
            cam.update();
            Ray centerRay = cam.getPickRay(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
            Intersector.intersectRayPlane(centerRay, xzPlane, intersection);
            float centerX = intersection.x;
            float centerZ = intersection.z;

            if (centerX < 2) {
                cam.position.x = (float) (2 - (cam.direction.x * cam.position.y));
            }
            if (centerZ > tiles - 2) {
                cam.position.z = tiles - 2;
            }
            if (centerX > tiles - 2) {
                cam.position.x = (float) (tiles - 2 - (cam.direction.x * cam.position.y));
            }
            if (centerZ < 2) {
                cam.position.z = 2;
            }
        }
        lastSingleTapDrag.set(x, y, 0);
        setTilesInView();
        if (deltaSingleTapDrag.x != 0.0 || deltaSingleTapDrag.y != 0.0 || deltaSingleTapDrag.z != 0.0) {
            touchDragged = true;
        }
    } //end singleTapDragged

    /**
     * Create a selection rectangle and select all movable objects within it's range
     * @param x x-coordinate of the finger on screen
     * @param y y-coordinate of the finger on screen
     */
    private Vector3 startDoubleTapDrag = new Vector3();

    private void doubleTapDragged(float x, float y) {
        // TODO: create selection rectangle and select all movable objects within it's range
    } //end doubleTapDragged

    /**
     * If both fingers go up: tilt cam
     * If both fingers go apart: zoom cam
     * @param x x-coordinate of the finger on screen
     * @param y y-coordinate of the finger on screen
     * @param pointer pointer to identify the finger
     */
    private void twoFingersDragged(int x, int y, int pointer) {
        if (pointer == fingerOnePointer) {
            fingerOne.set(x, y, 0);
        }
        if (pointer == fingerTwoPointer) {
            fingerTwo.set(x, y, 0);
        }

        float xDistance = Math.abs(fingerOne.x - fingerTwo.x);
        float xChange = xDistance - lastXDistance;
        float yChange = (fingerOne.y + fingerTwo.y) - (lastY1 + lastY2);

        if (((fingerOne.y > lastY1 && fingerTwo.y > lastY2) || (fingerOne.y < lastY1 && fingerTwo.y < lastY2))
                && (Math.abs(yChange) > Math.abs(xChange))) {
            tiltCam(yChange);
        } else {
            // zoom in and out
            zoomCam(xChange);
        }

        lastXDistance = xDistance;

        //the method touchdragged registers only one pointer at once, so don't update both
        if (pointer == fingerTwoPointer) {
            lastY1 = fingerOne.y;
        } else if (pointer == fingerOnePointer) {
            lastY2 = fingerTwo.y;
        }
        setTilesInView();
    }

    /**
     * Tilt camera to have a more 3-dimensional scene from the side or more 2-dimensional from above (like GTA2 ;P)
     * @param tiltFactor The Factor the declination changes with
     */
    private void tiltCam(float tiltFactor) {
        cam.direction.x -= tiltFactor * 0.005;
        cam.position.x = (float) (centerX - (cam.direction.x * cam.position.y));
        cam.update();

        // don't tilt too much
        if (cam.direction.x < (float) -2.2) {
            cam.direction.x = (float) -2.2;
        }
        if (cam.direction.x > (float) -0.1) {
            cam.direction.x = (float) -0.1;
        }
    }

    /**
     * Zoom camera to have a wider or a closer view at the scene
     * @param zoomFactor The Factor the zoom changes with: (zoomFactor > 0) --> closer view ; (zoomFactor < 0) --> wider view
     */
    private void zoomCam(float zoomFactor) {
        // multiply with cam.zoom to get rid of the different zoom speed, depending on whether it close or not.
        cam.zoom -= cam.zoom * zoomFactor * 0.005;
        cam.update();

        // don't zoom in/out too much.
        if (cam.zoom > (float) (1.5)) {
            cam.zoom = (float) (1.5);
        }
        if (cam.zoom < (float) (0.8)) {
            cam.zoom = (float) (0.8);
        }

        touchDragged = true;
    }

    public boolean superTouchUp(int x, int y, int pointer, int button) {
        return super.touchUp(x, y, pointer, button);
    }

    private long touchTime;

    public boolean touchUp(int x, int y, int pointer, int button) {

        boolean isTouchUp = super.touchUp(x, y, pointer, button);

        lastSingleTapDrag.set(-1, -1, -1);
        // for pinch-to-zoom           
        if (numberOfFingers == 1) {
            Vector3 touchPoint = new Vector3(x, y, 0);
            cam.unproject(touchPoint);
            if (!touchDragged) {
                Ray pickRay = cam.getPickRay(Gdx.input.getX(), Gdx.input.getY());
                Intersector.intersectRayPlane(pickRay, xzPlane, intersection);
                float isctX = intersection.x;
                float isctZ = intersection.z;
                //debug stuff
                System.out.println("Map touched at: " + isctX + "|" + isctZ);
                //tilesForeground3D.clear();
                //for(int i = 0; i < 10; i++) {
                //tilesForeground3D.add(new MovableI3DO(Game.objectManager.villager, (float)Math.random()*10+95, (float)Math.random()*10+95, cam));
                MovableI3DO movable;
                /*movable = new MovableI3DO(Game.objectManager.villager, 102, 100, cam);
                movable.setDestination(100, 100);
                tilesForeground3D.add(movable);
                movable = new MovableI3DO(Game.objectManager.villager, (float)98.5, 100, cam);
                movable.setDestination(100, 100);
                tilesForeground3D.add(movable);*/
                movable = new MovableI3DO(Game.objectManager.villager, isctX, isctZ);
                movable.setDestination(100, 100);
                tilesForeground3D.add(movable);
                //   run();
                //}

                if (isctX >= 0 && isctX < tiles && isctZ >= 0 && isctZ < tiles) {
                    if (System.currentTimeMillis() - touchTime > 200) {
                        touchTime = System.currentTimeMillis();
                        singleTap(isctX, isctZ);
                    } else {
                        touchTime = 0;
                        doubleTap(isctX, isctZ);
                    }
                }
            }
            touchDragged = false;
        }

        numberOfFingers--;

        //if there were more than 2 fingers on the screen
        if (numberOfFingers > 1) {
            numberOfFingers = 0;
        }

        //if something was not registered properly
        if (numberOfFingers < 0) {
            numberOfFingers = 0;
        }

        lastDistance = 0;

        return false;
    }

    @Override
    public boolean keyDown(int keycode) {
        super.keyDown(keycode);
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public boolean keyUp(int keycode) {
        super.keyUp(keycode);
        return false;
    }

    @Override
    public boolean keyTyped(char character) {
        super.keyTyped(character);
        return false;
    }

    // for pinch-to-zoom
    int numberOfFingers = 0;
    int fingerOnePointer;
    int fingerTwoPointer;
    float lastDistance = 0;
    float lastXDistance = 0;
    float lastY1 = 0;
    float lastY2 = 0;
    float centerX = 0;
    float centerZ = 0;
    Vector3 fingerOne = new Vector3();
    Vector3 fingerTwo = new Vector3();

    public boolean superTouchDown(int x, int y, int pointer, int button) {
        return super.touchDown(x, y, pointer, button);
    }

    @Override
    public boolean touchDown(int x, int y, int pointer, int button) {

        boolean isTouchDown = super.touchDown(x, y, pointer, button);

        if (!isTouchDown) {
            // for pinch-to-zoom
            numberOfFingers++;
            if (numberOfFingers == 1) {
                fingerOnePointer = pointer;
                fingerOne.set(x, y, 0);
            } else if (numberOfFingers == 2) {
                fingerTwoPointer = pointer;
                fingerTwo.set(x, y, 0);

                Ray centerRay = cam.getPickRay(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);
                Intersector.intersectRayPlane(centerRay, xzPlane, intersection);
                centerX = intersection.x;
                centerZ = intersection.z;
                float distance = fingerOne.dst(fingerTwo);
                lastDistance = distance;
                lastXDistance = Math.abs(fingerOne.x - fingerTwo.x);
                lastY1 = fingerOne.y;
                lastY2 = fingerTwo.y;
            }
        }
        return false;

    }

    public void pause() {
        numberOfFingers = 0;
    }

    @Override
    public void dispose() {
        super.dispose();

    }

    @Override
    public boolean scrolled(int arg0) {
        super.scrolled(arg0);
        return false;
    }
}