Crazy Simple Raycasting E2 - 🎮 How to make awesome 3d games in Scratch

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello fellow scratchers i'm griff patch and i am super excited to get right into coding our raycaster today oh my gosh yes i hope you enjoyed designing your levels and are ready to go because we have so much to cover today we'll be creating light rays light beams with god rays that is in itself such a joy to play with basic 3d projection and finally a lens corrected shaded render of our level wow oh come on let's get scratching and so we continue straight off from where we left our projects in episode one our levels are designed and we can walk around first person style using the wasd waste and cursor keys right then raycasters they're called as such because they work by sending out rays of light from our player in straight lines across the level to find where they collide with walls casting rays a good place to begin then is with the process of casting or firing out one ray to do this we'll need a new sprite but rather than starting from nothing we'll instead duplicate the player sprite now rename it raycaster and then we can delete all the blocks yeah we don't need these next go into the costumes tab and also delete the player costume so the only thing we are keeping is the little hitbox costume from episode one right on we go let's set up the raycasting sprite when flag clicked switch it to our hitbox costume and we'll set the rotation style to don't rotate doing this will ensure the touch sprite sensing blocks are as consistent as possible for now we'll fire off a new projectile when the space key is pressed we want to fire the projectile the same direction the player is facing so point in direction now to get the player's direction we look in the sensing category and get the elusive thing of thing block a tricky blocked find but ever so useful now switch the right side to read player and the left side can then be set to direction so point in direction direction of player great now for its position easy go to player quick test and this is doing what we expect we should find that every time we press the space key a little square hitbox costume is positioned just at my player's feet not so exciting so let's set it off moving like a projectile until it collides with the level so repeat until we are touching the level and until we do we just move the projectile forwards with a move four steps now before i explain why i chose four steps here let's give this a quick test smash that space bar and off it goes trundling in a straight line across the level and when it hits the wall it stops the repeat loop is ended now remember i told you to make sure the level was fully surrounded by walls i hope you listened because if not this projectile loop would never end right now that's not such a big problem but later on that will cause great lag so be warned coming back to that move four steps how did i come to that number well obviously a smaller number would mean the projectile would move slower you can try it if you like but when creating a raycaster one thing you do not want is a slow project speed is everything so then why not bump this number right up to say 16. well then the projectile would move in such large steps that it can skip right over a wall without gliding and that would be bad news for us so we need to find the largest step we can take that will not have this problem well if we look at our costume we see that it's 4 pixels wide therefore if we move by anything more than 4 pixels we will be leaving gaps between the sensing locations so 4 is the biggest step we can safely move moving by four pixels does have the benefit of getting the projectile across the level quicker but a disadvantage is that it can leave the projectile deeply embedded in a wall luckily we can deal with this by carefully reversing it back out again so that we find the true point of collision to do this duplicate the existing repeat block and this time we repeat until we are not touching level and to reverse slowly out we need to move by negative one step perfect wanna see that in action sweet each projectile now ends up very nicely flush up against the wall no overlap to be seen i find it quite funny though that if you look closely you can see the projectiles wiggling back out of the wall after they've collided that's because we are not using any run without screen refresh blocks that means every move we make in a repeat loop is being animated well we'll stop all that animation now anyway make a new block and name it single ray and we make sure to tick the run without screen refresh okay move everything below the point in direction block into our new define block and then drag in a new single ray block to where we move the scripts from so where before we were animating the flight of the projectile now we have wrapped the entire process in a run without screen refresh boom the projectile finds the wall instantly and we can change direction and at every press of the space key our projectile just materializes at the point of collision very neat indeed what we've created here can be thought of as a line of sight raycast it shows us what is directly in front of the player a fun enhancement to this might be to draw the line between the player and the collision like a laser gun so have you ever used the pen extension before just click on the add extension button down here and add scratches pen extension sweet a whole new category of scratch blocks to play with to avoid ending up with a screen full of lines drop an erase or block in to begin each shot next we set pen size to 4 to keep the width of the line similar to our projectile and then set the pen colour to 53 this is a hue colour and should be a nice jedi blue then to draw the line itself within the single ray script after the go to player we drop in a pen down now every movement of the sprite will leave behind a line so then pop a pen up at the bottom of the script as we've finished moving super let's test hit the space bar zap what a beautiful blue laser gun we have made that works really well and we can rotate and shoot it off again and again the lasers trace from player to wall instantaneously and with very good precision you getting any ideas for awesome games you could make with this seriously there's so much we could do with the things we cover in this tutorial it's one you'll find you can keep coming back to again and again okay the next step is to go real time with the laser gun changing it into a laser beam or laser pointer so no more when space key pressed bring in a when i receive block and we'll make a new message named raycast swap all the scripts from the space key over to that and now all we need to do is broadcast this event so click into the player sprite now locate the bottom of the main forever loop and just pop in a broadcast raycast okay so how beautiful is this i feel like we need a bright spark on the end and a sizzling sound as we cut a big chunk of level away with this huge awesome laser beam each step of this tutorial brings with it fun new toys to play with this is just too cool so moving fast now we've done a single beam how about we widen it out to make a full spread like god ray-like no problem surround the single ray block with a repeat yeah for ten why not but we need to turn within the loop so that the rays are spread out apart from each other turn clockwise that's to the right by 5 degrees ah but this repeat needs to be within a run without screen refresh 2. otherwise it just won't work so make a new custom block naming it raycast and tick the run without screen refresh the repeat 10 goes in there and drop a raycast block in where we move the scripts out from splendid i'm feeling good about this run the project oh man that is cool i like it a lot it reminds me of a laser show at a concert each ray emits from the player and individually finds the furthest point it can travel to before it collides you get some really interesting patterns being cast by these rays now so no problem here things are still running really smoothly shall we try and up the number of rays even more we'll begin by making a variable to define the spread of rays that we want to generate name it fov fov for all sprites that stands for field of view and will be useful for raycasting later on but for now we can think of it as the spread out of the raise under the when green flag clicked set 5 to 60. that's a good standard setting that will work well for us later on however for extra entertainment right click the fav reporter on the stage and make it into a slider then i'll set the minimum value to 30 and the maximum to 120 degrees nice now back in the define raycast we'll use the fov variable as the number of times we repeat wow that's going to be a lot of rays now 60 of them and since there are so many we'll reduce the turning angle to just one degree to squeeze them all in leaving less of a gap it's testing time oh wow wow wow the rays are so tightly packed that they have formed what looks like a solid flashlight beam that looks so amazing and watch this i can adjust the fog slider to expand and contract how wide the beam is so neat but do you see a problem we have here the beam is not centered on our player instead it's always being sent out to one side of us to fix this we need to rotate the whole beam half of its width to the left counterclockwise okay then before we start drawing the beam add a turn left block and half of the beam is easy to calculate it's 5 divided by 2. that's the ticket the beam is well centered and you can see it clearly as we play with the fog slider so cool i could play with this like forever what i especially love is to watch the shadows being formed by these light rays as i move rotate and strafe around the level look at the shadows cast by the little pillars they are particularly cool don't you think well if that doesn't get your imagination flowing i don't know what will but we are not done yet not even close for now we are going 3d are we excited oh yes take a look at this example scene up until now we've been using this blue beam to represent light shining from our player into the level and i've talked about this being the player's line of sight that is everything our player can see so for example the player can see this front wall here but won't be able to see through it to the wall behind in this scene we can identify five distinct wall sections visible to the player from this viewpoint if i pull up a 3d view of the scene we can clearly see the same five matching sections so how do we go from our 2d raycast to a 3d view well let's slow down the raycasting and watch the scene build one ray at a time we cast out rays from left to right as before making a note of just how far a ray had to travel before it collided with a wall this tells us just how far away the wall is in that direction and so when we begin to draw a 3d scene again from left to right we know we need to paint a slice of wall we just need to know how tall to draw it a close-up wall is large and a far away wall is tiny this is called perspective and it's a simple concept to be precise an object that is twice as far away appears half as big that is perceived height is equal to size divided by distance using this idea we raycast and draw an entire 3d scene one ray at a time so here goes nothing make a new variable x for this sprite only we'll use this to keep track of how far across the screen we've drawn set variable x to negative 240 the far left and drop it into the top of our raycaster custom block then we change variable x by now over the course of this repeat fov we want the x variable to travel a total of 480 pixels because that's the full width of the screen so to split that distance into five equal parts because we're repeating both of we divide 480 by 5. next find the define single ray script remove the pen down and pen up blocks so that we no longer draw the 2d rays to begin drawing our 3d scene we need to know how far a ray has traveled and therefore how far away a wall is scratch has a block for that distance to player that will tell us the length of the current ray from the player to the wall let's make a new variable to store that in name it distance for this sprite only and set the distance variable to distance of player super next we need to apply the perspective calculation to this distance so we know how tall the wall should appear on the screen make a new variable naming it height again for this sprite only and then set height to some value divided by the distance but we still need to fill in this left side and this is known as the actual wall height or size of the wall this is a weird one really as it's all relative but for now just enter the size number as 4 000 yeah it's quite big sounding but don't worry that should be about right and you can play around with it later to see what effect it has now we have everything we need to draw a slice of wall bring in a go to xy block the x position is simply the x variable we created that a moment ago the y position can be our height variable now lower the pen to the paper pen down to draw the wall move the sprite using a set y2 followed by zero subtract height so if height was 100 then we'd now be drawing a line from a y of a hundred to a y of negative one hundred so then pen up once more to complete the line and our single ray is done and by the nature of being called in a repeat loop the next ray will begin to draw until the whole scene is completed oh man yeah we are in a position to run this baby what do you think it will look like oh wow now what is interesting is that you can really see these vertical lines they are all very distinct it's kind of hypnotic like a really old console game i love it though we can still see the map where we were walking around overlaid on top which is kind of funky at this stage and even though we are just drawing lines we can easily make out the 3d scene with its corridors and rooms it's quite something how we have suddenly magicked up a virtual world from our simple level map it really amazes me that it can be done so simply and that really is the joy of raycasting right to improve things further let's hide the 2d map click into the level sprite now don't just use a hide block that won't work at all in fact it would break the project since we are relying on touching blocks to detect the walls of the level so instead use a set ghost effect block set to 100. this causes the sprite to become completely invisible without actually hiding it and yet they remain visible to the sensing blocks just as we need yep look at that very cool so next we'll try to remove the gaps between our wall lines so do we just want to bring the lines closer together if i slide the fog value wow that does the trick but the level ends up being distorted squashing the scene horizontally what we need is a way of changing the spacing of lines without changing the field of view this is often referred to as resolution or just res for short make a new variable named res for all sprites and at the top of the raycasting sprite in the green flag script set res to 8 this means we want every vertical line to be 8 pixels wide then make it into a slider setting the minimum value to 4 and the maximum value to 16. we can instantly drop the res variable into the set pen size block oh yeah you can see our level instantly fattened up but we're not done yet see how the lines still become gappy as we adjust the res slider let's see what the problem is come down to the raycast custom block these figures are now all wrong we need to space out the lines based on the res variable not the fov variable so how many vertical lines can we fit on the screen make a new variable named scan lines set the scan lines to 480 that's the width of the screen divided by red the thickness of the lines this is now the new value for our repeat loop one thing leads to another and we must also adjust the turn by angle this wants to still turn by 5 degrees in total so this becomes 5 divided by scan lines the last value is the x variable and obviously we want to move across by the width of the pen which is res what a reshuffle right but do we have success run the project it looks fine at a reserve eight great let's slide that down oh hmm okay we still have a small issue with gapping at odd numbers but the even numbers all look to be really tight this is probably due to where we begin drawing so you see how the first line starts halfway off the screen let's try moving the whole drawing half a pen width to the right instead of setting x to negative 240 bring in a subtract operator and enter 240 on the right and then on the left we want half of the pen width that is res divided by 2. there let's see if that fixed the problem yeah awesome that looks perfect now what do you think let's have a walk around oops too close to the wall there oh yeah yeah this is really coming together and it's very fun to explore the level but because it's all in one shade of blue it can be a little hard to make out some of the turnings a quick improvement we can make is to darken the walls as they move further away from us find the define single ray script and look for where we get the distance to player we want far away to mean darker so from the pen category bring in a set pen brightness block in brightness terms larger numbers mean brighter so we are going to need to flip this number so that larger distances become darker bring in a subtract block and we'll start from a brightness of 120. rather than just putting distance right in there we use a distance divided by 1.5 to make the level fade out a little more gradually feel free to play with these values the larger the number we divide by the more illuminated the level feels brilliant you can see the effect that this has had on our 3d rendering it feels so much more atmospheric there's just so much more perception of depth it's quite spooky in fact i don't think i'd want to be walking around this maze in real life i can tell you oh look at this i especially love this room because it really shows off the perspective of the 3d projection right we have an important adjustment to make now that many scratch raycasters not all but many fail to implement so look at this wall straight in front of me but do you notice something weird is it just me or does the wall look like it's curving away from us the effect can be amplified if i whap up the field of view wowzers now you can really see the curvature ha that's a crazy fisheye lens effect and surprisingly it's completely natural think about what we are seeing standing close to a wall the distance to the wall directly in front of us is way closer at the distance to the wall to our left or right so given that perspective says the wall further away appears smaller it's obvious the wall should indeed curve away to the edges of the screen but unless we want to feel giddy and get all motion sick we should probably follow the general convention of most first-person computer games and apply a lens correction to straighten these lines up luckily this is not very hard the fix is to stop considering the distance from the eye to the wall and instead measure the distance from the wall to the player's view plane this is defined by the direction the player is facing we can always draw a triangle from the player to the wall and then form a right angle from their view plane like so if you've studied trigonometry then you can calculate the adjacent length here using adjacent equals the cosine of t multiplied by the hypotenuse did i look that up on wikipedia of course i did okay let's code it up we'll use another set distance block and as the mass dictates we'll multiply the current distance that is the hypotenuse by the cosine of ah we need the relative direction of the ray we don't have that yet it's given by subtracting the direction of the player from this ray's direction to get the original direction come back to the define raycast script we'll make a new variable de dir for this sprite only and now set der to the initial direction cool so quickly back to the single ray script and now we can subtract d from the current direction there that makes the direction relative to the way we are facing splendid this is just begging to be tested let's see what this effect has on our scene so this is looking good the walls do now appear straighter backing away and yes hardly any curve to be seen awesome now while i go for a little walk around let's have a think about what else we could improve gosh i do hope you managed to get this far it's just too much fun okay what i think we should add is a floor and a ceiling the pure black does make the walls appear a little floaty since the walls appear to be bright close up i feel the floor and ceiling probably should do the same so click into the backdrop and then into the costume editor i'm going to start painting a completely new costume and draw a filled rectangle to cover the entire bottom half of the canvas right up to the midway mark now that's cool look at the 3d scene it already makes a difference just having a horizon but i'm not quite sure about the color though with the rectangle selected change the fill to be a gradient i want the top color to be black but the second color you can make a bit lighter and any color that suits your game there oh i like this and the ground is more defined now and yet it still feels like it's fading into the darkness in the distance how about for the ceiling now we could choose a pure black for a night sky but i think i'll just duplicate the floor you can use copy and paste if you wish or drag with the alt key and then finally flip it vertically yeah there we go let's see that in action man that's good with every upgrade it gets more immersive hold on i just noticed the player sprite and raycasting sprites are still showing we should have hidden these a while ago shouldn't we click into the raycaster sprite first finding the when flag clicked just set ghost effect to 100 to hide the hitbox we then do the same in the player sprite under the when flag clicked set ghost effect to 100 much cleaner right let me just show you some other things that it might be nice to improve sometimes when you approach a wall you'll see a significant jittering like a wall edge can't decide whether to draw or not do you see that not the nicest is it now remember i told you we could move our raycaster sprite by four pixels each time so that it moved fast but didn't skip any walls well that is only half the truth sure we won't skip over a complete wall but when moving by four pixels at a time we can still skip over the edges of a wall and that is what is happening here click into the raycaster sprite and find the define single ray script for a test try reducing this to a move by two steps instead testing that does indeed show a great improvement in the jitter wow but we do have to realize that the cost is that the raycaster will now run approximately twice as slow as before and that could be a bit too slow for some so bear that in mind and consider whether you want speed over accuracy of course you can always set the resolution to a higher number to keep things running fast it's up to you now since we're in this bit of code there's another thing we can tweak when i face a wall do you see the slight wobble across the bottom this is due to a sensing wall collisions to the nearest pixel we can adjust this move -1 to be just half a pixel instead try it using move of minus 0.5 steps and see how this improves the axi of the line it's far smoother isn't it again this will have a slight impact on the speed of your raycaster but this time not as dramatic but you can leave it at -1 if that does bother you okay guys enough little fixes we are close to complete but i do have one more significant enhancement to show off and it's cool you may have noticed that although shading for depth works wonders for distinguishing between walls that are behind each other it doesn't really help for corner junctions see how the corner here has no line or difference in shade or color to help us see it clearly what i want to finish with is a way of coloring walls to distinguish them apart look at this diagram we want all vertical walls to be colour a and all horizontal walls to be color b so array collides with a vertical wall here we want to paint the wall with colour a right but how can our vein customer know this well how about we paint another level costume and everywhere we have a bit of color that means the wall next to it should be color a if i draw a color all down beside the vertical walls then all i now need to do is check whether i'm touching this color after a wall collision to know if i should paint color a or b this seems like a plan but do you really fancy painting these colors in by hand no me neither so let me show you a faster way start by duplicating the level sprite naming the copy as level color okay are you ready you need to carefully follow these steps in the costume editor begin by making sure you are zoomed to 100 with the little equals button start by duplicating the level costume we need to select all the shapes that make up the costume either by dragging a selection box around them or by pressing ctrl a next up using the keyboard press the right arrow key just once this will move the entire duplicated level costume slightly to the right now click the copy button ready to make use of it again shortly got that so far great now we delete this entire costume don't worry the copy is still there ready to paste next up select all the shapes that make up the first costume again by dragging a selection box around it or pressing ctrl a but this time with your keyboard we press the left arrow key just once and the whole costume moves just that little bit to the left and here we go finally we press the paste button this results in our left and right shifted costumes being laid out on top of each other in a single costume you can see them both there the magic of this is that we are left with the color only to the left and right of the walls of our level but not below or above just what we needed right then so click into the raycaster sprite to detect the level color find a defined single ray script separate off the set distance script we want to set the color before this drop in an if-else block and we'll check whether we are touching level color if we are then we've collided with a vertical wall so set pen color to let's go for 58 else we again set pen color to 53 or whatever color value you want of course are you ready to test this i most certainly am oh yes this is so smart the walls are really showing this effect off well that's such a clean corner now big improvement if i walk about you can clearly see how the walls alternate between the two shades of blue depending on which way the wall faces i've got to say i'm really pleased with how this raycaster has turned out oh and here's my favorite room again look even better than before awesome the only problem with this technique of colouring appears on walls that are either curved or run at an angle in this case we tend to get a rather unstable flashing of color there is a solution though just come back into the costume editor for the level color sprite for walls that are not horizontal or vertical we must paint the colors in ourselves it's not really a problem i'm going to draw a big rectangle through the middle of this circular level structure here and then delete the circle part completely now the coloration should be very well defined let's see that in action amazing the large circular pillar is now segmented into four areas by the rectangle i've just painted in you could actually have quite a lot of fun coloring in levels the way you want to what do you think wow what a mammoth episode this has been and goodness have we made a lot of progress we've gone from just having a 2d level and a player to a fully 3d game just like that i really hope you've had a lot of fun following along if so then don't hesitate to smash that like button and let me say i really really look forward to taking a stroll through some of your levels so continue to submit them to the scratch studio linked under this video now if you haven't already to avoid missing any future videos subscribe to the channel now we've just passed 100 000 subscribers what a milestone right thank you everyone that just blows me away and if you want to support my channel further to help me make these awesome videos then please consider joining my channel membership there's a lot of perks to be had including more direct access to me through priority comments you get the fun channel emoji early access to videos before anyone else and for those who need them the scratch projects themselves but this is it we've run out of time thank you for watching have a great week ahead and scratch on guys you
Info
Channel: griffpatch
Views: 1,300,481
Rating: undefined out of 5
Keywords: scratch coding, scratch programming, scratch game, scratch 3, griffpatch, Pen, Stamping, Special Effects, Tutorial, Help coding, scratch coding games, scratch, coding for kids, scratch tutorial, scratch tutorials, how to scratch, coding for beginners, scratch 3d, scratch games, scratch 3d games, scratch 3d tutorial, scratch raycasting, how to make 3d game in scratch
Id: Vihr-PVjWF4
Channel Id: undefined
Length: 35min 34sec (2134 seconds)
Published: Wed Jan 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.