How computer games are created

28 March 2024 11 minutes Author: Lady Liberty

You will learn about the basic elements that make up the structure of computer games, including graphics, sound, controls, physics and gameplay logic. You will get an idea of how games interact with libraries to extend functionality, how the main loops of games are organized, and also about data processing and interaction with servers in multiplayer games.

Where it all began

Video games have long ceased to be just entertainment – they are now an entire industry that combines art, technology and business. Thanks to the development of technology, they have become a universal medium, suitable for both self-expression and entertainment. From text games of the 70s to modern VR projects – this path has been fascinating and full of revolutionary breakthroughs.

1. Historical context

The development of video games reflects technological progress and cultural changes.

  • The early years. The 70s saw the emergence of text-based games like Zork and simple arcade games like Pong. These were the foundations that defined the concept of interface and interactivity.

  • The 80s: The beginning of the golden age of arcade games. Space Invaders and Pac-Man became cultural phenomena, and Super Mario Bros. laid the foundation for platformers.

  • The 90s: The real breakthrough in 3D. Doom showed what real action looks like in 3D, and Half-Life integrated the story directly into the gameplay.

  • The 2000s: The beginning of the era of multiplayer games. The Sims offered a life simulation, and World of Warcraft created a new standard for MMORPGs.

  • Today: Technologies like Unreal Engine 5 allow for graphics that are difficult to distinguish from the real world. Games like The Last of Us 2 combine cinematic storytelling with immersive gameplay.

The history of gaming shows that every decade brings revolutionary changes, and this trend continues to this day.

2. Modern tools for creating games

Today, game engines greatly simplify development, allowing even small teams to create competitive projects.

  1. Unity is a universal choice for indie developers and professional studios. It is suitable for 2D and 3D projects, has a huge library of assets and supports all popular platforms.

  2. Unreal Engine is a leader among AAA projects. It uses Lumen and Nanite technologies to create realistic lighting and textures.

  3. Godot is an open source tool aimed at indie developers. Easy to use, suitable for rapid prototyping.

  4. GameMaker Studio is a popular choice for 2D games. It allows you to focus on gameplay mechanics, minimizing the complexity of programming.

Thanks to these tools, even beginners can start their journey in game development without having to create everything from scratch.

3. Development Careers

A development team is a multidisciplinary structure that encompasses various specializations. Game designers are responsible for developing the concept and mechanics that make a game exciting. Programmers implement these ideas through code, creating physics, artificial intelligence, and player interaction with the environment.

Artists shape the visual style of the game: from characters to textures and animations. Sound designers create the atmosphere, ensuring player immersion through music and sound effects. All of these specialists work together to create a holistic product.

For example, in Red Dead Redemption 2, a huge team of artists and sound designers created a realistic world that is brought to life by programmers and designers.

4. Trends in game development

Modern games integrate advanced technologies. Artificial intelligence is increasingly used to create complex NPC behavior. For example, in the Far Cry series, enemies adapt to the player’s actions, which makes combat more dynamic.

Virtual and augmented reality allow for unique experiences. Games like Half-Life: Alyx transport the player into a virtual world that feels real. Procedural generation, like in No Man’s Sky, opens up endless possibilities for exploring new worlds.

Technology is changing game development not only now, but also preparing the ground for a future that will be even more interactive and personalized.

5. Game Development Stages

Creating a game is a complex process that goes through several main stages. First, developers create a concept and detail it in a Game Design Document. This is followed by creating a prototype that allows testing of the main mechanics.

In the alpha version, all the game features are added, which are then improved and tested during beta testing. Only after thorough testing does the project reach release. For example, in Cyberpunk 2077, the team spent additional time improving technical details after an unsuccessful initial launch.

Each of these stages is important for creating a quality product.

6. Challenges in game development

Game development has its challenges. Optimizing a game for different platforms is one of the biggest challenges. For example, a game may run perfectly on a powerful PC, but have problems on older consoles.

Another problem is bugs, which sometimes become more well-known than the game itself. Situations like the early versions of Cyberpunk 2077 show how important testing is. In addition, deadlines and limited budgets can create stress that affects the quality of the product.

However, teams use innovative methods like Agile to minimize risks and find creative solutions.

7. Educational Resources for Beginners

For those new to game development, online courses like Coursera and Udemy are a good place to start. They offer lessons from professionals in Unity and Unreal Engine. YouTube is a great source of free tutorials, including the Brackeys and Game Maker’s Toolkit channels.

Recommended books include “Game Programming Patterns” for programmers and “The Art of Game Design” for designers. These resources will help beginners better understand the industry and get started with their own projects.

Parts of the game

Although games are programs, they are complex and consist of several parts. Some of them include:

  • Graphics

  • sounds

  • Introduction

  • Physics

  • Game logic

Because of the complexity of each part, most games use external functions for these parts. These external functions are combined into something called a library. The libraries are then used by other programs to reduce the amount of code written. For example, most games use the DirectX or OpenGL library to draw images and shapes on the screen.

For some types of hacks, it is important to identify the libraries used. A wallhack is a type of hack that allows a hacker to see other players through solid walls. One of the methods of programming wallhack is to modify the graphics library of the game. Both OpenGL and DirectX are vulnerable to this type of hack, but each requires a different approach.

For most hacks, we will be changing the game logic. This is the instruction section that is responsible for the game progress. For example, game logic will control how high a character jumps or how much money a player gets. By changing this code, we can potentially jump as high as we want or get an infinite amount of money.

The structure of the game

Game logic consists of instructions, just like all computer code. Due to the complexity of games, they are often written in a high-level language and compiled. Understanding the general structure of the source code is often necessary for more complex hacks.

Most games have two main functions:

  • Settings

  • The main loop

The setup function is performed when the game is launched for the first time. It is responsible for loading images, sounds and other large files from the hard disk and placing them in RAM. A main loop is a special type of function that runs forever until the player exits. It is responsible for processing input, playing sounds, and updating the screen, among other things. An example of the main loop might look like this:

function main_loop() {
    handle_input();
    update_score();
    play_sound_effects();
    draw_screen();
}

All these functions call other functions. For example, the handle_input function might look like this:

function handle_input() {
    if( keydown == LEFT ) {
        update_player_position(GO_LEFT);
    }
    else if( keydown == RIGHT ) {
        update_player_position(GO_RIGHT);
    }
}

Each game is programmed differently. Some games may prioritize updating graphics before processing input. However, all games have a certain basic cycle.

Data and classes

Any data that can be updated in the game is stored in a variable. This applies to things like player account, position or money. These variables are declared in the code. An example of variable definition in C might look like this:

int money = 0;

This code will declare the variable money as an integer. As we learned in the last lesson, integer values in C are integers (such as 1, 2, or 3). Imagine if we had to track money for multiple players. One way to do this would be to have multiple declarations, such as:

int money1 = 0;
int money2 = 0;
int money3 = 0;
int money4 = 0;

One disadvantage of this approach is that it is difficult to maintain as the game gets bigger and more complex. For example, to write code that increases each player’s money by 1, we would have to manually update each variable:

function increase_money() {
    money1 = money1 + 1;
    money2 = money2 + 1;
    ...
}

If we were to add another player, we would have to go and update every section of code that changed the players’ money. A better approach is to declare these values in a list. We can then use an instruction known as a loop to go through each element in the list. This is known as iteration. In C, lists are usually implemented using a so-called array. For our purposes, you can think of lists and arrays as synonyms. One type of loop in C is known as a for loop. For loops are divided into three segments: an initial value, an end value, and a way to update the value after each iteration. An example of the preceding code can be written as follows:

int money[10] = { 0 };
int current_players = 4;

function increase_money() {
    for(int i = 0; i < current_players; i++) {
        money[i] = money[i] + 1;
    }
}

Now we just need to update the current_players variable to add support for another player.

To facilitate the development of complex applications, developers often use a programming model known as object-oriented programming, or OOP. In OOP, variables and functions are grouped together in collections called classes. Classes are usually self-contained. For example, many games will have a Player class. This class will contain several variables, such as the player’s position, name, or money. These variables inside a class are known as members. The classes will also contain functions to modify these members. One example of the Player class might look like this:

class Player {
    int money;
    string name;

    function increase_money() {
        money = money + 1;
    }
}

Games often contain lists of classes. For example, the game Quake 3 has an array of all players currently connected to the server. Each player has their own player class in the game. To calculate the score screen, the game will look at each player on the list and look at the number of players killed.

Memory

Games have a lot of great resources like images and sounds. They need to be downloaded from the hard drive, usually during the game setup stage. Once downloaded, they are placed in RAM along with the game code and data. Because games are so large, they have to constantly load various data from RAM into registers in order to work with them. This loading is usually done by the mov command. This command will move some memory into a register. Our example CPU-executed increase_money function might look like this:

function increase_money:
    mov eax, 0x12345678
    add eax, 1
    mov 0x12345678, eax

In this example, we use 0x12345678 as the location of the player’s money in RAM. Most games will have this structure but with a different layout. For more complex games, these locations will be based on other locations. If our game had a player class, the increase_money code executed by the CPU would need to use the location of the player class to get the money.

function increase_money:
    mov ebx, 0x12345670
    mov eax, ebx + 8
    add eax, 1
    mov ebx+8, eax

In this case, the CPU had to compensate the location of the money based on the location of the Player class.

Multi-user clients

Multiplayer games allow multiple players to interact with each other. To allow this, multiplayer games use clients and servers. Below is an example of a client-server model:

Clients represent a copy of each player’s game and contain all information about the local game. For example, each client will contain that player’s money. When a player calls an action to change their money, the client is responsible for sending that update to the server.

Information can also be sent in both directions. An example of this is player movement. One client will tell the server that a player has changed their position. The server will then notify all other clients to update their associated positions for the moved client.

Multi-user servers

While the client represents each player’s copy of the game, the server ensures that all connected clients are playing the same copy of the game. Servers often limit what changes they accept from clients. For example, imagine we wrote a hack to change our money in a game. If it’s a multiplayer game, the server will reject our changes. This is why single player hacks often don’t work in multiplayer.

Other related articles
Found an error?
If you find an error, take a screenshot and send it to the bot.