I'm working on a prototype of a 2D WW2 hex-and-counter wargame for Windows, just trying to test mechanics for now. I started with a little 10 x 10 hex grid overlaid over a .jpg of a stretch of North Africa, and I've had no performance issues.

But is that the optimal approach for a larger map and grid -- say a 100 x 100 or even 200 x 200 hex grid? That is, should I simply make one big ol' color JPG map and put a hex grid over it in Photoshop? Or is it better from a performance and memory standpoint to make a tilemap out of individual hex tiles?

I see some advantages to tiles, apart from performance. They could make it easier to let the player create and edit the map, and thus make scenarios of their own. And they might promote a more uniform look.

But I see disadvantages to tilemaps too. The hexgrid-tile demos I've found on the asset library all use offset squares to emulate hexes, and while they work, they're a bit kludgy -- sometimes the mouse isn't quite detected in the right hex. (Is there a way to tell Godot to recognize hexagons? I tried messing around with "custom" tile shapes but couldn't figure out how to tell Godot I want to use a hexagon shape. Admittedly, my grid-over-jpg map is kludgy too: I have to fudge to get mouseclicks to land in the right hex. And maybe that's okay, as the player usually clicks in mid-hex anyway, to grab a unit.) Finally, a hand-painted map might look prettier, if busier.

Anyway, can anyone offer general advice on which path to pursue -- a "picture" map or a map of tiles? Thanks in advance.

You probably just want to use Sprites. I'm not sure TileMap can handle a hex grid, but I've never tried it.

Thanks; that confirms my intuition.

I imagine I should limit my sprite-maps to 2048 x 2048 pixels, say? I'll probably need more than one, so that I have overlapping 2048x2048 textures covering the entire map. If so, can I just load them all at once and still get reasonable performance? I guess it won't hurt to try.

Well the tiles themselves (the blocks) can be individual Sprites. If the tile graphic is the same, it makes no sense to duplicate that in Photoshop, and it makes things harder to program. But if you have a world background (like a photo of the earth) that could be a TextureRect with a static image. Images have a limited size, and it depends on the hardware, but 2048 x 2048 should be okay on desktop.

You should probably decouple your hex map logic from visual representation and handle all positioning (be it tile sprites positioning, selection/clicking, unit movement paths, ranges etc...) via math. That way it wouldn't really matter if the map is constructed from tile sprites or it's only a single bitmap. It's not hard math though. Here's a really good resource that covers all things related to hex grid maps: https://www.redblobgames.com/grids/hexagons/

If you're planning to have a very large tile map (millions of tiles) you'll need to employ some type of space partitioning method to avoid performance issues.

For reasonable sized maps, Godot can probably handle both approaches quite well. So it's less of a technical question and more a matter of aesthetics.

Thanks for your replies. @xyz , I have relied heavily on Amit's site at redblobgames, and yes, I do all the positioning via math. I've done a more extensive prototype in Game Maker Studio but it doesn't seem hard to convert into GD Script. Lots of Amit's examples are in Python.

The hex-to-pixel conversion stuff doesn't worry me as much as the map itself, which could be rather huge. At most I'd have 300 x 300 tiles, or 90,000, and probably less -- more like 200 x 200, or 40,000. But as I mentioned, I don't love the idea of kludging hexes by representing them as squares. I see now, though, that Godot 4's new "terrains" will support hex (and isometric) grids! Woo! I WANT IT NOW! https://godotengine.org/article/tiles-editor-progress-3 . But..release date is now 2022, so I dunno.

For now, I'm inclined to prototype with 2048x2048 bitmaps. If I decide to try tilemaps, I'd rather try with Godot 4. My main worry with bitmaps is: what if I need, say, 9 such bitmaps? Each might be 400K or more. Do I just stick 'em all on Texturerects and implement code to move the viewport around, or is that not going to work, memory-wise? Again, I'm aiming for Windows PCs, not iOS etc.

Great!

I'm not sure why you're bothered by the fact that you're drawing rectangles. Everything ends up as rectangles in the gpu anyway. And it can handle a lot of them. Every 2d hex based game draws masked rectangles. No big deal. You can draw actual hexes (triangle fans) if you wish but there's no real benefit, you only burden the gpu with more vertex data. Some systems even use overlapping to make smooth transitions between hex tiles for less rigid look.

You could additionally speed thing up with tiles if you use instanced quads or triangle fans instead of plain sprites.

As for large bitmaps, yeah, I see no problems there. Just put your bitmaps on rects or sprites and you're fine. This is piece of cake for modern hardware.

Thanks! OK, maybe I should get over drawing hexes-as-rectangles. I dunno, it just looks so ugly in the 2D view in Godot. I look over at Unity's built-in hex-tilemapping and it looks so pretty! But not pretty enough to make me switch engines, heh.

In the meantime, it's quicker for me to prototype just by tossing in some 2048x2048 bitmaps and overlaying them with a hex grid. That's one nice thing about a historical setting: I can just dump in some real-world (public domain) maps to get started, and maybe later redraw them using Photoshop to make them prettier. I've already got that done. Now I'm about to add code to move the camera around.

Thanks again for the help!

@xyz and @cybereality , if you're still reading, I'm also wondering how best to store hex-grid data. In my first iteration of this project in Game Maker, with only about 150 hexes, I created a two-dimensional array containing Hex objects, defined by a Hex class. Each Hex object tracked occupants, weather, the hex's current victory-point value, defensive bonuses, etc. That worked fine with 150 hexes.

But will it work with 40,000 or 90,000 hexes? Can Godot process that many objects? Would it help to use the Reference class? Would it be better to have a huge array of dictionary entries? I suppose it won't blow up my PC to give it a go, but I have a feeling that approach would be suboptimal.

Maybe I'd do better to use bitboards, as with chess? 1s and 0s indicate whether there's something in a cell; another board of 1s and 0s indicate that there's something else in a cell; etc? But a 200 x 200 board would be a lot more confusing to depict as a bitboard than an 8 x 8 chessboard.

Finally, is a two-dimensional array a bad idea for such a large grid? I am hoping to represent the grid as map[x][y], and translate those offset coordinates to cube coordinates for algorithms.

I'd vote for a simple one dimensional array of Hex objects, and some get*() function that converts 2d coords to an index in that array. If I remember correctly GDScript arrays are better optimized for iteration than Python arrays. You're probably going to iterate through all of it once per turn (or even less depending on the game). Nothing to worry about there. If/when amount of work that you need to do on hexes in a single frame starts to exceed reasonable frame time, you can just delegate it to threads.

And yeah, inherit the Hex class from Reference for less footprint, or even from Object. Just note that Object is not memory managed while Reference is. So if you don't need to create/delete any hexes during a mission, Object may be a good option. Just need to manually delete them when map is destroyed.

Watch out for premature optimization ;)

Thanks for your reply, @xyz. Everything I've read emphatically supports your vote! This page at GDQuest, for example, presents some stark speed differences between 1D and 2D arrays. https://www.gdquest.com/tutorial/godot/gdscript/optimization-code/

I don't need to create or delete any hexes, so maybe I'll just inherit the Hex class from Object. This will be like a board game: the board's dimensions never change, and the board is never destroyed. The campaign is played out on one map and one map only. Individual hexes on the board do change, however: they get different occupants, their weather (and terrain) changes, their ownership may change, and their victory-value may change. And they have other static properties too (defensive value, infrastructure, etc).

Yep, I am always flirting with premature optimization. But I never produce optimized code anyway, lol. I'm very much an amateur and a hobbyist. I did start college as a Comp Sci major, and I wrote bad code in summer jobs back then, but my life took me in different directions. It's fun to get back into it decades later. :) Anyway, I really appreciate the help of everyone here.

a year later