Recreating DOOM in Python. Ep1 - WAD DATA

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
dude [Music] was distributed using a shareware model similar to previous ID software games and this version included the first episode with nine levels called knee deep in the dead and when you try to start the other two episodes an advertising screen appears with an offer to buy a full version of the game and besides the shareware version fit on only two floppy disks which contributed to its rapid spread among gamers so after installing the game from these discs apart from text files and drivers two main files are directly related to the game itself the first Doom X-File was the game engine itself and all the assets of the game were in the Doom wad file the extension of which just means where is all the data so for our work we need only a wad file for the shareware version it is called Doom 1 and for the paid version it is just Doom and since the first version is for free distribution I will use it but you can use any of these too and when you have decided on the version of the wad file then place it in the project folder let's say in a directory called what so as I mentioned in the introduction we will be recreating the Doom engine in Python using the pygame graphics Library which is essentially a wrapper for the C language sdl Library and I would like to say a few words about the version of python used this is version 3.10 this version is used because at the last moment for texturing I decided to use a 3D array as a frame buffer and in order for the iteration speed over such an array to be at the level of compiled languages I use just-in-time compilation of some functions using the number module this allowed me to achieve higher performance and get rid of some of the shortcomings that arose when applying textures using the standard pygame tools and since at the time of the creation of this video number supports a version of python no higher than 3.10 therefore the choice was made in favor of this version and getting back to the wad file according to the Doom Wiki this file always starts with a header so let's get the project ready to read the data from the wad file so in the main file we will create the Doom engine class at the input of the Constructor of which the path to the wad file is specified we will take the path into an attribute and create an instance of this class now to read the data we will create a wad reader file there will be a class of the same name where we will open our file for reading in binary mode and we need to create a method to close it and to store and transform data we will create a wad data class that will have access to an instance of our engine and in which we will create an instance of the wad reader class and with the help of which we will read the necessary data then we import the wad data class in the main file and create an instance of it in the on init method such a class structure will be quite convenient for getting data and now we can move on to reading the header so to get the header we need to read 12 bytes the first four bytes are ASCII characters indicating the type of wad file and then there are two signed integers of four bytes each necessary to get the file directory with which we will get access to all file assets and for this we will use the struct module with the help of it we can convert the read bytes corresponding to the data types of the C language into the data types necessary for python then we will write the main method for reading bytes for which we specify the offset in the file the number of bytes to read in their format for using the unpack method of the struct module and now using this method we can write a method for reading strings from a wad file for this we take into account how to decode bytes and use the notation for the Char data type according to the struct module and let's create a method for reading four bytes specifying the data format it can be used to read both signed and unsigned 32-bit integers and so we can now read the header of the wad file let it be a dictionary with keys for the type of file the number of so-called lumps the lumps are the assets of the wad file and the initial offset where these lumps begin and let's call this method to get the header and then print its data if we run the program we can finally see the First Data that we got from the wad file and we need this information to read the directory with which we will get access to all the lump assets of the file so to read the directory we need to read 16 bytes for each lump this will be a list in which we will place a dictionary for the next lump the keys for which will be its offset in the file size and name we read the name eight bytes long since it was the maximum size for a file name in Ms dose times let's use this method to get this directory and look at its contents so we see that we now have a list of all lumps with their names offsets and sizes but to make sure that we got this data correctly I suggest installing the Doom editor slate 3 and if you open your wad file in this editor you will see a list of names these are the very lumps that are in our directory and in our case I recommend using this editor specifically to check the correctness of the data received from the wad file so e1m1 is the name of the first Doom map followed by 10 lumps that contain specific data for building and rendering this map subsequently we will consider all this data and figure out what they are for and let's start with getting the vertex data obviously vertex is the 2dx and Y coordinates on the map and in the wad file these coordinates are two 16-bit signed integers then we need to write a method to read two bytes as 16-bit numbers and along with this method we will also need a method to read 8-bit numbers later on so now we can write a method to read a single vertex at a given offset and for convenience we can use the 2D vector class from the pi game math submodule for the vertex coordinates but now we need to specify that we will receive the vertices for the first Doom map and all the main data for the engine will be contained in the wad data class let's write a method by which we can find the index of a lump in our directory and this method will come in handy more than once and then we use it to find the index for our map if we run the program we will see that the index of the e1m1 map is 6 we can also verify that this index is correct using the data from the Slate editor and we also need a dictionary the keys in which will be the names of the lumps that go directly after the name of the map and the values will be additional indices and as you can see there are 10 of them so now we need a method to get data lump here we will use the read function from the wad reader class by getting information about the lump from the directory then dividing the size of the lump by the number of bytes of the lump instance we find their number by iterating over this number and calculating the appropriate offset we read all these instances using the specified reader function and put them in a list at the same time we take into account the fact that some lumps have their own header which we will skip and now we are all set to receive lump data so let's get all the vertices for the current map here we take into account the additional index in the fact that one vertex is equal to four bytes and if we print the values of the obtained vertices and compare them with the coordinates of the vertices from the Slate editor then as we see the obtained values coincide and thus we have received the correct mechanism for obtaining data from the wad file and the most interesting thing is not to look at the numbers but let's render this map in 2D mode to do this let's create a settings file here we set the original Doom resolution but this is a rather low resolution and therefore we debt find the value of the scaling factor and from which we calculate the final resolution and also calculate the center of the screen now let's import the settings Pi game and sys modules in the Constructor we will create a rendering surface of a given resolution a clock object running and Delta time variables in the update method we will receive the Delta time value update the screen and display the current frame rate in the window title in the draw method we will simply paint the screen black and in the check events method we check the events for the closing of the application in which case we set the running variable to a false value the run method will contain the main Loop here we will call all these methods in turn and upon completion of the loop we will exit the application correctly if we call the run method of the application instance and run the program we will see a black window of the set resolution and thus everything is ready to render the wad file data so let's create a map renderer file and here after importing settings in pygame we will create a class of the same name that has access to our engines instance then you need to import this class in the main file and create an instance of it in the on init method now we will get access to an instance of the wad data class and accordingly to the list of our vertices and let's write a method in which we iterate over the list of vertices and render them as a circle and in turn we will call this method from a separate draw method and let's call this method from the general draw method and run the program and as we can see nothing is displayed for us because if you look at the coordinates of the vertices it becomes clear that none of them fell within our screen so let's remap the coordinates of all the vertices so that they can be displayed so first of all let's determine the maximum boundaries of the map for this we sort the X and Y coordinates of the vertices and select the minimum and maximum values now with these values we can write remap methods for vertex coordinates within our screen with a little padding around the edges and at the same time we take into account that for the y-coordinate the y-axis in pi game goes from top to bottom and let's apply the remap methods to our vertex coordinates and look at the result and finally we got the display of the map in the form of vertices this is much better than looking at the coordinates in text form but of course we would like the vertices to be connected by the appropriate lines and let's do that and in Doom the line that connects two vertices is called line def it also serves other purposes we'll talk about this later and as you can see each line def has seven attributes of two bytes each in the form of 16-bit unsigned integers as things get more complicated let's create a file called data types here we will define a class for line def I will use the slots magic method for faster access to attributes and efficient use of RAM and unlike the Doom Wiki I change the names of the attributes a little in my own way so having imported the data types file we need to write a method for reading data for one line def from the specified offset here we create an instance of our line def class and read the appropriate data for each attribute given its C data type it is also important to correctly increase the offset when reading the next attribute and in the wad data class we will get the data of all line defs in the same way as with the vertices and in order to check for the correctness of the received data I propose to write a convenient method for printing attributes for the case when slots are used for the class and let's apply this method to print line def data and look at the result if we compare the data from the Slate editor then we can say that they are all the same except for the last column this is affected by the signed or unsigned type of the 16-bit number Red we will process this later I just went along the path like most Doom Source ports so let's get back to the map renderer class and here we will get access to line defs iterating over which we will get two points on which we will build our line it remains for us to call this method and run the program and as we can see we were finally able to render the first legendary level of Doom but only in 2D mode I do not know how easy or difficult it seemed to you leave a comment about this but there are still many interesting and different things to be done ahead [Music] foreign
Info
Channel: Coder Space
Views: 67,358
Rating: undefined out of 5
Keywords: coding doom in python, creating doom in python, doom, doom history, doom history game, doom in python, pygame, pygame 3d game, pygame doom, pygame tutorial, python, python doom, python doom engine, python tutorial, doom how it was made, doom how it works, makind doom, creating doom, make doom in python, creating doom engine, creating a doom-style 3d game in python, creating a doom-style 3d game
Id: XV-cSvFM3ak
Channel Id: undefined
Length: 12min 12sec (732 seconds)
Published: Sat Mar 04 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.