
Show HN: A 2D game engine in under 1000 lines of C - ryanpcmcquen
https://github.com/ryanpcmcquen/basque
======
jsd1982
Looking at your `init` function, I would refactor it to not be so nested with
if statements. Try logically inverting the if checks and returning early up
near the top of the method and remove the else branches. Keep repeating this
kind of refactoring on all your if statements. Eventually, you'll find that
the "happy path" ends up at the bottom of the method and can return a success
status without being so far indented. This style makes it easier to reason
about what conditions are possible at various points in the method, i.e. you
don't have to mentally compose the boolean logic conditions of all the nested
if/else statements.

Here's an example I did:
[https://gist.github.com/JamesDunne/a94782bc39d95515f7dcc8516...](https://gist.github.com/JamesDunne/a94782bc39d95515f7dcc8516a18c5cb#file-
init-refactor-c-L113)

Also, I would generally move all implementation code out of header .h files
into standard .c files. Header files are traditionally just meant to contain
forward-declarations of types and methods.

~~~
blondin
nested ifs work here too. i personally don't think cognitive overload is an
issue because you are not composing all the conditions at once. in fact, each
block should only care about one condition. but you make a good point.

tbh, i have seen nested ifs used in video game programming a lot. and i came
to the conclusion that it has to do with the else clause that the return early
method doesn't provide. the else clause is always doing something because
games are never supposed to fail...

~~~
setr
?

If cond return err means everything after is an implicit else block

~~~
dragonwriter
> If cond return err means everything after is an implicit else block

Right, but inverting to get to return early format means that the “else block”
that needs to do substantive work becomes the if block, and it needs to be
doing something substantive not just “return err”.

Which may be a valid criticism in some cases, but doesn't seem to be in this
particular code base, where most of the ifs don't have an else and those that
do it's log-error-and-return.

------
caymanjim
What's with the majority of the code being in header files?

~~~
ryanpcmcquen
I know that using .c and .h files is the traditional way of doing it in C, and
I started the engine this way, but to be honest, is there any gain to it in
this scenario?

The headers are library code, and having more files just means more
maintenance and build complexity. Is there another advantage I am not aware
of?

~~~
jdmoreira
You can read some of the criticisms here
[https://en.m.wikipedia.org/wiki/Header-
only](https://en.m.wikipedia.org/wiki/Header-only)

~~~
macleginn
None of them seem relevant for a small-scale unitary project.

~~~
chongli
Even a large project like SQLite is provided as a single, unified header file!

------
kazinator
There is no need for this nonsense:

    
    
      #if defined(__WIN32__) || defined(__WINRT__) || defined(_WIN64)
        fopen_s(&file_to_read, path, "rb");
      #else
        file_to_read = fopen(path, "rb");
      #endif

~~~
ryanpcmcquen
What would you recommend?

