Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Game programming books that focus on design and ideas

This thread is locked; no one can reply to it. rss feed Print
Game programming books that focus on design and ideas
Ariesnl
Member #2,902
November 2002
avatar

I'm looking for some nice books that (at least partly) focus on ideas and techniques. Instead of again a book about how to program a directX game engine.

Anyone ?

- Inspiration
- Design
- Strategy
- World building
- AI

I prefer 2D since I'm not a 3D artist and I don't have eternity.
I know there is a lot of info on the internet, But I like to read from a book ;-)

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

RmBeer2
Member #16,660
April 2017
avatar

I can only think of old C64 books and magazines. They were always great for developing your programming.

Now the books, even the courses or the tutorials on the internet are a shit, the only solution they recommend is that you must buy more memory, more processor and more disk space. :-/

🌈🌈🌈 🌟 BlackRook WebSite (Only valid from my installer) 🌟 C/C++ 🌟 GNU/Linux 🌟 IceCream/Cornet 🌟 🌈🌈🌈

Rm Beer for Emperor 2021! Rm Beer for Ruinous Slave Drained 2022! Rm Beer for Traveler From The Future Warning Not To Enter In 2023! Rm Beer are building a travel machine for Go Back from 2023! Rm Beer in an apocalyptic world burning hordes of Zombies in 2024!

Chris Katko
Member #1,881
January 2002
avatar

I've bought dozens and honestly never found any that were that applicable to high-level design. The successful people with real-world experience aren't sitting around writing books. But they occasionally give lectures. There are "Game Programming Gems" mentioned, which I have, but those are books of little snippets to specific problems like "how do I find the angle to bullet trajectory".

There are Game Programming Patterns [free and online], which you should be familiar with but not following like doctrine--like it's the magical key to all problems.

https://gameprogrammingpatterns.com/

And one good series of books I read on mass-multiplayer game development.

http://ithare.com/contents-of-development-and-deployment-of-massively-multiplayer-games-from-social-games-to-mmofps-with-stock-exchanges-in-between/

These guys actually, clearly, have significant experience in the MMO industry. It's an interesting read. But not necessarily applicable to non-multiplayer games.

Also, any lecture by Mike Action [engine chief of Insomniac Games] on data-oriented design which is how you organize your game's data into cache friendly structures. Basically everything is JBOD (just a bunch of data) and treated like streams of data. And it's the only way you could have any performance if you wrote code for the Sony Cell processor. Basically, many people's biggest problem goes back all the way to school. Treating a "class" like a single object, to be operated on solely in isolation, one at a time--completely at contrast with modern CPU design. Not just multiple cores, but also caches. If every object is treated in isolation, that basically means you toss out ALL cache and branch prediction for every single object.

Another huge related no-no, is "overgeneralization." We're all taught to make some sort of superclass that then gets inherited fifty ways down and is filled with crap just to make the lower classes work. Specialize. Specialize. Specialize.

particles should be in their own array, separate from objects. Who cares if they're similar, they're not USED similarly. Particles are short lived and super simple AI--they have almost nothing in common with a general object like a person or a tree. If you're having a huge set of nested if statements checking "is(object.human && !object.amonster)" put humans and monsters in different arrays.

The data-oriented people do lots of crazy stuff like positions are all in a single array, and any class that has a position, uses composition (not inheritance) with a pointer (or index?) to it. So you can batch 8/16/32 positions all together in terms of cacheline sizes.

Learn the techniques and apply them as much as you want to make your life easier. But most of the ones I mentioned are more about optimization--which can be helpful if you plan on making a huge object count game, like Factorio. But less applicable for "Froggy The Frog, The Platformer".

I have general books on "programming patterns" and also "antipatterns" but without the experience of living through them, they're mostly dry lists of patterns that a wiki would suffice for. Unless you're experienced a specific anti-pattern, you don't really appreciate why it's terrible or why "this antipattern" is more of a big deal than another one.

Read other people's working gamedev code online for hints on how to write proper code. For example, the Dolphin project is a hugely successful, LARGE codebase, that would collapse if not written at-least vaguely properly. Quake 3 source code is online. So is DOOM 3.

-----sig:
β€œPrograms should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Ariesnl
Member #2,902
November 2002
avatar

@ RMBeer2 Not to mention the youtube tutorials made by people from India. I cannot get used to their accent..

Another huge related no-no, is "overgeneralization." We're all taught to make some sort of superclass that then gets inherited fifty ways down and is filled with crap just to make the lower classes work. Specialize. Specialize. Specialize.

particles should be in their own array, separate from objects. Who cares if they're similar, they're not USED similarly. Particles are short lived and super simple AI--they have almost nothing in common with a general object like a person or a tree. If you're having a huge set of nested if statements checking "is(object.human && !object.amonster)" put humans and monsters in different arrays.

The data-oriented people do lots of crazy stuff like positions are all in a single array, and any class that has a position, uses composition (not inheritance) with a pointer (or index?) to it. So you can batch 8/16/32 positions all together in terms of cacheline sizes.

Those are some great Ideas..
But what is your particles have a depth and can be drawn over some sprites, but under other sprites ( and sprites can change depth ) ?

Perhaps one day we will find that the human factor is more complicated than space and time (Jean luc Picard)
Current project: [Star Trek Project ] Join if you want ;-)

Chris Katko
Member #1,881
January 2002
avatar

Another one I've done is always put global variables inside a single global stuct named "g". So it's super obvious whenever you're hacking around and not passing all dependencies to a function or class. So you can speed write hacks to test things out, and then control-F for "g" to fix things without forgetting them to do them proper.

Ariesnl said:

But what is your particles have a depth and can be drawn over some sprites, but under other sprites ( and sprites can change depth ) ?

Depends on game. Do you have some particles that are always under, and some that are always over? Then put under particles in one array, draw it first, then sprites, then draw the second particle array after. Now you have three batches without messy "if(particle && !transparent_dude && !opaque_monster)" if-chains.

If your particles MUST have draw order you can could either split them and batch them into runs based on draw order, or combine them under one type of drawable_object that everything inherits from. But it's gonna be messy either way if you have thousands of particles that are going to be inbetween normal objects. At that point, it's either sort into batches, or just accept that you gotta draw them one at a time. Most games aren't gonna be speed limited for 2D games anyhow so it's whatever is easiest for you do be productive and maintain the code.

[edit]

I just remembered another one. Pure functions are great.

A pure function is a simple concept. It's a function that takes inputs, does something, and returns the output. The key however: It has no side effects. That means it touches no globals, it touches no system calls. With the same inputs it must always produce the same output.

Often times you'll have to rewrite functions that "mutate" (change) variables to instead use secondary variables that hold the "mutated" results. (So a string, when modified, is a new string.)

The benefit of pure functions is that they're completely safe for multi-threading, as well as easier to debug, and you should strive to make your functions pure were possible. (D language, for example, lets you compile-time check for functions marked pure.) When you're debugging a pure function, you know for a (99%) fact that nothing outside of the function is the problem and the bug is sitting inside this function. [edit] They're also perfectly suited for UNIT TESTING. Any pure function can be separated from the rest and tested on its own. The converse, an impure function, requires the entire global state to be correct before running.

If you've ever used a functional language, then you're already doing that.

https://en.wikipedia.org/wiki/Pure_function

Another nifty thing that C (with GCC and maybe Clang extensions), D, and maybe others support is nested functions. If you have a code that gets repeated inside of a function, you should put it inside its own function, right? But, here's the problem. You end up cluttering your class/interface with all these functions that are only applicable to specific methods or functions. You don't need 300 functions listed in your class (or worse, global because its C) just because 290 of them are helper functions to the real 10 functions.

You should only really know about them when looking at the function they apply to. That's a nested function. It only exists inside of one other function, with an additional property: They can access all variables of the owning function as if they were at its scope. Which makes it way easier to not have to pass variables around.

void my_function()
{
int x = 0;

void taco()
 {
 x = 5;
 }

taco();
// x is 5
}

You might think "if it can access the outer variables, won't it cause name collisions/shadowing/weird stuff". Yeah... it could. But only if you're wrongly writing huge mega functions are you going to run into that problem.

Basically, it makes everything fit much nicer and encourages writing helper functions instead of massive functions with repeating code.

-----sig:
β€œPrograms should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Go to: