Programming

"Square pixels in 4:3 ratio really triggers me"
- Anon

Learning / getting started

How is game made?

Game development (and programming in general) could be thought of as many layers; first you make a tool, then you use the tool to gather resources, then you make something with those resources, then you assemble those things into other things, etc. You can jump into a specific layer depending on your preference, but that means you have less control of the layers below it. For example if you decide to use a game engine, you can't choose your programming language or alter the engine itself much so you'll just have to deal with it.

There's a few main paths that you can choose from:
1. Using a game engine such as Unity. This is one of the highest "layers" and gives you very little control over everything below it, so you'll have to deal with all the quirks and limitations that the engine comes with. However it allows you to skip a lot of things and get to a game quicker and easier, engines handle a lot of very complicated tasks (such as 3D physics) that would be difficult to do yourself.
2. Making your own engine using various libraries and frameworks. This will involve a lot more programming and research and making things by hand. Libraries and frameworks are basically code that someone else wrote that you can use for your own project. Some of them can be very expansive and handle most of the work for you, for example Ogre3D and Raylib handle graphics so you don't have to write your own rendering system, SDL or SFML will handle operating system calls so you can easily create a window and take input and play audio.
3. Writing nearly everything from scratch. This path is mostly taken by people who really like programming and are interested in the underlying systems behind a game, or otherwise want control over every part of their game. There's no clear distinction between writing things from scratch and utilizing libraries, you could make everything from scratch but then use a library for path finding, it's completely up to you when and where to rely on them.

Which tools and methods you should use mostly depends on your intentions and personal preferences. If you just want to make a game and don't care about the specifics, learn a game engine. If you want to improve your programming skills, making your own engine from scratch with basic libraries is a great way to do just that. If you're very picky about freedom and being in full control of everything, there's nothing that serves you better than making your own engine from scratch. If you're comfortable with programming and your skills but primarily want to get a game done, look into game related frameworks and libraries or experiment with engines. If you're limited by time and need money, get a job instead.

All methods are free so just try something that piques your interest, or try all of them.

Do I NEED programming? I want to just like make game.

Short answer: no.
Long answer: yes.

It is completely possible to just download an engine and start poking buttons and watching tutorials and copy pasting some code snippets. However it is very difficult to do things if you don't understand at least the basics of programming, you'll end up googling "how to do X in Unity" even though it's solved with basic programming and isn't an engine problem. That said, it is valuable to be motivated so jumping straight into an engine to explore isn't necessarily a bad idea, but be aware that you should learn how to program sooner or later and it will be difficult to make a game for real until then.

How long does it take to learn?

Everyone is different. You can learn the basics in a day or two, but it may take a few weeks before it starts to sink in how to do stuff. You'll never stop improving though and you shouldn't expect to write good quality code until you have a few years of experience behind you. You'll get that experience as you work on games, it is usually a good idea to work on some small games first for this reason, so you won't start your dream project and then have it fall apart a few months later because you realize that all of your old code is shit.

Visual scripting

If you have difficulty with or strong distaste towards programming, there are engines that let you use visual methods to create game logic. These engines allow you to add properties to sprites and game objects and create logic through a GUI that gives you options. These engines are typically much less flexible and capable than traditional programming, but are fine for simpler games and can be helpful for getting into gamedev. Some popular games like Baba is You and Five Nights at Freddy's were made with such engines.

The most popular visual scripting engines are Multimedia Fusion, Construct, and Stencyl. Unreal Engine has it's own visual scripting system called "blueprints", but the engine as a whole isn't designed around it so it's more of a side feature.

How to learn to program?

Everyone programs in different ways with different languages and learns through different methods, so you'll have to explore a bit yourself and find the way that works for you. Try to learn "how to program" first, not "how to use X programming language". When you know how programming works and how to do things in any language, it is easy to switch to any other language.

Using game engines like Unity for learning will introduce many unrelated things into the mix, increasing the amount of things you have to learn and confusing you about what's part of the engine and what's just general programming. The tutorials for such engines also tend to be made by amateur indie developers thus may be inefficient and even incorrect.

Recommended starter languages:

  • Javascript - very easy to use, very popular, has countless tutorials and guides, easy to experiment with (any web browser runs it, see if you can open the browser console/scratchpad, it accepts javascript code), lets you make browser games if you're into that, is generally a useful language to know due to it's usage in the web and as a scripting language, and has similar syntax as C-derived languages making it easy to switch to them later. If you want to experiment with browser games, learn how to make a simple HTML document with <canvas> on it.
  • Lua - Love2D is a free framework that lets you easily make games using the Lua scripting language. It's a very simple program that doesn't require installation or any special configuration, just write some lua code and give it to Love2D. The Lua syntax is somewhat different than C languages, but Love2D is a fine tool for making basic 2D games, so if you like it you could just stick with it. Lua is also useful if you're interested in modding since many modding APIs use Lua. Note that you should use Love2D in console/debug mode so you can easily print text, Love2D documentation should have instructions how.
  • C - C is much simpler than it's relatives (C++ and C#) so there isn't that much to learn in terms of the language itself. The simple nature of C also means that when learning it, you're more likely to learn programming, not just some language features. C is similar to C++ (industry standard) and C# (often used by engines) so it is easy to switch to those later. The main downside of using a compiled language is that you can't draw things onto the screen or listen to mouse/keyboard presses without setting up a bunch of things first, which makes it harder to experiment with code.

Which engine is best?

All engines have their own pros and cons, none of them is strictly better than another.

Unity

  • + For most people it's easiest to make games with
  • + Has the highest amount of resources and help online and it has the biggest community of gamedevs
  • - Games made with it tend to have bad performance, though it may have to do with incompetent developers
  • - Although it has a big community, most of it is incompetent retards so getting help from them may not be that useful

Godot

  • + Free and open source
  • + Well suited for 2D games
  • - Lowest "quality"
  • - Not well tested, not many games have been made with it

Unreal Engine

  • + The highest quality engine with the most advanced features, used by indies and AAA developers alike
  • - Many people find it harder to use than other engines
  • - Geared towards big 3D games, so it may not be ideal if you want to make a 2D game
  • - Owned by Tencent

Game Maker Studio

  • + Specifically designed for 2D games so it makes that very easy
  • - Not made for 3D games
  • - Acquired by a Chinese company in 2021

RPG Maker

  • + Makes it extremely easy to create a specific kind of game
  • - Not a general purpose engine, so you don't have a lot of freedom about what kind of game to make

Making my own engine?

There's many advantages to making your own game engine, but it is also much slower, harder, and makes it exceptionally difficult to accomplish certain things like 3D physics and realistic graphics. It is not recommended if you have some kind of timeline for when you expect to have finished a game, don't like programming much, or want big realistic graphics. If you want 3D then you should also be familiar with vector math. Ask yourself what kind of developer you want to be and what kind of things you want to create, and whether making your own engine is relevant to it.

One of the common arguments against making an engine is that it takes a longer time and many people never end up making a game, however the exact same thing can be said for people who use a big engine like Unity. Games have been made with both methods and eternal nodevs exist in both areas, whether you make a game has more to do with your attitude and motivation, not what method you use, therefore you should pick the method that you're personally interested in, not what other people prefer.

Pros

  • Your programming skills will improve much more since you're forced to implement various systems yourself and make them work together instead of relying on an engine to handle things for you.
  • You can choose exactly the languages and tools that you personally prefer, and aren't limited by any decisions and designs that someone else made.
  • For some people it is more enjoyable to develop games on top of your own engine using your own tools. There's even a term called "not invented here" or NIH.
  • You aren't limited to what kind of IDE the engine is compatible with, you get to choose what IDE, text editor, and compiler you want.
  • You won't be affected by undesirable third party things happening to a game engine (gets involved in politics, degrades in quality, increases royalty fees, becomes abandoned, adds hidden shit into your program, etc) because the engine is made by you.
  • You will learn much deeper and broader programming skills that serve you in more ways than just making a typical videogame.
  • It is easier to change any part of the engine since you thoroughly understand it, while in big engines it may not even be possible.
  • You won't be limited to any platform. If you want to make a game to some obscure or unusual device or otherwise unsupported platform, you'll be much more equipped to do it if you have engine programming experience.
  • Your game will be much smaller, and likely also faster and more responsive.
  • Your games will not be limited by the performance or features of the engine, and you can make the game work much better on older or weaker computers. For example uf you want to make a simulation game that moves a lot of data, such as Factorio or Noita, it may be difficult to do in a big engine. As an example Cities Skylines handles large scale simulations and was made in Unity, but they had to modify the engine to make it work out, and at that point it might become more desirable to just make the engine yourself.
  • You will be able to implement any image, model, audio, and music formats that you want (or make your own) as opposed to the ones that the engine supports.
  • It is easier to do various non-game programs and tools if you have enginedev experience.
  • You can blur the line between a videogame and an application. If you want to make some weird program that utilizes windows and other programs in interesting ways (for example Desktop Goose), it's much easier to do that.

Cons

  • It will take years to learn all the skills to make a proper game engine.
  • Will add a steep learning curve to an already skill-intensive process that can be avoided entirely if you just want a working game faster.
  • Unless you are doing something that really hasn't been done before, you probably don't need to make an engine unless you just want to.
  • There's some game systems that are very complicated to do yourself, particularly in 3D, which are usually handled automatically by big game engines. You can use libraries to help with them, but it's still not as easy as it is in a premade game engine.
  • It is much harder to accomplish advanced graphics and shading. Generally speaking, the more advanced graphics you want, the harder it is to get the same quality and speed as big game engines have. You can accomplish decent graphics yourself, but big engines have professional teams dedicated to honing the engine's graphics pipeline and it is very hard to compete with it even as a small team.
  • It is particularly difficult to make 3D games due to 3D math being more complex.
  • You will need to create your own map/level editor and a parser to load the levels. Alternatively, you can use a universal map-editor like Tiled, but you still have to write your own parser.
  • You may require more math knowledge depending on what kind of game/engine you make.
  • It is more work to port your game between different platforms, you can utilize cross-platform frameworks like SDL but it's still limited, for example porting your game to HTML5 is far from straightforward. Big engines usually support the most common platforms out of the box.
  • If you want to join with other developers, there's a good chance they're using an engine like Unity or Unreal. While enginedev gives you a broader skillset and in theory makes it easy to adapt, developing games in a big engine can be quite different and will require adjusting to.

How does code become a game (without an engine)?

There's 2 primary ways to turn code into a program; compiling and interpreters. The method is mostly determined by the language you use, for example C++ code must be compiled, but python code must be given to a python interpreter.

A compiler is a program that converts the source code text file into machine code that your actual computer hardware understands, usually turning it into a file such as .exe or .dll. Compilers are usually command line tools, so you'll have to use CMD (Windows) or Terminal (Linux) to give your source files to the compiler.

Another way to run code is to give it to an 'interpreter' or a 'virtual machine' or a "just in time compiler" which can process and run your code without compiling it to an executable file. For example in order to run Python code, you must install a Python interpreter and use that to run your code. Similarly web browsers have a built-in Javascript interpreter, and can thus directly run any Javascript code. There also exist tools to turn interpreted code into a program file, so you can share a python program without requiring other people to install the interpreter.

IDEs like Visual Studio and Code::Blocks can be configured (or may be automatically configured) to compile/run your program with a simple button press, and most text editors can be configured to call a compiler command with a keyboard shortcut. It is helpful to learn how text commands work so you can configure such things easier.

Which language to use?

The debate of the languages is a never ending one, everyone has their own preferences so you will never get an unanimous answer about what to use. It's best to look into many languages and make a decision for yourself, even the best and most popular languages aren't objectively the best options for everyone. If you're using a game engine however, the choices are probably narrowed down to one or two choices as it is very difficult to use any language that the engine does not support. In that case look into what language(s) your engine of choice supports and learn that.

It is possible to use multiple languages for one program. For example, many programs written in C++ and Python use libraries programmed in C and assembly due to the better optimization those languages have, and many games use scripting languages like Lua and Python to script things such as AI and in-game events.

Note that a "powerful language" does not automatically make your program powerful. It simply gives you power, but it is up to you to use that power responsibly.

Common/popular/relevant languages

  • Assembly is the lowest level programming language that is human readable. Every computer architecture has it's own version of assembly, thus it's not easily portable between computers. The benefit of writing Assembly is that you have minimal CPU overhead, and you can take full advantage of the hardware. Unless you're autistic and/or writing for much older platforms like the Atari 2600 or Apple ][, there is no practical reason to write games in assembly these days, especially since compilers are in some cases better than humans at creating optimized assembly from another language. Assembly is sometimes used alongside another language when you need a particular piece of code to have very high performance (particularly for consoles that have fixed hardware), so assembly knowledge is still useful for advanced gamedev. Some languages and compilers allow you to write "inline assembly", i.e. write assembly code in the middle of other code. Assembly knowledge is also useful for debugging, since you can read the assembly that your code turned into and get a better understanding of your program at a much lower level.
  • C++ is the industry standard and probably the safest language choice at the current time, although it is a very old abomination covered in duct tape and swiss army knives. Use it with care and you can consider it an upgrade from C. However, while C++ is technically "C with more stuff", it has had so much bloat added to it over years that it is very difficult to fully learn, and the compile times can get slow if you use certain features like templates. You can ignore those features for yourself, but as soon as you start reading a tutorial or someone else's code in general or using a library, you'll run into it again. As a result C may be recommended for learning before you move onto C++.
  • C is the older brother and a much simpler version of C++, it is a very capable language although quite lacking in convenience features like classes and namespace/syntax options and standard library features. Many people still prefer it over C++, it does exactly what it needs to and nothing more and is much cleaner than C++ as a result. If you want to use C, you MUST get comfortable with the idea of pointers and memory management. C is one of the fastest languages and is often used as a benchmark language to test speed against.
  • C# is a higher level cousin of C++ created for Microsoft's .NET framework. It is somewhat easier than C++ but doesn't give you as much control, but is a good and popular choice for game development either way. It is commonly used as a user/scripting language in big game engines such as Unity.
  • Java is one of the most popular languages (if not THE most popular), but also one of the most hated ones and often not considered a good language. However there's a huge amount of help online, so it is a relatively easy language to get into. It is mostly used in server/web environments, but many games are made with it too. C# is sometimes considered to be a better version of Java.
  • Javascript is a terrible piece of shit, if you use it for anything other than HTML5 games then you need to swiftly remove yourself from this earth. That said, it is one of the most easy and forgiving languages out there, and thus excellent to learn programming with. The syntax is similar to C/C++, making it easy to transition to those languages later. A bonus note: Javascript has absolutely nothing in common with Java other than the name.
  • Python is one of the most popular scripting languages due to how easy it is to do simple things and it's large "ecosystem" of libraries to help with tasks. It is not very popular for gamedev, but there's engines and tools such as Pygame that let you make games with it.
  • Lua is currently the fastest (LuaJIT) scripting language and it's the most common scripting language for game development. Like Python, there are engines and frameworks like Love2d that allow you to make games. It is also a common language used in modding.

Niche/unpopular/new/obsolete languages
It is generally not recommended to use one of these, since they're less utilized and there's less help and resources and tools for them online. You can try them though if you're willing to do more independent research on them.

  • BASIC is an old family of programming languages made specifically for beginners. It was extremely popular for beginning programmers back in the 70s, 80s, and early 90s, but has been slowly replaced by scripting languages like Python and JavaScript. The most recent dialects of BASIC are object-oriented and are usually designed for gamedev. Examples of modern dialects of BASIC include Visual Basic, FreeBASIC, and Gambas.
  • Lisp is an ancient family of languages made for AI programmers and emacs users. Some people swear by it, it's very different to most other languages and using it may give you a different perspective on programming. It's rarely used, especially for games, but wrappers for frameworks like SDL and SFML exist.
  • D is a newer language in the C family. It attempts to be a modernized alternative to C++, but can't seem to decide what it really wants to be, and may be confusing as a result. It's behavior can be changed, and can be something in-between C, C++, and C# depending on how it's used.
  • Go is a new-ish language developed by Google with the aim of bringing back procedural programming in the tradition of C but with modern conveniences such as garbage collection, memory management, and structural typing. It's more commonly used for servers and web-related software than games.
  • Haskell is an old functional programming language like Lisp, but with a syntax similar to more common languages like C. There are wrappers for common frameworks like SDL, but the gamedev community is small.
  • F# is the functional programming version of C#. It is supposedly on par with C# and compatible with most C# libraries, but is rarely used.
  • Swift is a new language created by Apple to replace their Objective-C language. It is intended to teach normalfags how to program to the point where you can use emojis to name variables, classes, and functions. There are game development libraries and frameworks, but this language is not recommended unless you somehow want to make mobage.
  • Perl is a scripting language most commonly used for web servers and as an alternative to shell scripting. Though there are wrappers for multimedia libraries, it's lack of certain features and slow nature makes it unpopular for gamedev.
  • Ruby is a scripting language that aims to be a more powerful version of Perl and a more object-oriented version of Python. It is often used as a server-side language for websites and not common for game development, but frameworks for it exist like Gosu and Rubygame. It's also notable for being one of the few FLOSS projects to be based in Japan.
  • Rust is a new language from deep within the headquarters of starbucks, created by the hippest of beards and thickest rimmed glasses. It is controversial due to it's obsession with safety which gets in the way of productivity, slow compile times, and community of mostly hipsters and faggots, but some people consider it to be better than C++.
  • Jai is a language in development by the creator of The Witness, with the goal of replacing C and C++ in most cases. Some say it might end up doing just that in the future, but some say "fuck that guy". It's goal is to stay true to the way computers work and reduce "friction", allowing more work done with less annoyance getting in the way.
  • Zig aims to be a competitor to C, with compatibility to C libraries. It has many advantages, especially in regards to error handling, but has incomplete documentation and small userbase which makes it hard to get into, and the syntax is quite verbose.

Modding

Instead of making a game yourself, for some it is more interesting to modify other people's games. This can be simple as adding new content, fixing bugs, translating the game to another language, or creating whole new games using the modded game's engine and logic (usually called "total conversion" mods). How this is done varies. Some games can be modded by changing the games assets while some are modded by altering the binary directly. Many popular games have official tools for creating mods (usually level, script, and sprite/model editors) but unofficial tools exist for popular games without official modding support.

There is usually still programming involved when it comes to making mods. Usually it's done through scripting languages either common ones like Lua or Python, custom languages made specifically for that game or engine like CaveStory's TSC language or UnrealScript, or Assembly or the language the original game was programmed in if you are modifying the binary directly. Also keep in mind that many games (especially commercial games) have terms and conditions when it comes to mods such as only allowing distribution on a certain site/forum/platform, restricting controversial content, or out right banning mods entirely. Freeware and FLOSS games usually don't have this problem and may even allow you to distribute your mods with the binaries so you can release them as standalone games.

"ROM hacking" is basically modding for console games (usually ones that can be emulated). Unlike modding, ROM hacking is usually done by changing the binary directly since all of the game's code and assets are usually compressed into a single file. Many popular retro console games have ROM hacking tools created by fans so you don't have to worry about reverse engineering everything yourself. To avoid copyright infringement, many ROM hacks are distributed as software patches, requiring the original ROM or ISO to be played.

Explanation of terms and concepts

Crash course to programming terms, variables, statements, and data types

Note that the exact wording and behavior varies from language to language.

  • Variable - some data that you can refer to by name and modify. For example "shekels = 500" will set the value of the shekels variable to 500.
  • Index - index is a word that describes positioning in a list. For example the third item in a typical array may be at index 2 or 3 depending on the indexing method. Lists are often 0 indexed, which means the first item is 0, second item is 1, and so on.
  • Bit - the smallest amount of data possible, it can be either 0 or 1.
  • Byte - 8 bits. Memory is usually grouped into bytes, rather than being interacted with 1 bit at a time.
  • Binary - data of bits and bytes, all data is technically binary, but the word is usually used to refer to data that isn't in a specific or commonly readable format such as text.

Data types

  • int / integer / short / long - a number value without decimals. The different names refer to how many bytes it has (and thus how high the number can go).
  • char / character - an integer that's 1 byte in size. It can also be used as an ASCII text character, for example "A" or "7" or "/".
  • float / double - a number value WITH decimals (e.g. 1.35). Floats are kind of imprecise, and double has a higher precision than float ("double precision") but is larger in size.
  • boolean / bool - a value that can be either true or false. The actual data and size of a bool varies by language, but usually true is 1 and false is 0.
  • String - a sequence of characters in the form of an array, used to store text in a variable.
  • Array / list - a contiguous list of variables. To access the items, you would do for example "myarray[5]" to access the 6th item.
  • Associative array / dictionary / map - an array of sorts where you can access the items by name rather than index. For example "mydictionary["faggot"]" might access an item that has "faggot" as it's name.
  • Stack - a type of array that only has its most recently entry accessible and accessing said entry will cause it to be removed (or "popped") from it. The word 'stack' also has a different meanting; part of the computer's memory where data and variables are stored.
  • class / struct / object - a collection of variables that can be referred to through the object. For example in order to access the "hitpoints" value of the "slimegirl" object, you use "slimegirl.hitpoints". Class and struct are effectively the same thing, though some languages define them as separate and have some minor differences. Usually struct is more plain data while class is a more complicated system.
  • Vector / Vec2 / v3… - a vector is essentially a struct or an array that contains coordinates of some point. Vec2 contains X and Y, Vec3 also contains Z, and there are some others. C++ has a data type that some retard named "Vector", but it has nothing to do with actual vectors. C++'s vector type is just an array that expands automatically as you put items into it, also known as a dynamic array or flexible buffer.
  • signed / unsigned - Integers can be signed or unsigned. Signed means the value can go to negatives, but it can only go half as high (e.g. -128 to 127 for signed vs 0 to 255 for unsigned).
  • constant / const - a constant is a variable that cannot be modified. When you create it, it will keep it's value forever, and you will get an error if you try to change it.
  • static - a variable that keeps it's value between function calls. When you call a function for the first time, the variable will get initialized. However every call to the function from then on will skip the initialization, and the variable will have whatever value it had when you last called the function.
  • u8, s8, i32, f32, uint8_t… - these are just alternate names for integers and floats that some languages have, or they may be defined in the program code. For example instead of having to type "unsigned char", you could just type "u8", and then i8 or s8 for a signed char. The number refers to the size of the variable in bits, char having 1 byte which is 8 bits.
  • Pointer - a variable that has a memory address as it's value. In other words, it points to some data in another location in memory rather than having any data of it's own. Pointers are usually interacted with by adding & or * next to the variable.
  • dereferencing - dereferencing is when you go to where a pointer points to, and interact with the data that's there, instead of interacting with the pointer itself.
  • void - a special data type that refers to the lack of type; it's nothing. Void is usually used to either refer to data of unknown type, or used as a way to indicate that a function doesn't return anything.
  • null / none - means that the variable currently has no value.
  • NaN - means that a variable is "Not a Number". In some languages, number variables can become NaN if you set a non-number value into it.
  • casting / cast - a value can be converted, or "cast", to another type. For example you can cast a float into an integer. In some cases you don't need to do it and in some cases it's automatic. You can also cast void into some type.
  • global variable - a variable that is not tied to a function, struct, or object and can be accessed anywhere in the program.
  • local variable - a variable that is tied to a function, struct, or object and can only be used there.

Common statements

  • print/printf/echo - a statement or function that outputs text to the console. In most object-oriented languages this is usually a method like Console.Write() or Console.Writeln().
  • input - a statement or function that prompts input from the console. Once the input is given it is assigned to a variable.
  • if/else/else if - a conditional statement. Basically the computer will run a block of code if the statement is true. If the condition is false, an else if or else statement can be used to run a different block of code.
  • switch - an alternate variation of an if/else statement that can only be used to check the result of one value.
  • for loop - a loop with a variable (usually labeled as i) that increments until a certain maximum value is reached. Often used for reading/writing values in an array or list.
  • foreach loop - a variant of the for loop that loops through the items in an array.
  • while loop - a loop that runs while a condition is true. Once/if the condition becomes false, the loop will stop.
  • do while loop - a while loop that will run once regardless if the condition is true and will repeat as long as the condition is true.
  • break - you can "break" out of a loop even if the loop is still going by using the break statement.
  • continue - similar to break, it will exit the current iteration of a loop early, but unlike break, it does not exit the loop itself.
  • return - similar to break, it will break out of all loops in the function, and exits the function. It is also used to return values from the function to the caller.
  • goto - a statement that allows the computer to goto a certain line or block of code. This is more used in older languages like C or BASIC.
  • eval - a statement/function that allows you to execute a string as code. Be warned that this is a very dangerous statement if not used properly.
  • assert - a common function/macro that checks if the condition is true, then exits the program or function if not and possibly writes/displays some kind of error information. In other words it is used for debugging purposes.

Misc

  • function / procedure / subroutine - a bunch of code that you can call up from anywhere without having to re-type it. You can also give some values to it. For example "dosomeshit(20, 500)" will call the function whose name is "dosomeshit", and gives the values 20 and 500 to it. Functions can also return some values back to whoever called it, for example the dosomeshit function could multiply those two values together and then return the result.
  • method - a function that is tied to an object. Used to modify data of said object or even other objects. Usually called by typing object.method().
  • constructor / deconstructor - a method that is called immediately when an object is created or destroyed.
  • label - A block of code that can be accessed with a goto statement so it can be accessed without referring to its line number. This is more used in older, unstructured languages but still used in shell scripting languages like Batch.
  • exception - when an error happens during runtime (e.g the program is accessing a file that doesn't exist), the program will throw an exception and will go to a block of code to handle the exception if it exists otherwise, the program will crash.
  • Bitwise operations - usually you handle data in bytes, but bitwise operations let you modify then bits within bytes more precisely. For example "«" will shift the bits to the left.
  • enumerator / enum - a list of named values called elements or members that behave as constants. Each element has a different number value, you can add elements to the enum and they will automatically gain an unique number unless you define it separately.
  • scoping / block - a block is an area in the code where variables and everything live. For example each function has their own scope, and variables created inside of it are not available outside of it. Blocks are usually indicated by curly brackets {}. Blocks can also contain functions and structures, making them unusable outside of that block.
  • comment - comments are a part of your source code, but they do nothing. The compiler/interpreter will just cut them out as if they were never there. You should always add comments to clarify what certain parts of your code do, and where different parts of it begin. They are also useful for debugging since you can "comment out" parts of your code and uncomment them for later use.
  • namespace - a place to store objects, structs, and functions making it easier to organize them.
  • using - (note: usage of this mechanic may vary by language) it is possible to "use" a namespace, allowing you to access variables and functions from that namespace without using it's name. For example, "nodev.games = 0" changes 'games' from the nodev's namespace. To use a namespace, you use the keyword 'using', for example "using nodev", now you can modify nodev.games with just "games = 0".
  • union - a way of grouping different datatypes so the same memory can represent multiple different types of data. Usually you use a separate value to decide what data the union memory represents.
  • debugging - The act of testing a program for potential bugs and exploits.
  • Refactoring - Refactoring is when you change the way some of your existing code works. Usually it's done to optimize the performance, expand it so it can support new features, or just cleaning it up so it's less shit.
  • Spaghetti code - Spaghetti code refers to source code that it is so messy and disorganize that it is virtually unreadable. Usually caused by poor planning, little to no comment usage, or writing more code than necessary.
  • Psuedocode - refers to a mix between computer code and English. Usually used to help plan out an algorithm.
  • Standard library - A library that is bundled with a language's compiler/interpreter and is usually considered part of the language. Usually contains functions and objects for commonly used algorithms like printing text to the console, mathematical functions, file handling, networking, and in some cases, basic graphic and audio functions.
  • runtime - refers to a time when the program is running, i.e. not before or during compilation.

Dynamic vs. static typing

Dynamic and static typing refers to the way you create and refer to variables. Basically static typing means you need to tell your computer exactly what kind of variable to use, and dynamic typing means the computer figures it our for you depending on what you do with it.

Dynamic typing:

var myvariable;
myvariable = 10; //valid
myvariable = 1.52; //valid
myvariable = "Anon"; //valid

Static typing:

int myvariable; //myvariable is an integer value
myvariable = 123; //valid, 123 is an integer
myvariable = 1.52; //invalid, 1.52 is a float
myvariable = "test"; //invalid, "test" is a string

Why not use dynamic typing all the time? Runtime safety. With a static-typed language, you can guarantee that certain functions, variables, and objects all take up a predictable amount of memory, the right values are being passed to functions, etc. Static typed language will not compile if you try to do an invalid operation, but dynamic typed language will, and your program might crash due to invalid operation unless you check for the proper types.

Compiler, Linker, and libraries

The code you write is just a text document, your computer can't actually use it in that form. When you run that document through a compiler, the text is converted into data that the operating system and hardware can understand, and it takes the form of a compiled program (usually an .exe when on Windows). Alternately, you can generate other things such as a library file (.a and .dll being examples) or an "object file" (.o being an example) that's used to link with other files.

Linking is the second part of the compilation process, and is often implied to be done when someone talks about "compiling". The compiler only compiles your project files halfway into an executable, the linker is actually the one that ties them together into an executable file that the user can run. The linker is usually part of your compiler or operating system, and may even link your project automatically unless you tell it not to.

Library files contain functions and code that you can use for multiple projects or share with other people, for example a pathfinding library could provide path finding functionality which does not need to be re-written for every project, instead you can just call functions from the library. If you're using third party libraries, they sometimes come as one of the aforementioned library file formats. In order to use them, you need to tell your compiler to do the compiling and linking in 2 separate steps, first to compile your own code without linking it (which creates the object file), and then to use the linker to link it with the library files.

Additionally, dynamic library files (e.g. .dll) are automatically linked every time the program runs rather than when the program is compiled. When you compile your program with dynamic libraries, the program looks for the .dll file whenever it's run instead of integrating the code into itself. If you delete the dll file, the program probably won't run anymore. It is also possible to use operating system calls such as GetProcAddress from your code, which searches for functions and variables from a given dll file, this may be useful for handling errors if you expect the library files to be modified for some reason.

Cross-compiler

When you compile source code for a program, it usually compiles for the platform it is compiled on. For example, a program compiled on a Windows computer will effectively be a Windows program. So usually, it is required to have multiple computers/VMs for each platform your targeting. A cross compiler allows you to compile for a different platform than the one that you are currently using.

Transcompiler

A transcompilier or source-to-source compiler converts source code from one language to another. This is useful if you somehow want/need to switch languages for your project without rewriting the code from scratch or if you just want to see how your program would perform if it was written in another language. Some languages are made just to be transcompiled since it is easier to transcompile to another language than to write a compiler or just to make writing a certain language easier. Examples of transcompiled languages include Nim and CoffeeScript which compile to C and JavaScript respectively.

Decompiler and disassembler

A decompiler is a program that takes an already compiled executable and attempts to create source files of the program. A disassembler is basically the same thing but creates assembly files instead hence its name.

Note that a decompiler and a disassembler don't give you the actual source code. It's just a guess on how it is made and the result isn't that human readable. They're useful for reverse engineering programs however.

Debugger

A debugger is a program that is used to test another program for bugs. They can help detect runtime errors, track and change variables, pause the program at anytime, and jump to any point of the programs execution. While debuggers are useful, you can replicate the functions of them by creating debug output in your programs.

Parser

A parser is a program or a library that reads information from one format (usually plain text), and converts it to another format. For example browsers have a JSON parser which turns JSON text into JavaScript objects that can be used by the JavaScript code. All compilers and interpreters also use a parser system to read the plain text code.
It can also be used to convert information backwards, e.g. from code into text, which can then be saved in a text file.

Interpreted languages

Some code is not compiled, but instead is run through another program called an interpreter which reads the code and either runs it in real time or does something called "just in time compilation", or JIT, i.e. compiling it during runtime before using it. Examples of such languages are Python, Lua, Ruby, and JavaScript. The advantage of this is that the code is much simpler and can run on many different platforms with little to no modifications. The disadvantages are that the program will run slower, the user will need to download and install the interpreter and the code's libraries, and the code can be easily modified.

High level lanuages, low level languages, scripting languages, visual scripting. Why are low level languages "hard", why are high level languages "slow"?

Programming languages come in various levels of abstraction. High level languages attempt to make programming easier for you by doing more with less and hiding some details so you don't have to think about them, while low level languages are typically more faithful to how the computer and data actually works thus you need to be more specific with what you do.

Scripting languages are some of the highest level of languages, although it doesn't necessarily differ from a "real" programming language in their function. The actual definition of a scripting language is a bit murky, sometimes the term means "a high level language", but sometimes a language can be referred to as a scripting language due to the context in which the language is used or how it works. For example C# isn't a scripting language, but can be used for "scripting" within some engines and systems. Games are usually never written entirely with scripting languages, but are instead used to interact with deeper, compiled parts of the program/engine.

Visual scripting is essentially the highest level of programming languages. Instead of writing code, a visual scripting language allows you to create programs with a graphical user interface, for example by adding boxes and connecting them together and tweaking numbers. These languages are often used by artists and sound designers and other people in the development team whose job does not involve programming. Visual scripting languages are unusual in that sometimes due to their inflexibility they can be better optimized than normal scripting languages, and may offer better performance as a result as long as you don't abuse them. An example of a visual scripting language is Unreal Engine's Blueprints. Multimedia Fusion and Construct are examples of game engines based on visual scripting.

Although higher level languages try to make programming simpler for you by hiding all kinds of details behind a curtain so you wouldn't need to concern yourself with them, the computer has to do those things anyway because that's just how computers work. Having the language secretly do them and try to make things work conveniently comes at a performance cost, and may make certain kinds of optimizations difficult or impossible to do since you don't know exactly what's happening behind the scenes or have control over them. A low level language doesn't do that, and it's up to you to use your data according to your desires, and there's rarely any secret magic that's happening without you knowing. Some lower level languages like C++ and D also have some such 'conveniences' and may really want you to use them, but the language lets you program without them if desired.

Examples of things that may not exist in high level languages but that you can/need to consider in a low level language

  • Memory management - many high level languages have automatic memory management, but low level languages require you to manually reserve space in memory for data and free it when you don't need it anymore. Automatic memory management has a certain performance cost and makes some optimizations difficult, which is why you can't just add it to all languages.
  • Number types and "casting" - different kinds of numbers need different kinds of data to represent them. For example a "char" (character) is a small number that only ranges from -128 to 127 but is very small in memory size (1 byte). The biggest common number variable (usually called "long long") can reach up to around 9,000,000,000,000,000,000, but is 8 times bigger than a character, so usually using it is very wasteful. In order to represent negative numbers, you need what is called a "signed" value. It halves the maximum value of the variable, but in exchange allows it to become negative, for example a signed char ranges from -128 to 127 while unsigned char varies from 0 to 255. Representing decimal numbers in data is kind of finicky, so for them you will need a special variable type called "float" (which is always signed). In order to convert one type of number to another, you need to do what is called "casting" (although it's often automatic even in low level languages). High level languages often do various tricks to hide all of these facts from you and pretend than there's only one kind of "number" type, so it's either difficult or impossible to optimize your number variables.
  • Dynamic arrays - array is just a straight sequence of values, they can only contain a fixed number of items because the computer needs to reserve memory for all the space when it's created. If you try to add more items after the last item, some other data may be in that position in memory and you will override it, corrupting the memory. In order to increase the array size, you need to either re-allocate memory which may cause all kinds of complications if not handled properly, or use special array functionality that creates segments when needed and travels along them (such as C++ "vector"). High level languages often treat all arrays as dynamic arrays to avoid these complications and just let you dump variables into any array whenever you feel like, but there's no solution that's as fast as using a fixed array when you can.
  • Strings - a string is an array of characters, but high level languages often act like "string" is an UTF-8 encoded dynamic array object that you can modify. A "low level" string may not support characters besides the 127 or so ASCII characters without using additional procedures, and you cannot make it longer than you originally defined without reallocating the memory.
  • Pointers - pointer is a variable that points to some other place in memory. They're required for a lot of different things such as arrays and data of unknown/various types, but high level languages usually avoid pointers or may not even let you use them at all, and makes things work for you without them. For example in C, a variable cannot contain an array in it, instead you get a pointer to memory where the first item in the array resides, and then access the other items by moving from the pointer's position. Another complication with pointers is when you move memory, if a pointer X points to value Y, then Y is removed or moved, X will break and may crash the program if you try to retrieve Y from it. There's various ways to get around that, but high level languages may not even let you know that any of it is happening.
  • Plain data - depending on how high level language you're using, it might be difficult to interact with the actual data that you have. For example in Javascript, objects can be and become anything, and you have absolutely no idea what's going on behind the scenes and what kind of real data your variables are made of and what kind of systems run behind the scenes at any time. If you put a variable into an array, you may have no idea if you're putting the variable's data into the array, or a pointer to the variable, or something else. A language like C on the other hand is the opposite; all your variables and data is just data, some amount of 1s and 0s, and you can do whatever you want with it. You could even treat data of one type as if it's the data of another incompatible type if you wanted to, there's no secret systems that you're not allowed to touch or know about, and you know exactly what happens when you do something. You may crash the program though if it's not prepared for what you're trying to do though (for example trying to access a part of the memory that doesn't belong to your program).

Markup languages (HTML, XML, etc)

Markup languages are languages designed for organizing documents and information so that a program (e.g. a videogame or a web browser) can read it easier. The document itself is plain text, you can create and edit these files with any text editor including Notepad. The information is usually stored in some kind of associative array after being parsed, and can then be queried by the program at any time.

In game development, markup languages are usually used for storing game data such as level data, in-game text, game options, game saves, etc. The most common markup languages used in games are XML, JSON, and S-expressions. HTML is usually used with JavaScript or WebAssembly for <canvas> games, and as an alternative to plain text for documentation and README files.

Although static HTML documents could in theory be used to make a simple text adventure game (by adding links from one document to others), markup languages do not allow for programming per se, thus you cannot make videogames with them alone.

Alternatives to markup languages include binary files, config files, and SQL databases.

JSON

JSON (JavaScript Object Notation) is one of the most popular languages for storing data such as text and numbers and arrays, it is similar to markup languages but technically not considered one, and is often seen as an alternative to XML. Libraries for parsing it exist for most languages and many engines support it by default. It is essentially a JavaScript-style object written as a string. JSON files, like XML files, are plain text, thus you can create one with Notepad if you want to. BSON is JSON but in a binary file instead of a text file.

Formats with similar purpose include YAML and S-expressions.

Binary file

A binary file is a non-executable file that is in binary format rather than in plain text, making it harder for the end-user to modify them externally. This is useful for files that you don't want the end user to easily modify (i.e save files and high scores). Also, reading and writing binary files is much faster than text files. However, binary files are much harder to parse than plain text and you need to keep track of which byte holds which data and you need to learn how to read/write in hexadecimal. A hex editor is a program that allows you to modify binary files externally.

Config file

A config file (or configuration file) is a text file used to store settings for a computer program. Unlike markup languages, config files are solely designed for storing configuration data and are usually only read once during start up. However, markup languages can be used in place of configuration files, and are usually a better option since they can handle more complex data structures like objects, arrays, and dictionaries. Examples of config file formats include Windows INI files, property lists, and Java's .properties format.

Virtual Machine

Some strongly-typed languages such as C# and Java, and most dynamic-typed languages, run on a virtual machine. Rather than rely on your physical hardware, the program runtime creates a memory state that acts as if it were a simple computer, with dedicated sections for memory, processing, etc. The advantage to this is that you only need to write your code once, and if the hardware and OS is compatible with Java, for example, every single Java program can run without an issue. The disadvantage is that your program can take up a lot of memory and will run slower than if it was a native application but not as slow as if it was interpreted. Also, programs that run on virtual machines can be decompiled easier than native applications, but depending on your point of view, this isn't really a problem.

Historically, languages like C and C++ had (and still have) many implementations to guarantee cross-compatibility between platforms. This is why some games can have differences between Windows, Mac, and Linux distributions, because it literally needs to generate a specialized program for each. With modern engines and technologies like virtual machines and HTML5, you don't have to worry about such details; but the advantage of older languages lets you cut away needless features and gives you the most control over how things work.

IDE

An IDE (Integrated Development Environment) is a single tool that contains various functionality to help you write software. It is usually a combination of a text editor, hex editor, file manager, some compilers/interpreters, project templates, versioning control management system, and debugging features. Examples of an IDE are Visual Studio, MonoDevelop, Xcode, and Code::Blocks.

Despite what Microsoft and many other companies want you to think, you almost never need an IDE, they're mostly for convenience. You can pick whatever compiler you want with whatever text editor you want with whatever other tools you want, you could write all your games using nothing but Notepad and your language's compiler/interpreter if you wanted to. Though note that some IDEs have unique tools that you cannot get out of it, for example, Visual Studio has some of the best debugging tools period, so if you want to use them you need to deal with Visual Studio.

Open source and Free software

Main article: FOSS

Programs which make their source code available are open source and are usually freely shared and/or modified. However, depending on the project/library, some licensing terms can restrict what you can do for it (eg, some may give you source code for personal or education purposes, while others allow you to make modifications for commercial purposes, as long as you reserve the right for others to make the same use of your code).

For large projects, the source code is common stored in a git repository (eg, GitHub), which is a kind of versioning control management system. These let you publish and branch codebases, and rollback changes. Most people here probably won't need to worry about this, but they can make for a good backup of your project.

Note that "open source" is not the same as "free/libre software". While open source software may have it's source code available, you may or may not have certain freedoms that the definition of "free/libre software" entails. Open source is often used interchangeably with free software however.

Memory management / garbage collection

Every time you create a variable or load an asset, your computer has to reserve memory for it, and when it's no longer needed it needs to be "freed" so it stops reserving memory. Some languages such as C# and Java do this for you, these are called "garbage collected" languages. Other languages like C and C++ have manual memory management, which means it is up to you to allocate memory for your data and free it when you're done with it.

There are two places where data (variables) are stored in; the stack, and the heap. When you create a variable, it usually goes into the stack automatically, and gets freed when the function runs to the end. This process is automatic and you do not need to manage it yourself even in low-level languages like C. However any data that you want to access throughout the game, such as game state, map tiles, player data, etc. must be stored manually in the heap. The heap is controlled by you, and if you keep allocating more data into it without deleting old unused information, it'll keep growing and growing with useless data, this is called a memory leak. Memory leaks are very easy mistakes to make and sometimes hard to track, if you allocate memory and then overwrite or delete the pointer that points to it (which may be inside stacks of other allocated data), the data becomes inaccessible and the memory will be stuck in the void until the program is closed.

The advantage of garbage collection is that it is easier to develop software since you do not need to think about keeping track of your data, but the downside is that it has a "significant" performance penalty. This performance penalty is not meaningful or even noticeable in most cases due to the speed of modern hardware, but it is something to consider if you need very high performance, are making something mechanically complex, or are targeting older/weaker hardware.

Programming paradigms

Programming paradigms are used to categorize languages based on their features and programming style. Some programming languages only allow one paradigm (like C), while other allow multiple paradigms (like Python). Here is a list of commonly used paradigms and their description:

Unstructured programming is the earliest programming paradigm. As the name suggests, the code isn't structured into functions, structs, or objects but is instead one continuous block of code. Jumping to certain parts of code has to be done manually via GOTO statements. The advantage of unstructured programming is that you have a lot more control over your program, but complex projects end up as "spaghetti code". Examples of unstructured languages include Assembly, Fortran, Batch, and many earlier dialects of BASIC.
Procedural programming groups individual code into functions and subroutines which can be accessed at any time during execution. These functions can be reused in other programs through code libraries and modules. Before the rise of object-oriented programming in the late 90s and early 2000s this was the most common programming paradigm for game development. Examples of procedural languages include C, Fortran, Pascal, and Go.
Object-oriented programming groups code and data into self contained objects. These objects can have built in functions called methods which can modify the data of said object or other objects. Objects are grouped into classes which determine the type of object and what properties and methods the object has. This is currently the most popular paradigm for game development because it makes it easier to organize your game's code. However, objects take up more memory and resources. Examples of object-oriented languages include C++, C#, Java, Python, and more recent dialects of BASIC.
Functional programming is similar to procedural programming in that you write your code into functions but the functions in functional programming only return a value and nothing else. So functions cannot modify values or do anything like that. Currently, this paradigm is not commonly seen in games, but it is possible and many functional programming languages have bindings for frameworks like SDL. Examples of functional languages include Haskell, F#, and many dialects of LISP.

Data-oriented design/programming

Data-oriented design is a programming style/viewpoint where you care and pay attention to the actual data and memory that you're interacting with, and try to design the program according to that. You have some data, and you operate on it to get a desired result. The opposite is to think of your data as abstract objects and things, such as "enemy" and "sprite" that have various methods and functionalities attached to them, with little regard for what kind of data they consist of and how they're organized or accessed in memory.

Computer processors are insanely fast, but memory is not, which is why it is highly beneficial to organize your data in a way that the program can access and operate on it easily. The primary methods are to a) group data that's accessed often or at the same time, and separate it from data that is accessed less often or at a different time, and b) laying data into contiguous lists, as opposed to using pointers to point to random parts of the memory or using related systems like linked lists.

Memory is a huge bottleneck whose speed is limited by actual real world physics and the physical distance from RAM to the CPU. The CPU has it's own small memory and keeps recently accessed data in it for faster usage. When the CPU loads something from the RAM, it actually loads a "cache line" which has other nearby data along with it, for example other variables from the same array. However if it the data is spread all over the RAM, it needs to access multiple parts of the RAM separately and needs to keep multiple cache lines in it's cache. The speed difference between retrieving a value from RAM vs retrieving a value from the closest cache can be up to 100x.

SIMD is another CPU feature that can be considered related to data-oriented design. SIMD allows you to modify multiple variables in one go, greatly improving the speed of repetitive operations. It requires you to group the data for variables in a way that allows you just give them to the CPU without moving things around.

Errors

Compilation errors occur when you try to change your written code into machine code. This could be as simple as a syntax error (eg, you wrote "conts" instead of "const"), or something more complex that the compiler detected as wrong (such as using an undeclared variable).

Run-time errors happen when the program is executing. The most common ones are "index out of bounds" errors when working with arrays, and "null reference" exceptions, when you try to access a value that belongs to a null object, which is an impossible state. Like compilation errors, almost every language will tell you when something is wrong.

Logical errors are the most devious, and cannot be detected by the computer. These occur when your game behaves in unexpected ways, and can be difficult to track down since the game has no idea of knowing what you actually wanted to happen - but as far as its concerned, the game is in a correct state. These occur less often with experience, but a common occurrence among new programmers is to mess up conditional logic, perhaps putting ">=" instead of ">" or getting the sign backwards, and spending several hours tracking down the error. It happens!

Tips

Help! I'm worried about performance!

The Indian approach to performance

If you are just starting to build an engine or are in a very early stage of your game, chances are that you are being paranoid and suffering from ye old premature optimization. The purpose of programming is to provide the developer with the tools and interface to achieve a written piece of software in a human-to-computer-comprehensive manner. If you worry about performance without even measuring the gains, you would not only be prolonging your development time, but also be misusing the interface and tools on code that does need to be profiled. In some cases, you may even cause worse performance refactoring code on a whim. As a result, a good game programmer should strive to develop an application as neatly and swiftly as his/her skill allows. Some tips include writing, planning, and designing beforehand and making use of the engine's prototyping tools. Remember: Do not give in to your optimization itch.

B-but I like doing it the slow way!

Good for you. You will be a great programmer. But your game will age faster than the code it runs on.

Random 2D Vectors:

gamedev%20random%20vector2.jpg

See also

Articles

Related articles

Helpful links

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License