The Impact of Impact

Impact was one of many options available to us among JavaScript game engines. Of course, trying out every single one would be just a little bit insane (there really are a lot of options). So we picked two engines that seemed like they would work well – I had heard of Impact previously, and Dr. Shapiro had heard of the Isogenic Game Engine – and produced a little mockup with either engine to compare them. Ultimately, though both engines were comparable in performance and features, Impact won the competition because of its modularity of design and superior documentation.

Impact has a lot of features that will make our lives as developers much easier when it comes to making games for the web. It has a nice object inheritance mechanism based on John Resig’s Simple Javascript Inheritance. It also splits its functionality into individual modules that can be extended (through the aforementioned inheritance system), included, or ignored as desired. This functionality is extremely useful in a game engine – having a neat and tidy object inheritance system allows a game to avoid a lot of annoying and bulky code duplication, since games often involve lots of objects that are similar to one another in many fundamental ways. Impact gets you started in that direction with its Entity class, which are special objects that the engine is able to manage all on its own, including drawing, updating, and even colliding them and setting up the appropriate callback functions. These entities can be constructed with arbitrary attributes very easily thanks to JavaScript’s powerful typing system (or powerful lack thereof?) in combination with the inheritance system, and even configured with an included level editor to make things even nicer, though our game doesn’t really need one. Long story short, Impact feels like a real game engine for real, big-boy games, and that’s a powerful thing.




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.



Your Comment