Code a DOOM-like game engine from scratch in C [PART I]

  Рет қаралды 19,144

The Old School Coder

The Old School Coder

Ай бұрын

This is part I of the DOOM-like game engine from scratch tutorial.
It introduces the basics of 2.5D (Pseudo-3D) graphics rendering and movement mechanics. Also concepts such as portals, rendering, world transformations, and others.
You can download the source code from here: github.com/jeuxdemains/DOOM-l...
Some notes to keep in mind about Part I:
- we do the minimal required work to get started
- code style is not really the focus here
- back-to-front rendering (i.e. Painter's algorithm) is a bad idea, it will be revisited in Part II
- sorting sectors by their centroids with bubble sort is very inefficient and lacks precision -- it's there just to leave you with a bit more compete solution until part II comes out
www: yuriygeorgiev.com
twitter: x.com/georgievyuriy
fb: / yuriydevlogs
For more advanced topics and complete courses by a professional lecturer, you can take a look at Pikuma's lectures at pikuma.com

Пікірлер: 102
@ethanevans8909
@ethanevans8909 28 күн бұрын
Its so annoying how many tutorials there are for "doom renderers" when they're actually about raycasting. Thank you for this wonderful explanation
@pikuma
@pikuma 29 күн бұрын
I usually don't like videos that are fast typed. But for some reason yours is actually nice. Great one!
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
🙇 thank you!
@1b2m
@1b2m 27 күн бұрын
Good effort, but to me it seems rushed. Not because of the fast pace, but because it seems like you have the finished code open on a second screen, and you're just copying what's written in those other files, like including a block of headers that don't even exist yet, typing down data structures that weren't needed or explained yet. It's a great way to show off that "you did it", but it's not good teaching. Good teaching would be to go through the project step by step, hit a proverbial wall, discuss the solution and implement it, then continue until the next wall. Not just provide all the solutions without context, and then never hit a wall in the rest of the project.
@Zedv.0.0.1
@Zedv.0.0.1 28 күн бұрын
I'm learning C at the moment, this is what i want to do when i have experience
@jeffreyshaffer3076
@jeffreyshaffer3076 29 күн бұрын
Really excited for this one -- long live C!
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
long live C, amen! :)
@ziondhill
@ziondhill 28 күн бұрын
I've been hoping for a good tutorial series like this, looking forward to the next part!
@acatisfinetoo3018
@acatisfinetoo3018 27 күн бұрын
I am so glad you are writting this in C...easy to follow and intuitive is what i look for in these programming videos😉
@TheOldSchoolCoder
@TheOldSchoolCoder 27 күн бұрын
I do it for my own health sake! :D
@cariyaputta
@cariyaputta 28 күн бұрын
Amazing series ahead, look forward to its completion.
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
Glad you enjoy it!
@hamedrezaeec
@hamedrezaeec 25 күн бұрын
Superb, Looking forward for the next part. 👌
@DeepRockLabs
@DeepRockLabs 28 күн бұрын
Goated, I am gonna try and follow along with ZIG.
@Nashadelicable
@Nashadelicable 27 күн бұрын
Came here from Facebook, love the video!
@martian0x80
@martian0x80 29 күн бұрын
Thanks, will be following along in rust or zig.
@madPL1239
@madPL1239 28 күн бұрын
Greak work. I wait for next parts. Thanks:)))
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
already planning part 2. smile!
@onaecO
@onaecO 29 күн бұрын
Beautiful!
@gnoooo
@gnoooo 29 күн бұрын
Nice! This looks like a cool project to improve my C skills with! I work in infosec and my C experience is basically limited to Winapi stuff around malware development and reverse engineering. Never created any code that did display anything. Looking forward to code along 🤩 Subscribed to your channel, looking forward for more of this
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
win32api is actually fun (IMO). I used to do quite a lot of reverse engineering myself when I was younger. It's a really exciting field to explore. I remember I patched my IsDebuggerPresent() in kernel32.dll to always return false on my Win98 computer. It was the way to go with SoftIce at that time. :D
@gnoooo
@gnoooo 29 күн бұрын
@@TheOldSchoolCoder not saying win32api is not fun. quite the opposite actually, i like my job a lot and i get to find funny ways of running shellcode and i learn new stuff about evading detections and detecting other peoples code but it is a very niche area. And my entire C career evolves around that topic. So I am very happy to broaden my C skills a bit with content like the video you created here. Good stuff :)
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
thanks! you have a very interesting occupation. :) back in the days I was giving everything to get a job on such area.
@zxenon555
@zxenon555 20 күн бұрын
Waiting for the continuation of this series! Hope you keep doing more C related stuff, it's great to be able to learn through this type of videos. Буду силно ждать за следуший видеос, надеюсь ты продолшаешь с болшем С видеос. Мой русский язык ещё бедний :p, надо ещё занимать.
@TheOldSchoolCoder
@TheOldSchoolCoder 20 күн бұрын
I’m already working on part II and coding a level editor meanwhile. I’m sorry, I don’t understand the last part. It’s just my name that’s russian but I don’t speak russian. :) I’m glad you liked the tutorial!
@nucknine
@nucknine 28 күн бұрын
Cool! Thank you!
@sebastianemanuelsson7846
@sebastianemanuelsson7846 29 күн бұрын
heck yes, subscribed!
@hanakun
@hanakun 27 күн бұрын
I found this tutorial in the post you put on the fb group. I hate when people put stuff that turns out bad, but this is actually gold. Thank you for this.
@warwolt
@warwolt 29 күн бұрын
Nice video. I think for future videos it's better to introduce some code and data structures at a time and explain them, right now everything's added up front which makes it more difficult to see what's going on
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
Totally agree with you. I noticed that after I watched it from start to end after I finished editing it. Will try better next time. Thanks for the remark!
@7etsuo.c
@7etsuo.c 29 күн бұрын
Love this!
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
thanks!
@eversonmay
@eversonmay 27 күн бұрын
I wanna see all this series of videos
@santitabnavascues8673
@santitabnavascues8673 28 күн бұрын
You can save the square root of the distance when sorting the sectors, the square of the distances is still valid, and is less costly 🙂👍
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 28 күн бұрын
I did not see the video, but doom checks if the camera is in front or in the back of a plane. There is no “distance”.
@santitabnavascues8673
@santitabnavascues8673 27 күн бұрын
@@ArneChristianRosenfeldt Yeah, the BSP traversal sorts the sectors for you, but this has no bsp, so the sorting step is necessary
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 27 күн бұрын
@@santitabnavascues8673 just, you can’t sort polygons perfectly. Id software never likes glitches. Others used scanline rendering (Pixar Gameboy Advanced). Quake has span buffer and z buffer. PS1 has this hardware interface, but for a pure software renderer I don’t understand why we should paint back to front. With PS1 I like how they decided to use many small triangles. These are like a point cloud and can easily be sorted. And you only need affine texture mapping on them. And with the known “granularity”, the SDK uses super fast bucket sort. The worst rendere is Elite2 . Elite1 has convex objects and sorts them by z. Elite2 has complex space ships, and forced the modellers to come up with an order!?
@jackcurrie4805
@jackcurrie4805 26 күн бұрын
This owns, will be following along 🫡
@InvestorFIRE
@InvestorFIRE 28 күн бұрын
Жду продолжение !
@samllea1
@samllea1 29 күн бұрын
i wish this was in C#, good job though :DDD
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
haha, I hope someone with skills in C# will port it. I’m not good with managed languages except for python probably.
@hiimdaisy946
@hiimdaisy946 29 күн бұрын
This is good for beginners? Cause I would love to create my own doom clone from scratch. So I just follow along?
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
I believe it's very accessible to newcomers. All you need is GCC or any other C compiler and follow along. Also the complete source code of this tutorial is available on github. Link in the video description.
@pedroalvesvalentim7652
@pedroalvesvalentim7652 29 күн бұрын
I think it would depend on what you're a beginner in. If you're unfamiliar with programming, for example, I'd think this is a rather harsh experience 😂
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
@@pedroalvesvalentim7652 :D
@jokesterthemighty227
@jokesterthemighty227 29 күн бұрын
Noice
@errandam6219
@errandam6219 17 күн бұрын
when Ι try to load more than 6-7 sectors obj the program breaks. Ιn this is the cpu responsible or Ι wrote something wrong?
@TheOldSchoolCoder
@TheOldSchoolCoder 17 күн бұрын
I can't tell without seeing the code. As long as your arrays are big enough and you're addressing pointers and other vars properly, everything should be okay.
@darthtrex9356
@darthtrex9356 29 күн бұрын
Didn't @tsoding do this in typescript
@gadsgadsx
@gadsgadsx 24 күн бұрын
Does this can be followed on windows? All the initial commands for the setup were used in Linux. I found it kinda hard to understand if its possible to setup on windows
@TheOldSchoolCoder
@TheOldSchoolCoder 24 күн бұрын
Windows project initialization is coming soon.
@kennethrapp1379
@kennethrapp1379 24 күн бұрын
I'm doing it in Windows using CMake and VS. Get the SDL2-developer binaries for VS or MingWin and just link it like any other library.
@mitaskeledzija6269
@mitaskeledzija6269 26 күн бұрын
can u add members system and have custom vids and longer for coding, I wanna get to know deep into C so i can understand syntax for other languages and also practice my dexterity haha
@TheOldSchoolCoder
@TheOldSchoolCoder 26 күн бұрын
you mean like patreon or similar where the non-edited raw material could be available?
@gsdcow
@gsdcow 29 күн бұрын
Can I request KZbin automatic translation? It's difficult because I'm not a native English speaker. I'm really interested in it, so I'd like you to add it!
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
sure thing!
@mutantleg
@mutantleg 29 күн бұрын
this is the second doom like engine I see where the sectors are 'additive' (you seem to add stuff into empty space instead of carving out caves) - I wonder what is the benefit of this approach compared to what doom and build used? 🤔
@TheOldSchoolCoder
@TheOldSchoolCoder 29 күн бұрын
You're absolutely right. The player should be able to walk inside the sectors and not watching them from outside like in this tutorial. It's a matter of the way the rasterization works. And more specifically how we define a "back-facing" wall. To make a sector to appear as a room, we just need to flip the A and B points when rasterizing. Essentially not rasterizing the faces outside the sector but inside it. However, as a start I wanted to just construct a basic geometry and render it, I didn't take into account the way the rooms should be constructed. In fact, we have no rooms here. Just objects in space. That's a good catch! Thanks!
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 28 күн бұрын
BSP supports solids. Leaf nodes are either empty or filled. There is neither add nor sub.
@mutantleg
@mutantleg 28 күн бұрын
@@ArneChristianRosenfeldt take it easy .. how bsp got into the picture anyway 🤔
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
😀I guess it's my fault. I had to mention that this will be a very basic part and we won't deal with spatial partitioning or sector splitting, etc. It's out of my capabilities to do everything in one video. I also believe excessive information could be a deal breaker sometimes. It should be provided in a proper cadence.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 27 күн бұрын
@@TheOldSchoolCoder maybe give the part a descriptive name ? I just had a minute while my computer was blocked. Then I don’t have premium and skimmed the comments.
@user-yi9yk8dg3z
@user-yi9yk8dg3z 26 күн бұрын
it maybe was a perfect video if there was subtitles :)
@gpt-10
@gpt-10 16 күн бұрын
when the part 2?
@TheOldSchoolCoder
@TheOldSchoolCoder 16 күн бұрын
not sure. I'm currently working on a CAD-like level editor that will help me with building more complex maps.
@BERNOUSSAMA
@BERNOUSSAMA 20 күн бұрын
does doom like mean raytracing?
@TheOldSchoolCoder
@TheOldSchoolCoder 20 күн бұрын
No, ray tracing is physically based rendering (realistic materials, shading, lighting etc.). DOOM-like in the context of this tutorial series means a polygon renderer.
@sisqobmx
@sisqobmx 28 күн бұрын
why raycasting instead of actual 3d?
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
we do not cast rays in this tutorial. however, I see what you mean. I decided that there is enough information about 3D already, yet the topic of pseudo-3D can benefit of one more tutorial.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 28 күн бұрын
How do you do occlusion culling in 3d? Portals out difficult constraints on the level design. Occluders need strange heuristics. So : hierarchical z-buffer and bounding volume hierarchy. Turns out that these use very similar data structures as doom: column run length compressed z buffer and BSP . So solve the difficult part in 2.5 d and upgrade later. Learn that rounding is evil ! PS1 wobble invalidates bounding volumes.
@Kitulous
@Kitulous 28 күн бұрын
because that's how some games were made in the 90s. raycasting was faster on that hardware when the actual 3d support was very limited
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 27 күн бұрын
@@Kitulous raycasting like in Wolfenstein3d does not need a multiplication per vertex nor per column. 8088 already has quite fast (faster than Amiga) MUL as shown in Microsoft Flight Simulator.
@skilz8098
@skilz8098 27 күн бұрын
Having the game's level information hardcoded into the source code is also a naive approach. Anytime you want to change the height of a room, or its position or orientation we have to modify the hardcoded values within the source code, recompile and rebuild it. Instead, it's better to implement a file parser to read in the game's level data, objects, contents, textures, etc. that will need to be parsed. From there, we can automatically create and populate the necessary objects on the fly. This way all we would need to do is make changes to the level file which could be in either text or binary format. Text is easier to visually read and manipulate but harder to write the parser. A binary file scheme is easier to implement the parser, but it's harder to visually read and modify the file. However, and regardless of which type of parser you write, all we need to do to modify the level is make changes to the data in the level file, save it. Then just run the engine. With this there's no longer a need to recompile and rebuild the application.
@kennethrapp1379
@kennethrapp1379 27 күн бұрын
It's perfectly fine to hardcode values in a prototype, which is what this essentially is, rather than add unnecessary complexity. There are also a ton of SDL functions he could be using, including the geometry API, that might be more efficient but wouldn't be as useful for educational purposes.
@skilz8098
@skilz8098 27 күн бұрын
​@@kennethrapp1379 That's true, but from my perspective where I've actually written a 3D Game/Graphics Engine from scratch in C/C++; For the most part I didn't use 3rd party libraries such as SDL. I've written almost all of the underlying functionality, boilerplate code. The same thing with all of the Engine's GUI elements, and even font rendering. All of that was implemented. There were no 3rd party libraries. The only libraries that I did end up using was the things for audio such as OpenAL and Ogg-Vorbis, and things for compression such as zlib, and perhaps for image loading such as the required libraries or dlls for handling tga and png textures. I still wrote the file loaders, and how to interpret the image data to be suitable for my engine's internal data structures. Outside of that, even all of the math functionalities such as vector and matrix operations, integrators, interpolates, and other math class objects were all built from the ground up. The same thing goes for all of the Windows's code including the window's instance and windows class setup code, the event handler, the call back procedures, etc. So, for me, when I read the description of the title that states from scratch and yet I see where a large portion of the core functionality of the engine is hidden below layers of abstraction, I think you might understand where I'm going with this now. File Parsing in general is just as important as the scene graph and or graphics pipeline, rendering units and shader engine. It's just as important as the Physics Engine, the GUI, the Event-Handler - State Machine, Audio Processing, and such. Even with the idea of this only being a prototype, still, to have such a parser implemented, incorporated this early into the design stage would at least for me would be a better approach than waiting until after you have the rest of the engine completed. It doesn't add that much more complexity to add a parser. Sure, the parser itself can become a complex beast of its own, yet the integration and use of that parser into the engine is quite trivial. It also allows and makes any kind of development or testing of that engine to be much simpler and easier to use, debug, and unit test in the long run during the "game development" process. If one has to recompile and rebuild the engine every time you want to change a wall's height by say 0.01 units, or to rotate a candlestick by 1/2 degree. You're going to be spending 100s even 1,000s of unnecessary hours of recompilation just to make a few internal, game specific data - content changes all because you didn't want to add 5% more complexity to the engine from the beginning of the design and production process. This isn't "early optimization". This is planning ahead with the intent to integrate this type of functionality from the foundation and core part of the entire framework. If you wait until you have the entire engine built and let's say you have close to 100k lines of code within your engine and then you decide to add in a parser how much of your engine's internal source code are you going to break by trying to "squeeze" in and fit this parser? Now, consider the design process where you are building both the parser and the engine simultaneously so that as you add more functionality, you are also incorporating that functionality or at least the parts that you want to be handled by your parser. In this second case, the integration, the framework, the interface between the Engine and the parser has already been there since the beginning. Again, for me, this is something that shouldn't be put off or put on the back burner just to try and "reduce" complexity. This should be at a higher priority to be implemented as early as possible. Now at least within the context of this 1st video of just being able to get something rendered to the screen is just fine, just to make sure that the renderer is working as expected. Yet it is at this stage where the file parser for level data should be incorporated into the design process of the project. This would be a good starting point. Here is where the parser should be implemented to get its core basic functionality working that can be expanded upon as the Engine's internal features grow. Then once that is working with the rendering engine - scene graph, from there it would be quite trivial or easy to add newer features into both the engine and the parser such as textures, texture mapping, lighting effects, and other types of transforms, object placements, particle engines, shaders, etc.
@TheOldSchoolCoder
@TheOldSchoolCoder 27 күн бұрын
@@skilz8098 😀
@cvabds
@cvabds 12 күн бұрын
I bet you can't do it on templeOS
@TheOldSchoolCoder
@TheOldSchoolCoder 12 күн бұрын
I did it without an OS on a UEFI: kzbin.info/www/bejne/aXS1p5x3YtSDn9Usi=a--6a5uquC12u34c
@martinvasilev6099
@martinvasilev6099 29 күн бұрын
I disagree that doom is 2.5D. Although the enemies and player and pickups are 2d the rest is fully 3d space.
@chiefcloudyeye0489
@chiefcloudyeye0489 28 күн бұрын
the entities being 2D images has nothing to do with the categorization as 2.5D, it's called that because the "fully 3d space" is actually just an illusion. it's simply a 2D space that has a single height at any point. unlike true 3D, Doom cannot have any rooms go above or below each other. ironically the entities are one of the few things in Doom that are actually 3D as they do track a current height and it can impact the gameplay, for example your shots will only aim up or down to a certain extent, beyond which you will fire straight ahead.
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
the illusion of depth is not achieved the way the real 3D rendering works. we call this pseudo-3D because we do not perform 3D transformations, and we have just two components in our coordinate system -- X and Y (Z is missing). it really looks like 3D when drawn on the screen but the process behind building the frame is different. with other words, it's a technical detail, not how it appears on the screen, therefore the confusion maybe.
@Ehal256
@Ehal256 28 күн бұрын
It's a sort of restricted 3D, not all arbitrary 3D spaces can be represented, but it's clearly not 2D. Plenty of game objects move within the Z axis in doom, not just entities like fireballs and rockets, but also map geometry, like crushers and doors. Vertexes in doom clearly have a Z coordinate, or rather sort of represent two 3D world space coordinates, but the two Z coordinates are stored in the sector floor and ceiling height fields, and would be redundant to store per-vertex.
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
Very well said! We simply have an X and Y coordinates of each line segment (wall) on the map. If we simply render that we will get a line on the screen. Therefore, we clone this line and use a predefined height of the sector to displace the cloned horizontal line vertically, essentially pushing it upwards on the screen Y axis. This happens in screen-space coordinate system. To achieve a 3D looking picture we simply divide each line segment vertex (or point) by the distance to the player. This distance acts as our Z coordinate essentially. It’s generated on the fly artificially. Thanks for the debate! It’s an interesting topic to discuss.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 28 күн бұрын
Dark Forces has fully 3d Tie fighters in the levels.
@hulakdar
@hulakdar 28 күн бұрын
we don't work in 3d, 5 seconds later, elevation and height 🤣🤣
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
elevation and height are just numbers stored in the sector. they later help us define at which vertical pixel to start drawing. that's all. we do not perform any 3D transformations.
@ArneChristianRosenfeldt
@ArneChristianRosenfeldt 28 күн бұрын
I want a 3d BSP made of walls and floors for stacked sectors .
@watercat1248
@watercat1248 28 күн бұрын
Taknly speaking all the 3D stuff the screen shows it fake 3D no matter you use 3 axis or not seens the monitor have X and Y axis 😅. In the end it doesn't matter if the 3D is real or not what is matter is the final results.
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
totally agree with you.
@raigneier6266
@raigneier6266 27 күн бұрын
HAIGH
@3idet
@3idet 28 күн бұрын
The background music is very distractring besides the great content.
@TheOldSchoolCoder
@TheOldSchoolCoder 28 күн бұрын
thanks for the remark. I'll take that into account for Part II
4 Months of Game Programming With My Own Engine
21:30
jdh
Рет қаралды 430 М.
1,000 Diamonds! (Funny Minecraft Animation) #shorts #cartoon
00:31
toonz CRAFT
Рет қаралды 38 МЛН
路飞太过分了,自己游泳。#海贼王#路飞
00:28
路飞与唐舞桐
Рет қаралды 35 МЛН
The Basics and Fundamentals of Doom Mapping
11:34
Readyon
Рет қаралды 18 М.
WHY did this C++ code FAIL?
38:10
The Cherno
Рет қаралды 239 М.
Why Doom is Awesome: Binary Space Partitioning
26:25
ShreddedNerd
Рет қаралды 1 МЛН
What is the Smallest Possible .EXE?
17:57
Inkbox
Рет қаралды 329 М.
I Made Doom in Scratch
9:12
UsmanDev
Рет қаралды 26 М.
Voxel Space (Comanche Terrain Rendering)
2:43:36
pikuma
Рет қаралды 25 М.
I made an entire OS that only runs Tetris
22:37
jdh
Рет қаралды 1,6 МЛН
I Optimised My Game Engine Up To 12000 FPS
11:58
Vercidium
Рет қаралды 612 М.
Blazingly Fast Greedy Mesher - Voxel Engine Optimizations
23:35
НОВЫЕ ФЕЙК iPHONE 🤯 #iphone
0:37
ALSER kz
Рет қаралды 349 М.
Todos os modelos de smartphone
0:20
Spider Slack
Рет қаралды 64 МЛН