Yes, there are different ways to define states. For example, in one of the demos I was working on, I made a function to check for jumping. It looked something like this:
func is_jumping():
return abs(velocity.y) > 1.0:
I still had a jumping state, because it made things easier to transition states and also disable certain actions while jumping. However, you could design a system without flags, with a bunch of simple functions like that that operate on some global state (like velocity, in this case).
That said, I'm a big fan of OOP and I think it does make many things easier. I find a lot of the classes I write, if well designed, can be copied to new projects and they work out-the-box without any modification. But it's very easy to over-engineer something, and there have been times I just restarted a project from scratch because the design was bad and it was easier to rewrite it than try to fix it. So it can go both ways.