The main module is getting rather long.
You have these lists of variables that are grouped by comment, e.g., # level variables. And you have behavior associated closely with these variables, executeGameFrame and handleGameEvents, whereas these variables are never used outside of these functions.
Consider creating a class from these data and behaviors, and move this code into a separate module. # level variables is already a hint about what abstraction this class will capture.
Some comments can be replaced with better identifier names. E.g.,
# handle the user-related events like mouse clicks or keyboard presses
handleGameEvents()
Why do you explain what the called function does when it's called with zero arguments? If you don't believe that handleGameEvents() is clear enough, rename handleGameEvents such that it will be clear.
If you've moved this code to a class that captures the abstraction of playing a single level, then this will probably be a method of that class. This is excellent for naming methods, you can omit "Game" from the method name because the class will already tell us that this method deals only with playing the game.
TechMech.wasClicked assumes arguments to be map coordinates, but it's called with mouse coordinates. As a result, once you scroll such that screen's top-left no longer coincides with map's top-left, we cannot click exactly on mechs to assign skills.
Which of the two modules, main or techmech, has the bug? Is it possible to prevent calling the method with wrong data (ideally static error, next best is runtime throws)? If it's not possible to prevent the bug by design, is it at least possible to define the method such that, once we call it with wrong data, the calling code looks wrong? Or is convention really the only solution, in which case we should document it glaringly?
-- Simon