Ball Projectile Physics Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello fellow scratchers have you ever wanted your projectiles in scratch to have better physics collisions motion and bounce this could be hard to get right but keep watching and we'll cover everything you need to know in just one amazing episode let's begin by drawing a tank costume that can fire the ball projectiles make sure it's centered on the canvas by dragging it till it snaps in position i'm adding a special invisible rectangle around the costume to avoid the unpleasant clipping that you get on the edge of the sprite name both the costume and the sprite tank next we'll create a level sprite using the rectangle tool to draw some nice borders all the way around the level and a couple of other boxes to join in the fun we need one more sprite now we'll name ball for the projectiles i'm drawing a red circle hold down shift whilst dragging to ensure it stays perfectly circular not too big now anything around the 16 to 17 pixels or so will be good again after drawing select it and drag it to ensure it's perfectly centered this is very important so don't miss this step okay we'll begin with the tank scripts i'm not going to do much here we'll position the tank in the center of the screen and then forever loop pointing at the mouse pointer a second loop can listen for the mouse clicks and space key presses these simply trigger a clone of the ball sprite to launch our projectile and then wait for 0.2 seconds this will prevent us shooting too fast if we hold down the fire button now to the ball sprite we initially hide the original sprite we'll let the clones do the actual work when i start as a clone move the bullet to the same position as the tank and point towards the mouse pointer to get our direction of fire now if we move the ball forward by 20 pixels it should be located pretty much at the end of the tank's bowel you might have to play with these values to get it right and then show the new clone if we run the project now and click the spacebar we can check whether the position seems good or not for me the 20 pixels is spot on however we don't want the ball appearing in front of the tank so if we go back to the tank sprite i'll stick a go to front layer before the first forever loop okay back to the ball sprite we need to set the projectile's initial velocity that is its speed in the x and y direction make two new variables speed x and speed y for this sprite only and we'll set them to mouse x and y divided by 10. so the further the mouse is away from the center of the screen the faster the projectiles will travel in that direction then we add a repeat loop for 200 cycles we don't want our balls to live forever the main processing for the ball will be done in a new custom block we can name tick run without screen refresh stuff the tick block into a repeat loop and then after the loop delete the ball clone nice okay the tick custom block first wants to simply move the ball so add a change x and change y by speed x and speed y respectively a good point to test run the project and the balls fire out towards the mouse nice what we should do next is stop them from traveling through the level walls we check if the ball is touching the level and if it is simply delete the clone you can test it again great the balls no longer penetrate the level walls but disappear instead a good proof of concept but not very impressive we want to create balls that can bounce let's rearrange the script so that we can check the collisions after both the change x and change y independent of each other this way of doing collision detection is perfect for levels that are only made up of vertical or horizontal walls without any slopes and i use it a lot in my platformers if a collision occurs due to us moving the x position then we already know the bounce will be horizontal and if we glide after moving the y then it's going to be a vertical bounce calculating the bounce is therefore easy we just negate the speed in the x or y direction now if we run the project you can see that we have succeeded in creating some beautiful horizontal and vertical collisions you may recognize these physics from games such as my taco burp game here let's just add some gravity into the simulation change speed y by negative 0.5 and there we have a super bouncy ball simulation so why is this not the end of the video well watch this if we edit the level to include a curved surface and test again now look at this the balls should not be bouncing directly up off the curve like that you see as programmers we often design our games to hide issues like this so for example in taco burp i purposefully made no sloping platforms this simplifies the taco collisions greatly but in this tutorial we're going to try to make things bounce way better right this simplified movement collision scripts have to go we'll start by putting it back to changing position x and y but then when a collision occurs rather than deleting the clone we move the projectile out of the collision using a change by 0 minus speed x and the same for speed y like this if i run the project you can see the first problem we have to solve after a ball collides it is currently thrust back out of the level leaving it floating quite far away from where it collided we want to make the projectile end flush against the wall to do this we'll back the ball out of the collision more slowly by wrapping the change x and y in a repeat until not touching level and then move the ball out a little at a time by multiplying speed x and speed y by negative 0.1 if we run the project you can see that the bullets are now ending their flight flush up against the walls that sets us up perfectly for our next step make a new block named find normal and we'll make use of it down here under the tick script do you know what a surface normal is if we draw a collision like this then the normal of the collision is this red arrow pointing out perpendicular to the surface we have collided with to be able to calculate how the ball will bounce we are going to need to know what direction this normal arrow should point in to do this we will employ a little trick rather than checking for a collision with the ball itself we sweep an offset ball costume around first in a full circle checking for collisions when we know where the surface begins and ends we can take an average and that will be the surface normal duplicate the ball costume naming it normal i've renamed the original costume as ball then back in the normal costume zoom out and with the ball selected i will use the arrow keys to move it six pixels to the right by pressing the right arrow six times just make sure you are zoomed out when you do this now back in the scripts under the define find normal switch to the normal costume we'd better also make sure to switch back to the ball costume at the top of the tick script we need a new variable named dir der for this sprite only to store the normal direction in set it to zero and point in the same direction of der make a new custom block named rotate with a numeric input of by in here we change dir by the input by and then point in the same direction now it's important to check whether the first position in our circular sweep is already touching the level or not if it is then we need to locate the point where the collision starts we repeatedly rotate until we are no longer touching the level rotating right by 15 degrees as we go create a new variable named der start to record the collision point for this sprite only set dir start to der but subtract 15. that was where the last collision occurred now for the case where we start sweeping and there is no collision duplicate the loop but modify it to repeat until we are touching level get rid of the knot and we rotate counterclockwise by negative 15. when we have found the collision point we record it in dir start as before but don't negate it by 15 this time afterwards we need to bring our sweep back to the top to prevent us rechecking the points we have already checked by setting der to zero and pointing in direction de move the script into the else here now all that's left is to sweep clockwise until we find the second collision surface duplicate this last loop script again checking for a collision but make the rotation b by positive 15. once found we can average the two directions by setting du to der plus der start all divided by two let's test this works by first ensuring the ball sprite is visible and that we are using the ball costume then drag the sprite on the stage to right next to a wall and click on the find normal script to run it you can see it sweeping around first left and then right before reporting a dir of 45 degrees that's quite correct brilliant so now we have the normal vector we will create a new custom block named bounce to calculate the correct bounce off the collision surface include two numeric inputs nx and ny standing for normal x and normal y make it run without screen refresh we can make use of the bounce block right after finding a normal we just need to convert the normal direction der into a normal vector using sine of der and cosine of der simple okay now for some rather magical maths let me draw you a diagram we have a speed x and speed y represented here with the blue arrow the red arrow is the normal vector that we calculated and is represented by an x and n y it points directly away from the collision surface the purple arrow shows the speed we want to calculate after the collision now this bit i looked up on google we can calculate the dot product of the speed and normal vectors like this and the new vector can be calculated using this from the tail of the speed x and y to the collision wall now why is this super awesome because if you now rearrange these vectors to line up here like this we can see that the new green arrow if doubled allows us to calculate the correct speed vector after the collision that's pretty awesome and a little mind-boggling but let's just go with it and put it into action create a new variable named dot product and set it to speed x multiplied by nx plus speed y multiplied by ny and then we change speed x by -2 multiplied by an x multiplied by dot product and the same for speed y but with ny instead of nx cool that's all the math's done already now come back to the define tick and make sure to set our sprites costume back to the ball costume after calculating the bounce this is an exciting moment we can run the project and see what we have got oh my word it's a miracle the balls are actually bouncing pretty much in the directions you'd expect it's amazing what a little dot product maths can do but hold on there there seems to be a little bit of error in the bounce right here see how the ball is bouncing off to the right i'd expect it to be coming right back down at me it actually took me quite a while to track this one down here's me using say blocks to show the normal directions i'd expect them to say 180 when colliding with the ceiling but they are reporting 172. okay if we go into the ball costumes and select the normal costume all we need to do is resize the ball by about half and when you do this hold down the alt key alt the alt key before you start dragging this causes the resize to occur from the middle of the circle not the edge very important now this improves the precision of the circular sweep quite a bit as the larger circle was colliding with the floor too early testing again shows the collisions are now reported as 180 as expected so i can remove the debug and we can continue let's add back in the gravity to our simulation oh yes this is very satisfying the only thing missing is that the balls are exceedingly bouncy now why is this well it's because our collision maths are absolutely perfect there is no loss of energy from these bounces in the form of friction and luckily this is really easy to add in find our define bounce block and we'll change the minus two values here a value of minus two means a perfect bounce and minus one would deliver no bounds at all we'll pick a number in between minus one point six now look at this the balls are quite visibly losing speed now on collision but you can see too that this has caused some quirks but the balls are appearing to stall and stop moving this occurs because sprite collisions are never perfect we need to ensure we allow for a little ever by moving the ball away from the collision surface just a bit to prevent them getting stuck dur is already pointing away from the surface we'll move the sprite gradually in that direction using a repeat 10 and within it we'll move the ball by half a pixel by sin of der and cos of der then stop the script when we detect no collision we do it this way so that the loop will always run once through even if it originally would not detect a collision in the unlikely event of not being free from the surface after 10 repeats we delete the clone running the project now and oh nice we've got a much more stable simulation the balls are no longer sticking to the surface now just a few more tweaks to finish this project off we can fade out the balls instead of just deleting them when they time out duplicate the main repeat loop and make a second short loop of twenty that also changes ghost effect by five now let's make the level a little bit more exciting try whatever you want this is the really fun part of making projects like this i love how the balls are naturally rolling down the slopes isn't physics great but ah we've hit an issue and you see my simulation has suddenly slowed down to a crawl or mega lag and look i can see the culprit right there that sprite is stuck in a wall in an endless loop in theory this should not happen but sadly as i said costume-based collisions in scratch are not perfect let's protect ourselves from this happening by making our repeat loops more robust locate the define find normal script this has the potential not to end if it doesn't ever escape from the level collision we can fix it by adding an if to the define rotate block and check if the absolute value abs of der is larger than 720 that's two full rotations then simply delete this clone there's one other loop in the define tick script that is worth fixing too make a new variable named count to keep track of the loops for this sprite only initialize it to 0 and change it by 1 each time around the loop check if count gets larger than 20 and then we again delete this clone now if i were you i'd like to add in some code to make the player's tank movable that would be super fun but i think i'll leave that to you however to allow us to test out firing from different locations i'm going to set the tank sprite as draggable with this block from the sensing category then in the ball sprite because we are no longer launching balls from the center of the screen we update the ball launching script to offset by the start position x and y of the projectile and that is it we can run the project full screen and drag the tank around i really love how the balls roll around in the disc shape i made to the right that is very satisfying so to round it all off let's just look back over the scripts to see what can change to make this project your own firstly the projectile velocity that's how fast the bullets travel through the air is set here in the ball sprite it is dependent on how far your mouse is from the tank but we could for example change it like this to give a constant speed in the direction of the mouse a value of 14 is quite fast but eight would give us much slower bullets we can play with gravity too just change speed y here zero for example turns gravity right off then there's ball bounciness scroll to the define bound script and see the number minus 1.6 and remember values can range from -2 for complete bountiness down to -1 for no bounce at all and lastly in the tank sprite we can change the fire rate by modifying this number a smaller number makes a tank fire faster like this and that folks is a wrap i know what you'll be asking for next what about bald ball collisions and man yes that would be really cool but it also is a whole other level of scripting and would get complicated very quick definitely a tutorial for another time what i think you should try next is developing the player movements and then adding in objects to be shot at wouldn't it be cool to add other players too do you think you could give it a go well i hope you've enjoyed this tutorial if you have then please do smash the like button and don't forget to subscribe to the channel to avoid missing my next exciting video leave me comments to let me know how you've got on and don't worry about posting your project ids here too if you want but until next time thanks for watching and scratch on guys
Info
Channel: griffpatch
Views: 633,669
Rating: undefined out of 5
Keywords: block coding, scratch physics, scratch, scratch tutorial, coding, physics, scratch tutorials, bounce, scratch roll, scratch coding, programming tutorial, scratch tutorial game, scratch gravity code, scratch programming, scratch game, coding for beginners
Id: Ge1DbXkyMKo
Channel Id: undefined
Length: 21min 21sec (1281 seconds)
Published: Mon Apr 12 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.