Scrolling Tiledmap Slick2D

So I just started a new game again, it’s gonna be a top-down view with bow and arrow, monsters and quests.
The Camera class is doing really fine.
For the map I’m using tiledmap, where I got in problems.
It renders the map fine, but the problem is: it renders the whole map.
Now there is this method TiledMap.render(x, y, sx, sy, width, height); where sx and sy stands for start x and y.
This method looked really fine until I read that the sx, sy, width and height were in tiledmap blocks. This results having full tiles rendered and not the smooth scrolling idea.
Does someone have any idea how to fix this?

Link to the TiledMap.render#:

http://slick.ninjacave.com/javadoc/org/newdawn/slick/tiled/TiledMap.html#render(int, int, int, int, int, int)

Github link to Level.java:

Thanks in advance!

There used to be a great example by kevglass on this exact topic, but maybe it was lost when slick was taken over by other developers.

The basic idea is that you use Graphics.translate(float x, float y) to move everything so that the player (or wahtever your camera is following) stays at the center of the screen. The key to this is to find the offset of the player from the center and translate everything by that much.

I got that part working already but it’s more the part of rendering a section of the map, for performance.

You can just check how close your offset is to being a multiple of your tilesize and use that difference to move the map slightly so for example if your xoffset is 100 and your tilesize is 30 then your code would look like


map.render(-20,0,100/30,0,width,height);

or more generally


map.render((xoffset%tilesize)-tilesize,(yoffset%tilesize)-tilesize,xoffset/tilesize,yoffset/tilesize,width,height);

that may not be perfect because I just came up with it on the spot, but it should be the right idea. You might have to add 1 to the width and height, but you’ll be able to figure that out.

That usual is the way to do this, yes.
But, because all the coordinates besides x, y are in tiles, it will only render full tiles, so that means an ugly scrolling in a block-by-block way.
I wish I could make a video of this…


public void render(SpriteBatch sb, Camera camera, float delta) {
        float camX = camera.position.x;
        float camY = camera.position.y;

        float startX = Math.max(((camX / TILE_SIZE) * camera.zoomFactor), 0);
        float startY = Math.max(((camY / TILE_SIZE) * camera.zoomFactor), 0);

        float endX = Math.min(((camX + Gdx.graphics.getWidth()) * camera.zoomFactor) / TILE_SIZE + 1, SIZE_X);
        float endY = Math.min(((camY + Gdx.graphics.getHeight()) * camera.zoomFactor) / TILE_SIZE + 1, SIZE_Y);

        // map
        for (float x = startX; x < endX; x++)
            for (float y = startY; y < endY; y++) {
                int tx = (int) x;
                int ty = (int) y;
                Float drawX = x * TILE_SIZE - (camX * camera.zoomFactor);
                Float drawY = y * TILE_SIZE - (camY * camera.zoomFactor);
                drawX -= (x % tx) * TILE_SIZE;
                drawY -= (y % ty) * TILE_SIZE;
                if (drawX.isNaN())
                    drawX = 0f;
                if (drawY.isNaN())
                    drawY = 0f;
                if (x >= SIZE_X)
                    continue;
                if (y >= SIZE_Y)
                    continue;

                if (x < 0)
                    continue;
                if (y < 0)
                    continue;

                // renderTile(x,y);

this allows for floating point smooth scrolling of a tile map, nevermind the zoomfactor :slight_smile:

Result:

FhSydhUiRNs

Yes, I understand what you mean and the video was very clear. I had thought that the code I posted would fix that because it takes into account the block issue by using the remainders. I can’t test anythign becuase I am at work right now. So the code I gave you produced the same results as you had before?

Ahh yes I fixed it!
This is the final render way I’m using:

map.render((int) - (camera.getX() % 64) - 64, (int) - (camera.getY() % 64) - 64, (int) camera.getX() / 64, (int) camera.getY() / 64, (1280 / 64) + 3, (720 / 64) + 3);

I divided screen width by tilesize and added 3 to it(smoothed it out) so it only shows the visible area plus a little margin :).
The fps is finally normal again and pretty solid :D.

I want to thank you both for helping me out! :slight_smile:

unless if I am misunderstanding your code, thats pretty much what I told you to do :persecutioncomplex:?

anyways, kudos :slight_smile:

That’s right, I got it fixed thanks to you :p.

Oh woops, I thought you said it didnt work. Ignore me I am obviously confused today ;).

It didn’t work at that moment, but after checking that code twice it worked :p.