Of course, it wasn’t all high frame-rates and handshakes all around at first. In fact, in the initial testing, the Isogenic Game Engine got far better performance in rendering our 128 x 128 isometric map containing data from Vilas County, Wisconsin. The cause was naïveté; where IGE had support for optimized isometric maps built-in, Impact only had its entity system, far more suited to active objects in the game world than large amounts of static tiles. The simple implementation of producing 16384 entities in Impact was definitely not the smart one. Each of those entities iterated every single frame at an attempted 60 frames per second, so even with culling based on the camera position the poor engine was trying to call the Canvas API’s .drawImage() function some 48,000 times a second depending on the zoom level. The solution was implementing a relatively simple caching system (inspired by the system that IGE uses) that splits the map into square sections, draws all of the sections of the map once to off-screen canvases, stores them in memory, and finally draws those pre-rendered sections on the screen as needed. Combined with programmatically reducing the resolution of the individual tile textures, this solution was so optimized that it could handle – granted a hefty initial load time – a map the size of the entirety of our data from Vilas County, approximately 1,300 by 800 tiles in size. (That’s over a million tiles in total!)
Another problem we originally had with Impact was that it was designed with pixel art rather than high-resolution art in mind, so while it’s easy to scale your game by integer factors and get nice-for-pixels nearest-neighbor interpolation, the engine doesn’t support smoother interpolation and non-integer scaling factors out of the box. Thankfully, the Canvas API has its own scaling methods that do support non-integer scaling factors! Since Impact uses regular old Canvas contexts to render things, most of what it took to support a zoom function was simply calling .scale() right before we draw anything to a canvas.
Compare: Above, bilinear filtering. Below, nearest-neighbor filtering.
We’ll have to do some fancy things with caching and culling to make a nice-looking, smooth experience in the web environment for very large maps of data. Once we’re ready to start working with dynamic entities interacting with this map, Impact is going to really shine.