“You are Alex Mercer, the Prototype: a shapeshifter with amazing powers of combat, destruction, and deception.
Mankind is your mask.
New York City is your hunting ground!”
Early in development on Prototype, I was actually working on the Titanium Engine team at Radical, but was pulled over to help with Prototype here and there. I became more and more involved with the project, and when Activision bought Radical and dissolved the Engine team, I was brought on as lead for the Prototype Frontend team.
My work there was pretty straight forward, as most of the back end architecture was done during my time on the Titanium Engine. However, I was particularly happy with some of the performance improvements we implemented.
When I first joined the Prototype team, it could take up to 25ms to update the HUD. That’s not a typo… We were literally capped at 40fps just updating the HUD! This was a combination of many things, mostly centred around ScaleForm GFx (our middleware flash player).
ScaleForm GFx (version 1 at the time) had some major performance bottlenecks in 3 key areas: updating lots of MovieClip objects (the building blocks of flash), communication between Flash and C++, and executing ActionScript (the scripting language of Flash). Since our entire Frontend was built in Flash, these issues were happening everywhere. The worse case though, was the minimap.
Our minimap could have dozens of objects on it at any given time, it gathered data about each object through C++ calls, and it updated each object using Actionscript every frame; the trifecta of ScaleForm disaster. This was a drastic case, and required and equally drastic solution: we completely circumvented ScaleForm GFx. However, we didn’t want to just render our own map in a totally separate system, because we needed it to render nicely with the other layers HUD. So instead we added a dummy object to the HUD at the position and layer that we wanted to render our custom minimap. When the Flash renderer attempted to draw that dummy object, we intercepted the call, and forwarded it on to our own rendering system. At that point it would render the minimap using very fast, and direct, rendering calls. When it finished, it returned control to ScaleForm GFx, and the Flash rendering continued completely unaware of what had transpired. Thankfully ScaleForm GFx had the hooks for us to do this.
The really cool part about this solution is that the minimap rendered with all the same passes as it regularly would being part of the HUD. For example, we put a mask (stencil) on the map in flash so that only a small circle portion of the map was visible. Rewriting this stencilling logic in another renderer would have been a bit of a headache but since our dummy object was still part of the regular Flash renderer, the mask was automatically applied, even to our custom minimap. A simpler example was that when we hid the entire HUD, it also hid our custom minimap. This was because hiding the HUD hid our dummy object, which in turn would not attempt to be rendered.
There were quite a few more steps to getting our Frontend performance in check on Prototype 1, but in the end our team was able to get us from 25ms updates to under 1ms! It is something I am quite proud of and one of my highlights from the entire project.