Creating a Mario style level in Python / Pygame with a visual level editor [Tiled]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello there in this tutorial we are going to be creating this level in pi game with the tiled editor so you are going to learn how to use this editor to set up a level and import it into pygame and the only requirement to follow along for this tutorial is that you know basic pie game and if you don't i would recommend you to check out my introduction to pygame that is going to explain all that you are going to need however this video is also part of a series so while you don't need anything for the first part the second part of the video is about integrating a main player character into this level and to follow that one you will need to have watched the first part of the series but that is going to come much later if you just want to understand how to use the tiled editor and how to import all of this into pygame the first part you can just watch by itself so with that let's install tiled and let's create a level all you have to do is go to the website of tiles click on download and then it links you to the correct site now on here it does suggest the price but you do not have to pay it you can get tiled completely for free you just have to click on the link above and on that page you get different options depending on what operating system you have in my case i have windows 10 and then you download an installer and if you click on that you get this kind of dialog and then here you just click on next and it basically does all of it for you and then by the end of that you can just launch the program and then you are going to see something like this a whole lot of grey but in the top left you can see these different options here and you have open project save project s add folder to project open file new map and new tile set and in our case the only two options here that really matter are new map and new tile set anything else we can ignore and let me explain what those two actually do and this is also going to detail how tiled works in general so we have a map and a tile set and the best way to understand them is to think of a painter so if you want to paint something you need three different things you first need a canvas then you need a brush and then you need some colors and in this analogy a map would be the canvas to draw on then a tile set is going to be each individual color so where we are going to get our information from now for the brush we first have to open a project and essentially how we start is by creating a new map so we are essentially creating a new canvas so let me click on it and now we're getting a couple of different options we get orientation tile layer format and tile render order and all of these options are basically perfect by default at least in our case so i would recommend to leave them exactly as they are below that we have map size and tile size and for the map size you can set the width and the height of your project in my case i have 60 tiles for the width and 11 tights for the height which is already what i want so i'm going to leave them as they are and if you follow along i would recommend to use the same dimensions it becomes important later on and then we have the tile size which is the size of each tile which in my case is 64x64 which i'm also happy with so now that i have all of that i can click on save as and now tiled wants me to save all of this somewhere and in my case let me show my folder structure so i have code graphics and levels and i want to store all of this in levels and in here i have one folder called zero then level data and tile sets and for now i just want to save this in level data and let's call it level zero and let me save it and now we can see a proper tiled setup so let me explain what we are going to see really quick although all of this is going to make much more sense when we actually use it but let me go over the different panels really quick now the most important one right in the middle this thing this is your actual level so this is the canvas we are going to work on or well the map now besides that on the left side we have our properties and in there you can get some information in terms of what you're working on so right now we're looking at the map you can get tile width and tile height the width of the level the height of the level and basic stuff like that although that's not too important in our case then on the top you can see a couple of basic selection tools the really important ones are these couple here and the one we are going to use the most is this one here and this is called a brush which well is going to be used as a brush so think back of the analogy i used a second ago this is literally going to be our brush but there's also a paint bucket a selection tool and quite a few more but we're going to see in a second what they actually do then on the right side you can see layers here and tile sets here and for the layers all it really means is that you can draw on different layers so if you want to put stuff on top of each other you will use different layers and then the tile sets is the actually important part where we are going to get different colors that we can draw with and this is actually what i want to do so let me click on new tile set and in here we are going to get a new dialog and the one important aspect you need to know here is this type and if you click on it you get two options based on tileset image or collection of images and you're going to see later on what that actually means but for now i want to create a tileset image and to create that i need an image so below that i have to click on browse and if i do that it brings me to my file structure again and i want to go to my graphics and in there i have a folder called terrain and let me make all of this a bit larger and here we have one file called terrain tiles and this i want to open and now tiled is going to give me quite a few more information first of all it now gave me a name terrain tiles which i am happy with and it gets the name from the name of the file and then you get tile width tile height margin none of the stuff we really are going to need so now this i also have to save and i want to save this in my tile sets and let's keep it with the name terrain tiles so let me save it and now you can see the actually important part now we have a tile set and we can select each of the tiles from what we have selected earlier and what is also important if you look at the top we are now in a new tab called terraintiles.tsx and in here you can work on your own title set in quite some detail but i want to instead go back to my level so the first tab and now what i can see for my title sets i have the title set still available and well what i can do now is use this thing to draw so let me just select the middle part here and now i can use this to draw and select different elements and draw them wherever i want them to be and obviously right now this looked terrible so instead let's do this a bit more deliberately and first of all i want to zoom in so with control and the mouse wheel you can zoom in and let me go right to the start of the level and then here i have to have my stamp brush selected so this thing here at the top and with that i can just select different parts of my tile set and draw them on the screen and another important part here you can also keep on holding your mouse button down and then move along and that way you keep on drawing different elements and well this is then how you would create the basics of a level so the stamp brush here is the tool you are going to use the most but there are quite a few more so let me go over some you are going to use a lot the first one is the paint bucket tool or the bucket fill tool and if you select this one you can fill an entire level with a certain color or well a certain tile so i can use this to draw well one tile over the entire map and this tool is context aware so let me go back a tiny bit so this tool selects also similar tiles so if i hover over the platform we just made it also can tell if we have similar tiles which is quite powerful then besides that we also have an eraser so if you want to get rid of something you can just use the eraser and finally we have a rectangular select and you can use that to select the rectangle i guess and if you have that you can use ctrl c and if you then use ctrl v you're copying entire sections of your map and you can then use them and place stuff somewhere else that is literally all we needed so if you left click then this stops working so there are quite a few more tools like the terrain brush or this magic wand or well all of this stuff here and tileset is really really powerful so you can use it for quite some more things but in our case we don't really need it we can just rely on the basic tools and create our level with that so i am just going to rely on these tools and well let's actually use them to set up our level and all i really want to do is to select different parts and then create the level so let me rebuild this platform and now i guess i am going to speed up the process here to make this not as boring but this would probably be a really good exercise for you try to use the level editor to set up and fill out this entire map with platforms or about whatever you want to have on the map from this section here alrighty so this is going to be my basic level now in your case this is probably going to look slightly different but in here you can set up your own level and an important thing to work on now is that we have to rename this thing because right now it's called tile layer one and i want to call this terrain and the names here are going to be important later on when we import this into pygame so i would recommend you to follow along exactly with the naming convention but with that we have our first layer so next up we have to create another layer and for that you have to go to this icon here let me highlight it a bit better this icon here and if you click on it you get a couple of different options we have tile layer object layer image layer and group layer in my case the only important one is a tile layer and this tile layer i want to call coins and well what i want to do in here is to add all of my coins and to create coins we first have to import them and that means we have to create a new tile set and a new tile set you create by clicking on this icon down here which looks identical to the new layer icon and if you click on that we get the same dialog again and in this case i want to click on browse again go to my graphics folder and then there i have a folder called coins and if you click on that let me maximize it we get a folder called gold silver and then coin tiles and coin tiles is what i want to import and now again we have our coin tile name and i want to save all of this as its own file and this i want to save again in tile sets and there i still have my terrain tiles so now i save it and now i have my two coins so i have a gold coin and a silver coin and all of this again happens in a new tab and well if i go back now i have a new tab in my tile sets which is called coin tiles and then here i have my gold coin and my silver coin and now before we are placing all of this on the map there's one important thing to consider so right now i have my coin selected so i can select my gold coin and draw coins all over the map and i can even draw on top of the existing tiles so the existing stuff does not get deleted however let me undo all of this if i have my terrain tile selected and i draw over stuff i can't really draw over it because the coin replaces what we have drawn previously on the terrain map so let me undo it and the important thing here is what layer you have selected really matters and also the hierarchy of these layers really matters so let me draw a coin again on top of these tiles here and let me zoom in a tiny bit so right now you can see that the gold coins are on top of the terrain and that is because the coins here are on top of the terrain in our layers but if i click on this down arrow now my terrain is on top of the coins so you can't see the coins anymore so i want to undo this and now i can see my coins again so this layer setup here is incredibly important and make sure to always be on the layer that you actually want to work on and it is very very easy to work on a layer you don't actually want to work on which might cause quite a few problems so it's an important thing to consider but all right let me delete the coins i have put there and now that we have covered that on my coin layer i want to place a couple of gold coins and let me place one here one here one here and i guess one here and one here and then i can place some silver coins as well let's place them here here and here let's say here here and here and a couple all around and it literally doesn't matter where you put them it's really what kind of level you want to create in my case i am happy with this so now we already have two different kinds of layers we have coins and we have terrain and you can also click on this eye level to hide the entire layer and you can lock the entire thing as well in case you want to make sure you don't change it by accident and there's one more tile set i do want to import so let me go again to the bottom and create a new tile set and i again want to go to browse and go to graphics and there we have a folder called decoration and in there we have clouds grass sky and water and i want to look at my grass folder and then here we have one long file called grass and let me open it and let's call this grass tiles and save it along with our other tile sets so in the same folder we have coin tiles and terrain tiles and now you can see different grass tiles that all look very very similar so if i go back to my main level and also if you have a star in this tile here it means you haven't saved so i would recommend to press ctrl s fairly regularly tiled has a tendency to crash once in a while not very often but usually when you wanted the least so do save regularly but now i have my grass tiles and all of those look identical and well it would be kind of a pain to select each individually and place it somewhere on the map and also right now i'm on terrain and i don't want it on here instead i want to have a new tile layer that i call grass because later on this layer setup is going to be important and grass should be on its own layer you're going to see later why this is important but the important thing i want to do now instead of placing each of these grass tiles individually i want to be able to select all of them and then only place one of these at random so right now i have selected all of them and if i go to my map i can place all of them at once and this would already make my life much easier but well we would always get the same kind of setup so instead what i can do i can click on these dice up here which is called random mode and what that means is that tile is going to pick one of these selected tiles and place them so now if i just drag this along we get grass with random tiles from our selection it's very hard to see because our grass looks identical but let me zoom in a tiny bit more and place a tigress now and i place stuff on top of each other and every time i click we get a different grass tile set which that means i can just go around my level and place individual tiles and it is always going to be random and let me just go around and play some tiles i don't want to have grass everywhere but at least for most places it's probably going to make the level look better and alright with that we have some grass but now the level still looks fairly stale because we don't have any crates or palm trees and we also don't have any enemies so i want to import all of that and let me start with the palm trees however we have a problem with the palm trees here because we do not have a tile set for the palm trees so let me actually open the folder with the palm trees so here i have my folder with the terrain and in there i have pawn vg which is a background pawn then i have a palm large which is different animation frames so all of this should be the same poem and then i have a palm small and then i have a crate but all of these are just individual images it's not a tile like terrain tiles and as a consequence we couldn't just import all of this as a tile set instead if i go back and i want to create a new tile site here i cannot select based on tileset image instead it's a collection of images and now we have to select a name and let's call this palms and save s again and again i want to put this in my tile set and now we get an empty looking file and essentially what we have to do now let me open up my folder again in here we have to drag and drop different things so let me start with my palm small in here we have the different animation frames and i just want to grab one of them let's say small one and i just drag and drop it into here and now i have it available and i want to do the same thing for the other ones as well so let's say large one and then i go back to my pawn pg and bg palm one and there we go now i have a couple of different palm trees inside of my level editor and now if i go back to my main tab i have a palm step in here as well and now i can just select them and place them wherever i want them to be but before we can do that i first again have to create another layer so let me create a tile layer and i call this one fg palms for foreground pawns because we also have a background palm that are supposed to be on their own layer but now really all you have to do is to move these palm trees around like all the other tiles we have used so far so let me place one here place a larger one and just place stuff all around the map and i'm not going to worry too much in terms of how this is going to look because that's not the part of this tutorial but obviously in your case if you want to make a nice looking level you want to spend a bit more time in this i can also place some palms on the level as decoration which i think looks very nice so let me place one here and one here and a couple around here and let's say a few more at the start one here as well and yeah i think that looks respectable so now we have a bunch of different palm trees and all of them later on in the game are going to be collidable with the player but i also want to have the background palm trees and those are just to be there for show so there's not supposed to be any collision for them so i want to create another layer and let's call this one bg palms and this should be all the way at the bottom because it needs to be behind everything else and now if i zoom back in again i can drag my palm wherever i want it to be and add some decorative palms to the level and let me just place it all around and in here again just play stuff wherever you think it looks good it's really entirely up to you and all right with that our level really is starting to shape up to look quite good and that is actually all the tools you are really going to need to set up any kind of level and let's actually do an exercise to practice this in the terrain folder there's a great file import this one and then place the crates all across the map wherever you think they're looking good all right so the first thing we have to do is to create a new tile set and it's again a collection of images and let's call this one crates and let's save it and again i want to go to my tile sets and save it in here and now again i have an empty thing and let me go back to my folder and in the terrain folder we have a crate and i just want to drag and drop it into here and well that's all we needed so now if i go back to my main level there's a new tab called crates and now i can select my crate and let me zoom in a bit again i can just place a couple of crates all across the level and well again wherever they look the best um i guess this one here i'm not sure if the player could jump on this because it is quite high so let me actually move the coin a tiny bit up so to my coin tiles i want to leave this coin and place a new one right on top and this should be a good distance to jump for the player and this one here should also be doable and let me place a coin here as well ah and now i realized i did make a mistake because we have not created a new layer for that crates which well would cause problems later on so i press ctrl z a couple of times to remove all of the crates it's really a very easy mistake to make i want to create a new tile layer and call it crates and this i want to be behind the grass and well now let's do all of this again let's place a couple of crates all across the map we can put one here as well let's place one here space one here i guess one there and then let's place one here and now let's move the coin again one place up and really make sure you are on the coin layer otherwise you are going to end up in problems and i place one here as well and let's go back to my crates and let's place a couple of crates in here as well uh not there and okay so with that we have a level that is really starting to look good and really make sure you always draw stuff on the right layer it is a really easy thing to mess up and i guess the easiest way to double check this is if you hide specific layers you know what's going to disappear on the map and in my case this is looking quite good so yeah i think this is all working but now we are going to need two more things number one is the enemies and number two is the player so where i want to spawn my player and where the level is supposed to end and this is also going to be a tile so let me explain and let's do this with the player so i first of all want to create a new tie layer that is for the player and let's place it all the way at the top and now i also want to create a new tile set and this is going to be a tileset image and let me browse and if we go to graphics there's character and if i zoom in a bit there's a file called setup tiles and if we open that one i can save it as tile sets for the setup tiles let's actually call it player tiles that makes a bit more sense and now we have start and end and well in my level i want to use these two player tiles setup tiles to determine where my player is starting and ending and well i just want my player to start here and then the end of the level should be let's put it here and that way i can control exactly where my level is going to start and where it's going to end and now finally i want to import my enemies and this is also going to be on its own layer so i create a new layer and this one i call enemies and let's place it below the player although it really doesn't matter all that much and now i want to create a new tile set again and let me go to graphics and there's enemy and there's also a setup tile and let's open this one and let's save it and again i want to go to my tile sets this is going to be the last one and let's call this the enemy tiles and now we have something weird we have our enemy and then we have a red square and for now let's focus on the enemy so i go back to my level and now i can just place where i want to have an enemy and let me select this one here now i can just place the enemies on the map so let's place one here let's place two here let's say one here and one here then i can place let's say two here and i guess now it looks a bit weird that they are in front of the palm trees so let me put the enemies below the palm trees and that is looking better so now we have our enemies on the map so what is this red square form so let me explain basically in the actual game i could approach the enemy movement in two different ways i could give them really complicated collision detections so that let's say for so let's say this enemy here i could check if this guy's on the floor or if he's in front of a cliff like here or here or i could check if he's colliding with a box i can do lots of different things however this would also be really complicated because i would have to add a ton of code for the well different collisions and to understand what the enemy is doing which would be a lot of code so i'm not going to do that instead what i'm going to do is i'm going to only move the enemy either left or right so they don't have any gravity they don't have any proper collision detection they don't really do anything besides moving left and right and then this red rectangle here is to give them a constraint so all i'm really going to do for the enemy i am going to move it left until it hits an obstacle and i'm going to put an obstacle here and if that's the case he's moving right again until he hits another obstacle so i'm going to put one here as well and that way our enemy movement is going to be significantly easier because we don't have to worry about gravity proper collisions all of that stuff and for that we have these red squares so i'm going to create a new tile layer and i call this one constrains and now i'm just going to place these constraints wherever i want this enemy to turn around and this i can do for all of them so there's going to be one here and one here and one here then one on top and let's say one here and then there's one here and not there here so this is going to allow me to specifically tell where an enemy is supposed to turn around which gives me a lot of control over where stuff is going to be and with that we have our entire level setup so this actually works out really fast once you have the basic files and once you have all of this you can also create new levels really really fast it doesn't take all that long so now what we can do if i save the file i can go to file and export s and then again i end up in my folders and then here i want to go to levels and this is going to be level 0. so in here i want to save all of this and now you might be wondering what are we actually going to save so let me open all of this so i go to my level to level 0 and in here we have what's called comma separated values or comma separated value files and let me open the one for terrain and in here you can see something really strange we get a whole bunch of negative one and then sometimes we get a zero we get a four we get a five six so what do these numbers mean and well the answer is quite easy let me go back to tiled and let me go to my terrain tiles and let me zoom in a tiny bit so if i select the top left one in here if you look at the properties you can see id of zero and this is what is actually being exported literally all we are exporting uh let me actually go back to my actual level so what we're actually exporting is not any kind of image or anything of that sort instead all we're exporting is the information for each of the tile so on the top left this tile here would be negative one this one would also be negative one because it's empty however if we get to a tile like this one here this would get a tile of zero and it would get zero because if i go to my terrain tiles and select zero here you can see in the top left we have an id of zero so this one here would have an id of zero the one to the right of it i think is going to have an id of one and then each successive one is going to have a id of one one one and the next one is going to have an id of two and let me actually double check so if i click on them this time here is going to have the id of one at the top left and then for the one corner tile we have an id of two so this one here works out quite well and this way we can tell exactly where stuff is supposed to be and we are going to do this for literally every single one of these tile layers so we have one for the terrain layer one for the player layer one for grass palms enemies grades and so on so we have quite a few different layers to import into pie game and well this is going to be the next part and then here we have to address a couple of different things so let me go through what we are going to do number one we have to import the comma separated value file into pygame then number two we also have to import all of our images and we are going to start with the terrain file that's the most complicated one so what we are going to do here is to import a tile site into pygame and to slice it into parts that we are going to need and then number three we are actually going to use those bits of information to lay out the level in pi games so we can see it but that is going to be quite a bit of code but let's actually go into pygame and let's have a look at this all right so here we are in pygame and right now we have a very simple setup so if i run this code we get a pretty basic looking screen that has a screen dimension of 1280 by 720 and it shows plain black and we are well not doing very much so first of all we have to add a couple of things here to make this a bit more responsive so i know right now for example that my screen is not 720 pixels high so i want to adjust this a tiny bit and for that i'm going to create a new file and let me save it oh and by the way if this is our level setup i am in the code section and in there i want to create a settings.pi file and in here i first of all want to create a vertical tile number and in my case this is 11. and this is the same number i picked earlier when i created the map and tiled and another number i picked in there is the tile size and in my case this is 64. and now with that information i can get a screen height and really all that is going to be is my vertical tile number multiplied by my tile size so that way we are going to have the same height that we created earlier in the tile map editor and then besides that i also want to get a screen width which can just be a plain number in my case 1200 but in here choose essentially what works best on your computer it doesn't matter all that much for the functioning of the game but with that i can go back to my main file and from settings import everything and this way i can still keep my screen width and screen height so these two variables here now come from my settings file and as a consequence i can get rid of the ones i've declared inside of this file so if i run out of this we still get the same black screen the only difference now is that this is not 720 pixels high anymore instead it should be 704 if mf is right but well you can't really see that and it doesn't matter all that much but now we have our basic setup for the window next up we can actually start working on the level so before we import anything we first need some kind of class that organizes our game and for that i want to create another new file and this one i'm going to save as level dot pi and the first thing i have to do in here is to import pi game as always and then i just want to create a class called level it does not inherit from anything else but we do need an init method which is actually going to become quite long and then here i want to specify a couple of parameters the first one is going to be the level data so the actual information that we created earlier in the tile map and we are going to store all of that in a dictionary i'll show you later how that is going to work besides that i want to get a surface so the display surface of our window and that is actually all we need for now it wasn't actually all that much and the first thing we have to do in here is to create self.display surface and this is just going to be the surface we pass into here and then besides that i want to create another method and this i will call run and in here later on i'm going to run the entire game or well the entire level but for now we're just going to add pass in here so this is a very basic setup now what i want to do with that in my main file i want to import from level import level and now i can just create an instance of this level we're going to pass the arguments in there in just a second and now in here i can just call level dot run and this way we can write our entire game logic inside of this run method and we don't have to add a ton of code in here we're just going to make our life a bit easier so now we have to figure out the arguments for our level and let me just copy them so we can work with them a bit more easily so in here we need the level data and our surface and the surface is the easier part because literally all we want is this display surface or our screen so really we just have to pass it in here and we are good to go this part is very easy so i literally just going to type screen in here but now we are going to need some level data and what this is going to be is essentially a dictionary with the link to all of our csv files because they basically contain the blueprint of our level and this is going to be quite a complex dictionary so i'm going to store all of this in another separate file and let me save this as game data dot pi and in my case this is going to look something like this so we start with a dictionary and the first key is called terrain and terrain has a fairly long file path so first of all we are going up one folder then we go to levels then to the folder 0 and then we pick the level 0 terrain.csv and let me actually illustrate how this is going to look in the actual folder so here you can see the code that we are working with so we have gamedata level main and settings and from there i want to go one folder up and that is going to be in our code this double dot so if you ever add in your file path a double dot you're going up one folder so now we are in the parent folder where we have code graphics and levels and i want to go to levels then to zero and now i have all of my csv files and the one we are looking at right now is level zero underscore terrain and that is this one up here and well then we are doing the exact same thing for all the other files as well so this is a dictionary that targets all of our csv files and then this is what i want to pass inside of this argument here so first of all i have to import it so from game underscore data import level zero and just pass it in level zero and for now let's just try if this works and we don't get an error message which is generally a good sign cool now first of all before we continue let's talk about why this is helpful so in this case you might be wondering why do we store all of this data inside of a dictionary and the answer here is organization later on when i have different levels so in a future tutorial this setup allows me to just replace this argument here and get a new level so later on this is not going to have just level zero there's also going to be level 1 level 2 level 3 and so on and all i have to do to load each individual level is to load this class here and pass in a different argument and that way it's going to be very easy for us to organize our game and especially after creating an overworld organizing our game like this is going to make our life much easier so with that we have our data in our class so now i can close the game data file and go to my level i can also close settings we don't need it anymore so now in here we first have to figure out how we can actually access our level data and that is then going to be about how can we import a csv file and in here we are lucky because csv files are very commonplace for basically any kind of database so python has lots of tools in build to make all of this work and there literally is a whole inbuilt python module called csv so this we can use very well to make all of this work but let me talk through how we are going to approach this and let me do this straight in code this is going to be best so here we are back in the level class and what i want to create let's start with the terrain and let's call it terrain layout so in this we just want to import our csv data and for that i want to create a new function and this i called import csv layout and into this we pass one argument and that is our level data and in there we want to get the terrain key or the value associated with this key so now we have to create this file here and since i am going to use this function quite often i'm going to put this in another new file and this i call support dot pi so in here i want to define a new function that is called import underscore csv dot layout i think i called it yes and this one is going to need one argument and let's call it a path because this is literally what we are going to get so this data here is going to give us a file path to a csv file and this is what we want to import so now we have to figure out how to import a csv file and for that we are going to need the let's call it import csv and this module will give us a lot of different functionality to work with csv files although we don't really need all that much we only really need one function inside of here so i'm not going to import all of csv instead from csv import reader so this allows us to read a csv file and this is really all we want to do for example we don't want to write a csv file so now we have to figure out how to actually open this csv file and you are doing that with the command with open and in brackets you have to pass in the path you want to target so this is path in my case and now we need s map and essentially what this map here is doing is that it functions as a variable that we can work with that represents this path here so right now we're essentially storing all of our csv inside of this map and this allows us to work with this data quite a bit more easily and all of this is actually vanilla python so right now we could run this without importing anything so now we have the csv file available in our python document but now i actually want to read the file and convert it to something in python and i want to store all of this in a variable i call level and for that we are going to need our reader method and in here we have to pass in two different arguments the first one is the csv data and then what is called a delimiter and well our csv file is literally just this map that's the easy part now with that what's it delimiter and the answer here is actually quite simple all python really wants to know here is what we're using to separate each individual data point inside of our csv file so in our case this is literally just going to be a comma because we have a file type called comma separated value so this should be quite obvious here but if you had a different kind of file type with a semicolon or a dot or just a space you would pass something else in here but this is basically all we needed for this part so now we have imported the csv file and let's actually print what we are getting here and i hope i get all of the file paths right so now i can go back to my level file and since we are running this we should be seeing something so back in my main file let's try this and we are getting an error because import csv layout is not defined so this is quite easy because i did not import this thing here so from support import import csv layout so now let's try this again and now we can see at the bottom csv reader object at one point in our memory so at the very least we know that we are not getting an error that is always a good start but obviously this isn't particularly helpful but now this variable here we can loop over and this is exactly what we want to do so what i want to do is for row in level and now let's actually print our row i think we should be able to see what's in there now and there we can see all of our data points we have created earlier so for example here we can see our first row then our second row and all of these are negative one because there's no tile here however if i go a bit further down we can see a 14 we can see 12 13 and quite a bit more so we know we have the data correctly imported so that's a really good start but now i don't just want to print it instead i want to put it into something else and really what i want to do is to create first a new variable that i call terrain map and this is just going to be an empty list and then inside of this for loop i'm going to get my terrain map and append each row and there is one slight complication because this data here i want to make sure to convert this into a list which is going to make it easier to work with it the data type can sometimes be a bit finicky but if we're importing like this all we get at the end is the list where each row is one row of our game and that is exactly what we want so at the end of all of this i can just return my terrain map so now when i run this function here all that's being imported is the layout that i want to work with so in my level class let's print this in here so terrain layout and now let me run all of this and now we can see let me close this now we have imported all of our data and we can see it inside of our level class obviously right now this well doesn't really look that feasible because it's just a crazy long list but we know we have it that's a really good start but now we have to convert this to something that we can actually use in pygame so let me talk through what i am going to do right now we essentially have a table of where stuff needs to be so we know for example that in the top left corner at position 0 and 0 they are supposed to be nothing and then right next to that so in position 0 and 1 there's also supposed to be nothing and then further down let's say at position 10 and 3 we want to have a tile with the id of 0. so we know how the tiles have to be in relation to each other but we don't know how these ids translate to a position on our pi game screen fortunately that is very easily done because all we have to do is to multiply the x and the y position by the title size so for example the top left tile is at position 0 and 0. this one stays exactly the same however the one right next to that with the row 0 and the column 1. this one should be at position 0 and 64. since each of our tiles is 64 pixels high and 64 pixels wide so really all we have to do is to multiply the column by one and the row by one and that way we are translating the table position of our tile into the actual position on the screen and then we can use this position to create a sprite with a size of 64 and 64. and that way we get our entire level and if you followed the earlier tutorial there we had list with strings inside and this was basically the same kind of data we have now except in a more basic setup but really our csv data is very similar compared to that list with strings so the logic here is going to be very similar but let me go through this step by step and let's actually implement all of this in code so here i'm back in my level class and i want to get rid of this print statement here and instead i want to create a new sprite group and let's call this one terrain sprites and in here you might be tempted to use something like pygm.sprite.group but in my case i am not going to do that instead i'm going to create a function that is going to return a sprite group and let's call this one self dot create tile group and this one i do want to be part of the level class because this is really important for the level but in here i want to pass in two bits of information first of all i want to put my terrain layout in here so i know what the blueprint for this layer is going to be and besides that i also want to give it a string and i'm going to call this terrain and this terrain is essentially going to be used so we can figure out what graphics we are going to work with so for example for this terrain layout we know that it is for the terrain but pygame does not it just sees a csv file over the data from a csv file so we don't know if this is from the terrain or not and let me illustrate why this is important all right so here we are back in the titled editor and one thing that is really important that i didn't show earlier is let me click on one of the tiles so right now we have here our terrain tiles and you can see in the top left this one has the id of zero so this is kind of what we saw earlier that if you click on one two three and so on you always get the proper id for these tiles and this by itself is working really well however now let me open the coin tiles and now if i click on the golden coin this one also has the id of zero and then if i click on the silver coin this one has the id of one so essentially the problem here is that when child is importing these tile sets it always starts at 0 and then goes upwards and if we have different graphics it always starts from 0. and this is a massive problem for us because in our csv files we want to clearly separate what id belongs to what tile and if you have multiple ids with zero for example and that could mean a golden coin some grass a terrain tile a setup file we would end up in a ton of problems so we have to specify what kind of graphic we are looking at this is really important so back in my code this terrain is really just there to make sure that we are looking at the terrain graphics and not at the coin graphics not that the anime graphics the terrain graphics and this is the information that we couldn't get from this terrain layout here and this is why we need this argument so i hope that makes sense but now let's create this method so define create tile group and in here we need self we will need the layout and we will need the type i called it and now essentially what we have to do is to create a loop that will cycle through this terrain layout and then whatever we create in there we want to put into a sprite group so by the end of this loop we can return a sprite group in here so the first thing that we have to do in here is to create a sprite group so spread group and this is going to be highgame.sprite.com and towards this group we're going to add all of our sprites and then return this bright group at the end of this loop and well now we just have to cycle through this layout so i want to go for row in layout and this is going to tell me what my row is going to be and let me actually print this row and see what is going to happen so back in my main file let me run this and now if i close all of this now i can tell this is my first row this is my second row this is my third row and so on oh well this is row of the index zero but now we have a problem because while i can get the information of what is inside of this row what i really want to know is what the index of this one here is going to be so the information i want to get is that this here is going to be row 0 this is going to be row 1 this is row 2 and row 3 and so on so right now this information doesn't help me all that much but well for that we can use the enumerate method so let me put this into brackets and i want to get the enumerate method and in here i want to get my row index and my row and essentially all that the enumerate method does is it tells us inside of this loop on what index we are on so the first index would be 0 then 1 then 2 and so on and let me actually print what we are going to see so i first want to see my row index and then my row and now let's try this and now i can see that for row 0 i have this row here then i have row number one and then i get all of this and this is then already going to give us the y position of our tile so really all we have to do is multiply this by 64 in our case and then all of those would be in position zero and all of these here would be at position 64 and then so on so now we have the y position and now inside of that we have to create another for loop to get the x position so now we want to loop over every single item inside of the row and i think this would be a pretty good exercise for you so if you want to code along try to write the enter for loop to target every single value inside of the row and also get the index on what that row is on all right so what i want to do is to get for column index and let's call it value in enumerate and now i want to get the row so i want to cycle through every single item inside of this row and i want to get the index and the value and now inside of this i can try to figure out where stuff is going to be and well all i have to figure out in here is first of all if an item is negative 1 or not because at position negative 1 we know there isn't supposed to be anything so i can already start with an if value ideally spelled correctly is different from negative one and only if that's the case i want to do something but there's one problem here that inside of this data set we don't have numbers instead we have strings so this minus one here has to be a string of a negative one and this can be quite confusing but when we import this we don't import numbers instead we import strings of numbers can be a very easy source of mistakes but once we have that we now know where stuff needs to be so we have a row and we have a column and from that information we can get our x and our y value and for the x value literally all i want to do is i want to get my column index and multiply it by the tile size and then for y this is going to be the row index multiplied by the tile size as well right now we don't have access to our tile size but let me open it again from settings so here in setting we do have our tile size so all we really have to do is from settings import tile size and that way we can access it inside of here so already with that we have some basic information and now i want to target my terrain so i just going to add if type is equal to terrain and now on here i want to create a sprite and for now this is just going to be a tile and this tile is going to have three bits of information the first is going to be the tile size then x and then y so we know how big the title is going to be and where it's going to be and then i'm going to get my sprite group and add this sprite towards it and let me put all of this a bit closer together so for now we are going to get a basic sprite although we do have to create it and for now this sprite is not going to show a graphic that comes later for now i just want to focus on the layout so well we have to create this class here so let me create another new file and i'm going to save this one as tiles.pi and in here we have to import pi game and then i want to create a class called tile and this one is going to be a pie game dot sprite dot sprite so we have to inherit from it and and there we have to create an init method that gets self as always then a size then x and then y and now on the first line here as always we need super dot init to get the proper inheritance and now in here we don't really need all that much complicated stuff so we first want to get self.image and then self.rect afterwards and well in this setup all i want to get is pygame.surface and then in here for x and y i just want to get my size and my size since we well do want a square and then self.rect is going to be self.image.get underscore rect and then the top left is going to be at position x and y and there's one more thing that we are going to need and that is self.image.fill and let's say in my case for now i want to fill it with a gray color and if we didn't do that the entire thing would be black and since our background is black we wouldn't see anything so this is then going to be our very basic setup and well let's run this and see if we're getting an error so if i run this we are getting an error as always because i did not import this tile here but that is very easily done because all i need is from tiles import tile and now let's try this again and now we can see that we can't see anything and since we did not want an error which we don't get this is looking good cool but now what we do have is a sprite group inside of here and what we can do now is to get this self.terrain sprites and i just want to draw it and now to figure out what surface to draw it on and in my case i just want to get my display surface and now if i run this there we can see the basic layout of our level obviously it doesn't look particularly good right now but you can tell it's the same layout we had earlier in our tiled editor so this is a really good start and next up we can also make this entire thing scrollable which is very easily especially if you watch the first part of this tutorial series but literally all you have to do back in my tile i want to give this one another method that is called update and this one itself and then is shift and then literally all we have to do is self.rect.x plus equal that shift and now back in my level i can call self dot terrain sprites dot update and now in here i can just add in a number let's say one for now and now back in my main file if i run all of this now we can see our level moving right now in the wrong direction so let's go with negative four to see the entire thing and now let's try this and there you can see our entire terrain and that is already looking really good so this is working quite well and now this number later on we are going to change when the player is moving so this should be an attribute of the class and let's call this self.world shift and let me create all of this early on and let's place it right here and for now it's going to be zero and i think here it's going to be really helpful to use comments so let's call this general setup and this is going to be the terrain set up this init class here is going to be quite long because essentially what we have to do is what we have done for the terrain we have to do for every single layer of what we created in the tiled editor so this is going to be quite a few lines of code but before we get to that we first have to figure out one more thing and that is for my terrain i don't want to have a plain color instead i want this to have a specific graphic from our terrain tiles so what we have to figure out is how to import this terrain graphic and then how to slice it up so we can use it in here and well let's go through this step by step and the code inside of this if statement i first want to create a list with all of our terrain tiles and let's call this one terrain child list and to get this list i want to create another function let's call it import cut graphics and this one is going to need a specific string which is just going to be the path towards this image which in my case looks like this so we go one fold up we go to the graphics folder then terrain then terrain tiles and then dot png and everything else is going to happen inside of this function and i want to create it inside of my support.pi file i think it's quite good for the input functions in here so let's call it define import cut graphic and we need a path and now the very first thing that we have to do in here is to fully import this graphic and put it on its own surface so i want to create a surface and this is going to be pygame.image.load and we want to get the path and don't forget convert alpha so we don't tank the performance now we do know how big each title is going to be it's 64 by 64 pixels but besides that i also want to know how many slices i should take of the surface and well for that i'm going to create two new variables let's call it tile num x and tile num y and really all i'm going to do is to divide the width of this surface by the tile size and that way i dynamically know how many tiles i am going to get and this could actually be a really good exercise for you try to figure out dynamically how many tiles are going to be on this graphic all right so let's do it together now the first one we are going to need is the width and the height of this surface so well i want to get surface dot get size don't forget the brackets and this is going to return the tuple with zero being the width and one being the height so let me actually copy all of this and let's put a one in here and then this i just have to divide by my tile size for both of these statements and now right now i don't have access to my tile size in here so from settings import tile size and right now this might return a double which would be a problem so i'm going to convert all of this to an integer and that way it's going to make my life much easier so now i know how many tiles are going to be inside of this graphic which is actually quite important because what i want to do now is for row and range tile num y so i go for each row in this image and then for column in range tile num x so i am essentially going to use these two variables here to figure out how many tiles i want to get out of this surface and this is actually going to be quite similar compared to what we have done in here the only difference is that now we are not using the enumerate method for the simple reason that we don't need it because this tile num y and this tandem x are numbers by themselves already so i think in my case tile number y is going to be four so this time number y is four so if we use range we are going to get the numbers zero one two three and four and the same for tile num x and that way we already know by the content of this variable on what index we are going to be on so we don't need the enumerate method and well now we can just continue what we have done in here because now all i want to get is the x and the y position so i want to get an x and a y position and well all we have to do in here for the x position is to get my column multiplied by my tile size and then for my y is going to be row multiplied by my tile size and literally all we have done in here is the same thing we have done it here bars some minor differences so now we know what position we are on in this tile set and also how much of a tile we want to cut out so with that information i can create a new surface and this new surface is literally just going to be pygame dot surface with my tile size and my tile size so with this line here we are just going to create a square surface that is 64 by 64 pixels and onto the surface i want to blit one specific part of our main image that we just imported so this thing here our terrain tiles and for that we are going to need blit so let me explain what i am going to do first of all i want to get my new surface and then blit and what i want to put on the surface is well my surface i just imported so this surface i have put up here and this i want to bleed on this new surface but i don't want to bleed the entire thing i don't want to bleed one specific slice that is 64 by 64 pixels and this split allows us to do because now for the second argument we need a position and the position in my case is just going to be x and y so right now we would be creating a massively too large blitz on this new surface but blit also accepts a third argument and that is a rectangle and this is essentially going to be a mask that we only want to cut out one specific part of this surface and not split the entire thing and in here we have to pass in a rectangle so pygame dot rect and now the arguments we are going to need is the top the left the width and the height and width and height are both very simple because we just want the tile size again and now for the top and the left we also have this information this is just going to be x and y and i think this part might be slightly confusing so let me explain it on the actual terrain tile set and this one looks like this and literally all we have done is we first got a top left point and then we picked up one specific slice of this tile set so for example for the first one it looked something like this and only this part we have blitted on a new surface and we got this information by first getting this point here so this was the row and the column and then we multiply this by 64 and 64. so in this case the state 0 and 0. and then the size of this slice we already knew it's always 64 by 64. so then the next slice was going to be this one the next slice was going to be this one then we picked up this slice and so on then we went to the second row and got something like this and then we just kept on going and always picked up one specific slide and then blitted this slice on a new surface that's literally all we have done in here so i hope that makes sense it does get slightly more complex but well if you just look at this it's not actually all that complicated and this way we have a completely new surface with one specific part that we actually want and now all we have to figure out is how to put this on its own list and for that i'm just going to create let's call it cut tiles this is going to be an empty list and at the end of this function i want to return my cut tiles so now all we have to do is to get the cut tiles and append the new surface and this is all we needed inside of this one class so now i can go back to my level and this time i am not going to forget to import this function it's a mistake i make all the time and now let's trail of this and we are getting an error and let me see what the problem here is we are getting an import error that python cannot import import cut graphics and this is a very common error and usually what it means is that you misspelled something so let's have a look so in my level i import import cut graphics and in my support file i have called this import cut graphic so the only problem here is this needs an s and now let's try this again and now we're getting another error name pie game is not defined let's have a look and yeah also another thing we need to import pi game and now four times the charm there we go now we can import all of this we don't get an error message anymore so this is a good sign and now we have a list of our terrain tiles in here available in the class which is super useful and now we have to figure out how to put this inside of this tile here and well that's actually very simple because all we have to do is first of all to get a new tile surface so i want to pick the right tile from this list depending on what value we are looping over right now and in here we can approach this very intelligently because entitled in the id we always start in the top left and then go to the right and once we reach the end of the row we go to the next row and start from the left to the right and in this function here we have used the very same logic so each index inside of this list is going to have the same id that we created entitled so all we really have to do is to get this terrain tile list and then in there get an integer of our value and this way we automatically get the right tile for the simple reason that tiled and the list returned by this function here are following the same naming scheme and now the last thing we have to figure out is how to pass this tile surface into this tile here and for that let me go to my tiles.pi file and in here i want to keep the title class as it is with one difference i want to remove the fill command and instead of changing this class i want to create a new one and let's call it stat static tile and this one now is going to inherit from the title class so instead of inheriting from sprite we're going to inherit from tile and tile itself inherits from sprite now why am i going to do that well later on in this tutorial we are going to create lots of different tiles so we have a tile for the grass for the coin for the enemies for lots of different things and all of these are going to share lots of similarities for example they are all going to have this update method here and if i kept on creating new classes that all of these attributes in common it would be quite a waste of writing so instead i'm going to work quite a bit with inheritance here to create the titles and that way i'm going to save an enormous amount of writing and in here first of all we are going to need the init method as always and i need self and besides that i want to get a size an x a y and now i want to get a surface and now the first thing i have to do in here is to get my super and then dunder init method and now we are essentially initiating this class inside of our static tile so i have to give it the same arguments and i have all of the parameters so i can just copy them and pass them in here so now i have essentially copied this tile and now i just want to make one individual change and that is going to be self.image is going to be the surface and that's literally all i had to do so instead of copying this entire thing i just copied this with inheritance and then changed one line of code which is going to make my life significantly easier because we are going to copy this process multiple times but now we have a static tile and let me import it in our level so static tile and then the sprite is going to be aesthetic tile and now we still need tire size x and y but now i also want the tile surface and now let's trail of this let me run it and we are getting an error and the reason for it is that our super object gotten in it so let's have a look so in my tiles all that i really did wrong was i forgot the brackets and now let's try all of this and we are getting something slightly weird so we can't see the top left tile but nothing else and i just realized i made one mistake in the support class because right now this x and y is wrong it should be zero and zero and the issue here is that we always want to put the graphic on the top left of this new surface and this did work in the top left because their x and y were both zero however once we got larger than that we always put the graphic outside of this surface so it ended up being black but now once we have that i can run this and now we can see the entire level so this is working very nicely and now what we can do i can set this word shift to let's say negative five and now let's run all of this and now we can see the level going by very very nicely and this is looking great and cool so with that we have imported one layer of our tile really all we have to do now is repeat this process about seven times and then we are good to go and as a matter of fact the terrain tile list was the most complicated one because for this one we had to separate a graphic this we don't have to do for any of the other layers so our life is going to be significantly easier but well with that the next big section is going to be to import all of the different layers and in here i am just going to repeat the same process except in a slightly different way for each of them because they all have slightly different requirements so let's go for them step by step and let's start with the grass tiles those are going to be the most similar to our terrain and in here we still have to cut some graphics and then put all of this on a new title and well let's jump straight into our code and let's have a look at that so here i'm back in the level and i want to add a new section here that i call grass setup and literally all i'm going to do is create a new grass layout and then i import csv layout level data and i've got this one grass so essentially what we're doing i just copy this paste it in here and then change a couple of names but the underlying principle is identical so this layout would give us all we need to place the grass tiles so now we would need self dot grass sprites and this would be self dot create tile group we need our grass layout and then in here i pass in the string grass again the exact same thing what we have done here and now in this for loop i want to add another if statement that if my type is equal to grass then i want to first create a new grass tile list and in here i can just reuse this function and the path in here is the higher up folder then graphics then decoration then grass and then grass dot png and once we have that i can create another tiled surface and this is going to be my grass tile list and then i just pick the integer of the value literally the same thing that we have done up here so this is again the very same setup so just like we have done up here we are essentially copying the same layout and then finally i can create a new sprite and this is also going to be a static tile so we need to tile size we need x we need y and now we are going to need a tiled surface and what we can do now is this line here we can place all the way at the end so that way we only have to call it once and let me add a bit of white space in here so it's slightly easier to read and well this way we are going to have our grass now the last thing we have to do is to actually display all of this inside of our run method so let's call it grass and self dot grass sprites draw self dot display surface and then we also want to get self dot grass sprites dot update and self.world shift and i guess the update method should always come before the draw method although it's not strictly necessary and okay this should be working now let's try so my main method i'm running this and now we can see the grass this is looking very nice so with that with our terrain and our grass next up i want to work on the let's say the crates let's not use by crates that's how you use by crates and in here same thing we have a great layout and this is going to be import csv layout level data and in there we have a key called crates and let me just start this properly and then self.grade sprites is going to be self.create tile group with my create layout and then create and then in this for loop again i want to have another if statement that if type is equal to crate or crates actually we want to do something else and this time we are going to have a slightly different approach and let me explain why for the terrain and the grass we had to cut up a graphic but for our crates we only have a single graphic so we don't have to do that and this is actually going to make things quite a bit easier and really all i want to do in here is to create a sprite and this sprite is going to be from the class crate something we have not created yet and this one is going to need three different arguments the tile size x and y and now in my tiles file i can create this so i want to create a new class that i call create and in here i want to inherit from static tile and then i still need an init method that needs self size x and y and then inside of that we again need our super and init method and then here we have to get all the arguments for all of this so we need the size we need x y and the surface and now for the surface literally all that we need is the image of the crate and there only is a single one so what i want to do here is pygame.image.load and then the path to the create is this one here so we go up a folder we go to graphics terrain create.png and then this has to be convert alphbot but now for this one we do have a problem and let me explain why by drawing so right now our tile looks like this and it is 64 by 64 pixels and this is working perfectly fine for both the grass and the terrain however for the crates it is not going to work because the crate is not as high it's only i think 48 pixels high and it's also not as wide so it's only something like this so the crate is not going to fill the entire space of the tile and if we didn't account for that we would have a problem because pygame always puts stuff in the top left so by default our crate would start here and since it doesn't cover the entire height it would kind of float in the air which well would look very very silly so we would have to account for that but i guess let me first do it without the offset so you can see what i'm talking about and without the offset this is actually all we needed so i can go back to my level and make sure i import crate and now this should already be working by itself so down here i can create a crate so in itself dot crate sprites dot update self dot world shift self dot create sprites dot draw and self dot display surface and now let's try this and there you can see what i'm talking about our crates are floating in the air which well looks very very silly so we have to give them an offset and this is going to happen in this class as well and essentially all i really want to do is to create an offset y and this in my case is going to be y plus this size and let me explain what this means let's say again this is going to be our tile with 64 by 64 pixels now the top line here let me use a different color for this the top line here is going to be y all the way at the top and from that we add the height or the tile size so once we add the size we are all the way at the bottom here so this point here is going to be our offset y now why is this point useful well now we can overwrite the rectangle argument and just place the mid bottom or bottom right and then our rectangle would start down here instead of the top left and that way our rectangle would always be at the bottom and we haven't done an exercise in a while so this might be a good thing to do now and essentially what i want you guys to do is to overwrite the rectangle argument and place the crate at the bottom could be the bottom left bottom right or mid bottom it's really up to you so first of all i want to overwrite self.rect and in here i'm going to need myself.image.getrekt and in my case i'm going to go with bottom left and in here i need a tuple with x and y and x in this case is just this x here the one we already have and y is just going to be my offset y and that way we are moving down our crates a tiny bit so it is actually at the bottom of this tile not at the top anymore and now back in my main file this is looking significantly better so we are making progress cool now next up we have a minor problem and let me explain why so right now we place the terrain the grass and the crates and all of these are static however for the rest of the tiles that we have to place they are all animated so we have to create a basic animation and this is going to involve a couple of steps number one we have to import lots of different art assets and we are going to write a specific function for that so we don't have to manually import a ton of stuff then next up we have to figure out a basic function to animate something which i already covered in the previous video but i will go over it again just in case you haven't watched that one and all of this is going to happen in its own separate class so this is what we also need to create so a couple of things to work on and let me do all of this in code it's best to explain this while i go along so here we are back in our level class and i want to go to my tiles and in here i want to create another class and this is called animated tile and this one is going to inherit from tile so we don't have to reinvent wheel and we still need an init method that needs self we need size x and y and now i need a path so in the previous examples we always had a surface because we only had a single image but for an animated tile we want a path to a folder with multiple images and we will then loop over these images later on and then here we still need our super init method that needs a size x and y and then the first thing we will need in here is self dot frames so all the frames we want inside of this class and this is going to happen inside of a function that i called import folder and this one is going to have a path and now we have to create this import folder and i want to do this in my support.pi file and let me minimize all the other stuff we don't need those and let me place this one all the way at the top so i want to import folder and this needs one argument which is a path and now we have to figure out the function to import all the images inside of a single folder and python has a specific module for this sort of thing it's called os so i want to import os however i only want a single method of os so there's no point importing all of it so what i want is from os import what is called walk and let me put it next to the others and walk is basically giving us the ability to walk through file paths and get the names of files inside of a folder which is very very useful and essentially you're going to use walk in a for loop so let's say for now for information in walk and walk just needs a path so what folder we are looking at and for now let me just print what we are going to get so now we have a basic import folder and if i go back to my tiles when we create this for now i just want to print what we are going to get so back in the level let's say for now i want to create my coins and for that i need a coin layout and this one is going to work just as the ones before so import csv layout then level data and in here it is called coins and then i want self dot coin sprites is going to be self dot create tile group we need the coin layout and then the string coins and now down here i want to create another if statement that if type is equal to coins then for now i want to create a sprite that is an animated tile and i have to import this one as well so animated tile and now we need the arguments which is size x y and path and size is just going to be tile size x and y we already have and now we are going to need a path and for the coin for now i am going to work with the gold coins so we need to go one fold up then to graphics coins and gold and inside of gold we have four different coins each for different part of the animation so now once we run our level class we should be seeing something so now we can actually work with animated tile so i want to go back to my tiles file and here now we have to work with animated tile and the first thing that i did forget is we have to import from support import import folder and now let's actually try if this is working so let me run the code in the main and now at the bottom we can see a couple of bits of information and let me go back to support so right now all the stuff you see at the bottom is this information here and there are three parts that are important here we first get the name of the folder we are importing and this we don't really care about because we already have it now the second part this bit here is any kind of folder that is inside of this folder we are targeting and in this case there is no folder inside so this list here is empty but then finally this list here is what we actually care about because these are the different images that we want to loop over so essentially we get three informations back and we only really care about this one here so we can safely disregard all of this stuff because we don't care about it so let me close all of this so instead of information i get the folder name i get sub folders and i get the image files and well i don't really care about the folder name and the subfolders so i'm going to replace them with an underscore and a double underscore and this way i indicate that this information just isn't relevant for me and now image files is going to be a list of different images so i can add another for loop that is going to be for image in image underscore files and in here i get the name of each file and it is really important i am only getting a name i'm not actually importing anything just yet but the name of the file we can use to create the full path and well let's call it default path and literally what that is going to be is i'm going to get the path i already have and that's the path to the folder to what's that i'm going to add a slash and then we are going to add the image so literally what we are going to do is we get the path we already have and we are adding the image name towards it and that way we are getting the full path to all of the files inside of this folder and that information we can now use to create a new surface and now all we need is pygame.image.load and pass in our full path and then convert alpha and this way we don't have to manually import every single one we just do it all in one function so with that i will get all of my surfaces but i also want to return them and for that i'm going to create a new variable let's call it surface list and this for now is just an empty list and inside of this for loop i just want to get my surface list and append my image surface and then at the end of this function i just want to return my surface list and that way we should be getting all of the images inside of this one particular folder and i could be running my code now and well let's actually do this and it is working so we don't get an error message but right now we don't use any of these images so well we at least know it's working but now i can go back to my animated tile and now i can work with this a little bit more and in here i want to create two new attributes the first one is going to be self dot frame index and by default this is going to be zero and then i want to overwrite self.image and this is literally just going to be self.frames and then we pick one index with self.frameindex and that way we are going to have an actual image so now what i can actually do is down here in my level class i can add another part that is called coins and this is just going to be self dot coin sprites dot update self dot world shift and self dot coin sprites dot draw self dot display surface and now let's try this and indeed we can see our coins they're not animated yet but that is going to come in just a second but at least we know it's working although if you look closely and let me set the world shift to zero so we can see a little bit better what's going to happen so now you can see the entire thing static and right now there's one problem with our coins and think of what the position of each gold coin is that you can see for example for the crate the 64 by 64 tile is roughly going to be something like this and for our crate we place it right in the bottom left and for the coin you can see it's way too far to the top left so later on besides animating it we also have to move it something like this so it's not in the top left of each tile instead it's in the middle of it that is something we are also going to work on but i guess step by step let's first animate this thing and let's talk about how animating this is going to work and i actually made a separate video on how to animate something and also if you followed the previous video this is also explained in there but let's go over it really quickly essentially what we want to do in our animated tile is to pick a different frame from self.frames and set it as our self.image and to achieve that we are going to update self.frame index so in the most basic sense all we have to do is update our self.frame index with plus equal one and then use that to get another image from self.frames however the problem with this setup is that our animation would run way too fast because we are picking a new image every 60 milliseconds it's just far too fast so instead i don't want to update myself.frame index by one i only want to update it by 0.15 and then we are only going to pick the next index once we are reaching the next integer so once we're reaching 1 2 and 3 and so on and i guess the other point you do have to remember is that self.frames only has four different frames inside so once we're reaching the end of that we have to set our frame index back to zero but that also isn't a big problem let's actually implement this so here i am back in my tiles and inside of animated tile i want to add another method that is called animate it does not need any arguments and in here i want to create the logic for our animation and the first string i want to get my frame index and plus equal 0.15 now this number i have picked only because it looks good you could choose another number if you think something else looks good it's perfectly fine now once we have that all we need to do is get my self.image and assign this to something new and again i want to get myself.frames and now self.frame index so we are essentially updating our self.frame index by a tiny number and at some point we are picking a new self.frames but now there are two problems the first one is that we can only select something by index if we have an integer and right now self.frame index is going to be a double so we have to turn this self.frame index to an integer which is very easy all we need is the in method so this was a very easy thing to fix and next up the problem is that this self.frames only has four frames inside so we have zero one two and three but if we keep on running this self.frame index we would very very fast end up with a number like four five six and so on and as a consequence we would get an error so ideally what we want to do is after we have reached three we want to move back to zero or to make this even more dynamic once we reach the end of self.frames we want to go back to zero and this we can also achieve quite easily is an if statement so try to write the if statement yourself that once we have reached the end of the length of our frames we want to set frame index back to zero all right so we do need an if statement and what i want to check if self dot frame index is greater or equal than the length of our self dot frames and if that is the case self dot frame index is going to be zero and that is all we needed to animate this kind of thing so with that we can now create an update method and be aware here let me scroll up once we create this update method we are overwriting this update method so once we create update we also have to cover this part here it's very easy to forget so let's first just copy the entire thing so self and shift and i just want to copy this line here so our coins move along with the level but besides that and let's put it right before i also want to call self dot animate and well that should be all we needed let's go back to our main file and let's try this now and there we go now we have animated coins which is looking quite nice but now we have the other problem that the coins have this weird offset to the top left and this we can work on quite easily but in my case i have a couple of animated tiles so instead of updating this here to adjust it for the coins i'm going to create a whole new class that is going to be coin and this one will inherit from animated tile and that way we can reuse this animated tile for the palm trees later on as well so we don't have to recreate this entire thing twice for the coins and for the palm trees but in here i just want to call my init method again and in here the arguments are going to be self we need a size we need x we need y and we are going to need a path and now as always we need super dot init and then here i want to pass in my size x y and the path so for now we are basically just recreating this entire thing and once we're calling this we basically have all of this copied and the only real update i want to make is to self.rect because by default we are placing this animated tile in the top left but for the rect i want to place this in the center so really all i have to do is self.image.getrekt and now i want to get center and now for the x and y i want to get center x and center underscore y so what we now have to figure out is how to get these two numbers and let me put them as their own variables so set the x and center y and in here we can think about what we have done earlier so when we place the crate we used this line here where let me draw this really quick so here's our 64 by 64 tile size so 64 and 64. and for the crate we went with the top left and then went all the way down okay that's a bit too far we went all the way down to here and then place the origin point of the crate to this bit here now for the coins we do want to do something similar but now we want to go from the top left so the point we already have only half way down so roughly here and then we want to go halfway to the right and this way we are going to end right at the middle of our tile so that's literally all we are going to do and to achieve that let's start with x we first want to get x by itself so that's the left side of our tile and towards that i want to get the integer of my size divided by 2. so this right now would be this offset here this is going to be our x and now besides that we have to get our y as well and that is also going to be quite easy because all we need is the same logic so we need y plus the integer of the size over 2. and now let me delete all this this is literally all we needed to place the coin in the center of the tile let me actually minimize all of the other classes it's getting a bit hard to read so now we have our coin that is basically an animated tile except with a slight offset but with that i can go back to my level get rid of animated tile because we don't need it anymore and i just want to use my coin and now animated tile is going to be a coin and now we've run all of this now we have our coins right in the middle so this is looking significantly better cool this is also working very well but now we have one more problem for the coins because we have two different kinds of coins we have a gold coin and a silver coin so in here i have to add another if statement that if my so this value here is going to be 0 i want to add a gold coin however if the value is 1 i want to add a silver coin and this should be quite a straightforward thing to do so let's try to do this as an exercise that i want you guys to add the if statement to either add a gold coin if our value is zero or silver coin if the value is one and both gold and silver coins are going to have the same coin class all right so literally all we are going to need is once we have our coins i want to check if value is equal to the string zero and if that is the case my sprite is going to be this one and if value is equal to the string 1 then my sprite let me just copy the entire line is going to be this one with the only difference now that we don't pick from the gold folder we pick from the silver folder and that is all we needed so now let's try this and now we can see silver coins and gold coins this is also working very very well all right so with that we have already quite a few different elements and i guess we can just keep on going and next up let's start working on the foreground palm trees let's call it fg palm layout and this one again is going to be import csv layout level data and in here i have called this one fg horns i believe let's actually double check this so game data foreground problems no underscore and then self dot fg underscore palm sprites and again self dot create tile group and in here fg pawn layout and i've called this one f g palms so now we have to do the exact same thing for palm trees so this is going to be another if statement that if type is equal to fg palms then i want to create another sprite that is now going to be from the class pawn and this is going to be very similar compared to the coins so again we are going to need a tile size we need x we need y and then we are going to need a path and for now let me go with this one here where we have graphics.terrain.palm small although later on we also have a large palm tree so this we will have to adjust for but step by step so first of all we have to create another class in our tiles and this is going to be palm tree or just palm and this one is also going to inherit from animated tile and in here we again need an init method that needs self size x y and a path and then instead of that as always we need our super dot init and we need size x y and path let's just leave it at this for now although later on again we will have to create an offset just like we have done for the coins but step by step so back in my level once i have this i also at the bottom want to create a foreground poems and this is going to be self dot fg palm sprites dot update with self dot world shift and self dot fg palm sprites dot draw self dot display surface and well let's just see how this is going to look so if i run this we are getting an error because palm is not defined because i am not importing it so paul now let's try this and now we have animated palm trees but they are all a little bit too far down so you can see it especially in the top right so in here it's very obvious the palm trees are way too low and the reason for that is that we have set the origin point in our tiled editor this is the origin point we actually placed but in pygame we always place the entire image at the top left so we placed it here so literally all we have to do is give each of these palm trees an offset to move them up by certain amount of pixels so all i have to do in my level i want to give this one an offset here because later on we have the small palm trees and the large palm trees and they might need different kinds of offset so in here i'm going to add another argument and for the small palm tree this was 38 and this is going to be a y offset so back in my tiles i have to add an offset in here and now in here i have to again create an offset y and this is going to be y and this time it's minus the offset so this is very similar compared to the offset for the crate except the difference now is that we are moving upwards not downwards and we are using a different number but same principle but now we just need self.wrecked dot top left and this is then going to be x and the offset y so we are essentially moving the entire rectangle up by a tiny bit and well let's try this now and this is looking significantly better and you could even be fancy here and give each of them a slightly more random offset to make it look more chaotic but well that's something you can do on your own time and now the last thing i'm going to need just like i've done for the coins there are different kinds of palm trees and i believe unless i got it wrong that if the value was equal to the string 1 then we want a small palm tree and let me copy this and if the value was 2 we want a pawn large and the offset for this one for me was 64. and let's try this and this does not seem right and i think the reason is this should be zero and one and now let's try this and this is looking much better so now we have all of our palm trees and they are animated by default so this is also quite nice cool and now that we have that besides the foreground palms i also want background palms and this is again going to be another section let's call this background palms and in here fg pawn layout is going to be let me actually just copy all of this because we are only going to change one letter for most of this so this is bg pawn sprites self.great tile group bg palm layout and bg palms and now inside of this while loop i want if type is equal to bg palm i think yeah pg pawns and in here i just want to create a sprite because we only have one type of background palm and here we can recycle our pawn class and we actually need the large one and i've called this one palm bg and now all we have to do is to draw this thing let's call it the background palms and i again can copy all of this and change this to a bg and this should be all we needed so now let's try this and there we go now we can see our background pawns although the problem right now is they are in the foreground so all we have to do is to grab all of this and move it up behind the terrain and now let's try this again and there we go now this is starting to look much better and in here you are starting to see some problems that we have a couple of overlays so especially this bit here where the background of our coin is black and this overlays the background palm tree so it's very hard to see since i have drawn of it but here for example you can see the palms cut off you can see the same thing here you can see the same thing here you can also kinda see it here and the reason is because we don't have proper alpha values and as a matter of fact let me actually change the background color from black to gray and now let me run this again and now we can see the problem a bit more distinctly that we have lots of part where we didn't set the alpha properly so we get some black backgrounds and i guess here you can see it the most but also when you look a bit more closely for example at the terrain here and here even for the terrain we have some black background stuff that we do want to get rid of unfortunately this isn't all that difficult to fix and the main part if i go back to my support.pi when we import the cut graphics this new surface here doesn't have any alpha values so all the stuff that isn't filled by tile is going to be black fortunately this can be fixed easily all we need is to give it one more attribute and that is called flags and in flags you can give surfaces different kind of values to make them behave differently in my case i want to give it the flag of pygame src alpha and this is going to set all the pixels that are being used to invisible so they are not going to be black and now it's tries again and this is looking significantly better so a very easy fix but looks very ugly if you don't cover this but now we have our basic setup and there's one more problem with the layer setup so right now the crates are in front of the grass and i want them behind of it a fairly small detail but it did annoy me a bit so now if i run it again now this is looking much better so for example if you look down here now the grass is in front of the crate which i think looks a bit better now there are two more things i think that we have to add one is the enemies and the other is the player or at least the player head at the end of the level and i guess let's start with the enemy that's going to be the most important part so in here i want to again set another section and let's call this the enemy just keep it at enemy and in here i again need an enemy layout this is going to be import csv layout level data and this one i have called and mis i believe let's double check enemies yeah this one and then self.enemy sprites and here again self.create tile group for the enemies it's going to work exactly the same as all the other tiles and we need enemy layout and i've called this enemies so so far no difference and now in here if type is equal to enemies i want to add another kind of sprite and this sprite is going to be enemy and we are again going to need our tile size we need x and y for the position and let's leave it at those for now now for the enemy we are going to use a lot of logic that we have created in here but i think the enemy stands by itself so it should be in its own file so let's create a new one and i've got this one and me dot pi and in here i first have to import a couple of things so pygame we always need and besides that i want from tiles import animated tile so i am going to keep this animated tile and just add a few more extra parts to it so we don't have to reinvent everything and now in here i want to get my class enemy and this one inherits from animated tile now and there we again are going to need an init method that needs self size x and y all the arguments we passed in here and then we are going to need a super dot init method and this one is going to need size x y and a path now the path is quite easy because there's only one path for the enemies and that is going to be this one here so we got before that to graphics enemy and then run the enemies only have a single one and we only eventually going to flip this once in a while but that's all we need and i guess for now we can just keep it like this and let's actually import it so in my level file from enemy import and me so now we can use this enemy and we have our sprite group and then we can also draw all of this so self dot enemy sprites dot update self dot world shift and self dot enemies brides dot draw self dot display surface and now let's try all of this and there we can see our enemies and right now there are in front of the palm trees which i don't like very much so i want them to be behind the palm trees behind the crates and behind the coins and also i guess behind the grass so i can just take all of this and move it just behind the crates and now let's try this again and that is looking better but now we have the same problem we had for the crates that for example for this guy here let me use a better color that there's this massive offset between the bottom of the enemy and the ground so it looks like they are floating which is something we do have to address and fortunately it's not that hard to fix all i want to do is get myself.rec.y and add something to it and this number now i have to find and it's actually quite a simple thing to achieve and let's say this here is again my 64 by 64 tile size and right now our enemy only covers let's say roughly this distance here that's a terrible straight line so i want to figure out what this distance here is going to be and well all i really have to do is to get this number and subtract this number from that and that way what's left is this distance here so what i want to get is my size minus self dot image dot get size so this is going to give us the x and the y dimension of our image and we only want the y dimension and now we run this again now our enemies are nicely on the floor so this is working quite well so now what we have to figure out is how to move this enemy and well for that i'm going to add a method that i will call move and in here literally all we need is self.rect.x plus equal let's say self.speed and that means we have to give this enemy itself.speed and i guess the value here should be something random so from random import rent ind and let's say i want a randins between three and five should be good and this would always mean our enemy when it's starting is moving to the right and then obviously we also need an update method that needs self and again we are going to need shift because now we are overwriting the update method from this animated tile so the first thing we are going to need is self.direct.x plus equal shift then we need self dot and mate and be aware here self.animate comes from the inherited animate tile the reason here is we have to call it because we're overwriting animate so you can't see it in this class but it does exist then we also need self.move and that should be all at least for now so let's see if this is working so let me run the code and now i can see all of my enemies moving to the right at different speeds so this is indeed working so i guess the one thing we have to work on now is if an enemy is moving to the right we want to reverse the image so let's call this reverse image it doesn't need any arguments and all we need in here if self.speed is greater than zero so we're moving to the right then self dot image is going to be pygame dot transform dot flip and we just put in our cell dot image in here and then true and false so in case you haven't seen this one yet all it does is it takes a surface and then it flips it either in the x-axis or in the y-axis and in my case i only want to flip the x-axis and now all we have to do is to call self.reverse image and we should be good to go so let's try this now and this is looking significantly better now obviously our enemies are not reversing and this we have to start working on now and this is going to need two major parts first of all our enemy class needs a method that reverses the speed and that is the really easy part because all we need is let's call it reverse it doesn't need any arguments and all we're going to do in here is self dot speed multiply equal minus 1. so as soon as we call this method here our speed is going to be reversed now the more tricky bit is when do we call this method and for that we have to go back to our level and this is what we created ages ago in the tiled editor those were the big red squares that we created back then and i want to place them on our level as well but well we just keep on doing the same so now i want to add a constraint and let's call this a constraint layout and import csv layout level data and this one i have called constraint i believe it is constraints this one and then self dot constraint sprites is going to be self.create tile group and constraint layout and then the string is going to be constrained and now again we have to add one more if statement in here so if type is equal to constrained and if that is the case i want to create a sprite and it doesn't really matter what we put in here i'm just going to go with tile and we need tile size x and y and this tile we already have this is our original tile in here and since we are not going to show it anyway it really doesn't matter what we put in here so this way we would get a basic tile and now what we have to do all the way down here let me actually put it right below the enemies i think it makes the most sense there so self dot constraint sprites dot update and self dot world shift and let me put it right above that so now we have these tiles in the world and we're also updating them so they're shifting along with the level however we are not drawing them as a consequence you can't see them but they do exist and that's the important part here and as a consequence we can use these blocks to change the direction of our enemies and this is going to be another method in our level class and let's call this enemy collision reverse maybe not the greatest name but i guess it's okay for now and it doesn't need any arguments besides self and all we want to do in here is for enemy in self.enemysprites.sprites so we are checking all of our enemy sprites and what we want to do with them is if pygame.sprite.sprite collide we want to check with the enemy and self dot constrained sprites and then false for the final argument and if that is the case i want to call enemy dot reverse so essentially all we are going to do in here we first cycle through all of our enemy sprites so literally all of our enemies so that's step number one step number two this one here is we check if any of these sprites is colliding with any of these constraints and if that is the case we want to call enemy dot reverse and in case you're wondering this faults here is called do kill so do we want to destroy the constraint if there's a collision which we do not want to do and well with that logic we have all we need to reverse the player so now i just have to call it and let's put it right below the constraints price so self dot enemy collision reverse and this should actually be working now let's try and we are getting an error that there's no such file directory that we don't have the csv file apparently and the reason for that is if i go to my game data i have called this constraints so now it should be working and there we go now we have our enemies all moving nicely along and we can control very much of where they are going so this is also working really well cool we are making some good progress now there's only one more layer we do have to take care of and that's the player setup and well most of the logic here is going to be identical although there's a problem now that we have created the entire player in the previous video so if you didn't follow this one you probably don't have access to the player so for this tutorial i am not going to place the actual player i am only going to place the goal of the player but if you have watched the previous tutorial at the end of this tutorial i'm going to integrate the first tutorial with this one so we have a proper game but for now i'm only going to place the goal not the player itself that will come later but well all we have to do if i go back we kind of have to do the same setup that we have done with the player and let me do it all the way at the top so this is going to be my player setup and here as always we need a player layout and this is going to be import csv layout level data and i have called this one however now we have a minor problem because this method here self.create tile group is always going to return a whole group but for the player i want to group single and i also want a group single for my goal hat so unfortunately we can't really use this method here anymore we have to approach this slightly differently so instead of using a method i'm going to create self.player it's just going to be pygame.sprite.group single and then self.goal is also going to be dot sprite dot group single that's not how you spell that and now that we have those two i am going to call another method that i call player set up and this one is going to need the player layout so now we have to create this method here and this is going to be very very similar compared to what we have done here so i can actually literally just copy it although generally not the best practice but i guess in this case it's fine so set up player i believe i called it needs self and layout or did i call it player setup i did call it player setup okay player set up and now in here we can just paste all of this because we are essentially going to do the same logic so i still want to do all of this i still want to do all of this but this value i do want to change because in this layout there's only really two values i care about either if the value is 0 or if the value is equal to one so zero is going to be the player and one is going to be the goal and i guess i can put all of this before the if statement now for this value here we would do something with our player which we do not have right now so let me for now just add a print statement player goes here but for value 1 we can create a sprite and this is just going to be a static tile and for that one we are going to need our tile size we will need x y and then the surface now the surface we don't have right now so we have to import it and let's just call this add surface and all we need here is pygame dot image dot load and then the file path we are going to need is this one here so graphics characterhead.png and don't forget to convert alpha this as well and then we can pass in head surface and now do not forget we need our self dot i think i called it gold sprite all the way to here oh just self.go so self.go dot add and i want to add my sprite and now all the way let's put it all the way at the bottom and let's call it the player sprites and then here self.gold.update self.world shift and self.gold.draw in self.displaysurface and now let me run this see if you have an error and we do have one and the error is oh i forgot the double colon now let's try this again and there we go and we can see player goes here but that's just a print statement so we can't see it so let's move the entire level let's say by minus six and let's try it now so now all of this is working really well and we should be seeing the hat in just a second and there we can indeed see it so this is also working quite well cool so with that we have all of the layers we needed to import and that did take quite a while but well when it comes down to it the logic here really isn't all that complicated we just had to repeat it multiple times and you could probably simplify this quite a bit to write less code but i guess for tutorial this was the best approach so with that we are almost done there are a couple more things that i do want to add and that is i want to add a sky some water and some clouds so that we don't just have a plain gray background which looks kind of ugly and each of those is going to be its own class so we have a sky class a water class and a cloud class and well all of those are not particularly complicated so i guess let's jump straight into them and let's have a look so here we are back in our main file and what i want to do is to create another python file and i call this one decoration dot pi and in here let's start with sky does not inherit from anything but as always we need an init method and in here i want to have self and what i called horizon and this is essentially going to be a y position where we have the switch between our ground tiles and our sky tiles in the background and in here we have a couple of files we need to import and usually we just imported an entire folder but in this particular case i want to work with each of them in a bit more detail so let me just copy all of the files so we have self.top self.bottom and self.middle and each of those are inside of our sky folder and these are very simple images so it's really nothing complicated happening in here and let me explain how i am going to use them so let's say this is our entire game window and right now each of these tiles is 64 by 64 pixels so right now for example one of those would look something like this and essentially what i'm going to do is i'm going to take this tile and stretch it to the entire width of my game window and then i'm just going to copy each of these tiles multiple times and once i reach this horizon tile i'm going to switch to another tile so all of these are going to be the top tiles then at some point let's say here we have the horizon tile and then below the horizon tile we have the bottom tiles and that way i can very easily create my sky so the first thing i have to figure out is how many vertical tiles i actually need and fortunately this i already have because if i go to settings it's this number here so all i really have to do is import it hence from settings import i think i called it vertical tile number and also but i did forget import pie game so now we know how many vertical tiles we need but besides that we also want to know self.horizon is going to be horizon so at what point do we want to switch between the tiles so let's put all of this right at the beginning of the class and now let's add this in another section here i want to stretch all of these tiles so essentially what i want to do for example with the top tile i want to get pygame.transform.scale and then here i have to pass in two arguments the first one is the surface and then a tuple with the x and the y dimensions of how i want to scale this surface now my case the surface is going to be self.top then for y i want to keep this at 64 or rather i want to keep this like in my settings at my tile size so i am also going to import tile size but now for the x this should be my screen width and that means i also have to import this one so with that i have all i need for my top now really all i have to do is copy this twice and change this to bottom and middle and this is also going to be bottom and this would be middle and that i think is all we needed yeah that looks good and now once i have that all i need is a let's call it a draw method with self and we need this surface i want to draw on and that way we can use it inside of our level class and well all i need now is for the row i want to work in in range and the number here is vertical tile number and now in here as always we are going to need an x and a y position although in this particular case x is always going to be zero so we can just skip this one entirely and for y all we are going to need is the row multiplied by our tile size so this is essentially the same logic we have always used except only in one dimension and now what i could be doing is get this surface dot blit and then self dot top for the surface and for the x and y dimensions and y is going to be well this y here the one we already have and this would fill our entire surface with one color and let's actually see if this is working in the first place so back in my level class i want to create the sky and i guess we can put this all the way at the bottom and i have called this that corporation and in here self dot sky is going to be sky and as an argument for now let's put in an 8 so this would be the horizon line and to use sky we have to import it so from decoration import sky and this would then be our sky and now all we have to do all the way at the bottom is our decoration and here we need self dot sky dot draw and this happens on self dot display surface and now let's see if this is working and oh well it is working but the problem here is that we are drawing the sky on top of everything else and obviously the skype should be all the way in the back otherwise we can't see anything so this is much better and this is feeling significantly better and i guess for this step here you could have just filled the entire sky with one color would also get you the same result although in my case i want to add some more details in here which is why i haven't done it but alright so what i want to do i only want to use the top tiles if we are below this number here so right now this is 8. so i have to add an if statement in here that if my row is smaller than self dot horizon only then do i want to use this line so now if we run this our horizon only goes to a certain point now after this l if my row is exactly equal to self.horizon then i want surface dot split with self dot middle and we are still going to pass in 0 and y for the position and let's write this now and we get invalid syntax because i forgot the double colon again and there we go now in the background we have this horizon line thingy i guess it's a transition and finally we need an else statement that now if neither of these conditions are true we want self dot bottom and now we run all of this we have our proper sky so this is looking quite nice cool this is working so this is already finishing up our sky so i can minimize it and not think about it for a while and i guess next up let's create a class for the water and in here i again have to create an init method that is going to get self then i want a top parameter and this is going to determine how high our water is going to be or rather where the top of our water will be in our level and finally i'm going to need a parameter that i have called level with and let me explain why this is going to become important let's say this line here is the width of our level so level with and essentially what i'm going to do i'm going to spawn the water in such a way that we start sometime before the level starts and somewhat after level ends so all of this is going to be water and that way i can make sure that the player is always going to see water at the bottom and we can scroll the water along with the level and if we didn't do this and the water would start with the level and end with the level the player could look to the left of it and see just nothingness which would look very very silly so we have to keep the water a bit further than the width of the level and for that we have to know how wide our level is going to be which is a fairly easy thing to get so all right with that we have to figure out a couple of parameters and i guess let's first initiate this water class in our level and then we can talk about it so let me actually minimize a couple of things in here so this doesn't get too complex okay now besides self.sky i also want self.water and this would just be water and again i have to import it so besides sky i also want to import water and now for the height of the water i want to get my screen height let's say minus 40 i think is a good number and then we have to figure out the level width and i don't think i've imported the screen height in here uh fire size screen height so now this should still be working so how can we get our level width and this i think could be a really good exercise for you try to figure out how wide our level is in pixels and this should be dynamic so if the level gets wider or closer it should still work perfectly fine let's put this in a new variable that i call level with and here's how i approach this essentially when look at any of our imported csv files let's say in my case i looked at terrain layout this is essentially just going to be a list that includes lots of lists inside and each list is going to be one row of our level and all of these rows have the same length so all we have to get is the length of one of these rows of any of these layouts and multiply this by our tile size so in my case i want to get the length of my terrain layout and then i just picked the first row and this then i multiplied with my tile size and that way i'm going to get the amount of columns i have multiplied by the tile size which should then give us how wide our level is so that's all we needed so now we can work with the level width and actually before we do that let's run all of this to see if there's an error and again i made a mistake somewhere let's check decoration water i guess back in decoration all right this here should have a password now so we don't get an error and okay it is still working just fine cool so now we have to work inside of this init method and the first argument i am going to need is the water start point and this is a number that i want to start one screen with to the left so our starting point is zero and i want to go to the left of that by one screen width so this is just negative screen width then i will need my water tile width and in this case i know my water tile width is 192 pixels wide and after that i need to know how many of these tiles i will need so let's call the tile x amount and in here first of all i want to get my level width plus one screen width so this is then going to be the pixels how wide i want my water to go but this right now is just a pixel and that's not what i really care about instead i want to know how many tiles i need to fill this entire space and to get that all i have to do is put this in brackets and divide it by water tile width and then all of this i want to turn into an integer and that way i'm going to know how many vertical tiles i will need and then finally i need a water sprites sprite group and this is just going to be pygame dot sprite dot group and well now all we have to do is to place our water tiles along this position here and for that i'm going to add a for loop so for tile in range tile x amount and now we need an x and a y position and the y position is the easier part it's literally just going to be the top so the number we have specified in here as an argument that's all we're doing here and for the x position all i really want to get is my tile so this is a number between 0 and whatever we got in here and multiply this by my water tile width but this number here would always start at zero so towards that i have to add my water's start so this way we would start at this position here and now we can just as always create a sprite and all we need in here is an animated tile so what we created earlier in our tiles so this animated tile here and to use it we have to import it so from tiles import animated tile and now we can use it and let me copy the arguments we are going to need so we need size x y and path and now for the size we don't need our tile size we need 192 because the water tiles for some reason are wider x and y are still perfectly fine and now for the path i want to get this graphics folder and this should be a string so graphics decoration and water is the folder i will need and at the end of this i want to get myself dot water sprites and add this sprite towards it and that is all we needed so now i can give this a draw method as well in itself it needs a surface and this one will need a shift argument because this animated tile expects an update method with a shift argument so we need that part as well and well in here how we need his self.water sprites dot update let me pass in the shift argument in here and then we need self dot water sprites dot draw and now we need the surface and that should be covering our water so now back in the level i can draw in our run method i can draw the water on top of everything else so let's call this water so self.water.draw [Music] and in here we first of all need the arguments for surface and then for shift and again let me copy them so first of all we need the surface and this is self dot display surface and then shift is self dot world shift so now let's try all of this and this is working cool the water might be a little bit too high let me put it down a touch further down all of that happened here let's say negative 30. and still a bit high i guess you can play around with this quite a bit more now with that we also have our water now the final thing that we are going to need is our clouds class and in here we again are going to need an init method in itself we also going to need the horizon line then i also want to note the level width and then i want a number of how many clouds there are going to be so cloud number and in here first of all i need my different clouds and since i'm not going to work with them in too much detail i can just import all of them on its own list so we can just create another variable and this i am just going to get from this file here i just want to import the folder so i have to import all of this so from support import import folder and now import folder and the folder path i need is this one here so graphics decoration and clouds and now i need a couple of different arguments and let me draw this actually so let's say this here is our entire level and i need four different arguments in total the first is on the x-axis where our clouds are supposed to start and where they are supposed to end so this is our vertical start and end number and besides that i also want to place my clouds below the top of the screen and then wherever the horizon line is going to be so only in this line here i want to have clouds and once i have this area essentially what i'm going to do is i'm going to pick a couple of random numbers and place a cloud there that's all we really need so let's put all of this on its own variables so first of all i need minimum x and this i've put down to negative screen width then we need a maximum or max x and i've put this to my level width plus screen width then for minimum y this is the easiest one it's just going to be zero and then max y is going to be my horizon and after i have all of that i again need a sprite class so let's call it self.cloud sprites and then here this is just pygame.sprite.group and now we kind of have to do the same thing we have done for the water this for loop here except now we don't really care so much about specific numbers so let me explain what i'm going to do first of all i need a for loop before cloud in range cloud number so the random number we specified earlier here to pick a number that looks good for the amount of clouds and in there i just want to pick one cloud from this list here and this is going to happen with random.choice so we have to import it hence from random import choice and all that choice does is you have to pass in a list and it picks one item from that list so choice cloud serve list so with that we have one cloud available now next up we need an x position and a y position and in my case i want to use randint so i want for x a random number between the min and the maxx and for that to work i need to import randint as well so rent ins between min x and max x and then the same for the y position so min y and max y and well that is literally all we needed so now i can again create a sprite and this is going to be a static tile again the tile we have created here so again i have to import it and this one the arguments we need here let me copy them we need size x y and surface and the size here really doesn't matter because we can't touch the clouds anyway so i just pass in a zero x and y we already have and the surface is just going to be the cloud and then finally self dot cloud sprites dot add and i want to add my not the cloud this bright and this way once we initiate this class we have all of our clouds in place cool so now finally i need self.draw it needs self and it needs surface and also don't forget we need shift again and then in here self dot cloud sprites dot update and this needs a shift and this should be dot and then self dot sprites dot draw and this should happen on the surface and with that back in my level i can add self dot clouds is going to be clouds and in here the arguments we are going to need is the horizon the level width and the cloud number and the level width we already have for the cloud number i think in my case i went with 20. although this is a fairly subjective number now for the horizon we could have gone with the same number here but i wouldn't really like for cloud to be exactly on the horizon line so this one is a bit more flexible we can just pass in a pixel number in here and i guess in my case i went with 400 and now that we have that uh this we can go to our run method and let's call this sky and i want to get self.clouds.draw self.displaysurface and i think yeah surface and shift and then self.world shift and now if we run this we are getting an error that name clouds is not defined because as always i did not import it so we are really starting to import a ton of different things it's it's very easy to forget but now we have our clouds which is making the entire thing look significantly better and i think here 20 might be a little bit on the low side let's maybe go with 30 might be overkill nope still that looks good and yeah i'm happy with that and all right so with that we have finally finished setting up the entire level and that was a very long part so far and if you got this far you should have a pretty good idea on how to use tiled and how to import all of this into pie game which has taken quite some time now for the final bit we have to combine all of this with the player we've created in the previous tutorial so this is what i am going to start working on now so let's talk about how to import the player and fortunately this shouldn't be all that difficult because most of our basic setup is identical so let's talk about what we have to do first of all we have to import the code for the player and for the particle effects and then we have to integrate them into our level then next up we have to update our level class so that we can use it to control the player and then we also have to update the methods for the particle effects so we can check if the player is jumping or falling and again for all of this if you have not watched the first part of this series you will be completely lost so just a warning but all right let's go first of all to our folder so here is all the code we have written in the first part of this tutorial and the only two files i need is particles and player so i'm going to copy those and then i will go to my new file and i can just paste them in here so now we have a ton of different files that we can work with and the first thing we have to do is to integrate the player inside of our level so let's go back to my level so here we are back in the level and the first we have to do is from player import player and this should be spelled correctly and let me actually open the player class this one here and we just want to import this player and this one mostly works by itself at least for now to move it we need something else in the level class and now in the init method we already have our player group single so this one is working by itself and then we have our player setup and in here we have to spawn our player so in here i want to create a sprite and this one is going to be my player and now we need all of the arguments for the player so in my player let me copy all of the arguments we are going to need so we need position a surface and create jump particles now position is the easiest we just need x and y this we already have then the surface this is just going to be self dot display surface and now we need to create jump particles and this we earlier created in our level class so we have to import it and for that let me open the previous level class here we have the earlier level class we created in part one and the one method we do want to get is create jump particles and this is great jump particles this one here so all we need to do is to copy all of this and place it inside of our level class then new one and then we can just pass this one in here and now i guess what we can do is just run the code and see what is breaking first and well it's all still working so that's actually a really good sign so now we have a player and we have to add this player to self dot player i believe let's see what i called it several player yeah so self.player.add and we want to add the sprite and then in the run method i want to add the player and the player let's put him right here where we already have our gold sprites so in here i want to get myself.player.update and self.player.draw and don't forget for player.draw we need self dot display surface and now let's try this and there again we can see the player so this is working quite well cool now obviously it doesn't particularly work well with the level because this one stays in a constant place and while we are creating the player let me set the world shift to zero so it doesn't look too weird and now let's try this and now we have our player so this is already a pretty good start now next up let me minimize all of this again [Music] we are going to need the two methods that make the player move so in our original level this was this horizontal movement collision and this vertical movement collision and if i open both of them they were getting quite long and well i am just going to copy all of this and paste it in our level let's put it right at the bottom here and let me minimize them for now so we only work on one at a time and let's go through in here these two lines should still work just fine however this four sprite in self.tiles.sprite is not going to work anymore because we do not have a tiles class but what we have instead is all of this and i don't want my player to collide with all of them essentially i want my player to be able to collide with the terrain sprites the great sprites and the foreground palm sprites so those are going to be our actual collidable terrain so we have to use this for loop only with those sprites and that fortunately is quite easy to do so let me get rid of this part here and i want myself dot to rainsprites dot sprites so this would be one of the groups we need but now we also want to loop over the other sprite groups so right now we have the terrain sprites but we also want to loop over the crate sprites and the foreground pawn sprites and well all we really have to do to fix this is to add a plus here so self dot create sprites dot sprites and then plus self dots foreground palm sprites dot sprites and i guess you could put all of this in its own variable let's actually do that so let me cut all of them and let's call it collidable sprites and that's going to be all of this and that should be a bit easier to read and now we have to do the very same thing in our vertical tiles so let me just copy this line here go to this part and edit here it's a very long line and in [Music] collidable sprites and this should actually be all we needed for these two methods so let me minimize them and now obviously we have to call them so in my player sprites after update i want to call self dot horizontal movement collision and self dot vertical movement collision and let's see what's going to happen if we run all of this and this is actually working really well although if i jump we get particle effect is not defined so that's something we do have to work on but without jumping if i just run around this is working quite well so we already have a basic setup we are getting very close to being done so now pygame is complaining that we don't have a particle effect and the reason for that is in my player class if i am jumping i want to create jump particles and this is a method inside of my level it starts to become a fairly long code let me look for it create jump particles this one here so right now whenever we jump pygame is trying to create this particle effect which we don't have right now however if i open it this is the one we imported earlier so this is just this particle effect so well all we have to do is to import all the way at the top from particles import particle effect and now let's try this and we are still getting another error level object has no attribute dust sprite so let's have a look at that in my level and in here we need a dustbrite sprite class which well we can create and let me close all of this and i guess we can put this along with the player up here and i guess let me add another section for dust and here self.dust sprite is going to be pygame.sprite.group single so now let's try this and now i can jump and this is already working quite well now obviously our window isn't scrolling so the game doesn't fully work yet but we do have a pretty good start so next up let's add the scrolling behavior and if i go back to my original file so in here we have define scroll x and this i just want to copy so now in my new level class i want to paste this as well and i think most of this should still work just fine so back when i called all of the stuff for my player i also want to call self.scroll x i called it and it did not have any arguments no that looks good so let's see if this is working and it does not because screen width is not defined so let's have a look we need scroll x and we need screen width which we don't have available right now because we are not importing it but we can get it quite easily so let's import screen with and now let's do it again and this is working now cool so now our level is scrolling with our player and we can jump on all of this and this is working very very well now next up we are going to need some more minor methods for the landing particles so if we look at the original level in there in our run method we had get player on ground and create landing dust and those two surround the vertical movement collision so let me just copy get player on ground and let's paste it in our run method so right here and then i also need create landing dust and this comes after the vertical collisions and i guess i can add some space between them to make it a bit more readable although the code is getting very long is is getting to be very hard to read but okay now we have to copy get player on ground and create landing dust and let me just copy both neither of them is particularly long so i can copy them and paste them in our new level class as well and now we have to work through those two first of all i have to create the attribute self dot player on ground so in the init method let's do it with the player actually let's do it with the dust so self play on ground by default is going to be false then i can minimize the init method and all of this should now be working fine and all of this i believe is also good to go so let me save it and let's run all of this and we do not get landing particles but we do get the running particles but we don't get any jumping or falling particles so i think the problem is that we are not drawing this dust sprite sprite group so let's check yeah we're just not drawing any of the sprite groups which is a very easy thing to fix what i want to do below the player i want to create my dust particles and here self dot dust sprite dot update and this again needs self dot world shift and then self dot dust sprite dot draw in self dot display surface and now let's try this again and now we get the jump and the landing particles and this is making the entire thing look much nicer so this is working quite well cool okay except maybe this part in the level is not particularly well designed but i'm not going to worry too much about it so all right with that we have basically the entire thing and there's only one more thing i would like to add that let me minimize this and this that in our horizontal movement collision we have self.currentx that i also want to declare in the init method so let's put it in the general setup so self.currentx by default is going to be none and now with all of that covered let's run this and this is working surprisingly well so the level scroll is working we can collide with stuff we can jump obviously we cannot collide with coins or enemies that will come later but the rest is functioning surprisingly well and let me try to get to the end okay um yeah we might need a death state and oh i think i made a mistake for the water so we can fix that but besides that this is basically done so let's go to decorations and let's look at what went wrong with the water and then here let's just say we go and double the screen with and let's see if that makes a difference let's actually look at the other side so the water here works just fine and if i go to the right and this is only working because we don't have the depth state and now if i go to the right now the water is working and goes much further so all right with that we have our basic level so i hope all of that was helpful and i will see you in the next part where we are going to create the overworld i'll see you then
Info
Channel: Clear Code
Views: 17,988
Rating: 4.9766765 out of 5
Keywords:
Id: wJMDh9QGRgs
Channel Id: undefined
Length: 189min 12sec (11352 seconds)
Published: Mon Aug 23 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.