[LibGdx]Doesn´t understand Camera + Noob Questions

Hey,
I found libGdx a few weeks a ago and I like it so far.
But now I want to load a tiled map und render it.
My Problem now is I don´t knew how camera, Renderer, Map and the Frame are playing together.
I already read nearly all Tutorials and YT Tutorials, but these are most Sidescrollers.

I just want that my left bottom of the map is also there in the Frame, but the beginning of the map is approx. at 70% on x and 30% on y in the frame, the rest is blank. And my player which, startpoint is at x=0 and y=100 is spawning at this location, but on the blank part. (Hope somebody understands what I mean)
So, how is it possible to tell the camera really to watch the map and not the frame?
I guess when i call "batch.draw(player,…) it is drawing everything on the screen, so its normal that my player is on this position.

When I do it like that: camera.setToOrtho(false, map.tileWidth * 20, map.tileHeight * 20);
and in the render: renderer.render(camera,…)
The map is correctly beginning on (0,0) but when I add

camera.position.x=player.position.x-player.getImage().getWidth()/2;
    camera.position.y=player.position.y-player.getImage().getHeight()/2;

in render, the above thing is happening. So, how do I do it correctly?

What is project/unproject and combined doing?
Is this something like, I have a map with 4000x3000px and a Frame with 720p and I click now in the frame on 500,600 but I am in the map on 3000x1200 unproject is now translating to the map and project is then doing the counterpart?
Does that mean that i have to call everytime when I click on a object unproject() and when I done with the logic project()?

I am normally using Tiled, is there an other better Editor?
Like for collision detection? I am currently making an own layer and then draw a special tile on the blocked Tiles.
But what should I do when the Tile is a side tile? So, a 32x32 but only has 7px which should be blocked, is there a way to do it? It´s a little bit annoying to block an whole Tile for that. Or half water and half grass on a Tile, how to do?

Let’s assume you have a Map with 1000x1000 pixels (in this case a Sprite Image with 1000 width & 1000 height)
Your screen with is 1280x720

[in your show / create method]


cam = new OrthographicCamera();  // The camera will take the viewport (what you can see looking through the camera) of the screen size (1280, 720) if you don't specify otherwise
cam.setOrtho(false); // We want (0,0) in the bottom left corner
cam.position.set(Gdx.graphics.getWidth() / 2, Gdx.graphics.setHeight() / 2, 0); // this will render the camera so that 0,0 (of everything inside batch.begin() - batch.end()) will be rendered at 0,0 on your screen
cam.update(); // Updates the camera

[in your render() method]


cam.position.set(x, y, 0); // x and y could be changed by Keyboard input for example
cam.update() // Don't forget me ;)
batch.setProjectionMatrix(cam.combined) // Tells the spritebatch to render according to your camera
batch.begin();
batch.draw(map, 0, 0);  // Draws your map at 0,0 - width expands to the right, height expands up
batch.end();

unproject will convert for example your mouse coordinates to world coordinates:
If you for example scroll up on you map: 0,0 on your screen will be 0, 100 on your map image (we scrolled the map 100 pixels upward)
If you now would click on 0,0 on the screen without unproject, it will give you 0,0 as a result. But if you do cam.unproject(mouseClickedPosition) it will give you 0, 100

Hope this could help you : ) (and is right. not in front of eclipse right now)

That was a great explanation! I’ve recently decided to give LibGDX a try and I want to learn a lot before I start. It seems to easy though and I feel like I’m learning it all wrong because its just that easy!

Great thank you, so I was mostly correct with my thoughts.

But^^
In the API stands that setToOrtho dividides the viewport by two and the cam is centered there, but if I give it widht or with/2, there is no difference whats showed. Why?

So I have to call unproject() everytime i click on a object, just with the coordinates the Listener delivers me?

I still want to follow my player. But, when I add in my render Method the code to follow him the blak space appears and I am not able to undo this with any if,else construct.

 camera.unproject(new Vector3(player.position.x,player.position.y,0));
       camera.position.set(player.position.x,player.position.y, 0);
         if(camera.position.x>width) camera.position.x=width;
         else if(camera.position.x<0)camera.position.x=0;

        camera.update();
        spriteBatch.setProjectionMatrix(camera.combined);

And is this x Position now calculated from the bottom left corner or from the middle of the screen?

Well it depends on if you’re using your own position managment, or you’re using box2d coordinates. Box2D allways centers the position of the Body at bodyHeight/2 and bodyWidth/2. The camera expects the position to be at the bottom-left corner. So if you’re using Box2D you should subtract the halfwidth and halfheight to get the right position for the camera :).

EDIT: Well now that i read your post again, the camera allways assumes a bottom/left position :).

From what I’m reading, I am assuming you want the camera to follow the player? (apologies if I am wrong).

If you are trying to get camera to follow the player, try this:

Perhaps instead of using “player.position.x, player.position.y, 0” you should use player.getPosition().getX, player.getPosition().getY;

If your player class, or super class of player does not have a “getter” method for player position, then simply create one which returns the vector3 values like so:

	
public Vector3 getPosition() {
	return position;
	}

So your code would look like this:

 camera.unproject(new Vector3(player.getPosition().getX,player.getPosition().getY,0));
       camera.position.set(player.position().getX,player.position().getY, 0);
         if(camera.position.x>width) camera.position.x=width;
         else if(camera.position.x<0)camera.position.x=0;

        camera.update();
        spriteBatch.setProjectionMatrix(camera.combined);

Correct me if I’m wrong, but by calling player.position.x, you will just get a null value.

Yes, thats right, I want to follow the player.
Sorry, no English native :wink:

[quote]EDIT: Well now that i read your post again, the camera allways assumes a bottom/left position
[/quote]
Thanks, i already figured it out, but I still doesn´t understand that when i call in my render() cam.position.set(…), it seems that is then the middle of the screen and i can´t find anything related to that in https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/OrthographicCamera.java.

@Otreum
I really don´t understand your code, because its the same as mine?
I can´t get an null value because the x and y in Vector3 is public.

My Problem:
If I am doing it like that:

 camera.unproject(new Vector3(player.position.x,player.position.y,0));
       camera.position.set(player.position.x,player.position.y, 0);
camera.update();
        spriteBatch.setProjectionMatrix(camera.combined);

In the render Method, my Player is centered and the Cam also follows him, but I see this annoying blank space where no map is, like i explained in the first post. But if i do away this two rows my map starts correct at (0,0) in the frame, but (of course) I don´t follow the player then.

Now, I did many debuggins and it seems that the camera is related/mapped/linked with the map, because if i create my Player at (0,100,9) it is correctly placed on the map, but of course the map ist only at ~50% of the frame. Then when I give out my cam position it tells my at the start the x=0, yeah
When i am going with the player to the left (so to the blank space) it remains 0 if i am going to the right it goes up more than 1280.

So it seems that i have to set my map correctly at (0,0; related to the frame), but I don´t know howto do.

Well i think the problem is, that the TiledMapRenderer (OrthogonalTiledMapRenderer or any of the 4 available :)) needs to be set to the right camera projection like that:


renderer.setView(camera

If you allready do that, it would be helpfull to me, if you could post more code of your rendering process, otherwise its just guessing what goes wrong…

Read the code carefully, it is not the same. :wink:

I said to create a “getter” method which you can call on to return the position.

And then when you want the position, you call on the getter method.

So instead of using:

player.position.x

to get the players position, use:

player.getPosition().getX //Calling on a method which returns the value of the variable "x"

And obviously the same with the y value too.

Waa, sorry I haven´t seen that somebody postet something.

Hmm okay, I haven´t known OrthogonalTiledMapRenderer yet, but I am also not able to use it, it just doesn´t find the package??? I have even no maps package.

[quote]Read the code carefully, it is not the same. Wink
[/quote]
Nope, still can´t see a difference. LoL

Well I made a new Project, only for loading and rendering, but it´s still the same, here is the code:

create()


 map = world.map;
  atlas = world.atlas;
  tileMapRenderer = new TileMapRenderer(map, atlas, 32, 32);
camera = new OrthographicCamera();
spriteBatch = new SpriteBatch();
 camera.setToOrtho(false, map.tileWidth * 20, map.tileHeight * 20);
 Texture image = new Texture(Gdx.files.internal("assets/images/player.png"));
 initInputActions();
 player = new Player(new Vector3(0, 100, 0), image);
Gdx.input.setInputProcessor(manager);

render()

Gdx.gl.glClearColor(1, 1, 1, 1);
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        processInput();
        player.update(Gdx.graphics.getDeltaTime());


      //to follow the player
        camera.unproject(new Vector3(player.getX(), player.getY(), 0));
        camera.position.set(player.getX(), player.getY(), 0);

        isOnMap();

        camera.update();
        spriteBatch.setProjectionMatrix(camera.combined);

        //background
        tileMapRenderer.render(camera, new int[]{0});


        spriteBatch.begin();
        spriteBatch.draw(player.getImage(), player.getX(), player.getY());
        spriteBatch.end();

        //foreGround
        tileMapRenderer.render(camera, new int[]{1});

With this it´s still starting at 60% of the x-coordinate.
Which is normal because I am setting the position Vector in 8&9 to the player position.
And it seems that the position Vector in OrthoCam is calculated from the middle of the screen (I don´t understand the Code of OrthoCam correctly).

But even if i try to change the Vector with the screen width and height or just with control structures I am not able to set it correctly.

So, even if i set the cam.pos =0 like above and i debug this it just says 0 if I move the player away from the map. Without the if it says a minus value.

Well then you are using an old version of libGDX. You should redownload it (if possible the latest nightly).

If you use an OrthogonalCamera you should also use the OrthogonalTiledMapRenderer. Maybe thats where your issues come from…

Edit: I just read through the docs and it seems TileMapRenderer does not exist anymore :slight_smile:

lol, well just thought to use the newest stable one, didn´t thought that the nighly is so far ahead.

Now, using the nightly one. I am doing the same like before, but in the render:

  camera.position.set(player.getX() + player.getImage().getWidth() / 2, player.getY() + player.getImage().getHeight()/2, 0);
        camera.update();
        tileMapRenderer.setView(camera);
 tileMapRenderer.render(new int[]{0});
        spriteBatch.begin();
        spriteBatch.draw(player.getImage(), player.getX(), player.getY());
        spriteBatch.end();
        //foreGround
        tileMapRenderer.render(new int[]{1});

Now nothing is displayed only my Player on a blank frame. If I throw away the camera.pos… it´s the same as from the beginning, the map is correctly showed but (of course) no followment.

I asked about the same question: http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=9025&p=40847#p40847
Basically they have conflicting SpriteBatches.

Hmm thanks.
I also thought about Spritebatches at the start, but the code seemed okay.

Maybe I am misunderstanding the answer there, but aren´t I doing that?
Everytime the render() is creating an Spritebatch and closes it. So there shouldn´t be two Batches open at the same time.? https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/maps/tiled/renderers/BatchTiledMapRenderer.java

Well, okay I think I will try and ask in the official forum.

Just one thing.
Im creating with my Starterclass a tileTestGame, which extends game then setting screen to GameScreen which implements Screen. The GameScreen creates the World and Worldrenderer. and in the render() of the GameScreen the render() from WorldRenderer is called.
Can there be anything wrong?