1
\$\begingroup\$

I am creating a little 2D platform game, with the LibGDX framework. So far I have created a simple prototype level in Tiled, and loaded this map into my LibGDX game. I can use mouse and keyboard controls, to move the camera around my world.

The problem I am facing, is regarding the tiled map boundaries. Lets say my map is 30x15 tiles. How can I get my camera to only show my map, and not be able to 'go outside' the tiled map. When I am making my character to walk around my map, I don't want him to be able to run outside the map boundaries.

I hope someone can help me, since I am new to LibGDX.

My class is as follows.

package dk.martinrohwedder.libgdx.justicejoe.screens;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapRenderer;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.viewport.FitViewport;

import dk.martinrohwedder.libgdx.justicejoe.MainGame;
import dk.martinrohwedder.libgdx.justicejoe.parallax.ParallaxBackground;
import dk.martinrohwedder.libgdx.justicejoe.parallax.TextureRegionParallaxLayer;
import dk.martinrohwedder.libgdx.justicejoe.parallax.Utils.WH;
import dk.martinrohwedder.libgdx.justicejoe.tools.MapCreator;

/**
 * PlayScreen class is responsible for draw and render the actual game objects and playable levels in the game.
 * PlayScreen extends the abstract screen class {@link #BaseScreen}
 *
 * @author Martin Rohwedder
 * @version 1.0 (11/01/2016)
 */
public class PlayScreen extends BaseScreen {

    /* The class tag */
    private static final String TAG = PlayScreen.class.getSimpleName();

    /* Camera and viewport */
    private OrthographicCamera camera;
    private FitViewport viewport;

    /* Tiled Map */
    private TiledMap tiledMap;
    private TiledMapRenderer mapRenderer;

    /* Box 2D */
    private World world;
    private Box2DDebugRenderer b2dr;

    /* Constructor of PlayScreen objects */
    public PlayScreen(MainGame game) {
        super(game);
    }

    /* Parallax Background */
    private ParallaxBackground pbg;

    @Override
    public void show() {
        /* Setup game camera */
        camera = new OrthographicCamera();
        viewport = new FitViewport(MainGame.VIRTUAL_WIDTH, MainGame.VIRTUAL_HEIGHT, camera);

        /* Change game camera position to viewport */
        camera.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0);
        camera.update();

        /* Parallax Background */
            game.getAssetsUtil().getAssetManager().load("sprites/backgrounds/background1.png", Texture.class);
        game.getAssetsUtil().getAssetManager().load("sprites/backgrounds/background2.png", Texture.class);
        game.getAssetsUtil().getAssetManager().finishLoading();

        Texture skyBG = game.getAssetsUtil().getAssetManager().get("sprites/backgrounds/background2.png");
        Texture mountainBG = game.getAssetsUtil().getAssetManager().get("sprites/backgrounds/background1.png");

        TextureRegionParallaxLayer skyLayer = new TextureRegionParallaxLayer(new TextureRegion(skyBG, 768, 768), MainGame.VIRTUAL_WIDTH, new Vector2(.1f,.1f), WH.width);
        TextureRegionParallaxLayer mountainsLayer = new TextureRegionParallaxLayer(new TextureRegion(mountainBG, 768, 768), MainGame.VIRTUAL_HEIGHT, new Vector2(.2f,.2f), WH.height);
        pbg = new ParallaxBackground();
        pbg.addLayers(skyLayer, mountainsLayer);

        /* Load Tiled Map */
        game.getAssetsUtil().loadTiledMapAsset("sprites/maps/tutorial_level.tmx");

        /* Setup Tiled Map */
        tiledMap = game.getAssetsUtil().getAssetManager().get("sprites/maps/tutorial_level.tmx");
        mapRenderer = new OrthogonalTiledMapRenderer(tiledMap);

        /* Setup Box 2D world */
        world = new World(new Vector2(0, -10), true);
        b2dr = new Box2DDebugRenderer();

        /* Create the tiled map box 2D world */
        MapCreator.createMap(this);
    }

    @Override
    public void render(float delta) {
        if (Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) {
            Gdx.app.exit();
        }
        if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
            camera.position.x += 100 * delta;
        }
        else if (Gdx.input.isButtonPressed(Input.Buttons.RIGHT)) {
            camera.position.x -= 100 * delta;
        }
        else if (Gdx.input.isKeyPressed(Input.Keys.W)) {
            camera.position.y += 100 * delta;
        }
        else if (Gdx.input.isKeyPressed(Input.Keys.S)) {
            camera.position.y -= 100 * delta;
        }

        /* Clear the screen and set the color */
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        game.getBatch().begin();
        //pbg.render(delta);
        pbg.draw(camera, game.getBatch());
        game.getBatch().end();

        /* Render Tiled Map */
        camera.update();
        mapRenderer.setView(camera);
        mapRenderer.render();

        b2dr.render(world, camera.combined);
    }

    @Override
    public void resize(int width, int height) {
        Gdx.app.debug(TAG, "Screen has been resized: " + width + "x" + height);
        viewport.update(width, height);
    }

    @Override
    public void dispose() {
        //TODO: Dispose variables here.
    }

    /* Retrieve the tiled map */
    public TiledMap getTiledMap() {
        return tiledMap;
    }

    /* Retrieve the box 2D world */
    public World getWorld() {
        return world;
    }
}

My Solution I have come up with a solution, which seems to work

MapProperties mapProperties = tiledMap.getProperties();

if (Gdx.input.isKeyPressed(Input.Keys.D)) {
    if (camera.position.x <= ((mapProperties.get("width", Integer.class) * mapProperties.get("tilewidth", Integer.class)) - viewport.getWorldWidth() / 2) - 1)
        camera.position.x += 100 * delta;
}
else if (Gdx.input.isKeyPressed(Input.Keys.A)) {
    if (camera.position.x >= (1 + viewport.getWorldWidth() / 2))
        camera.position.x -= 100 * delta;
}
else if (Gdx.input.isKeyPressed(Input.Keys.W)) {
    camera.position.y += 100 * delta;
}
else if (Gdx.input.isKeyPressed(Input.Keys.S)) {
    if (camera.position.y >= (1 + viewport.getWorldHeight() / 2))
        camera.position.y -= 100 * delta;
}
\$\endgroup\$
1
\$\begingroup\$

One way to do this would be to clamp (limit) the x and y values of the camera to your width and height of the game. It may look something like this:

Clamp method:

public int clamp(int var, int max, int min) {
    if(var > min) {
        if(var < max) {
            return var;
        } else return max;
    } else return min;
/*
 * var = your variable that you want to clamp.
 * max = the maximum value of this variable.
 * min = the minimum value of this variable.
 */
}

then you can limit the x and y values of the camera by doing this where you update your game:

camera.position.x = clamp(camera.position.x, Gdx.graphics.getWidth()-camera.viewportWidth, 0);
camera.position.y = clamp(camera.position.y, Gdx.graphics.getHeight()-camera.viewportHeight, 0);
camera.update();

If your map does not occupy the entire game space you can just change the max and min values to fit your desired values.

\$\endgroup\$
  • \$\begingroup\$ I have found another solution to the problem... I found out that the TiledMap had some properties with the map with and height. \$\endgroup\$ – Rohwedder Jan 23 '16 at 22:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.