How ARE games developed procedurally compared to OOP? Are there any good articles/examples explaining the differences in approach? I assume the lack of access modifiers is a huge difference...
Somehow I almost feel like trying to make a game procedurally would be a breath of fresh air and feel freeing after so much OOP-style enforced organization, but then I'm not really sure what it's like...
...actually, might it be sorta close to the style of programming you might see in a Ludum Dare game? I've often quite liked the very "efficient" style of coding it forces them to adopt; no annoying getters and setters that you "should" make for every encapsulated variable that needs to be externally read/modified, no worrying about thinking ahead making sure it can be easily modified later or reused, and the functionality gets up and running much sooner.
Would be a nightmare to rush things like they do in LD for a large project, I'm sure, but maybe some experience with procedural programming would help me find a happier medium sometimes.
"OOP" - as reflected by languages like Java and C# is an "everything is an object, and probably inherits from an 'object' base class" concept. This is generally considered an abuse of the principles these days.
In my personal experience, modern programming has kind of settled onto two abstractions - the object, and the function. Both of these exist in all languages, though what you can do with each varies.
Objects store data, and expose some kind of interface that determines what operations are legal on that data. In some cases, they will involve some form of virtual dispatch, messaging system, or templating system to allow the operations to be customized without involving large if chains or switch statements. Note that basic types like "int" and "bool" are objects in this example, because they define a set of data (a certain number of bits) and operations that can be done on that data (addition, subtraction, negation, etc). You could say that their encapsulation makes sure that you can never have an invalid integer or bool, should you follow the language rules (floats can stretch this definition with the severan NaN representations).
Functions are operations performed on data. These can be classified as "pure" - not modifying data, but returning a result - and "non-pure" - which modify the data given to them. Pure functions are ideal for threading, but may consume more memory and cycles as they may have to make copies of data (smart compilers, especially when dealing with a 'functional' language, can almost eliminate these issues).
So in the end, an "ideally coded" video game will look a lot like any other "ideally coded" piece of software. It will use objects where invariants and encapsulation are important. It will use functions to group together repeated operations, with "pure" functions being preferred where immutability is important or required, and "impure" functions where "pure" functions are impractical. And then it will take advantage of special language features to reduce the amount of coding required to produce the desired result and minimize errors. (Example: Templates)
Where you will frequently run into "bad" code is where someone has fixated on a particular tool and used it everywhere, even where it is not suited or has a distinct disadvantage. Like a house builder who uses a hammer for everything and you wonder why there are no straight edges, only rough scalloped edges where he used his hammer to split the wood apart.