In this situation, it is trivial and a no-brainer.
I'll be bold and not look at the whole code. I'll assume that the function in which this
switch statement is (Game::updatestate()) is called once per frame.
This switch statement being called once per frame is a droplet in the ocean. Typically, graphics rendering, physics and AI take up much more CPU time than this type of decision making, whether it is a switch or a series of if-else-if.
From the couple of videos I've seen on youtube, the game runs smoothly, without lag.
I assume Terry Cavanagh, like any good dev, profiled the game at some point and fixed/improved/optimized some parts of it based on the profiler results; it's safe to assume that the issue was not that part.
That's the key part here. The syntax of the
switch is clean and clear with the minimum of overhead code, going another way would clutter more the code without real technical benefit.
To be honest, I would personally be more worried about the use of raw integers instead of constant in the
case parts, as this makes the code much harder to read. (I'll give the author the benefit of the doubt, as coming up with 300+ GOOD constant names could be a challenge. He used comments in an OK manner, in this case, and using constants like this removes the need to link all the files that share the constant names together.)
To answer your questions directly:
Are switch statements normally used in this manner to implement state handling
There are many games around, and many ways to do this, but yes, using a switch to handle a state (or multiple states) is a perfectly acceptable way of doing this.
and why doesn't something like this lag the game like crazy?
As it's been pointed out, this switch is called 30, 60, 90 times per seconds, it's trivial for a CPU to handle.
Finally, if you're curious to go and see the "under the hood" effects of the code you write, there is an online tool called Compiler explorer that lets you write some chunks of c++ code and see how it is compiled to assembler by the different compilers out there.
Although you can come up with trivial tests for this tool, you'll never know the full effects of actual real code compiled with optimization flags (because you ship your game with optimizations turned on). Compilers are very smart to not do some work.
As a simple, trivial, non-optimized test, I've written two similar chunks, one using
if-else (Link), and one using a
switch (Link). You can take a look and see for yourself the different output, and even toy around and add the optimization to see the effects (and see why using simple-trivial test code is often useless for testing real world situations).