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 Answer 1

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\$
1
  • \$\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\$ Commented Jan 23, 2016 at 22:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .