Game Development Patterns and Architectures in JavaScript

Rate this content

In the realm of game development, the right architecture and design patterns can make all the difference. This session delves into the world of game development patterns and architectures in JavaScript, offering a comprehensive exploration of the techniques and strategies used to create engaging and well-structured games.

28 min
28 Sep, 2023

Video Summary and Transcription

Today's Talk covers game design and architecture, including entity component systems, game loops, and decoupling game logic from rendering. Entity component systems are popular in JavaScript game development for representing games as entities and their components as behavior on data. Game loops control the flow of the game and updating its state, with different architectures like fixed time step and variable time step. Decoupling game logic from rendering improves performance and flexibility, allowing for independent updates and easy addition of new features. Having a clear separation of concerns in game development improves performance, increases flexibility, and makes debugging easier.

Available in Español

1. Introduction to Game Design and Architecture

Short description:

Hi, everyone! Today, I'm going to be walking you through game design and architecture. We will cover common patterns and architectures in game development, including entity component systems, game loops, and decoupling game logic from rendering. Let's start with entity component system, which is a popular pattern for game development. It represents games as entities and their components as behavior on data. Using the analogy of building a car with Lego blocks, the components represent different parts, and the entity is the assembled car. In JavaScript game development, entity component systems are essential.

Hi, everyone, thank you so much for coming to my talk today. My name is Olayinka Atobele and today I'm going to be walking you through game design and architecture. Before we start, I would like to give you a brief introduction of who I am. I'm a student of computer engineering at the University of Lagos. I'm also a software engineer, a technical writer, a GitHub campus expert. I'm very passionate about diversity and inclusion in tech. Basically, I organise events and programmes targeted towards that.

Today, we are going to be speaking about game development patterns and architecture in JavaScript. I'm basically going to be introducing us to some common patterns and architectures that can help us speed up game development in JavaScript.

So, what exactly are game developments, patterns, and architectures? So, they are basically reasonable solutions that you can use to solve some common problems that we face in game development. Game development can easily get bulky, and especially as you scale up your games, as your games become bigger and more powerful, it can get very easy for it to become more difficult to maintain, more difficult to expand or extend its features. Basically, what having good patterns and architectures does is that it helps you make your code more modular, more maintainable, more extensible and in the long run, you could even improve the performance of your game, how well it performs, how well users are able to interact with your games and how scalable it is, how easy it is for you to add other features or even on board new resources to your games.

So, why is it important? Like I mentioned earlier, game development is a complex task. It is challenging. It can easily get complex. Patterns and architectures, having good patterns and architectures in place will help you simplify the process of developing the games and will also help make managing the game more manageable. Also, it could even help you prevent some common mistakes, you know, having some bugs in your games.

So, what are we going to cover in this talk? So, we are going to start with...we're basically going to be covering some common and important patterns in game development. So, we are going to be talking about entity component systems, ECS, then we are going to speak about game loops, then we are going to be talking about decoupling, you know, game logic from rendering. So, now let's start with entity component system.

So, entity component system, ECS, is basically a popular pattern for game development. So, entity component system is a software architectural pattern that represents game as entities and their components as behavior on data. So, this had just big words, so just to break it down, I'm going to use an analogy. So, let's assume that, you know, a lot of us are probably familiar with Lego games, the Lego blocks, so let's assume that you are building a car with a Lego block, right, so you are probably going to have the wheels, the wheels, the steering, the body, all of those different parts, all of those different components, are going to be your components. So, basically, they just represent, you know, the behavior, it just represents, like, a particular part, like your data of your entire game, right, so your entire game and, basically, entities are just a collection of the components. So, when, let's say, you finish, you know, assembling all your different Lego blocks and you have a car. So, in that situation, like, where your car, which is basically, like, you know, a collection of the different components is basically, like, in this case, your entity, so, because it's just, like, you're assembling different components together, right. So, your different components that, basically, like, represent a behavior, like a particular data of your components, right. So, they basically just represent, you know, one single, you know, piece, so, like, one single data, one single behavior, and then your entity is basically, you know, a collection of some different components that, you know, maybe represent, like, a particular entity, a particular object in your game. So, just now to bring it back to game developments in the in the world of JavaScript, so, let's assume that you are building, let's say, a video game, right.

2. Exploring Entity Component System (ECS)

Short description:

In game development, entities represent objects in the game, while components are the data attached to entities. Systems are collections of entities and components that perform specific tasks. ECS promotes code reuse, supports efficient data access, and enables easy scalability. Entities are created and destroyed at runtime, and systems are updated regularly. ECS is popular because it separates behavior and data, making code more manageable. Code example: position and velocity components with a movement system.

In your video game, maybe you have a car that is moving or something. In that case, let's say, your car is going to have, you know, velocity, the speed, right, you're going to have a speed, you're going to have a position, like, where your car currently is at. All those two things are kind of your components, right, your velocity and your position, they are components. But the car itself, which is, you know, going to be like, you know, a certain car is going to have a velocity, is going to have a position, is going to have a color, the car itself is going to be an entity, because it's basically just, you know, a collection of different components brought together. So basically, that is the main concept behind ECS.

We basically want to separate, you know, different, you want to separate the different behavior and data in your games into components. And in that way, it is easy for you to, it is basically easy for you to, you know, pick any components that you need. You know, when building like an entity or to bring it down an object in your game, it's easy for you to, you know, just pick different components, you know, as part of the entities. And you basically like, you know, built a new, you know, a new object to your game, like straight out of the box. So, and basically, entities are unique identifiers, like I mentioned, and components are just data that are attached to the entities.

Now talking about systems, systems are on the other hand, is basically just a collection of entities and components that perform a specific task. So, just to, again, using that analogy. So, let's assume that in a situation where you have maybe, you want to perform a task, let's say in the case of a video game, right, where you have like a car, your video game and you want to basically, let's say, move the car. So, in that situation, the only component that you really need to perform that task is, let's say, position and velocity, right? So, in this case, you probably don't have any interest in, you know, maybe the colour of the car or how big the car is because they don't affect the particular task that you want to perform at that particular time, right? So, basically, what the system does is they are basically just like, sort of, functions that help you, like, separate, like, specific tasks and the certain components that are related for you to actually perform the task. And, basically, in the long run, what it just does is it makes it easier for you to, you know, manage your code, makes your code, like, more manageable.

So, and how, basically, how does ECS work? So, entities are created and destroyed at runtime by your game engine. So, entities are basically just objects in your games. You add components, your game engine adds, you know, or removes components from it at runtime. That is from your entities, right? And then your systems are updated at regular, you know, intervals, you know, depending on the operations that you perform or that the user performs within the games. So, why is ECS such a popular, you know, it's a very popular game development architecture, right? And why is that so? It is a good choice for game development because one, it promotes code reuse, right? I mean, like we explained earlier, you have, you know, specifically defined components, which means, like, you can easily grab a component and attach it to different entities, actually, not just one type of entities. You can you can easily create a modified game object. Like, basically, all you have to do is just, you know, you define game entity and just create a new one, attach some component to it. And it can also help to support efficient data access, just like, you know, separation of, like, all your data into well-defined components. And it can easily be scaled, you know, as your game gets bigger, you can easily scale it.

Just to add, like, a little code example, just to put some sense into what I've been talking about so far. So, in this example here, you can see you have, you have a position component, you have a velocity component. And your position component, you can see, like, basically, you just have your X and Y axis, right? And your velocity component, as well, you have your X and Y axis. And then you have your movement system. And those, okay, just going back. The components, like, you see, they basically, I'm not doing anything besides just representing a component.

3. Game Loops and Inputs

Short description:

A particular data in your game, and if you look at your movement system, that is basically just moving an entity. It's calling the components it needs, like position and velocity. Game Loops are used in almost every game, controlling the flow of the game and updating its state. The steps in a Game Loop include inputs, updates, and rendering.

A particular data in your game, and if you look at your movement system, so, basically, that is basically just moving an entity. So, it's basically just, and all it's doing is calling the components that it needs to actually perform the specific task, which is moving. So, it's basically just calling position and velocity. So, basically, this is just a small example of ECX in code.

Moving on to another very interesting pattern in game development, which is Game Loops, the art of every game. So, it is called the art of every game because, basically, it is used in literally almost every game that you would develop, right? And so, basically, what does Game Loop? So, you imagine if you are playing, let's say a game of tag, where you basically repeat some sequences again and again. That's basically Game Loop. So, it is basically a repeating sequence of instruction that controls the flow of the game. And literally, in almost all of the games that you play, that is what you do. You do something, you know, something happens on your screen. Then, at some point, whether immediately or later on in the game, you do the same thing again. So, that is literally what Game Loop is. And it is responsible for updating the state of your game, for re-rendering your game, and for handling inputs from the player of the game.

Game Loop basically consists of different steps. So, the first step is inputs. So, for example, let's assume that I'm playing a video game. Again, where, let's say, I have a car that is moving on the screen, and to move the car, I have to press a key on my keyboard. Let's say, maybe, M for move. I press M. In that situation, that is an input, right? The game is basically getting an input from me. And the next step is updates. So, depending on what I have pressed, I'm pressing in this analogy that we are currently using of the video game. So, I'm pressing M. The game receives the M key from me. And as soon as it receives the inputs from me, it knows that it has to, you know, update the state of the game. In this case, that is probably the position, right? So, that is the next step that happens, updates. The next step that happens is render. So, I've, you know, updated something in my game. So, I've updated the game state. So, the next thing is, for the game itself to render, you know, change what I'm seeing on the screen or maybe move the car from the current position to the new updated position.

4. Game Loop Architectures

Short description:

In game development, there are different architectures for game loops. Fixed time step architecture uses a fixed amount of time for each iteration, while variable time step allows the time to change. The most used architecture combines both approaches. A code example follows the mentioned steps: getting player inputs, updating the game state, rendering the game, and sleeping before starting over.

And then sleep, right? Like, basically, you wait for some time for, you know, the loop starts again and again, right? So, that is basically the whole idea of a game loop. And then in building a game that involves the use of game loops, you have some different architecture that you use. So, one of the architecture, fixed time step architecture. So, that basically means that if we go back to this where we talked about, you know, sleep and the number, and the amount of time that you wait before the next iteration of a loop. So, in fixed time step, the architecture basically uses a fixed amount of time for each iteration. So, that means that it sleeps well. You know, it's specified time, a fixed time before it starts the next iteration each time for all the iterations. And variable time step means that it allows the time to change for each iteration. And that could vary. It could vary depending on um maybe what your user types. It could vary depending on maybe the position of objects within the game and several other factors. And the third architecture, which is my opinion, probably the most used one, is basically, so this basically just combines both of the two architectures that we talked about earlier. So depending on the situation of the game and the kind of logic behind the game, basically, the time between each iteration would either be fixed or it could vary. So yeah, just a small code example. So you could in this example, you are getting, it's basically following the steps that we've mentioned, right. You are getting a player's inputs. You're updating the game state based on the inputs. Then you're rendering the game. Then you sleep, then, you know, start over again.

5. Decoupling Game Logic from Rendering

Short description:

Decoupling game logic from rendering improves performance and flexibility. Game logic and rendering are two different things. Decoupling them improves performance and flexibility. It can be achieved through separate threads for logic and rendering, passing messages between them, and using a component-based approach. Decoupling game logic from rendering improves performance and allows for independent updates. It also enables changing the appearance without affecting the logic.

So, so now next, another architecture, another design pattern that we are going to be speaking about is decoupling game logic from rendering, which is a pattern that basically helps you achieve better performance and flexibility in your game.

Okay. So why is it important to decouple game logic from rendering? So basically game logic and rendering are two different things, right? So there are some behind the scene code that represents what you see on the screen. So behind the screen you have some particular information that you are changing based on the user's action, right? So using the example of the video game that we have been speaking about, so you could have your position, you have your speed, and in this sense like when the user performs an action you are updating this based on the user's action, right? So that is the game logic, but and on the other hand basically what the user just sees on their screen is just the car moving the car in a particular position, so that is rendering. And those are two, you know, two different things, right? Because game logic is basically concerned with the rules of the game, the behavior of the game, how you change, how data is updated within the game, while rendering is, you know, mostly about, you know, how you actually display or render these games on the screen, and then when you decouple those, right, when you sort of like, make these two concerns separate what you do is you improve the performance and flexibility of your game.

So basically how can it be achieved, right? So, a way that this can be achieved is that, so before we even speak about how it can be achieved, just to give like, more background on, just to give like, more background on how helpful decoupling the two games can be, right? So let's assume, analogy again, oh, let's use an analogy again, so let's assume that you are playing a game where, let's say you are running in a forest, right? So in that kind of situation, what you see is, the forest with the leaves, the color of the leaves and everything, right? And then, on the other hand, which is rendering, right? Which is the game rendering. And on the other hand, you have the logic, which is basically, some behind the scene information on maybe how you move within the forest and everything. And basically what that does, what's, you know, separating these two things does is that you could easily change, let's say, how your game looks without necessarily changing, affecting how your game operates, if that makes sense, right? So, let's assume that, I want to change, maybe initially I was building my forest with the assumption that it's summer, right? Or maybe later on in the game, I'm like, oh, I want to change the colour of my leaves in the forest. I want to make it seem like they're falling. I want to make it look like it's fall, for example. So, in that situation, you are basically changing the look of your game, but you are not necessarily changing the logic behind the game or the rules behind the game. So, in that sort of situation, having, you know, clear separation of your rendering and your clear separation of your rendering and your logic is going to be helpful because that means that in that situation, all you just need to do is go to the particular part of your code that focuses on the rendering rights. You don't need to change anything that has to do with logic. And this is going to make development a lot easier for you, a lot more maintainable. How can it be achieved? The way it can be achieved is that you have a separate trade for the game logic, you have a separate trade for your game rendering, and basically even this in itself, having a separate trade is going to even improve the efficiency, the performance of your game, because that means none of them need to wait for each other to perform the task. You can be updating the logic of your game regardless of what is currently being rendered on your screen or to the user to see in your game. So basically, using a separate trade for your logic and your rendering is a way that you can achieve this decoupling mechanism. So another way that you could do it is that you could have maybe a system that passes messages between the game logic and the rendering engine. So you could have some way of passing information between these two separate parts of the game. But even though they are separate, you still need them to work together. You still need your rendering engine to get some information about the particular state of the game, which is the game logic. So basically that is what you mean by having a system between them that basically passes information between the two parts of your game. And then also you could have a component-based to represent the game object. And this is in a way, this is similar to the ECS that we talked about earlier, where we have a component to represent the different details of a game, and then you bring together different components to actually represent objects within your game. And this is sort of like, you know, telling you how each of these game patterns are not, you know, necessarily like separate. All of them sort of, like, walk hand to hand with each other to, you know, give you like more maintainable code, more maintainable way of actually working within your game development process.

So, what are the benefits of decoupling game logic from rendering? So, we've sort of touched briefly about some of the benefits earlier. So, the best, the first, sorry, the first benefit is that it improves the performance of your game. So, like I mentioned earlier, you know, having, like, different traits for your logic, for your rendering, decoupling these two things essentially is going to help you improve performance because each of them are able to, you know, run independently of each other. So, you could, you know, be, or you could be updating the logic of your game, you know, that's like the state of your game, you know, without having to worry about, you know, how the game looks to the user, right? And on the other hand as well, you could, you know, you could be changing, like, the position or the appearance of your game without necessarily, like, you know, having to worry, like, each having to worry about, you know, the logic, like, what is going on behind the scene.

6. Benefits of Separation of Concerns

Short description:

Having a clear separation of concerns improves game performance and increases flexibility. It allows for easy addition of new features without impacting performance or appearance. Debugging becomes easier as logic and rendering are separated. Example: separate functions for updating the game and rendering it, demonstrating the separation of concerns.

So, having, like, this clear separation of concerns is going to, like, improve the performance of the game. The next thing is, it's going to increase flexibility, so it would help you to make your game more flexible because you are basically able to, maybe, you know, add a new feature, add a new state to your game without even worrying much about, you know, changing the performance, changing the appearance of the game. Like I mentioned earlier using the, you know, forest analogy, you could easily, you know, maybe add a new, I don't know, maybe a new tree to your forest without thinking much about, oh, how is this going to change how my player moves within the forest. Because in that situation, those two things are, you know, separated from each other, right? And it is also going to help you easily debug your game, right? So, you know, if you are facing a situation where, you know, maybe the player is not..maybe the game is not..the logic is not, you know, changing as you want it to, right? So, you could, you know, just focus on one thing, right? You are able to just focus on, you know, just the game logic part of it without necessarily touching the..without necessarily touching the occurrence part of it. And what that is going to do is it is going to easy for you to debug your games. So, just another gimmick. Another code example of of that. So, you could see in this example, you have, you know, different function. You have a function for updating your game. You have a different one for rendering the game, right? And, each and each of them are basically separated from each other. And, you know, just to circle back to our earlier explanation of the game loop. So, you can see that the game loop is getting the input. Then you are updating the game logic. Then you are rendering the game. So, this sort of like separates, like, each of the concerns. So, you have a function that is basically just concerned about, you know, how the game looks on the screen. And you have one that is, all it is basically concerned with is how your player moves within the game. So, yeah.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Top Content
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
React Advanced Conference 2022React Advanced Conference 2022
29 min
Understanding React’s Fiber Architecture
Top Content
We've heard a lot about React's Fiber Architecture, but it feels like few of us understand it in depth (or have the time to). In this talk, Tejas will go over his best attempt at understanding Fiber (reviewed by other experts), and present it in an 'explain-like-I'm-five years old' way.
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
Top Content
JavaScript in the browser runs many times faster than it did two decades ago. And that happened because the browser vendors spent that time working on intensive performance optimizations in their JavaScript engines.Because of this optimization work, JavaScript is now running in many places besides the browser. But there are still some environments where the JS engines can’t apply those optimizations in the right way to make things fast.We’re working to solve this, beginning a whole new wave of JavaScript optimization work. We’re improving JavaScript performance for entirely different environments, where different rules apply. And this is possible because of WebAssembly. In this talk, I'll explain how this all works and what's coming next.
React Summit 2023React Summit 2023
24 min
Debugging JS
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.

Workshops on related topic

DevOps.js Conf 2024DevOps.js Conf 2024
163 min
AI on Demand: Serverless AI
Featured WorkshopFree
In this workshop, we discuss the merits of serverless architecture and how it can be applied to the AI space. We'll explore options around building serverless RAG applications for a more lambda-esque approach to AI. Next, we'll get hands on and build a sample CRUD app that allows you to store information and query it using an LLM with Workers AI, Vectorize, D1, and Cloudflare Workers.
JSNation 2023JSNation 2023
116 min
Make a Game With PlayCanvas in 2 Hours
Featured WorkshopFree
In this workshop, we’ll build a game using the PlayCanvas WebGL engine from start to finish. From development to publishing, we’ll cover the most crucial features such as scripting, UI creation and much more.
Table of the content:- Introduction- Intro to PlayCanvas- What we will be building- Adding a character model and animation- Making the character move with scripts- 'Fake' running- Adding obstacles- Detecting collisions- Adding a score counter- Game over and restarting- Wrap up!- Questions
Workshop levelFamiliarity with game engines and game development aspects is recommended, but not required.
React Day Berlin 2022React Day Berlin 2022
86 min
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
Top Content
Using a library might seem easy at first glance, but how do you choose the right library? How do you upgrade an existing one? And how do you wade through the documentation to find what you want?
In this workshop, we’ll discuss all these finer points while going through a general example of building a code editor using CodeMirror in React. All while sharing some of the nuances our team learned about using this library and some problems we encountered.
JS GameDev Summit 2022JS GameDev Summit 2022
121 min
PlayCanvas End-to-End : the quick version
Top Content
In this workshop, we’ll build a complete game using the PlayCanvas engine while learning the best practices for project management. From development to publishing, we’ll cover the most crucial features such as asset management, scripting, audio, debugging, and much more.
TestJS Summit - January, 2021TestJS Summit - January, 2021
173 min
Testing Web Applications Using Cypress
This workshop will teach you the basics of writing useful end-to-end tests using Cypress Test Runner.
We will cover writing tests, covering every application feature, structuring tests, intercepting network requests, and setting up the backend data.
Anyone who knows JavaScript programming language and has NPM installed would be able to follow along.
Node Congress 2023Node Congress 2023
63 min
0 to Auth in an Hour Using NodeJS SDK
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool.
We will enhance a full-stack JS application (Node.JS backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session for subsequent client requests, validating / refreshing sessions
At the end of the workshop, we will also touch on another approach to code authentication using frontend Descope Flows (drag-and-drop workflows), while keeping only session validation in the backend. With this, we will also show how easy it is to enable biometrics and other passwordless authentication methods.
Table of contents- A quick intro to core authentication concepts- Coding- Why passwordless matters
Prerequisites- IDE for your choice- Node 18 or higher