Hello everyone,
I’m trying to create a minimap using RenderTexture and a TMXTiledMap object in Cocos2d-X v3.10.
The code looks like this:
minimap_ = RenderTexture::create(map.width * tile.width, map.height * tile.height);
minimap_->begin();
map->visit();
minimap_->end();
minimap_->setScale(...);
Works perfectly when the map is a smaller size, such as 30x30 or 50x50 tiles.
However, if the map file contains a large size like 100x100 tiles, the process memory can skyrocket as high as 450mb-500mb while it’s grabbing RenderTexture since the pixel size for the image grows pretty massive.
Is there a better way to grab a snapshot of a TMXTiledMap object and scale it down?
I’ve tried to scale down the TMXTiledMap object to 0.25 before running Node::visit(), but for some reason it still grabs the map at full scale. Ideally the RenderTexture::Create() could be set to 250x250, but I’m having trouble getting it to capture the full map unless RenderTexture is set to the same dimensions as the map.
RenderTexture::setKeepMatrix(true) is great except that it only captures screen and not the whole map.
Any help would be greatly appreciated, thank you! 
EDIT: Solution
Using a fixed size for the render texture is the best approach.
Do you need to render the entire map? Most mini maps in games will show your immediate surroundings not the whole level. If your levels are different sizes and you want to render the whole map the zoom level will be different, and you will suffer loss of detail for larger maps. Even if you render to texture 1:1 you still have to scale down to fixed set of pixels on screen. You’re better off committing to a fixed size render texture and fixed zoom levels to ensure quality and consistency.
You might also consider stylising your mini-map to minimise artifacts that will occur from scaling down your map. Try assigning colours to tiles and rendering a pixel per tile, or perhaps using lower resolution and visually different assets for each tile type.
Hope this helps
2 Likes
Thank you for the response!
Sorry forgot to mention that it’s for a turn-based strategy game, so it needs the entire map to be visible.
I tried your idea to stylize the map using auto DrawNode objects, filling the minimap with small rectangles and assigning them a color based on Tile GID, but unfortunately the process memory still skyrockets to 450-500mb with this approach. So it’s likely that the 10,000 objects created from 100x100 tiles is causing spikes.
Perhaps the minimap could do a search algorithm and say “if 8 nearby tiles are green, make one green rectangle that covers 9 spaces” or something along those lines. There’s plenty of room for little optimizations like that, but I was hoping to find an easier solution that doesn’t require a lot of work and hurt my brain. 
Worst case scenario, the minimap could be pre-rendered and saved as a 250x250 .png, but ideally it would be nice for the game to figure it out “on the fly” with the .tmx file so it’s easier to make simple map changes.
Thanks again for the help, going to keep experimenting with DrawNode and RenderTexture and try to find the magic bullet. Very curious how RTS games manage to draw their minimaps so quickly and efficiently.
Got it! 
For anyone else curious how to create an RTS-style minimap background with a Tiled map:
Step 1: Create a 2nd TMXTiledMap object using the same .tmx as your real map. Keep it local.
Step 2: Scale your 2nd map object down proportionally to the size of your minimap.
Step 3: Capture it with a RenderTexture. (NOTE: YourGame::addChild(map2) is not required).
Step 4: Move the position of your RenderTexture into the UI, and addChild on your RenderTexture.
This is what the code looks like:
auto mapCopy = cocos2d::TMXTiledMap::create(mapPath);
mapCopy->setScale(...);
minimap_ = RenderTexture::create(250, 250);
minimap_->beginWithClear(0, 0, 0, 1); // Black background
mapCopy->visit();
minimap_->end();
mapCopy->autorelease();
minimap_->setPosition(...);
Process memory with a 100x100 map using 64x64 resolution tiles is only <90mb total, not bad at all!
2 Likes