Welcome to a unique C programming course that goes beyond traditional textbased terminal tutorials to focus on direct pixel manipulation and graphics. By leveraging the crossplatform power of the SDL3 library, you will learn how to safely bypass modern operating system restrictions to create and manage a low-level frame buffer. This hands-on approach demystifies how computers handle memory, giving you direct control over painting pixels to the screen, just like developers did in the classic MS DOS era. Whether you want to deeply understand CPU architecture or build a solid foundation for game engines, this visual method makes mastering C both practical and incredibly engaging. Hello everyone, welcome. My name is Gustavo Patsy and today as you just saw, we're going to do something a little bit different than what we are used to here at Free Code Camp, right? We're going to go a little bit more low. Look, C is one of my favorite programming languages. But to be fair, whenever people start learning C, they end up learning things like user, what is your name? User, how old are you? And then you do some computation and then you do some print f the solution. Right? So, it's very textbased. And if you ever went on hacker news or if you ever read a book about C, you know that C is not really popular to work with strings, right? C and C strings, they are not that popular and they have a lot of issues. So, you know what I want to do? I want us to look at C and if you have the basics already from C, right? for loops, variable declaration, while loops. If you know all these if and else these basics of the programming language C, I think a very cool step would be for us to be able to display something on the monitor, right? On our display. So I want us actually to see pixels being painted on the screen. I want to treat my monitor as this 2D grid of pixels and I want to say look I want to go to coordinate position X and Y 10 20 I want to paint that with a color red or I want to go to the first pixel and paint it green. So having this power of accessing the pixels and manipulating pixels with the C programming language, right? Because I think once we have that power, once we understand how to manipulate pixels, then C becomes a very interesting language for us to experiment and get closer to the CPU, to get closer to memory, to get closer, right? get students to be more used to working with memory, understanding how many bits a variable has, understanding uh where in memory are we actually accessing and storing a certain variable, right? C is very good for us to understand how the computer is really working because look if you want to work and display a circle, display a rectangle, draw something, most students end up learning things like JavaScript and using p5 js or processing or learning something in the realm of browsers and JavaScript canvas. I want us to have that power with the C programming language as well, right? Since C is one of my favorite programming language, I have been programming with C for a long long time and C is really powerful. It is the king of performance. And if you are talking about games, game engines, C is still the king, right? It still has the crown for that area as well. So, we are going to take our time. We're going to make this as fun as possible because trust me, the end result and the end power that we're going to get from this lecture is super super cool, right? So, let's just stop for a moment and think about our computer screen, right? If you really think about what's going on in your monitor, we are going to have something which is almost like this 2D matrix, this grid of values which are, if you think about this, our pixels, right? I think it is no surprise that we have pixels in these positions. And we talk about monitor resolution. We have the aspect ratio of the screen. So sometimes you have a full HD monitor. Let's say 1920x 1080 or sometimes you have those old school 640x 480. And then people also talk about the aspect ratio being kind of this 4x3 or 16x9 16x10. I think this MacBook that I have it is 16x10 right the ratio between the width resolution and the height resolution in pixels but let's simplify our life and let's just say that we have a very low resolution let's just say 320 pixels width by 200 pixels height right this resolution right here is no accident this was a very very popular resolution back in the old MS DOS games this used to be called mold 138, right? This was kind of the VGA way of doing things. [clears throat] And the way that that happens was I had 320 pixels by 200, right? So it was this kind of 2D. I can think of it as this 2D grid. And if I wanted to go and if I wanted to have access to a certain pixel in the old MS does days, we had a lot more freedom. I can just go and I could write to a certain memory position and the video driver would understand that memory position and then it will go and paint that color that I wrote in that memory position in the display. So what you will see is we used to think of this 2D grid as what we call a frame buffer. A frame buffer is this mirror in memory of this 2D grid here as well. So it's almost like I'm declaring an array and I'm just saying that it is an array where each position is an unsigned integer of 32 bits. Right? So this is a very C type. We're going to learn about this very soon. So unsigned integers of 32 bits. So each position of this array is an integer of 32 bits. So I'm going to call this array a frame buffer and it is an array of 320 * 200. Right? So I have 320 * 200 positions. Pay attention to how I'm thinking of them as 2D. But really we are talking about a linear a contiguous array of 64,000 positions 64,000 pixels. All good. And what we could do back in the day is we would create a simple function. Let's just say put pixel. Then I just say I want to put a pixel at position 30 60. So these are going to be my x and my y. 30 is the x coordinate and 60 is the y coordinate. So 30 in x column and 60 in y. And I can also specify the hexadesimal of the color that I want. Right? So if you ever work with HTML, CSS, this should be second nature to you, right? It is a hexodimal number where the first two nibbles is the red component. The next one is the green and then the blue. So RGB in this case full red, no green, no blue should be the color full red. And then when I say put pixel, it goes, it writes to our frame buffer at that position 3060. and our VGA display would go and paint that pixel at that coordinate position with the color that we asked for. Super super easy, right? And it was easy because back in the old MS DOS days, accessing the VGA pixels in our 2D rastering, this grid here, accessing those pixels in the old MS DOS days was easily done via mapped memory addresses. So in your memory in your RAM right in your memory you used to have all these addresses and right here on this address a 000000 this was the start of this mapped frame buffer in your memory. So all you had to do is basically say that the frame buffer, this array that you are declaring, you go and you point to this address right here, this is the start of your frame buffer and everything that you write to that frame buffer. This is mapped memory and the VGA driver knows that all this mapped memory right here actually correspond to a certain color in our physical monitor in our screen. Absolutely easy, right? And that is why a lot of people loved MS DOS games and love to code for MS DOS games. Of course, there are some cons as well, right? There were some issues with MS DOS programming, but accessing the display was that easy. But if you think now about modern operating systems and how we do things today, this is illegal. We cannot do that, right? No bueno. This is not allowed. We cannot nowadays have access, right? direct access to these memory positions. I cannot just go and write to these values right here directly and see that result in the screen. Why not? Because I have a shield. I have a protection layer and that protection layer is the operating system, right? Our operating system, right? Most modern operating system, Mac OS, Windows, Linux, FreeBSD, OpenBS SD, they do not let you access these memories and put these values right there directly. We have to protect that, right? Um Jonathan Blow, the creator of uh Braid and Order of the Sinking Star, he used to say that we are living in an era of you cannot just simply do something right with the computer. We always create these protections. we always have to create uh some difficulty in the way that we're doing things. So I cannot just simply paint a pixel on the screen with a modern operating system. I cannot simply save a file without having a manifest. There are so many things that you have to do right and all these protections and all these agreements that we have right this gentleman handshakes that we have to implement they are of course provided a lot by the operating system. So I cannot using the C programming language, right? Just the native C code and my C compiler. I cannot just simply go access a frame buffer and write to memory. The operating system does not let me access the display driver like that. And right here is our first huge problem because if I want to go and paint something in your display on Mac OS or Windows or Linux, if you want to actually go and paint a certain pixel, you need to use specific functions that the operating system API exposes to you. So if I am working on Windows, I have to go and I have to ask Windows. I have to use the Microsoft libraries that goes and know how to ask Windows to go and open a window and then paint that pixel in a certain position. But that is provided by Microsoft, right? Microsoft gives to me these libraries, these header files and all these.H files, these DLS, all these libraries that allows us to go and paint a certain pixel inside a window of the operating system. But this is the big problem because this will only work on Windows and it will only work on Windows let's say 64bits right if it is 32-bit is something else and if you want to go on Mac OS then everything that you know about Microsoft doesn't work anymore now you have to go and use the Apple way of doing things you need to use Objective C and you need to use Cocoa 2D and then you have a lot of lines of code and you include different libraries that only work on Mac OS. And on Linux the same thing right Linux you need a specific set of libraries and instructions because then you have to access let's say if you're using X system is one type of code if you're using Wayand is another type of code right because all these different ways of communicating to the display they are specific to the operating system and the platform and the CPU architecture that we're using and this right here becomes a huge problem not only for you, but for me as well as a professor, because I have to teach a Windows student that is using a Windows computer how it works only on Windows. And then someone else that is using Mac OS, I have to go and show them the Objective C that access the Coco, all those libraries for Mac OS. And then someone that is using Linux, I have to look at the DRO. I have to look at the libraries, how to install those libraries, and then ask, okay, do you want to use X11 or you want to use Wayland? And then I have uh 20 40 lines of code that only works for Windows way, right? That is a huge problem for a pedagogical point of view as well. So we're going to have to find a compromise. I think the best option is for us to use something that gives us what we call more portability in terms of code. I still want to have only one function called let's say put pixel and I want that to work on any operating system on any platform. Can we do that? Yes, we can. So in cases like this, we're going to have to find a bridge between our C code and the actual hardware, right? We're going to have to find a library that knows how to communicate with the specific hardware that we are compiling to our target machine. Regardless if it is uh Linux, Windows, Mac OS, or whatever operating system that you're using, we're going to have to find a library that is what we call a crossplatform library. And I would say that one of the most popular ones is SDL. SDL stands for simple direct media layer. So it is a layer that is going to be here between our C raw code and the hardware that we want to access and SDL is going to expose some functions for us to create a window on the operating system to create a renderer in the operating system to paint a pixel on the operating system. So everything is going to be done by SDL. So the only library that we need to include is SDL. And whenever we compile our code, SDL is super smart and knows exactly what is the target platform that we are trying to compile to. And then it knows and only creates the code behind the scenes for Mac OS or creates the code that works behind the scenes for Windows and Linux and Open SD and FBSD and etc. Right? So you understand SDL is the thing that is going to abstract this hardware access for us in our case the display and graphics but SDL also abstracts things like audio and input joystick mouse so you can use SDL to abstract this hardware access and it is crossplatform right so let me just leave things written down SDL is a crossplatform library that gives C program direct access to common multimedia functionality like graphics, input, and audio without having to write platform specific code. So with SDL, I'm going to go I'm going to include the SDL library and I'm going to use SDL functions and I don't have to go and learn how Windows expect me to do things or how Mac OS expect me to do things or Linux or X window or Wayland. So I don't have to learn this platform specific lines of code and all these functions that are only available in Microsoft or Apple or Windows or Debian. I don't have to learn any of those platform specific stuff. STL is going to do the hard job for me. So do you understand now why it is apparently so hard for people to use graphics with C? Because to start we already have to decide what is the exact platform that we want and what is the target that we're going to use. Because if you're using the browser like JavaScript, it doesn't matter what is the platform, right? You install the browser, you're using Firefox or Chrome, and then you have P5.js, you have the JavaScript canvas, and everything is done inside the browser. But if you're using C, we don't have a browser. We don't have anything. We have direct access to the CPU. We have direct access to the register. We have direct access to the memory of the machine. There is no abstraction layer. There's no browser. There is no browser window CSS HTML there's nothing like that we are talking about CPU instructions CPU metal instruction right C is very very close to the metal so that is why we have to usually talk about specific platforms and talking about specific architectures and specific operating systems this is what we're talking about so now that we know that we have to use SDL we are going to very quickly and very soon learn how to install the libraries SDL in our system. But just to give you already a spoiler of what we're talking about, this is what we're usually going to work with whenever we're talking about SDL. And I am going to use in this course already the latest version which is SDL3. The SDL2 version is really really popular but they released SDL3 not that long ago and they are both very similar. So I can just say after I include SDL I can go to my C program and say include the header right so from SDL3 folder SDL.h H. So I include this header file and then I say SDL_init and this is a function that is going to initialize the SDL multimedia dependencies that I want. In our case, I just want to init the SDL init video. So this is all I'm going to use in our course here. I don't want audio. I don't want anything else. And after I initialize SDL, do you see? I can start using all those SDL functions that are the same regardless of the platform that I'm using. So the first thing that I want to do is I want to create a window in the operating system that I am. I have to create a window to go and paint stuff inside this window. So an SDL window, a pointer to the window in memory equals to SDL_create window. And then we have some parameters that we're going to learn very soon what they are. Do you see it doesn't matter if I'm talking about Windows, Mac OS or Linux. I need to create a window in the operating system and this window is all I have access to. And here is where I can paint stuff. But you see this laptop might be running Mac OS, but the function call is just SDL_reate window. And this is going to be the same function SDL create window on Windows and it's going to be the same function on Linux and FreeBSD and manu OS. So it doesn't matter what is operating system the architecture. This is an SDL function that at compile time knows how to translate and write that platform specific code for the target platform that I'm running. Right? So as I create this SDL window, I have to create something else which is called an SDL renderer. And this render is basically this visible renderer portion that I have inside my window. So a window has a renderer inside. So SDL renderer this is a type that comes from this header file. Pointer to the render. So this is just a pointer to the render in memory that comes from the SDL_create renderer and then we're going to learn again the parameters that we need to create our render. Okay, this is just the highlevel overview of what are the functions that we have to use. So we create a window first. In that window we add our renderer and then something that we're going to do is we are going to have an SDL texture that we're going to add to our renderer. And this texture right here, we can think of it as an image, right? So the image that we want to display inside the render SDL texture pointer to the texture equals to SDL create texture and then the parameters that we need because this texture inside this renderer inside this window here is where we can now start creating our frame buffer which is basically that array of pixel colors. Right? So it is an array of 320 * 200. So 64,000 positions, meaning the 64,000 pixels that I want to display here. Let's just say that our window is going to be 320x 200, right? If you wanted a bigger window, then it's going to be a lot more pixels. But in our case, it's just 320x 200. I call this frame buffer. This is an array where each position is an unsigned integer of 32 bits or in other words, four bytes. Right? And in the moment that I create this array, then I can do whatever I want with that array. Let's just say that now I can manipulate the frame buffer as I wish. All right. So frame buffer at the first position receives the color green. So I can go I can do whatever I want with this array. I can paint the pixels that I want. I can do whatever I want. And then once I'm done manipulating this frame buffer in memory, I can use an SDL function to update that texture with the frame buffer content. So I can say SDL update the texture. So I'm going to update this texture image right here with the contents of the frame buffer which is what I have been manipulating. So update texture I pass the texture the frame buffer and the last thing I have to do to actually go and display is I have to display the frame buffer or the texture inside the renderer inside that window. So I have a few function calls here. SDL render clear to just clear the renderer before anything. SDL render texture inside that renderer and then SDL render present to actually go and display that content on the monitor. Right? So the render present is what actually displays that buffer with that texture with the contents of the frame buffer in the display. So in the moment that I say render present renderer, this is where I go and I see the result of what I have been doing in the monitor. Right? So you see the first pixel, the first position of the frame buffer is green. Exactly what I did here, right? Frame buffer at the first position is that number with the color RGB 00 FF00 meaning green. And I see that reflected right here. Phw. A lot of things, right? creating a window, creating a renderer inside the window, creating a texture that goes with that renderer, and then binding and updating that texture with the frame buffer array, which is the thing that I actually modify. So, there's a lot of things going on. But once we have all this boiler plate done and correctly in the future, all you have to do is worry about the frame buffer array. Does that make sense? Once you have all this boilerplate done and once we create our C program that creates a window, creates a render, creates a textures and then updates that texture based on the frame buffer. Everything that you want to do visually, if you want to go and modify the pixels, all you have to do is go and modify that frame buffer in the correct position that you want and you will see the pixels being displayed. So in a way what we want is a C program now that goes and manipulates that frame buffer array and as I go and I start putting values in the frame buffer I will see those pixels being reflected here inside my window inside my renderer inside my texture right this is the SDL way of doing things and this is exactly what we're going to learn how to do right now very well so I am in my terminal right I am using Mac OS but this is going to work also for Linux and Windows. So the same code that I'm going to write here should work for Linux and Windows and also other architectures that are supported by SDL. So the first thing that I want us to do is we need to find a way of installing SDL in our system, right? Because we want to use the library SDL and we want to use the header SDL.h so we can have access to those functions and how to create a window, create a render and all those things. So if you're using Mac OS, the easiest way to go and install the SDL library in the correct folders in your system is by using the brew package manager. So if you say brew install SDL3 and hit enter, brew is going to connect online to a repository, look at the latest version of SDL3 and it's going to start downloading the correct files of SDL3 in the correct folders of your operating system. Right? Because Linux and Mac OS for example, they already have some folders in operating system that expect to have these header files and this library files and implementation of those things. So this is what Brew is going to do. It's going to connect online, look at the latest version and download the correct files in the correct folders of your Mac OS. I already have this thing installed. So if I try, it's going to say that I already have SDL3 installed. So that's good news. So that is all you have to do for Mac OS and if you're using Linux you can use your package manager for Linux which is usually apt right so you can say sudoapp install I think it is lib sdl tree-dev right to get all those development files as well the header files and etc. So this is what you have to install on Linux and if you're using Windows you can use PowerShell and then in your PowerShell you can use winget install SDL3 like that right so Mac OS Linux and Windows all you have to do is use a package manager to go and download the correct files in the correct folders and you should have everything already installed in your system good stuff so what I'm going to show to you I'm going still use Mac OS and given that I have already everything installed, let me just check something. So, brew prefix SDL3. Let's just see where Brew installed the SDL3 files. So, look at that. This folder right here slash up SLHomebrew SDL3. So if I go to /ophomebrew SDL3, right here I should have an include folder. And in this include folder is where I have the folder SDL3. And right here, look at that. All the header files that I need, including that big main SDL.H that I'm going to use to create a window, create a render, create a texture, and all those things, right? Good stuff. So this thing right here is the folder where our header files are. So all we have to do is start writing our code. So let's just create a folder here in my home folder. So create a directory called SDL frame buffer, right? And then inside SDL frame buffer, we're going to start creating a couple of files. So right now we have nothing good. Let's create a main C which is going to be our entry door for everything. Right? So first things first I have to include SDL3/ SDL.h and if we install SDL correctly this should be more than perfect. And we have an ink main that returns zero. Right? The most basic program that we need. So let's just say predef Hello SDL is working fine and I cannot forget include std io to actually use print f. So this should be fine. We return zero to tell the operating system that we had no error, right? Everything ended correctly. And you can return zero or you can return what modern C programmers like to use which is exit success which is a constant that is basically defined as zero and we have to include from std lib if I recall correctly. All right. So SDL3 stddio to print f and stdl leave to have access to all these helpful constants here. So I return success to say that everything ended correctly. And do you think we can ask to SDL init SDL init video? Do you think we should be able to do that? Because if we can access this function, then it means that our SDL is correctly installed and is visible inside our C code. Right? So if I save everything, oh, and by the way, you probably saw that I'm using VI, but you can use anything. You can use Visual Studio Code, you can use Emacs, whatever editor you want to use, right? It really doesn't matter, right? So if I come here and I try to compile GCC main. C and I want to generate an executable called frame buffer. Can I do that? That did not work. And that's correct because we are not specifying we're not telling the compiler where to look for the SDL.h. And for that what you can do is we can say GCC main. C. And then right here I could just say include that folder /op/homebrew that we saw before, right? Include something. But if I don't want to specify all this thing all the time, there is an easier way which is I can just say back tick back tick and then between the back ticks I can say pkg d-config I can ask the shell to return that folder for me. So, pkg config dash C flag. So, get me all the flags for the C compiler for SDL3 and then generate frame buffer execute. This should go and find that.h for me. So, well, the error changed, right? So, it could find the SDL.h. So, this is already good news. But we have a different error, right? So, and this thing right here is an LD error, meaning that it's not a compilation error, but it is a linker error. And this is how C works, right? Whenever we include a header file in our C code, that header file doesn't have the actual implementation, doesn't have the body of the functions. It just has the prototype, just the signature of the functions. Whenever we are actually compiling we have to tell the compiler and the linker where to find the library right either the leaves the DLS the actual object. So where is the actual implementation the library that we have to go and link against the source code. So not just the header I need to actually get the library the actual implementation of those things. And we can easily get that as well by adding a separate set of back ticks here again config dash libs. So include all the library path from SDL3 to this build command and this should be enough. Look at that. Great news, right? No error messages is good news in the common line. So if I come here and I show my files, I have my main.c source code that I created, but I also have this executable frame buffer, right? And it is an executable. Do you see the X here on the left hand side? Executable file. So I can execute dot slash frame buffer. Look at that. Hello SDL is working fine. So we were able to compile include the header file and link against the implementation of the library SDL tree. We are good to go. So from now on we can use this entire build common. Yes, it's very ugly but this is everything we need to use from now. And you know what I can come here and say vi make file to make our life a little bit easier. So I'm going to create a make file and I'm going to create a rule build and I'm going to paste that entire thing. This is going to be my build rule. And let's also create a run rule which is basically dot slash frame buffer. Right? Very very simple make file with these two rules. Build that is going to execute this and then the run which is going to execute frame buffer. Because with this make file I can come here and I can say make build or just make because the build is the first rule. So make and make is going to run my build rule. And if I say make run is going to run my executable and that is absolutely great right very very simple make file just to make our lives a little bit easier. So we don't have to type all that thing all the time. We can just say make. Great. So we are ready to start coding. Super. So let me just declare here. I'm going to define a couple of important things. So what is the width of our window that we want? Let's just start with 320. And the height is 200, right? And I don't know about you, but I have been writing this for a long time. And I will never forgive whoever made height one letter more than width because it never gets aligned. Right? And this bothers me more than I care to admit. But still, again, just a little bit of OCD here. Cool. So, I'm defining the resolution 320x 200. And we're going to declare that unsign integer of 32 bits frame buffer, which is the width times the height. Correct? just an array a static array of 64,000 positions and just one thing do you see this type that I am choosing u in32 team when you are starting with C you might be tempted to just go and write integer right so just say int the thing is whenever you use int the C programming language it is not really a guarantee that these integer types are going to be 32 bits They usually are in most architectures and in most computers an int modern computers is usually four bytes meaning 32 bits. But back in the day I am old enough to remember right whenever I was coding in MS DO 16 bits. I had cases where an int the compiler actually gave us a size of two bytes 16 bits. So again, the C compiler and the C programming language, it doesn't really it's not a guarantee that an integer is always four bytes. It can be something a little bit weirder, right? It just specifies the minimum, but it doesn't give you the exact size. So if you want to work with exact sizes and C is a programming language that we usually want to have access and think about these exact sizes in bytes and bits. If you want to do that, we usually use a standard integer header because this std int gives us access to this u int32_t. This is a type that is guaranteed to be 32 bits long, right? Of unsigned values. Good stuff. So, we're going to start using this types from now on. So we have 220 and a frame buffer array defined in memory. Right? This static array defined in memory. Big big array. We don't need this print f anymore. And we're going to start doing those things, right? SDL window, SDL renderer, SDL texture. They're all pointers, right? And then we're going to start window equals to SDL create window. And the moment that I open my parenthesis, do you see I have a lot of parameters? I have the character pointer title, the W, the H, so the width, the height, and also some window flags if I want to pass. So what is the title that I want? Well, we can put a title STL frame buffer. This is going to be the title that is going to appear at the top of the window. What is the width that I want? Well, width. What is the height? Height. I have access to all those things. And now the flags. Do I want any specific flags for the window? Do I want it to be full screen? Do I want it to be without borders? Do I want to be resizable? No, I don't want anything. So, just flags zero. No specific flags. Just give me the default window. And usually what people will do with SDL functions, they kind of like to put things in their own line. Right? So I think that's what we have to do. Create a window with a title with the width with the height and no flags. Right? Nothing specific for this window. Just give me the default one. Right? So the window should be created. Let me just see make Oh, good. No errors. Next thing the render, right? So render equals to SDL create render and here we go. So create renderer it's asking for the pointer to that window that we just created. Right? So this render is going to be a renderer inside a window. So window. So we just created above and the name of the render. So here you can specify if you want a specific type of render like OpenGL, Vulcan, but in our case it's going to be a softer render I think or it really doesn't matter. So I can just pass no in this case. That should be it. All right, that's it. Window no. And we are done. That's the render. And remember the next step is a texture. So we have to create a texture that is going to be displayed and copied to the render. So this texture is SDL create texture. What are the parameters? First parameter is the pointer to the renderer. We have that we just created. So renderer is the name. Second is the SDL pixel format. Look, whenever we are creating a texture, we have to specify what is the pixel format that we want. In our case, we want to use that red red green green blue. Right? So it's going to be a 32-bit number hexadimal we usually use right but it is that format right r ggbb and it's going to be this kind of I think 32-bit number u we don't really have an opacity or alpha or transparency so I think we can just use 32-bit numbers with that format right there so the one I like to use is something called and we have a flag for that which is SDL pixel format at underscore and then we have some options. The one I like is XRGB where each component uses 8 bit. So 88 888. This is the pixel format that I like to use. All right. Next texture axis. Again we have to specify what is the type of axis that we're going to give to our textures. Can we update this texture after? In our case we want to update. We want to have this animation, right? We're going to have frames per frame. So, we're going to have this extra being updated constantly. So, SDL texture axis streaming. All right. And then the next parameters are the width and the height. Same thing. So, width and height. And that should do the job. Look, you're going to say, Gustavo, these are all very complicated. How do you remember all these constants and all these type of parameters? Well, you do have access to the documentation online, right? And all the API and all the functions. So, if you come here and look for SDL documentation, I'm going to have the wiki. This is the front page. You can come here and look by API or just the complete API index. You're going to have all these details here, right? So, let's just say create texture. So create texture I have the full prototype with all the parameters and then it explains that the function parameters are the renderer pointer the pixel format and if you want to look at the different formats you have this thing right here. Look at that all the different formats that you want to use. You can have access to here. You can pick a different one if you have a different unorthodox pixel format that you want to use. If you're using 8 bits, 16 bits, then you can kind of pick whatever you want. The texture axis, same thing. What is the type of axis? Is it static? Is it streaming? Am I using a render target? So, you have different types and all these constants. They're basically just nicknames for this type of enumeration options that we have, right? The texture access pixel color. So yeah, you're going to find yourself looking at the API of SDL a lot whenever you're talking about these things right here. Okay, let's say create window. There you go. Create window. These are the parameters. The title of the window, the width of the window, the height, and the flags. So what are the flags that we have? Look at that. It can be full screen, OpenGL, oluden, hidden, borderless with no borders, resizable. you have different flags to actually tell the operating system how that window is going to behave and you can pass these different flags if you wish to do so. Cool. So, we created a window done. We created a renderer done and we created a texture done. So, one thing that we can do here, let's just see if we can display the window and the render, right? just to see if we can actually see something on the screen. Even though we're not doing anything with the frame buffer, we should be able to just see a clear renderer inside a window. So, SDL render clear. So, I can clear a renderer. What is the renderer? This is the renderer. SDL render present render. Right? So, these two functions I clear my render and I just display, right? I go and I do that little swap of the double buffering to actually go and display this current buffer and this current renderer in the window. And I think I'm going to just do a while true because I want to basically just have this clear and render clear and render inside a loop almost like a frame by frame animation loop. We're going to fix this a little bit later. So save everything. Go up. I don't know why my init is right here. So let me just cut this one and let me move up. Right. This has to be above everything else. So right here as the element. And if I make beautiful and if I make run, what do I see? Well, look at that. I do see a window. Uh, but really nothing is happening here, right? So, we do have to do a lot of other things. And it kind of looks like 320 by 200. So, the size is kind of okay. But yeah, nothing really happening right here. I cannot even close my window. Nothing really happening. So, I'm going to have to come here and Ctrl Z. have to break that thing. And the reason why we are having this issue is because we are not really giving any option of the user to input or manipulate anything. We are not pulling the events of the system to go with this window. So while we are running our program, I should be able to go and pull the events of the system. And when I say pulled events are things like keyboard input or even you know when you go to the X and you close the window the little X button we need to get that event as well for us to be able to actually close that window. So let's just use SDL to pull all the events of our event Q. So while SDL pole event and then we need to pass an event right here. I'm going to create right here after the texture SDL event event right do you see this is just a strct this is not a pointer this is an actual vanilla strruct and then sdlpo event I want to pass the address of that event strct while and then this is going to go and pull all the events one by one and feed inside this strct And inside that while I have to handle that event. So I have to say look if this event that I just pulled if the type is SDL event quit I do something and this we're going to have a to-do right so stop running break our while loop basically. Does that make sense? So this is going to be a while loop that is going to pull all the events and handle them right. So instead of having a while true, do you agree that we could do something like while is running and we can start the is running with one or true if you want while is running is true. And then right here if by any chance the event type is of the type quit is running zero false right and let's just declare is running as an int 8 the smallest type right you would think that this should be a one bit thing right but that is not really how we work with booleans in C they are at least eight bits they are a number and in the case of C one or anything different then zero is true and zero is false. If you ever work with fe, you should be used to that. Cool. So I go is running. I pull the events render clear render present and as soon as I'm done at the end I have to destroy stuff, right? So SDL destroy texture pass in the texture. SDL destroy renderer pass in the renderer just going backwards right so SDL destroy window pass in the window right this is what's going to go and actually free and destroy those things from memory frame and the last one sdl quit which is the opposite of sdl in it that we invoke in the beginning of everything so that should be it. Let's see how this looks. Make and make run. Look at that. A lot better, right? So now I have an actual window with the quit event. Look, the quit event is not the escape key or anything. The quit event is this thing right here is the click on the X. And it looks like it worked. All right, so we are in good shape. And the magic is this whole event here. Right? So we are handling the events of the system. And one of the events that we're checking is the STL type quit because if it is quit, if we go there and we click the X button, we set this flag to false and we break our loop and we start destroying and removing and freeing all those objects that we had before. Cool. So look, we are using SDL to create a window. Create a render, create a texture, and that takes care of the operating system part of displaying the window and the renderer. But eyes on the price, remember what we want. We want to have that frame buffer array, right? That frame buffer of 320x 200. That frame buffer array, that is what we want to contain. And that is going to be a map in memory of what we want to display in our SDL window. So what we have to do now is create this binding, create this glue between the frame buffer array, and we're going to have to update the texture inside the renderer with the contents of the frame buffer. And we can easily do that. There are some useful functions that help us do that. For example, right here inside our while loop, every time that I'm displaying a frame, I can say SDL update texture. And the first parameter is the texture. So what is the texture? That one that we created above. So texture, I want to update this texture of my window. And then it's asking for something called an SDL rectangle. This rectangle pointer is if by any chance we want only a sub rectangular area of my texture to be updated, right? Just a portion of the texture to be updated. We can pass a rectangle dimensions. But since we want the entire texture and the entire frame buffer to be copied, I can pass no and just bypass this thing. Just say like copy everything, right? Copy the full texture. I don't want a sub rectangle section, just full. And then the next parameter is a pointer to the actual pixels that I want to copy. Who are the pixels that I want to copy? Well, it is my frame buffer, right? The frame buffer is the array that contains the pixels. And now the last parameter is the pitch. And pitch is basically the width of the texture in bytes. So to find the pitch of our texture that we're trying to update the pitch is the width right so how wide is that image so each row of that image what is the width but I want that in size of bytes right so how many bytes is the width of my picture that is the pitch and well if we have 320 right that is our width is 320 times how many bytes or how many bits is each position 32 bits. So four bytes correct four bytes times 320 that is the pitch of this texture that we are using but that always depends on the actual width that you are using right in our case is 320. So in our case our pitch is 320 times how many bytes per pixel is four bytes right 32 bits but we can be smarter because we can say that is the width that we are using times I don't have to hardcode four here I can just say size of and then I can use the size of operator to return the size of u int 32t which is the type of each one of the pixels of our frame buffer. So this is the pitch of our image our texture. It is the width the width of the image or our texture in bytes. And I'm going to leave this helper here just so we remember it. Actually I don't need this anymore. Does that make sense? So we update our texture. We go, we do whatever we have to do. Copy the contents of the frame buffer to the texture to our SDL texture that we want to render. And I have to remember that after I clear and before I present my renderer, I have to SDL render texture. All right. Uh so what is the renderer? We have that render. What is the texture pointer? We have that texture and the next parameters are uh the SDL rectangle. So the pointer to the source rectangle. So do we want to specify a sub rectangular section of that texture to display? No. So just use the entire texture and the destination rectangle. Do you want to specify also a destination sub rectangular area or just a small section of that target render to display? No, I want the entire render. So, no. And that should be it. Cool. And you know what? We are very very close to what we want. In theory, we are doing everything that we need. We pull all the events and then we go and we always update the texture. we update the SDL texture to go and copy the contents of the frame buffer array and then we display the texture. So in theory right here, right about here, here we can manipulate and change and do whatever we want with our frame buffer array as we wish. Because whatever we do with this frame buffer, let's just say frame buffer at a position I don't know 16,000, right? Let's just pick see if we can kind of get a random position here. Actually, if it is 64,000, I just say 16,500. So 16,500. This position right here, I want to put the color 0x FF000000. This should be the color red, right? I should see a pixel in that frame buffer that gets copied to the texture and then I just render the texture. Let's see if that is the case. We are very very close to what we want like run right. So [laughter] [clears throat and snorts] I don't know if you can see very very small right we have very tiny pixel red here and look our resolution our window is pretty small because we're using 320x 200 and my monitor resolution is super huge so it's very very small I think what we can do let's just maybe uh resize this window so everything that's kind of stretched and grow so we can actually see something right what we can do right here uh we can keep 320 and 200 for the frame buffer but right here whenever we create our window maybe I can just stretch the window and hopefully everything all that texture gets stretched as well so let's just multiply the width by four and the height by four you see what I'm doing I'm just creating a window bigger than the texture but this thing should stretch the content as well And just one thing I think whenever we create a texture we need to specify here um how we're going to grow how it's going to scale that texture as we grow. So SDL set texture scale mode and then I pass the texture that I'm trying to scale and what is the scale mode type. So I want things to be scaled and just respect everything and not distort much. So SDL scale mode I think there is something called nearest right. So it's going to use the nearest neighbor scaling mode that should keep those pixels sharp. Let's see. So make and make run. This should be more visible. There we go. So we have our window and do you see this pixel right here? This is the position the kind of random position 16,500 that I picked. Right. So you see red. That is great news, right? That's exactly what we want because remember what we wanted was a way of thinking about the pixels in our window only in terms of our frame buffer array. Everything that I want to do with my pixels, paint red, paint green, paint blue, paint white. All I want to think is only going and changing the frame buffer array. And then behind the scenes, SDL is kind of doing the dirty job of copying that frame buffer to the texture, displaying the texture, rendering stuff in and pulling the events. But still, as kind of a graphics programmer, all I want to do is think and worry about this positions inside my frame buffer. So if I want to draw something, if I want to paint something, if I want to do whatever crazy stuff I want to do, I have access to my frame buffer, that array of pixel colors that now SDL knows how to go copy and display for me inside an operating system window. All right, great, great stuff. So that's great news. I think we are almost there with what I wanted to show to you. I want to do something more interesting than just going to this position and also we have to think about how do we think about 2D coordinates and how do we actually get the correct position in the array right um but before I do that I just want to point out something before right we kind of continue uh you know how we are calling all these functions SDL init SDL create window SDL create render we have to be a little bit more careful and we have to maybe check if we have any errors when we are invoking these functions, right? That should be the reasonable thing to do. And let's do that, right? Because SDL it returns some error codes for us and we can check if things are wrong. Maybe we try to initialize the video and I don't know, you're using a Linux on the server that doesn't have a graphics mode or you're trying to create a texture and you don't have enough memory. So, we have to kind of catch this weird stuff. And STL is kind of pretty simple, right? I can just it returns error for us. So SDL init the SDL init function it returns zero if everything was successful but it returns some negative codes if something was wrong. So I can say for example if by any chance not SDL init right so the return of SDL init if that is not then it means that we had a problem right so let's just say that we had a problem f print f so I just want to format my print to the standard error output so I just want to say that this is an error and I want to say the message look init failed and I can even display a string here that comes from SDL get error. SDL provides this super useful stuff for us. And if we had an error, I have to return exit failure, right? I had to say operating system, we broke, we found an error, our program didn't finish successfully, right? So something went wrong. And we have to do the same thing for the window creation and for the render creation and the texture creation. So if by any chance right we try to create a window this window pointer is going to be no if there was an error. So right here after I tried if my window is no I had an error. So same thing as before f print f standard error I can just say that sdl create window failed and I get the error as before and besides returning exit failure. I cannot forget that before exit failure I have to SDL quit because I have to undo this SDL init that succeeded before. Right? So SDL init is the window that had a problem but I have to come here and before exiting I have to quit my SDL init that was done before. Cool. Same thing right render. After I create a renderer, if by any chance the render is no pointer yank SDL create renderer failed, SDL get error and return exit failure. And I cannot forget that if the renderer is giving me a problem, it means that my window was successful and my SDL in it was successful. So I have to destroy two things here before I exit. SDL destroy window and SDL quick before I exit failure. Right? I have to destroy these two things because they actually succeeded before. Right? And I think the last thing I have to check is my texture. So same stuff. If the texture return it a no pointer I have to show a message error. Destroy the window. Quit exit failure. So all those things SDL create texture failed. Then I have to remember to destroy everything including destroy render from before. And that should do the job. A lot of stuff, right? But again, just making sure that our code is reasonable. We are cleaning after ourselves. Everything is polished and ready to go. Right. Cool. So we are done. I think what we have to focus now is this thing right here. Look, you can kind of try to find where in that frame buffer you have to paint the color. But what we really want is instead of coming here and saying frame buffer at that particular position, I want to say something like I want to put a pixel at that X Y position with the color let's say red. Right? I want to create this function. And I want to implement this function called put pixel that thinks about our screen in terms of x and y coordinate right this 2D grid and the color that I want to actually go and paint the frame buffer there. So how are we going to do this foot pixel function that thinks of things in terms of x and y? Well I am going to come here and I'm going to create a void put pixel int x int y. So this is the prototype. This is the signature of my function and my color. All these colors they are hexadesimal numbers but they are 32 bits right. So you int 32t color and this is the function that's going to convert x and y into array index right the frame buffer array index for us. So it's basically saying frame buffer at a certain position equals to that color that we passed. The question is if I have X and Y, how do I know where in that frame buffer, right, that linear contiguous array position index I have to paint? Let's think about this. So if we think of our screen as this grid, this raster of pixels and I don't know if you can see but I do have 320x 200 pixels right this is kind of our frame buffer but we are viewing our frame buffer array as this 2D screen grid our raster this is not really this view right here this 2D grid is not really how things are in memory Right? Whenever we declare our frame buffer, it is this kind of linear contiguous array. So [clears throat] our frame buffer in memory, whenever we declare a frame buffer array of 320 * 200, so 64,000 positions and each position is an unsigned integer that has 32 bits each. That frame buffer in our memory, this is going to be pointing right to the first position here. And our frame buffer is actually a linear is this continuous array in memory that has 64,000 positions and it position is four bytes 32 bits each. Do we all agree with that? So even though we think of this 2D X and Y coordinate pixel positions, this is how things are in memory is this contiguous array is this linear contiguous address one after the other. So the question is given that we have this frame buffer this big grid array we want to think of X and Y positions as this row and column right so X is the column the Y is the row so we want to pinpoint an exact position in this 2D grid. So if I want to for example go to X pixel 60 and Y30, how do I access the correct array position? If you want to paint the pixel at the screen coordinates X60 and Y30. So I have X and Y. I want to find the correct array in this linear memory, right? Because that is what the frame buffer is in memory. It's this static array of linear contiguous values. Well, for us to go from 2D to array index in the frame buffer, let's just think about that. I have X and Y. So, we have 2D. We have to go to this 1D linear, right? So, if I want to get and go to that specific pixel there, I need to navigate the number of rows, right? So, I have to go 30. Do you agree that how many rows is 30, right? So I have to go 30 times the entire width of my frame buffer. So 320. So it is 30 * 320. That is going to position ourselves right here on the left. But then after I multiply 30 * 220, I need to offset to get to the correct X. Right? I'm going to end up in that first column. So I have to go and plus X which is 60. So again let's review that for me to go from X and Y 2D to the actual index position I have to go 30 * 320 plus 60. Right? So it's going to be kind of like this formula right here. I have to go to the frame buffer 30 * 320. Right? because I have to go 320 plus 320 plus 320 220 220 30 times. I'm going to end up here and then plus the 60 plus the x because I have to go and offset to get here to the right to the correct x position. So this is the formula that I think is going to be the frame buffer at 320 which is the width of my frame buffer width times the y plus the x and then I go and I set the color that I want let's just say green in this case right so if we convert this this is the width this is the y and this is the x this is the formula that I have to use to get from x and y to frame buffer index this linear array index position So look at that. My put pixel with an x, y, and a color is going to be frame buffer at index position width * y + x. And then I just assign the color. This is how we get from x and y to frame buffer index of my array. And it's just a matter of going and writing exactly that in our put pixel function. Right? That's it. frame buffer which is the width times the y and this is always going to be executed first right multiplication before addition and plus my x to just offset and go to the right to the correct x column that I want to equals to the column we are done. So, if I want to come here and I want to put a pixel in the X in the middle of my screen, width divided by two and height divided by two, right? This is the X and this is the Y. I want to put the color green. Can I do that? Absolutely. Right there. my green pixel in the middle of my screen. X and Y given by that put pixel function. I love it. Look, you could stop here and you have everything you need to go and draw in the correct X and Y positions the pixels that you want. You have this canvas that you can manipulate with C and that's great. But what we usually want is something more powerful that has the ability of remember displaying this frames almost like this animation right. So whenever you have an application you want to be able to have this kind of let's say 30 fps right frames per second or 60 frames per second you want to have something in terms of like almost like this animation frames one after the other. That is usually what we want. And we already are setting our texture for streaming, right? So, we should be able to go and update that texture and that frame buffer as fast as we want, frame per frame. Uh, all we have to really do is maybe control the timing, right? So, we really have 60 times per second. Maybe just cap that speed. So, we actually have 60 times per second, this rate of updates. And we can actually do that. SDL again comes to the help and help us do that. So right here whenever we have our while loop right inside the while is running we could come here and say that we can keep track of the start let's just use something big here so you int 64 right a big big 64-bit variable we can say that the start of this frame is SDL get performance counter So in the beginning of our frame right this is our while loop in the beginning of our frame if you want to think like that we get the SDL get performance counter this is recording the start and then right here at the bottom before we end while loop I can have something like 64 again and SDL get performance count right so I have the start and the end I can compute how much has elapsed. So elapsed this is the end minus the start divided by something called STL get performance frequency right and since this is a division right here uh this has to be a double value and I'm going to have to cast this to double and this one also to double right quirks of the C language for us to get a double out of the division both the numerator and the denominator need to be done. So this is the elapsed and I'm going to cap the frame rate to let's just say 60 fps. So if by any chance the elapse time is less than so here we're going to have to find the value right to kind of head to the 60 fps and if by any chance that's true I'm going to use something called SDL delay to just sleep for a while because it means that we are too fast and we have to cap that frame rate. So how do we make sure that we are running 60 fps? Well, I'm going to go up here and right about let's just in the beginning of this main function here, let's just create a constant double. Let's just have what is the target that we're trying to get. So, what is the target of this string? Well, the target is one divided by 60, right? Which is 0.016 approximately, right? So it's kind of 16 milliseconds. So if we're trying to get 60 fps, 16 milliseconds is our target is how much each frame should take. But if by any chance we are running too fast, right? So if the elapsed is less than the target frame, we're going to have to sleep for a bit until we get to the target. So I want to delay uh let's think about this target minus minus elapsed. Right? So the difference between the target and the elapsed and I just think I need to remember to multiply this by 1,00 because we are talking about milliseconds. Sorry delay expect milliseconds. sleep until we reach the target for 60 fps for this frame, right? Frame by frame, we are sleeping a little bit if by any chance we are too fast. And again, there are better ways of controlling FPS, smarter ways, right? Things to actually control the speed and slower games, how to actually be smart about stuff, but I just want to keep things as simple as possible. Just capping the frame rate to 60 fps and slowing things down so we actually get to 60 fps frame per frame. And that should be it everyone. I think we are in good shape. Let's just do something fun here. So instead of just putting one pixel, let's just do a for loop. So for all the eyes from zero while I is less than the height of the screen plus+. So for all the y's for all the x's I'm just looping through all the values. So all the pixels correct let's just see something. So if by any chance the x right the division by x by five is zero. So if x is a multiple of five or yeah if it is a multiple of five if divides perfectly by five then I go and I put a pixel that x that y and I don't know zero f so green and blue what do you expect to see make great and make run exactly what I expected right so now I have programmatically I can decide what to paint what not to paint and get whatever color I want right this case green and blue right I have this cyan color so yeah all the columns that are multiples of five I decided to paint otherwise I don't paint anything and also one thing that you will see that is very very common in this kind of frame buffer applications is we usually have something called clear frame buffer that you can just actually pass a color that I want to clear. So let's just clear with the color FF FFF. [laughter] I want to clear with white, right? So I have to go and implement the clear, not just put pixel very clearing 32. This should be super simple, right? Just fill in the entire frame buffer. I less than width time height. So all the positions I ++ and I go to the frame buffer at I and I just set the color which is this one. That's it. Right. Um oh by the way um do you agree that it would be a good idea to just protect maybe X and Y to be within the boundaries of the grid? So let's just the only way that we update is if Let's just say that we're going to return if something was wrong and then if we didn't we actually go and update. So if what tells us that X and Y are wrong. So if by any chance X is less than zero right? So if X is negative that's a problem. or if x is greater than or equal to the width, that's a problem. But also the y. So if the y is negative, that's a problem. Or if the y is greater or equal to the height, that's a problem. So if by any chance these things happen, I don't update my frame buffer. I don't put a pixel there. But if not, then frame buffer actually goes and receives that call. Right? I think that's a reasonable protection. Let me know if you think of something else. But I think that's a good thing. Yes, sure we are adding a conditional. Maybe that takes a hit on performance, but I think that's a reasonable thing to have. We don't want to have a buffer access outside the boundaries of our array, right? That is a big no no in the C programming world. Cool. So now we have a function that clears a frame buffer. So every frame that we start inside our while loop, here we go. We pull the events and then we proceed to clear the frame buffer and then do whatever we want with the frame buffer and then SDL does its thing. Right? Make make run. There we go. We're clearing with white and painting blue. Also, let's see if that idea of the animation is really working. So what we could do is we could have right here at the beginning. Let's just create a urint 32 called frame number or just frame that starts with zero. So I'm going to count the frames. I start with zero and then the moment that I display I increase frame ++. or does equals one just to make sure. And right here, should we try to paint? Let me just remove this if pixel int x equals to frame int y = to height /ed by two. All right. So I want to kind of get this an increase every time just to see if the animation looks okay. And the Y is always going to be in the middle of the screen, right? Kind of this middle vertical of the screen. And then I go and I put a pixel there. This is running frame per frame. So let's just see if that animation kind of works. Let's just clear with maybe black or kind of a gray color. 28 2A. And let's just put the green. And this frame, let's just always cap and keep it within um I guess 320, right? Just protecting. So it's always kind of this range of 320. The remainder of the division between the frame and is that what I want? So we see that pixel moving. Go go go go go. Yeah. So, it looks like things are being animated and hopefully 60 frames per second. I like it. Right. One pixel per frame, 60 frames per second. There we go. Animation is working correctly. So, look, it looks like we have everything that we need and our frame buffer is correct. And right about now, I think I should be responsible and tell you something extremely important about graphics and comparing the way that we are doing things with what you will see out there in the wild nowadays, right? Because do you see what we're doing with our pixels? We are basically going and using lines of code, right? We are using a C compiler to go and modify that frame buffer array. So we are dealing with these array positions of the frame buffer one by one right they are kind of going and the CPU is modifying all these processor instructions are executing and modifying that frame buffer. Look this way of doing things right having the CPU one instruction per instruction right instruction after instruction modifying these pixels. This is what we usually call back in the day a software renderer. Right? So it is done via software. It is the CPU. This is CPU based. We are not using any hardware acceleration. We are not using the GPU, right? The graphics processing unit that most computers now have. And look, don't get me wrong, a CPU renderer like what we're doing right here, painting the pixels using CPU instructions, this is okay, and it gets the job done. and we can actually see stuff on the screen. But if we actually look at how modern computer graphics works, you will see that most people would try to take advantage of this GPU that our computer has. And in simple terms, a GPU is this hardware. It is this component, this hardware component that can perform several things at the same time. It is this kind of parallel engine, this parallel super machine that knows how to perform and paint several pixels at the same time, right? Because do you agree that painting pixels it is this parallel friendly task, right? A pixel doesn't really depend on the state of the previous pixel. So you can basically just say paint all these pixels and send to the GPU to perform all these things in parallel. Right? So it has this kind of divide and conquer effect. So that is why usually computer graphics uses the power of GPUs. But what we are doing right here does not use the GPU. This is not a GPU renderer. This is a software render. We are using the CPU and sending instruction per instruction in this linear fashion or in this sequence of instructions one by one to be executed and manipulate our pixels. Right? So I thought it was really really important for us to make sure that we understand this difference. But still what we are doing is extremely important because it allows us to go and display stuff in the monitor and it is a beginnerfriendly way for us to start working with computer graphics before we actually go and we delegate all the power to a GPU to go and render pixels in our super high resolution monitors. You know what? I'm going to go one step ahead and just before we conclude, I'm going to show to you. I'm going to go ahead and just do something really, really interesting here and really fun. I'm going to come here and I'm going to paste something that I already have, which is some variables to display a super cool fire on this frame buffer. This is called the doom fire effect, right? And you can find this on GitHub, everywhere. This is really, really popular. Look at that. I'm just defining something called doom fire state variables uh fire width fire height which happens to be the same as our frame buffer width and height and also a pallet of color right so I have 37 different colors and I have int 8 the pixels of the fire which is another array that holds all those fire pixels right and then I have classic 37 color fire palette which is the colors that gives us the kind of fire effect in 32T which is fire pallet with 37 colors. These are the colors that are going to help us display that fire. And then I'm going to come right here in our init after we create our texture before we start our while loop. And right here I'm going to initialize a couple of pixels. So, we have the fire initialization that just goes and sets everything to zero. And then we have this thing right here, which is actually going at the last bottom row and starting with the maximum intensity of the color palette, which is going to be kind of the fire source at the absolute bottom of the screen. And then right here inside my while I have to update and render my fire which I can do right about here after my po event actually after my clear right we don't need any of these anymore. So I have a fire update routine and a fire render routine that goes and puts the pixel. Look, I know that we are not looking into detail of what all these formulas are doing, but just to prove to you that there is no magic. It's just see and manipulating byes shenanigan, right? That's it. So, if you do all of this and and if you come here and you run, look at the power of what you have in front of you. Like I said, all that you're seeing right here are just pixel manipulations. We have created this boiler plate that allows us to do stuff like this, right? Of course, we're probably going to start with something simple, creating a rectangle, creating a circle, but you have the power. Remember how we go and we sometimes use p5 js to draw stuff on the canvas. Do you know how you use JavaScript canvas, right? So the HTML 5 canvas, you go and you use the browser to display stuff. Now you can do those things. You can use the power of the C programming language and the speed of the C programming language to do cool stuff with graphics as well. And this is exactly what I wanted to show to you. And there we have it. Right. So do you see the power of what we accomplish here? Yes, it took us a long time to actually go and encode the frame buffer and deal with all these errors. creating a window, checking if there was an error, creating a renderer, checking if there was an error. But after we have everything created, then it's just a matter of getting our color buffer array, copying and updating to the texture, and then the textures get rendered, and then the renderer gets inside the window, and then we display, right? We go and we SDL present and we display there. And everything is running 60 frames per second, right? Do you see that animation that we just got before that is being running, right? Every frame, frame per frame, 60 times per second. So all these things are happening super fast. We are streaming the texture. We are updating everything. We get to a really really cool place. And look, I wanted to tell you that this thing that you have right here, this little boiler plate is actually really powerful. You can, you know, this is the entry door for super cool stuff. You can start thinking about displaying actual graphics, textures, rectangles, circles, polygons, triangles. You can reststerize triangles. And that opens the door. If you ever saw on my website, right? uh I teach how to actually go and uh display 3D objects. So you have all these triangles, these vertices and then you go they have color you project onto this 2D screen. So you have this ability of working with 3D as well if you want. So yeah, super super super powerful, right? These ideas of having this display and look I know that a lot of people start seeing think C is so boring, C is just like you know pointers and registers. But do you see what we can achieve? This is kind of like an intermediate Calele code. You already started creating variables, declaring stuff. You have arrays, you have pointers, you have to free your memory. So, we are already starting to enter some really cool areas of the C programming language. And that is exactly what I wanted to show to you here. I know that you know free code camp, we're not really used to low-level stuff. We're mostly talking about really high level operation, right? Very utilitarian stuff. But look, I am really passionate about the C programming language, especially low-level stuff, thinking about all the details of why we are doing stuff. This is what I live for, right? I love this topic. And if you want to learn more about this stuff, you know where to find me. But yeah, I'm really happy to where we got right here. Like I said, I'm going to leave the code and the video description. But look, this is super cool. We got to a really, really cool state. So, I'm just going to leave the fire running and I am going to say thank you so much and I will see you very very soon. Bye-bye.
Generated algorithmically for Search Engine
Indexing.