1

I've created a hex tile map and I a problem in combining two features: 1) scrolling the map by dragging with the mouse/finger 2) highlighting a tile on mouse over position

My world contains a map, which consists of custom Tile() objects. Each Tile has an x and y coordinate saved. In my game class I use an OrthographicCamera and a TileSelector, a class that gets the current mouse position and highlights the appropriate tile underneath those coordinates. Further more, my render() method checks whether the mouse/finger is down and if so, each tile's position is updated by the distance moved while finger/mouse button down.

The following code shows the relevant parts. As long as I don't move the map, the highlighting works. But as soon as I do move the tiles, the highlighting starts to be off (by the amount of the distance moved).

//initialiting orthographic camera
camera = new OrthographicCamera(800, 480);
camera.setToOrtho(false, 800, 480);

//draw screen black
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

camera.update();
game.batch.setProjectionMatrix(camera.combined);

//drawing to batch
game.batch.begin();

//drawing the tiles, simply getting x,y coords and putting on screen
world.render(game.batch); 

//highlighting tile under the current mouse/finger coords and drawing highlight on screen
selector.select(Gdx.input.getX(), Gdx.graphics.getHeight() - Gdx.input.getY(), game.batch, world);

game.batch.end();

//scrolling routine
if (Gdx.input.isTouched()) {
        Vector3 touchPos = new Vector3();
        touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
        camera.unproject(touchPos);

        deltaX = (float)Gdx.input.getDeltaX();
        deltaY = (float)Gdx.input.getDeltaY();

        //moving each tile by the distance moved
        for(int i = 0; i< world.getMap().getWidth(); i++){
            for(int j = 0; j< world.getMap().getHeight(); j++){
                tile = world.getMap().getTile(i, j);
                tile.x += deltaX;
                tile.y -= deltaY;
                world.getMap().setTile(tile, i, j);
        }
    }
}

See screenshots for visualization:

1)Map not moved, mouse(red arrow) over tile and it is highlighted https://i.stack.imgur.com/3d7At.png

2)Map moved but mouse on old position, no tile should be highlighted, but the tile is highlighted as if the map has not moved https://i.stack.imgur.com/dSibc.png

Now I understand that the problem seems to arise from not mapping/updating screen and world coordinates correctly. But due to my lack of knowledge about LibGdx/OpenGL/projecting/translating I can't pinpoint my mistake. So can this rendering algorithm be fixed as it is? Or should I switch from moving my tiles to moving my camera(how)? Please let me know, if you need more of the code, thank you.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Arthur
  • 43
  • 6
  • Quick question: is the world that you are clicking in being displayed on the full width of your game window? Because if it's not you will have to multiply your coodinates by a factor to make it fit. – AreusAstarte Nov 20 '14 at 20:06
  • I'm not quite sure what you mean. The map is 15 x 10 tiles big and only about 13 x 10 are displayed, as it stretches out of the view, if not moved. Otherwise the highlighting works very precisely on each tile. – Arthur Nov 20 '14 at 20:43
  • @Arthur hey I tried to understand what you want to do, but for my English, I think I'm not understanding well, but if you want to move or simulate move the map think it would be better to user the method in the camera class, translate ect is much faster, you move the map https://github.com/libgdx/libgdx/wiki/Orthographic-camera – Angel Angel Nov 20 '14 at 21:01

1 Answers1

1

Alright, I was able to find a solution on my own, since the problem was rather in the logic and not in the LibGdx API. In case somebody else has the same issue in the future, I'll provide the solution here.

At first I followed Angel-Angel's tip and started to move the camera instead of the map/world. Second, the main problem was the fact, that I used the screen coordinates of my mouse/finger for the tile highlighting, instead of the world coordinates.

The new code:

    //scrolling routine
    if (Gdx.input.isTouched()) {
        //get mouse/finger position in screen coordinates and save in a Vector3
        touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);

        //get the distance moved by mouse/finger since last frame and translate camera to that position
        //(I have no idea yet why the x-axis is flipped)
        deltaX = (float)Gdx.input.getDeltaX();
        deltaY = (float)Gdx.input.getDeltaY();
        camera.translate(-deltaX, deltaY, 0);

        //this is the solution, the coordinates that you use for tile highlighting
        //are translated to world coordinates
        touchPos = camera.unproject(touchPos);
    }

    //update the camera position and the math that is involved
    camera.update();
    game.batch.setProjectionMatrix(camera.combined);

    game.batch.begin();
    world.render(game.batch);

    //now the highlighting routine is working with world coordinates
    selector.select(touchPos.x, touchPos.y, game.batch, world);
    game.batch.end();

I hope this will help out in the future. If anyone is interested how I get the right tile for highlighting, I use the method described in the highest rated answer in this thread:

Hexagonal Grids, how do you find which hexagon a point is in?

Good luck and have fun!

Community
  • 1
  • 1
Arthur
  • 43
  • 6