Tworzenie TEKSTOWEGO silnika graficznego w języku C++
W swoim ostatnim filmie, Mashpoe zademonstrował, jak zainstalować kompilator C i IDE w systemie ReactOS. Pokazując rozwój tego systemu operacyjnego, postanowił stworzyć grę od podstaw, nie polegając na żadnej funkcjonalności poza ReactOS. Rozpoczął od konfiguracji projektu w Code::Blocks, wybierając C++ jako język idealny do tworzenia gier, z uwagi na jego zalety w tym zakresie. Większość gier korzysta z jakiegoś rodzaju biblioteki graficznej, ale Mashpoe postanowił stworzyć własny silnik graficzny, oparty na konsoli Windows. Dzięki temu jego gra mogłaby mieć swoisty, nostalgiczny charakter, inspirowany starszymi grami, takimi jak Dwarf Fortress, która rysuje znaki na oknie, zamiast wykorzystać konsolę.
Pierwszym krokiem było stworzenie klasy wyświetlającej, która przechowuje tablicę struktur char info, reprezentujących znaki w konsoli, wraz z danymi formatowania, takimi jak kolor tła i pierwszoplanowy. Z pomocą funkcji writeConsoleOutput, można ustawić całą zawartość okna konsoli, co pozwala na stworzenie funkcjonalnej biblioteki graficznej. Buffer przechowujący znaki graficzne zastępuje tradycyjne piksele, a klasa wyświetlająca inicjalizuje się z uchwytem okna konsoli.
Aby wyświetlać konkretne znaki, Mashpoe stworzył klasy tekstur, które ładują pliki tekstowe tak, jakby były obrazami. Dzięki specjalnemu połączeniu klas, można zmieniać znaki wyświetlane w oknie konsoli, a również dokonywać efektu przezroczystości. Opanował również funkcję rysowania linii, wykorzystując algorytm uzyskany z innej strony. Ciekawym wyzwaniem było także korzystanie z GIT-a, zainstalowanego na ReactOS, by przesyłać kod do repozytoriów podczas prac nad grą.
Zainstalował starszą wersję GIT-a oraz zbudował odpowiednią ścieżkę systemową, co umożliwiło mu przesuwanie swoich plików źródłowych do repozytoriów. Mashpoe pokazał, jak instaluje narzędzia w ReactOS, co było wielką przeszkodą, ale udało mu się to pokonać. W kolejnych filmach planuje zająć się obsługą wejścia i fizyką w swojej grze, co pozwoli uczynić z tego silnik gry dostosowany do tworzenia gier na Windows.
Na chwilę obecną jego film osiągnął 19,588 wyświetleń oraz 470 polubień, co świadczy o dużym zainteresowaniu tematem. Historia tworzenie gry od podstaw na systemie Operacyjnym, jakim jest ReactOS, z pewnością zainspiruje wielu pasjonatów programowania i gier.
Toggle timeline summary
-
Wprowadzenie do poprzedniego wideo dotyczącego konfiguracji kompilatora C i IDE w ReactOS.
-
Ogłoszenie projektu deweloperskiego gry używającego ReactOS.
-
Decyzja o użyciu C++ do rozwijania gry w celu lepszych możliwości.
-
Plan stworzenia własnego silnika graficznego z wykorzystaniem konsoli Windows.
-
Dyskusja na temat nostalgicznego systemu graficznego podobnego do Dwarf Fortress.
-
Użycie konsoli Windows jako podstawy dla silnika graficznego gry.
-
Stworzenie klasy wyświetlania do obsługi reprezentacji znaków.
-
Wprowadzenie funkcji writeConsoleOutput do wyświetlania treści.
-
Wyjaśnienie klasy wyświetlania obsługującej tablicę znaków i ich wyjście.
-
Wprowadzenie funkcji czyszczącej do wypełniania konsoli znakiem.
-
Stworzenie metody setColor do personalizacji koloru znaków.
-
Wprowadzenie klasy tekstury do zarządzania obrazami jako plikami tekstowymi.
-
Wyzwania, z jakimi się zmierzono podczas rozwoju silnika graficznego.
-
Instalacja ciemnego motywu dla bloków kodu w celu poprawy widoczności.
-
Szczegóły dotyczące funkcji klasy tekstury, takie jak ładowanie konkretnych części obrazów.
-
Wdrożenie właściwości przezroczystości dla klasy wyświetlania.
-
Nawigacja po ograniczeniach ReactOS w zakresie konfiguracji kontroli wersji.
-
Doświadczenie związane z instalacją starszej wersji Gita na ReactOS.
-
Sukces w przesyłaniu plików źródłowych na GitHub po pokonaniu przeszkód.
-
Zwiastun następnego wideo koncentrującego się na fizyce gry i obsłudze wejścia.
-
Plany na przyszłość dotyczące rozwoju samodzielnego silnika gry z obsługą wejścia.
Transcription
In my last video, I was able to install a C compiler and an IDE in ReactOS. In order to show the maturity of the operating system, I've decided to create a game from scratch without relying on any functionality from an operating system besides ReactOS. I began by setting up my code blocks project. I decided to use C++ rather than C, as it's a much better language for developing games. Most games use some kind of graphics library, but I thought it would be cooler if I was able to create my own colorful graphics engine using the Windows console. Many games use this kind of graphics system in order to achieve an old-timey feel, such as Dwarf Fortress. Dwarf Fortress doesn't actually use the Windows console though, or any operating system's console for that matter. Instead, it just draws a bunch of characters onto a regular window as if they were images. This is the reason you can install a tileset for that game. I want to actually use the native console for my game, and since ReactOS is built from the ground up to be compatible with Windows, this graphics engine should work on both Windows and ReactOS. First, I wrote a display class, which stores an array of char info structures. Windows uses these structures in order to represent a character in its console, along with any formatting data such as foreground and background color. The Windows API has a built-in function called writeConsoleOutput, which takes a two-dimensional array of char info structures and uses it to set the entire contents of the console window. Now we have the basis for a conventional graphics library. The array of char info structures acts as a buffer to draw content to, and the writeConsoleOutput function displays the contents of the buffer to the console window. Just about every graphics library uses this exact same system. The only difference is that our buffer is storing colored characters instead of pixels. The display class acts as a wrapper for our char info array and also handles writeConsoleOutput for the user. Display objects are initialized with the handle to a console window, and if no such handle is provided, it will try to use the main console that's associated with stdout. It will then take the width and height of the console in characters and make an appropriately sized buffer. Our display is useless if we don't have any way to draw stuff on it, so I started out by making a clear function, which takes a character as an argument and fills the entire console window with it. I also added a method called setColor that will allow the user to set the foreground and background color of any characters that are drawn to the console window or used to clear it. We could just add a method to set a particular character at any position in the console window and then call it a day, but that would be really inconvenient for the user if they wanted to draw any complex scenes or images. I decided to create a texture class that loads text files as if they were images. I made it a friend of the display class because textures have many characters and it would be inefficient to pass each character to the display object one by one, which would involve many redundant bounds checks. Bounds checks are necessary because characters must not be drawn outside of the charInfo buffer, so we have to make sure any characters we draw are within the bounds of the console window. Any attempt to set values outside the bounds of the buffer will cause undefined behavior. Now that a texture has access to all of a display object's private members, it can do bounds checking once to determine which characters will be displayed on the screen, and then it can start putting them directly into the charInfo buffer. At this point in the development process of my graphics engine, my eyes began to bleed at an unhealthy rate due to the light theme that comes with code blocks by default. Luckily, I managed to install a dark theme by following the tutorial, which I will link in the description. After installing the dark theme, I was able to add a few more features to the texture class. Now, by default, textures will ignore any spaces in order to create a transparency effect. If a texture needs spaces to be drawn, you can set any other character to be ignored instead. Most graphics libraries will allow you to draw a specific portion of an image rather than the entire image, which is very useful if you want to load a sprite sheet with many frames in it. Textures handle this by taking a pointer to a rectangle structure as an optional argument. Textures also allow you to set their foreground and background colors, and you can even set the background or foreground color of the texture's characters to be completely transparent. You can see this working when this stick man is drawn on top of a sky filled with clouds. The part of him that's overlapping a cloud takes its white background, while the rest of him takes the blue background of the sky. I also decided to give the display its own transparency properties for drawing individual characters. Finally, I gave the display class a method for drawing lines. I got the code for this from a cool website that gives an implementation for a line drawing algorithm in a bunch of different languages, which I will of course link in the description. Since I always provide a link to a github repository with the source code for my video projects, I had to find a way to do this in ReactOS. I could have just transferred the files to my host operating system via a shared folder, but that would be cheating because I'm trying to develop my game using only ReactOS. I don't know if this is because I had an outdated browser, but I was unable to upload my code directly to the github website. That was no problem though, because you can just push code to a repository via the command line. I had to install git first, and the latest version does not support the older versions of Windows that ReactOS currently aims to support, and I had to install an older version instead. The installer for the latest version would not download no matter how many times I tried, but I was able to download a zip file full of binaries. If you were to watch the uncut footage of me trying to install this, you would probably cry, but I did manage to figure it out. I basically just put all the binaries into a folder in my system's program files directory, and then added the folder where git.exe is stored to the path environment variable. I was then able to put all of my source files into a folder and finally push them to my github repository. That's it for now. In my next video, I'll set up input handling and create the physics for my game, which will probably be in platformer. I might fork the github repo later in order to create a standalone engine that supports input handling and graphics, which would be very useful for anyone who wants to make a Windows game using my code. As always, the code for this video will be linked in the description.