com.tm4rkus.screens.MapScreenNew.java Source code

Java tutorial

Introduction

Here is the source code for com.tm4rkus.screens.MapScreenNew.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.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g3d.ModelBatch;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.math.collision.Ray;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.tm4rkus.conquertheempire.Game;
import com.tm4rkus.helperclasses.Map;

public class MapScreenNew extends Stage {

    protected OrthographicCamera cam;
    protected boolean touchDragged = false;
    private final static int tilesOnSight = 10;
    private final SpriteBatch spriteBatch;
    private final ModelBatch modelBatch;
    private final Matrix4 matrix = new Matrix4();
    //private final Map Map = Game.Map;

    public MapScreenNew() {

        cam = new OrthographicCamera(tilesOnSight,
                tilesOnSight * (Gdx.graphics.getHeight() / (float) Gdx.graphics.getWidth()));
        cam.direction.set((float) -1, -1, 0);
        cam.position.set((float) ((Map.tiles / 2) - cam.direction.x * 10), (float) (10), (float) (Map.tiles / 2));

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

        spriteBatch = new SpriteBatch();
        spriteBatch.setTransformMatrix(matrix);
        modelBatch = new ModelBatch();

    }

    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 < 1; i++) {
                Map.createObject(100, 100);
            }
        }
        if (!Game.objectManager.isLoading()) {
            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();
            cam.apply(Gdx.gl10);
            spriteBatch.setProjectionMatrix(cam.combined);
            //spriteBatch.setTransformMatrix(matrix);
            spriteBatch.begin();
            modelBatch.begin(cam);
            Map.draw(spriteBatch, modelBatch);
            spriteBatch.end();
            modelBatch.end();
            super.draw();
        }
    }

    private static boolean stop = false;

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

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

    //final Plane Map.xzPlane = new Plane(new Vector3(0, 1, 0), 0);
    //final Vector3 Map.intersection = new Vector3();

    @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();
        Map.moved = true;
        return false;
    }

    /**
     * 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
    }

    /** 
     * 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) {
        Ray pickRay = cam.getPickRay(x, y);
        Intersector.intersectRayPlane(pickRay, Map.xzPlane, currentSingleTapDrag);

        if (!(lastSingleTapDrag.x == -1 && lastSingleTapDrag.y == -1 && lastSingleTapDrag.z == -1)) {
            pickRay = cam.getPickRay(lastSingleTapDrag.x, lastSingleTapDrag.y);
            Intersector.intersectRayPlane(pickRay, Map.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, Map.xzPlane, Map.intersection);
            float centerX = Map.intersection.x;
            float centerZ = Map.intersection.z;

            System.out.println("touchdrag " + centerX);

            if (centerX < 2) {
                cam.position.x = (float) (2 - (cam.direction.x * cam.position.y));
            }
            if (centerZ > Map.tiles - 2) {
                cam.position.z = Map.tiles - 2;
            }
            if (centerX > Map.tiles - 2) {
                cam.position.x = (float) (Map.tiles - 2 - (cam.direction.x * cam.position.y));
            }
            if (centerZ < 2) {
                cam.position.z = 2;
            }
        }
        lastSingleTapDrag.set(x, y, 0);
        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;
        }
    }

    /**
     * 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;
    }

    private long touchTime;
    protected long lastTouchUp;

    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, Map.xzPlane, Map.intersection);
                //Map.createObject(Map.intersection.x, Map.intersection.z);
                float isctX = Map.intersection.x;
                float isctZ = Map.intersection.z;

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

                lastTouchUp = System.currentTimeMillis();
            }
            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();

    @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, Map.xzPlane, Map.intersection);
                centerX = Map.intersection.x;
                centerZ = Map.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;
    }

    public OrthographicCamera getCam() {
        return cam;
    }

    public void setCam(OrthographicCamera cam) {
        this.cam = cam;
    }
}