The way tilemaps in games are traditionally understood, or at least how I was told they were understood, was that tilemaps are a grid of tiles that visually display the in-game world. Any value (with exception to 0 or whatever the empty space value is) represents a tile that is seen in the game world. Tilemaps are static and as a general rule, the tiles are a fixed size, being slightly bigger or smaller than the player but not by much.
This was generally how I viewed tilemaps for years as a game developer, that tilemaps were used largely for platformers, were big and blocky, and didn't move. I knew I could change them depending on what actions I wanted (like if I want a destructible environment), but it wasn't until last year that I thought I could break that tradition.
NOTE: I'm using a tilemap system written for my own open-source game engine, Vigilante Game Framework. I'm not going to go into specific code, as other engines and implementations can vary, but for the sake of this article, the tilemap system used is written to handle collisions and rendering as optimally as possible.
Case 1: Tunnel Bug
This was an arcade tunnel game developed for Ludum Dare 44, the concept was you're a travelling bug having to go through a winding tunnel as fast as you can, and you can only rotate and accelerate forward.
So one of the key features of the game was a randomly generated tunnel for the bug to travel through. Given it being Ludum Dare, I only had 48-72 hours, so not enough time to create a custom tunnelling system with collision detection so the bug could touch the walls at the exact point and bounce off appropriately. That was when the tilemap came in...
What I did was create a tilemap that completely fills the screen with very tiny tiles (2x2 pixels), and then carve out the tunnel using randomized points and cosine interpolation to make it curved and wavey. Because of the low resolution, the curve appears rather smooth, and because the tilemap system already has collision handling, I didn't have to implement a new collision system. It's worth noting that my tilemap system is optimized to take as few collision checks as possible by combining the bounding boxes.
Because I wanted to make the tunnels look more interesting than a plain colour, I also included other tiny tile colours and made a fancy pattern without affecting the collision bounding boxes. Results appeared to show as this game managed to rank higher in Graphics than any other category. As a programmer, art isn't my strongest suit.
Conclusion: Tilemaps can have tiles of any size necessary to solve a problem. If a tilemap is built right, it can be used to create levels that don't have the blocky appearance of a typical tilemap.
Case 2: Rectris
This was a Tetris clone I did essentially as game development practice after Ludum Dare 46, the aim was to make Tetris with all the modern guidelines and features such as hard drops, lock delay, holding pieces and whatnot.
Of course, I'd need to use a traditional tilemap to set up a gridlike board, I could have set it up with sprites instead but a tilemap with repeated segments would have taken one draw call instead of one for each sprite, or even just one large one that would have been tedious to tweak afterwards.
But what about the pieces themselves? Well engines may vary, but my engine is built on top of SFML, and most tutorials for a basic Tetris game often advise to draw a single block multiple times for each piece, with their positions stored in an array.
But what if you already have a tilemap system which can set up multiple segments in an array, but only needs to be drawn once per frame? That's what I did, I used another tilemap object to represent a falling piece, assigning where each segment goes and letting the object set up the drawable section. If I want a piece to rotate, I simply swap the tiles around so they render in the correct location.
Once a piece has landed, all I need to do is set the segments that have landed onto the board tilemap, and reset the position of the piece tilemap with a new tetramino shape.
As far as rendering goes, the scene below takes only two draw calls (plus one draw call for my engine to draw the scene to the window as part of its resolution scaling). In fact, the rest of the game as seen in the gameplay video above take up a vast majority of the rendering.
Admittingly, I didn't use the tilemap collision system, although it could have been used in theory as long as horizontal collisions and vertical collisions are responded separately (as the former is needed to keep the piece from colliding with the board and the latter to make sure a piece is landed).
As you may notice in the gameplay video, the same code for the piece tilemap was reused to show the next and hold pieces, so this wasn't a single-use solution.
Conclusion: Tilemaps can move! Assuming your tilemap is built correctly to handle that efficiently, take advantage of it. Tilemaps could be used as a playable object instead of a static feature of a level, and as a result, you could get a more optimised result.
The overall takeaway I want to offer from this post is that typical features that we implement in games like tilemaps could be used in more ways than we are used to. There are probably more complex, yet effective, methods to the two cases I suggested, but I'd argue tilemaps were more straightforward and achieved the results I wanted while keeping games efficient.
There are probably other features that we only use a few ways when there are many other possibilities for them to be used.