Code AI Swarms, Flocks & Hordes | Boids Scratch Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello fellow scratchers have you ever seen complex life simulators and wondered how they worked or perhaps ever wanted to create one yourself well hurrah because today i'm going to walk you through how to create this awesome flocking simulator in scratch and in just one single episode how cool is that the life system you see here is called voids man i dare you to count how many times i say boyd's by the end of this video voids first developed by craig reynolds in 1986 to simulate the flocking behavior of birds but it has many other potential uses from simulating schools of fish swarming of buzzing bees to waves of aliens and of course zombie hordes i bet you guys can come up with some amazing uses for this in your scratch games if you have an idea then drop it in a comment below the video i would love to hear it before we start coding let me give you a quick overview of how these boys actually work say hello to a boyd hello boyd each and every boy in our simulation follows just three basic rules rule one separation each void will try to keep at a safe distance from any other boyd to avoid collisions rule two cohesion yet each boyd will also want to be part of a flock will try to move towards the center of its local group and lastly alignment each boy wants to fly in the same general direction as the other voids around it and that's it from these three simple rules emerge all sorts of stunning and complex group behaviors so are you ready for this yes then guys let's get scratching great with me a new project i'll name it boyd's simulation and the first sprite can also be named boyt we'll begin by drawing the boyd's costume zoom right in because we want to draw this triangle that's 32 by 10 pixels in size i first draw a square while holding shift without an outline and then remove one corner using the shaping tool before rotating it so that it points to the right by holding the shift key now we size it to 32 by 10 pixels before snapping it to the center of the costume canvas making sure it's centered is super important so that our boyd will rotate nicely in our game the next step is to ensure the void can move off screen draw a large square it turns out mine is actually too small here so make yours around 48 by 48 pixels to ensure this works and then snap it to the center finally make it invisible by selecting the transparent fill color excellent we can tidy away these two cat costumes sorry scratchies maybe next time mate right let's do some coding we want a random scattering of cloned void sprites when flag clicked we hide this is one of those clone factories where only the clones are visible and the original sprite is hidden set rotation style to all around to let the boys face in any direction then to create the clones we repeat 10 and drop in a create clone of myself this will create 10 hidden clones it will become important later that we can identify which void is which so we'll make a new variable ah squish that default my variable and create a new variable named this void id making sure it's for this sprite only each clone needs its own unique id the first boyd wants an id of one so set this boyd id to one before our repeat loop after the first clone is created we can change this boyd id by one so that the next created clone will get a board id of two and so on perfect when we clone a boyd we want to trigger some actions when i start as a clone we begin with a go to a random position to scatter them all around the screen and then remember to show the clone to make it visible as we hid the original sprite awesome we can now run this project and check out those 10 clones that is working as expected but 10 is boring let's up that to 50 boyds there that's much better shall we get them moving the easy way would certainly be to just use a move block but i'm sorry we can't do this because coding voids is much easier if we use a speed x and speed y vector rather than a direction and speed for this reason we make two new variables speed x and speed y also for this sprite only to send each boy in a random direction set speed x to a random number between minus five negative five and positive five and the speed y we just set exactly the same and now to animate the movement we'll add a forever loop right here this means each boyd will have its own game loop right now so the scripts for moving this boyd can be defined in a new custom block name it move and i'm going to add two inputs old x and old y these are to keep track of the previous position of the void why we need this will be made clear later on click to run without screen refresh we can drop the move block into our forever loop and as i said pass in the current x position and the y position of this point great so let's code up the move script next this may seem silly but rather than using change x and change y i'm going to drop in a go to x y and sum the old x input that's going to be the current x position remember with the boyd's speed x variable then the old y input with the boyd's speed y variable this should have the same effect of moving us in the desired direction so slap that green flag and watch those voids scatter ah so our two problems i can see one the boyds are not facing the direction they are moving in and two the boys are getting stuck at the edge of the screen let's start by getting them to wrap around to the opposite side of the screen if x position is greater than 240 that's the right edge of the screen then change x by negative 480 the width of the screen to bring it back to the left side of the screen if x position is less than negative 240 the left edge of the screen then change x by 480 to bring it onto the right side of the screen then for the vertical if y position is greater than 180 then change y by negative 360. off the top wraps down to the bottom and finally if y position is less than negative 180 then change y by 360. off the bottom wraps back up to the top excellent let's give that a test shall we well gosh that was a complete failure wasn't it and i know what must be up i told you already in fact but now you'll see why the invisible box i drew around my boyd costume is not large enough to allow the sprite to move off screen select the invisible box and using alt drag it to be between 40 and probably 48 pixels in size yep there now we are talking so the other problem to solve was to make the boys point in the direction they are travelling that sounds easy but you have to remember the direction is given by a vector the two values speed x and speed y we could use some trigonometry to calculate the angle but i do have a sneakier option make a new sprite naming it center that's the british spelling we want this to always be in the center of the screen so when the green flag clicked go to an x y of 0 0. now scratch has a block that lets us point a sprite towards another named sprite so if we reposition a boyd at an x y of negative speed x and negative speed y then we can tell scratch to point it at the center sprite and this then gives us the direction we were after awesome let's do it go back to the boy's sprite and under the define move block just move the other scripts out the way we first position at negative speed x and speed y so go to x y and subtract in both inputs and subtracting speed x and speed y and finally point towards the center sprite and there you go it works awesomely the downside of this trick is that we had to move the sprite to calculate the direction this would be bad news for us except i anticipated it and kept the old positions safe and sound by passing them into this move block so now you know why i did it this unusual way so do you notice that some boys are traveling much faster than others in a flock simulation temporary changes in speed are just fine but eventually all creatures will return to their species natural flight speed we are going to define lots of fun settings to control these voids like flight speed and they're going to be defined as slider variables so that we can play around with them to our heart's content click into the center sprite and now make the new variable top speed making it for all sprites in retrospect you might like to call it target speed as it's the speed that the boyd wants to travel at not really their actual top speed place it above the when green flag click script as a way of resetting it if we want to set top speed to 2.85 click on it afterwards to set the variable now i'm going to switch this variable reporter to a slider with a right click and then again to change its range a minimum of 0.5 and a maximum of 5. however we'll also need a second variable resolve for all sprites this will define how quickly the animal transitions to its target speed make this a slider 2 with a range of 0.01 that's tiny to 1.0 and we'll set it initially to 0.2 and then click that block to set it cool let's make this work back in the void sprite separate off the go to x y block to know if we are traveling too fast or too slow we first need to know what this boyd's actual speed is that's the distance we are traveling by moving by speed x and speed y make a new variable named distance for this sprite only and set it to and this is cool distance 2 center yeah we got this for free too from our trick to point in the right direction make a new variable we'll name it target for this sprite only and we'll use this in our calculations first we'll calculate the speed x so set target to if we divide the current speed x by the distance that is the full speed then that gives us the speed as a unit vector that has a full speed of 1 and that means we can then multiply it back up to the top speed to give our desired target x scaled to match our top speed so we just want to gradually accelerate towards this target speed change speed x by and now we multiply resolve this is how long it takes to get to the top speed and we subtract from the target speed the current speed x yeah we change the speed by a fraction of the difference between the current and target speeds haha this has to be repeated for the speed y we can duplicate the set target and the set speed blocks above changing the three speed x's for speed wise and that's all we need to change so reattach the scripts below before smashing that green flag wow yeah all the boyds are now settling into a nice constant pace and you can have fun wiggling these sliders and seeing how a smaller resolve causes the boys to take longer to change speeds nice when you're done playing and you want to reset the sliders just click into the center sprite and tap on the set top speed block voila so thus far it's been every boyd for themselves they don't appear to care much about each other and in fact they have no idea what other boys are flying around them what they need is a way to see each other to achieve this in scratch we are going to have to begin to record our boyd's positions and speed data in scratch lists this way each boyd can then look in the list to find out what its neighboring voids are up to void x for the x positions boyd y for the y positions boyd sx for the speed x's and void sy for the void speed wise for the time being we'll keep the lists visible on the screen until we know they are working before our game kicks off we must remember to delete all the items from these lists delete all from boyd x boyd y void sx and void s y and drop that right at the top of the when green flag clicked hat block next we must add the new items to the list one for each void clone created add to boyd x devoid y to void sx and to void s y and we drop in the current sprites x and y positions and the current speed x variable and current speed y variable like so make sure to drop this whole thing in just before the forever loop after setting speed x and y above it okay so if we run the project you should see 50 items appear in each of the four lists one item for each boyd in our game but you'll note none of these items in the lists are updating as the voids move to be useful we need to keep this data bang up to date come over to our define move script and down at the bottom use a replace item of list block the item number is going to be given by the this void id variable remember that one it gives the id of each boyd one being the first and this correlates perfectly with the item number in each list we are replacing the value in the void x list with the up to date x position of this sprite cool so duplicate that for the boyd y list popping in the y position of the sprite and finally duplicate them both and we'll set the void sx and void s y of course these values are again the speed x and the speed y variables so pummel that green flag and the boyd x and y list items are spinning around to reflect each boy's current position since no boyd is changing direction yet you'll notice that the speed x and y lists don't change and that's fine excellent now that we have easy access to our void data we can do some very exciting things separation is the name of the game as we want to get our boyds to avoid getting too close to each other flying into another bird is never a very good idea after all we'll need some new slide availables to configure this click back into the center sprite and make a variable named range for all sprites this is the maximum distance this boyd can see any boyd outside this circle will not directly affect this boyd's navigational decisions i'll set it initially to pixels then make the available reporter into a slider with a range from 20 to 150 maximum a second variable named separation again for all sprites this one is the amount of force this boyd will exert to keep it away from any void within sight set separation to 0.2 and a good slider range for this is a minimum of 0.05 and a maximum of 0.5 click the scripts to set the initial values and then click back into the void sprite so the scripts that change the sprite's position are all in this define move block but anything that changes the board's direction will be defined in a new custom block which will name calculate make sure to tick the run without screen refresh otherwise this will run awfully slow trust me the new calculate block can be used in each boyd's main game loop just before the move block yeah just like that now back to that new define block every boyd will run this script and will want to compare its position to all the other boyds around it for this reason we need a new variable other id for this sprite only this will keep track of which other boyd we are comparing ourselves to start with it set to 1. before adding a repeat loop we repeat for the number of items in the boydex list we want to look at each one in turn we mustn't forget that this boyd is also one of the boys in this list to skip over our own boy data we make sure that the other id is not equal to this void id cool then before the loop repeats drop in a change at the by one to move on to the next void in the list the first thing we need to know is whether the other boyd is within range of this point that is they can see each other for this we must know the distance between these voids more variables i need more variables distance x for this sprite only and distance y for this sprite only so distance x is the difference between the two boyd's x positions subtract from item of list use the other id for the item number of that other void we want the void x list and we simply subtract from it this boyd's x position we want to do the same for the distance y just use the boyd y list and subtract this boyd's y position instead okay this is good but we need the actual distance not just the x and y distance for this we will have to resort some pythagoras set the distance to the square root of the sum of distance x multiplied by distance x and distance y multiplied by distance y right we got the distance so is this boyd within range or not if distance is less than range remember that that was around 75 pixels away then good what now though we are trying to maneuver this boyd away from the other boy that is getting too close to achieve this we just want to push directly away from them that's just the opposite of the distance x and y variables that we just calculated change speed x by and we'll need to multiply and then a divide so that we can divide the distance x by the full distance that will give us a constant force away from the other void in the x direction drop that into the multiply and we need the same for the speed y so duplicate that changing the speed x to a speed y and the distance x for a distance y but rather than just drop in our separation variable for that is the force we want to push these boys apart with we first need to invert it remember we want the opposite direction away from the other boyd make a new variable yep so many neg res for this sprite only that stands for negative separation ah i named it wrong it should have been neg sep sorry anyhow at the top of the calculate script set to zero subtract yeah separation what a numpty and we can drop in the variable into the left side of those two multiplies to add in the separating forces now this i've got to see it's time to run this project i'm hoping to see these little babies trying to avoid each other and would you look at that they most certainly are how awesome is that if we push up the separation slider then the boy's reaction to each other becomes stronger and they turn away faster what's more turn down the range and now they swerve out of the way last minute you can have a lot of fun just playing with these settings but i digress and we still have work to do these little purple guys are not showing any sign of flocking for they would need a desire to stay together rather than just being repelled the cohesion rule is that we find the center point of all nearby voids and try to move towards it not so hard we just need to add up all the distance x's and distance wise and then divide them by the number of voids to get the average distance then we'll need a new slider to control the applied force so back in the center sprite make a new variable naming it cohesion for all sprites i'll initially set that to 0.03 and after making it a slider set its range from 0.0 to 0.1 now in the void sprite to get an average of the distances we'll first need a count of how many boyds are close by make a new variable void count for this sprite only and set it to zero just before the repeat loop next up more variables to store these summed relative positions some x for this sprite only and some y also for this sprite only and what do you know also set them both to zero in the same place scroll down this is the point where we know the other boyd is within range so we change boyd count by one then we'll change some x by our distance x variable that is the position of the void in the x direction relative to this one and of course we'll do the same thing with the sum y and the distance y variable great so now we have summed up all the relative positions we need to average them by dividing by the count of voids at the bottom of the script oh you know what duplicate this change speed x and y it follows a similar pattern only not with any of the same variables the divide by is going to be the count of boyds in this case hey right now duplicate these two scripts we'll keep them safe you'll thank me for that later back to business the scaling slider for this effect is the cohesion variable so pop that in and the value that we are averaging is of course some x and our sum y variable too and here we go smashing the green flag oh yes wow this is looking dead exciting i'm just hiding the non-slide of elbows so look how the boys are now trying to bunch together quickly turning around as they reach the edges of the flock and that's really cool if we pull the cohesion right up then pow the boys are all pulled tightly together what's really exciting is how these behaviors are emerging i guess what we have here is much more like a swarm though than a flock like bees buzzing around each other but our desired end game is slightly different each member of a flock should work together to bring order out of chaos and let the flock move around as a whole with uniform purpose the final rule then is called alignment this is where each boyd will attempt to match its direction to the average direction of all the other voids in range this is achieved the same way as the average positions only we use the average speed x and speed y of each void instead so you know what we need then yep back into the center sprite and make a new variable alignment for all sprites and we'll set it initially to 0.02 the slide will have a range from 0.0 to zero point one now click the script to reset all these defaults and then we can move back into the boyd scripts to pull off this final bit of boyd magic we are going to sum the void speeds so two more variables needed yeah variable overload i know name the first some speed x for this sprite only and some speed y do i need to say this sprite only so set them both to zero before the repeat loop and now just like with the sum x and some y we need to change some speed x and some speed y it might have been quicker to bring in two new change blocks so change some speed x and some speed y by and we need the relative speed compared to the void speed so subtract from the item other id of boyd sx and of boyd s y and we subtract the current void speed x and speed y got it summing the difference in speeds now we can scroll down and use this handy pair of change blocks i prepared earlier popping in the alignment slide available and multiply by the average of the summed speed x and speed wise now that is what i'm talking about you ready for nothing obliterate that green flag and are you seeing anything different is this random swarm mobilizing and moving off in any common direction yes i believe so they definitely are now tending to move in the same direction perhaps if we pull the alignment slider right up oh man yes now they are very uniform indeed really love the natural flow of these voids pushing the alignment low again causes them to lose their purpose and begin to swarm around once more i can only just begin to imagine the different formations possible by playing with these awesome sliders however we do have rather a lot of them taking up far too much space on our screen let's try to hide those sliders when the mouse isn't nearby click into the center sprite and we add a forever loop to the when green flag click script but we'll wait until the mouse is almost touching the left edge of the screen that is until mouse x is less than negative two hundred and then we show variable top speed and show variable resolve and show variable range and show variable separation and show variable alignment and cohesion yeah all of them and then what do we do to hide them again we wait until mousex is greater than negative 50. that's almost the middle of the screen to allow for these long sliders then we hide all the sliders again hide variable top speed resolve range separation alignment and cohesion so many shall we give it a try okay so the variables are hidden that's great so move the mouse over to the left edge of the screen and up they pop but what's cool is that they don't disappear until we move far enough away to the right brilliant that means we are safe to change these sliders without them disappearing guys we are almost at the end of this tutorial but just before i go how about we add a little script to let us interact directly with these beautiful boys with the mouse yeah i like that idea too go back into the boys sprite and find the bottom of the calculate script if the distance from this void to the mouse pointer is less than range then set distance x to the mouse x subtract this boyd's x position the same for the distance y subtract from mouse y this boyd's y position then we just borrow these last two change speed x and y scripts these are for the separation remember my stupid moment naming it negrese instead of negsep it says nusep in my notes too the only thing we need to change is to replace distance with the distance to mouse pointer and on that note run the project one final time and bask in the glory of this clever void simulation no these boys i'm most certainly not keen on flying near my mouse point and now ha i can actually herd them around if i wish and that's so fun are there improvements to be made definitely for example i think my separation calculations should actually have divided by distance squared we push the voids away more gradually based on distance i'll look into that soon and to get more voids running at once we'd need to look into screen partitioning and boyd bucketing however for a quick jump in speed you can try running your projects in turbo warp 2. wow and this really is the end now if you've enjoyed this video then please please smash the like button and consider subscribing to my channel there's a link to the scratch studio in the description under the video so do post a link to your finished projects there i cannot wait to see them and that's it thank you for watching do have a great week ahead and scratch on guys [Music] you
Info
Channel: griffpatch
Views: 175,347
Rating: undefined out of 5
Keywords: scratch coding, scratch programming, scratch game, scratch 3, griffpatch, Help coding, scratch coding games, scratch, scratch coding tutorial, scratch coding tips, scratch coding beginners, scratch tutorial, scratch tutorials, scratch games, scratch game tutorial, lists scratch, scratch clones, boids, ai, tutorial, ai scratch, scratch boids, flocking ai, scratch herd, scratch life, code scratch ai, scratch sight, coding for beginners, enemy to enemy, bird sim, npc scratch
Id: Rv1tvWTtd5M
Channel Id: undefined
Length: 35min 22sec (2122 seconds)
Published: Fri Aug 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.