Creating particle effects in pygame

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi there for this tutorial we are going to be creating particle effects and before we get into specific code let's first talk about the logic behind these particle effects because it's actually quite simple what we are effectively going to do is to create a class that has one list and this list is storing all the individual particles and then this class has three different methods one method is to create particles that are going to end up in the list and all of these particles also have specific attributes this could be the direction this could be the size this could be a lifetime this could also be their color lots of different things that we could do in there the second method is there to destroy the particles once they reach a certain criteria like them becoming too small or moving outside of the screen and lastly we have an emit method and this one puts the first two methods together in the sense that it cycles through the list and moves all the particles and adds the visual effects to them and that's really all that's needed for the different kind of particle effects so let's jump right into the code so here we are in a really basic setup for pygame and if you don't understand what this means check out this video and i explain all of this but to get started i'm going to create a new class for our first particle project and for this one i'm going to click class and i call this one particle prince pill it doesn't need to inherit anything so we can just go to define and init and when we initiate this class all we need is self.particles and this for now is just going to be an empty list but basically what we are going to do later on is add particles to this list and then move them and draw around them and with that covered we are going to need three more methods and let me just write them out the first one is an emit method let me just right pass him for now it moves and draws the particles then we have another method that is called add particles and this one is well it has particles and then we need one more and that is delete particles and what this one is doing is it deletes particles after a certain time and this one is really important for the simple reason that if we didn't delete our particles after a certain amount of time we would end up with a crazy amount of elements on our screen and our game would be slowing down so this method is quite important but effectively what we are going to do is we always start with this add particles method and this one adds a particle to our self.particles list and then emit goes through all of the particles inside of this list and moves them around a tiny bit and then draws them and while emitting we also check for certain particles if they get too small and then we delete them if they are too small and that way we ensure that we will never have too many particles on the screen at one time so we have to start with our add particles method and i do want to call this method all the time very very often so every couple of milliseconds and to do that i am going to create a custom event so i call this one particle event and this one is pie game dot user event plus one so we are effectively creating a user event that we can use now event loop and trigger this every few milliseconds so for that i set a timer with pygame.time.set timer then i need our particle event and then the amount of time in milliseconds i want to pass between each call of the event in my case i went with 40 but you could make this longer or shorter depending on what you need i'll show you once we have our first particle setup ready alright now in the event loop i want to check if event dot type is equal to particle event and if that is the case i want to trigger this add particles so to make that work i first have to create an object from the class so let's call this particle one is equal to particle principle and then inside of this event particle one dot add particles there we go so what this basically achieves is that these lines call an event every 40 milliseconds and then when this event is being called we are calling this method so we are adding a particles so now we have to actually write some code to add particles to it and really all we have to do is that we are creating a point with an x in the y position a direction and a certain radius and then later on in the emit method we are just drawing all of these points and put a circle around them so well really simple actually but okay let's get to it i want to start with creating a x position and for now i just put this in the middle of the screen so i put this at 250 and do the same thing for y position and it's also going to be 250. so any particle we are going to create is going to start right in the middle of the screen then i want to create a radius and they are all going to be 10 at least for now and then i want to create a direction so i create direction and for now the direction is just going to be -1 so this would mean all the particles we are creating are just going upwards and that is effectively it what we need for our basic particle now all i want to do is to create a particle circle and this one is just well it's a list that has another list with position x and position y then we have the radius and then we have the direction so really all we're doing in here is adding all of these different variables into one list to make it easier to work with but we're not creating anything particularly new and once we have all of that i get self.particles and append our particle circle and that's all we needed for the add particles part so now we can actually look at emitting them so the first thing i want to check is if there's anything inside of the self.particles so we have something to animate and for that i can just go with self.particles and any list that has more than one entry is going to evaluate to true so self.particles once we have any particle in here is going to get to true and if not we're not doing anything and then i want to cycle through all of the particles so for particle in self.partic kills so effectively if there's any particle inside of softer particles we want to work with all of them and there are three things i want to do with the particles number one is i want to move the particle number two is i want to shrink the particle and number three is i want to actually draw a circle around the particle so let's work on them step by step first off we have to move them so we have to influence this position x and position y so first i'm going to target them so this is particle zero and for now i'm just going to move the y position so position dot y and this would be zero for this entire thing and then one for position y and this i want to move in the direction that we created so this is particle and this would be zero one and two so this is our direction so plus two so effectively what happens here is that we are taking the y position and adding minus one or whatever is in our direction to it so effectively right now we're moving it next up is we want to shrink it so we want to take this radius and make it smaller so again i want to go particle and this time 1 for the first element in this list and this time i want to get minus equal a very small number and i went with negative 0.2 but you can experiment around with this quite a bit all right now we're making this radius smaller on every single time this frame here is running so effectively our circle is going to be smaller and now all that's left to do is to actually draw all of this and since i want to draw a circle i'm going to go with pygame.draw.circle and now we need a couple of attributes the first one is on what surface to draw on in my case that's easy the screen then we need a color and i just used the pie game color attributes and i'm going to make them white white and now for the circle we need two more attributes first we need to center position and then we need the radius so the radius is actually super simple that's gonna be our particle one the one we have created and shrunk in here now for our center position we are going to need an x in the y position and fortunately we have them this is our position x and position y so all we have to do in here is particle zero and there's one more thing we need to do when we create a radius around the circle this has to be an integer but right now for us this is going to be a float because subtracting negative 0.2 from a number is going to create a float so we have to put in around here and there we go now in our game loop i can just call particle one and call the embed method and right now this should be working for a very short amount of time so let's try and there we go we get an error that we are creating a negative radius so the problem is here that from our radius we subtract a very small amount all the time but this radius has to be positive so after our code runs for about a second this one is going to get negative and the entire thing crashes but we can fix that quite easily and for that we have our delete particles method and really all i want to do in here is that if a particle gets to 0 i want to delete it but the method how i'm going to achieve this is going to be slightly different so let me explain so first let me get rid of all of this and the first thing i want to do is i'm going to create a copy of our self.particles and i call this list particles copy and now i'm going to use list comprehension and what i want to do is particle for particle in self.particles so right now we would take our self.particles list with all the elements inside and just make a one-to-one copy for it but i don't want to make a one-to-one copy instead what i want to do is only choose the particles that have a radius that is greater than one so into this list comprehension i'm going to add an if statement and it's going to be if particle one so the radius is greater than zero so effectively what we're going to do is recycle through the entire self.particles list but only copy particles that have a radius greater than zero and once we're done with that we just set our self.particles equal to our particle copy list and that way we are going to get rid of all of the particles that are getting to zero and now again up here when i cause several particles before we're updating all the particles i want to check self.delete particles so that before we get into any of this we delete all the particles that have a radius of smaller than zero so now let's try the entire thing again and there we go we have a very basic particle system now obviously this doesn't look particularly good but if we just make some changes this is going to look much better the first one is the direction of minus one is a bit too slow so let's make this to negative five ah now let's try again and this is already looking a bit better but i think it's moving too fast so instead of going with particle event 40 so we spawn this every 40 milliseconds let's go with 150 and now this is already getting a bit better but i think now it is moving actually a bit too fast so let's set this to lower number and there we go this is already looking quite a bit better so this is really the most basic kind of particle system if you have gotten this far you have understood basic particle system all we have to do now is to make adjustments to this to make it look a bit better so let's make it look better so the first thing i want to do is to not spawn this at a specific position and instead i want to spawn it at our mouse position so for that i have to get pygame.mouse.get pause and this is giving us the x and the y position of our mouse and from this position i just want the first one so the x position and then same thing for y but now i want the first one so now if i run this now our particles should follow our mouse and this is already looking quite a bit more interesting so we are making some pretty good progress next up i want to make the direction a bit more random and since we need a random number i have to import the random module and now for the direction instead of a fixed number i want random randint and this is going from negative three to three and now if i run this this should go into different directions so now it's going up and down which is well looking quite a bit better i think but okay now instead of just moving all of these particles up and down i want to move them also to the left and to the right and to do that i just have to copy this line so this is the line where we just moved it up and down and now instead of just targeting the y position we also target the x position and if i were to run this code right now we would get well a slightly weird effect but it doesn't look too bad actually but not what i wanted i want the particles to go in a random direction but this doesn't work right now because both move in the same direction so this direction is fixed for both x and y and what i need is that this direction has two axes so i'm going to put it into brackets and i'm going to have direction x and direction y and this is going to be direction x and this is going to be direction y so really now instead of having one direction with a random number we have two directions for each axis and then when we are using the numbers we want to use zero and one and now let's try this entire thing again and there we go now we have a random particle being emitted from the position of our mouse and now we can increase the speed again and see how it looks after that let's set it to 50. and there we go now we have a particle around our mouse that works quite well so this would be our very basic particle principle and well if you have understood this you could even do all the other parts yourself because they're not fundamentally different but let's go through them and the first one is going to be our neon cat so for the uncat we are basically going to follow the same principles but there are going to be two major differences the first one is that we don't have one emitter we have five emitters working at the same time and each of these images is going to emit a particle with a different color and the second difference is that we don't have a circle anymore we have a rectangle and i guess there's also a third difference that we put in nyan cat image on the screen but that doesn't really count because it's super simple all right let's jump right in so here we are back in our code and since we are going to reuse a lot of this stuff i'm just going to copy our entire class and rename it to particle neon and besides that let me minimize this i also want to import the image of our neon cat so for that i'm going to create a new variable neon surface and this is going to be pygame dot image dot load and the image is called neon underscorecat.png and i'm going to add convert alpha to it so we convert the image to a better format for pi game so our code is able to run faster but alright now we can actually work on our particles for the neon cat so we are still going to keep our self.particles but besides that i also want a new attribute that i called self.size and i have set this one to eight so this is going to be the width and the height of each particle we are going to create all right to omit we are going to come later first of all we are going to work with add particles and effectively what i'm going to do is i'm going to give it a couple more arguments you can pass into it and this is going to be an offset and a color so the offset is going to offset our particle when it's being spawned in the y direction by a certain amount so we could have a particle that is a couple of pixels above the mouse screen or below the mouse screen and the color is the color of the particle that one well it's quite obvious and now let's go through it i still want to get the x position of our mouse so this one stays exactly the same but for the y position i want to add the offset so this one gets less offset so if we don't get the exact most position in the y axis we add or subtract something from it and next up all of these things can go because we don't need them anymore and same for this one actually because instead i want to create a particle rectangle and this one is going to be pie game direct so a perfectly normal wrecked object for pie game and for this we need an x position a y position a width and a height and these two arguments are super easy because we have to find them up here so i'm just going to copy self.size and paste them for the width and the height so this one is the easy part but now we need to figure out where to spawn them and here you could be time to just type position x and position y and this would kind of work it wouldn't be wrong but the problem is that a rectangle is always spawned in the top left but we want to put this on the center so i have to move it a tiny bit more and what i want to do is self dot size over 2 so that from the top left position we are moving this thing to the left by half of its size and thereby we are spawning the center of the point and then we have to do the exact same thing for the y position and now we're good to go so now we have created a particle rectangle and this is what i'm going to add to our self.particles but there's one more thing we need and that's the color so instead of just passing in the particle rectangle i'm going to pass in a tuple with the particle rectangle and the color and that is basically it what we needed for this one and this allows us to call this add particles multiple times and change the offset and the color and that way we can create multiple particles at the same time and let's actually do that so i go further down back to our particle event and in here let me comment out particle one and instead what i want to do is let's go with particle 2 i'm going to name this dot at particles and in here i can set an offset and a color and let's just start with a really simple one and let's start with an offset of 0 just to illustrate the principle and then i want a color and i'm going to go with pygame.color again just to keep it simple and for the color i am going to go with let's say let's say red so this is going to be really similar to the particle one we have created earlier but obviously we have to create before i forget our particle 2 equals particle neon [Music] and then in our game loop let's comment out this one and let's actually call the emit method it wouldn't work just now but just to have it ready okay now with all of that stuff covered we can work on the emit method and this one is going to stay quite similar with some notable changes though so all of this part here stays exactly the same but now we don't want to move this thing in a y direction at all so this line can just go entirely we also don't want to shrink the particles anymore so this line can go as well and now for the x position we just want to target the actual rectangle so this particle wrecked and i want to move this entire thing by let's say two pixels to the left on every single frame and with that covered all we have to do is to draw the result and we're still painting on the screen but now for the color we are going to go with particle one so this is going to be this part here the color and then we can get rid of all of this part here and just call particle zero so again the particle rect we have created earlier and now with this we are almost done i just realized i made two mistakes this one shouldn't be draw it should be wrecked and for the particle zero we also want to target the x so we don't just want to target the particle rect we want to target the x position of this rectangle so now all of these lines should be correct but there's one more thing we have to talk about and that is this delete particles because right now our delete particles it looks for particle one greater than zero so right now it looks at this color but this color could never be smaller than zero or at least a comparison wouldn't make sense so we have to do something else and what i want to do instead is look at our particle rectangle and look at the x position and only keep the particle if the x is greater than zero because if it's smaller than zero it's going to be outside of the screen and if that is the case it's not going to be visible anyway so we don't have to draw it so we can get rid of it and all right now all of this coverage let's try and there we go we're getting a red particle moving to the left so it does a pretty good start now pygame is going to give me a slightly annoying message that these two should be integers so let's oblige and let's put integer or in around it to turn them into integers and now let's try this again and now we don't get a warning anymore and there we go now we have our red particles so now we have one particle all we have to do now is to work with this line here quite a bit or copy it a couple of times and change the color and the position so what we can do now is let me put this one to negative 20 and now it is always going to be slightly above our mouse cursor and let me actually change this to 100 so we get what this means [Music] so now we can see our mouse cursor is significantly below the particles and now all we have to do is call this method six times for each color and let me start in the middle that makes the math the easiest so i'm gonna start with negative four and that is going to be the yellow color so this one is going to be slightly above the mouse cursor and then slightly below the mouse cursor at position 4 we are going to create green particles then one layer outside of that we go to -12 and this one is going to be orange and then we go to plus 12 below the cursor and this one is going to be blue and then at minus 20 and plus 20 we create either a red or a purple particle and let's trial of this so now we are getting a rainbow so that's pretty workable and here you can see there's a gap between each of these so let me show this and this is because the particles don't spawn fast enough or they are moving too fast you can adjust either of these i'm going to go with how often we spawn the particles so let's change this one to 40 and see how that looks and it's getting a bit better there's still some gaps so let's change the speed of it to negative one and let's try this now and there we go this looks much better there are still some gaps but for now i'm not going to worry about them okay we are almost done the last thing we have to do is to draw our cat so for that i'm just going to create a new method that i call draw neon cat it doesn't need any parameters and all we're going to do in here is to create a rectangle around the cat so neon surface dot get rekt and we put the center to where our mouse is so pygame dot mouse dot get pause and once we have that we just use screen dot blit and neon surface and neon wrecked and then in our mid method i'm just going to call self dodge draw neon cat and then we should be good to go so let's try and well it's a bit large but i guess you get the principle i think i made the particles a bit too small so let's work on that really fast so for the particles i went with eight so far let's turn it up to twelve and then when we spawn them this is going to be negative six negative eighteen and negative thirty and then we get all numbers and positive so 18 and 30. and now let's try this again [Music] and there we go this feels much better and you do have to be aware if i move the cat around randomly on the screen this kind of breaks so you do have to be careful about how you use it but if you only move very slowly this creates a very nice effect that looks pretty cool so alright this finishes the nyankat and for the final one we are going to create a couple of stars around our mouse so we actually going to spawn images instead of just drawing with pygame and all of this is still going to be incredibly similar compared to the particle we have created in the beginning of this video but now instead of drawing circles around each point we are going to blit an image on this position but that is basically the entire difference so let's jump right in and let's see how this works so here i'm back in my code and now what i want to do is to copy our original class again and let me rename it to particle star and before i do anything else i am going to create particle 3 and create the actual object from particle from particle star and then in our particle event i'm going to call particle 3 dot at particles and then in our actual game loop i want to call particle 3 dot emit so exactly the same for now as we have done with the original particles but i'm going to make quite a few changes now so again let's go for it step by step i am still going to keep self.particles but now i'm going to add self.surface and this is going to be an image of our star meaning i have to import an image so pygame.image.load and the image is called star.png and again i use convert alpha to turn it into a file that pygame can work easier with now we need two more things the first one is self dot with so we have to know when we create the particles how wide our surface is going to be so i want to know our self.surface dot get correct and then i want the whiff and i want to do the same thing for the height so just copy the entire thing and change width to height so now we have the basic attributes that we need to create a couple of particles that are going to be rectangles and then later on we use those rectangles to bleed the surface on each rectangle again i'm going to start working with add particles and here we still want to get our x position from our most position but again if we were to just use this position our mouse would be on the top left of the star not in the center so we have to subtract something and what we have to subtract is self dot with divided by two and the same for the y position so self dot height divided by two next up the radius we can just get rid of because we're not going to need it anymore and direction x and direction y i'm going to keep and there's one more thing i do want to add and that's a lifetime and this one is going to be a rant in between let's say four and ten so this is going to be how long our star is going to live but all right that's all we needed all we have to do now is to create a particle rect and this one again is going to be pygame dot rect and we are going to use position x position y and self dot with and self dot height and the particle circle we can just get rid of because we don't need it anymore and now when we are appending the particle i want to get our particle particle rect i want to get the direction x and the direction y and i need the lifetime and well that is basically it so now we can look at the emit method again and make the changes we need to do and it's not going to be that many actually so we're going to start with particle.x and now instead of 1 i'm going to change this to x and this one is going to be y so we are targeting this particle rectangle and targeting the x and the y position and with that we have to add either the direction x or the direction y so this is going to be particle again for x is going to be 1 and for y it's going to be 2. and then we have to look at the lifetime to kill off the particle at some point so if look at particle 3 and i'm just going to subtract 0.2 again but you could change this number to whatever you want it just see what feels good and now this entire line we can get rid of and replace it with screen dot split because now we want to blit an image and what we want to blit is self dot surface and the position we want to get is particle zero so this particle zero that we're moving around is just a rectangle and this rectangle has the same dimensions as our surface so we can use it to put the surface in the place of the particle or the rectangle of the particle and that would basically be it the last thing we have to do is get our particles again and work with this if condition and what i want to look for is the lifetime here so particle 3 and if it's greater than 0 we are going to keep it and with that we should be good to go so let's try and we are getting an arrow that lifetime this should be random dot rending now let's try this again there we go and we have stars around our mouth screen so that's basically it and again python complains about an implicit conversion so i'm gonna put integer around the position when we are going to create our rectangle so now let's try this again and there we go the warnings anymore and we have our stars that disappear and work perfectly well so i hope you found this helpful and i'll see you around
Info
Channel: Clear Code
Views: 8,834
Rating: 4.9886365 out of 5
Keywords:
Id: yfcsB3SGsKY
Channel Id: undefined
Length: 35min 43sec (2143 seconds)
Published: Tue Oct 20 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.