Several months ago, I talked about the distinction between world space and screen space. As a recap, these are fundamental concepts that separate our game or simulation state from our drawn or rendered state. What gets drawn to the screen is not necessarily how things are laid out in the game’s actual (world) state. Check out the previous articles for more information.
The concept of tile picking involves a user hovering their mouse or some other input device over a tile in the game map. Usually the user is doing this in order to interact with the tile such as moving a unit to a location, placing an item on the tile, or inspecting the metadata of the tile. Fortunately for the developer, the process of picking is independent of the projection other than some simple math to do a conversion of coordinates.
Imagine that you are playing SimCity 2000, and you want to create a stretch of road from one location to another. The process involves the user hovering the starting tile, clicking the mouse, dragging the road to the end tile, and releasing the mouse. Tiles were picked out of the game map based on the mouse’s coordinates during game updates. Which space do we pick the tile from? Do we have to calculate if the mouse is contained within the projected tile or within the game’s world space coordinates?
Orthogonal
If the projection used in the game is orthogonal (think NES/SNES Zelda games), then the tile picking really is just a matter of answering the question, “Which tile contains the current mouse coordinate?” Answering the question is simple:
1 2 3 4 5 6 |
mousePosition = GetCurrentMousePosition(); worldX = floor(mousePosition.X / tileWidth); worldY = floor(mousePosition.Y / tileHeight); pickedTile = tiles[worldX][worldY]; |
To explain briefly, we get the position of the mouse (I use SDL which has a function to get the mouse position). We then convert the coordinates from screen space into world space. Finally we get the tile that is stored in our tile collection at the world space coordinates. We floor the coordinate conversion because landing in the middle of a tile will result in a partial index.
Reference the grid to the left. For the sake of discussion, let us assume that each grid contains 16 x 16 tiles. The top left most pixel is located in world space [0,0] and at screen space (0,0). The top right most pixel is located in world space [5, 0] and at screen space (80,0).
If the user moves the mouse to the screen space coordinate (25, 50), then the math to calculate the picked tile is as follows (using the aforementioned technique).
1 2 3 4 5 6 |
mousePosition = (25, 50); worldX = floor(25 / 16) = 1; worldY = floor(50 / 16) = 3; pickedTile = tiles[1][3]; |
Performing that calculation, we get a result of the tile highlighted in blue.… Read more