Sprites Behind Walls (Depth Sorting) | E4. Crazy Fun Raycasting

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello fellow scratchers i'm griff patch and i hope you're enjoying this 3d raycaster series as much as me in part 3 we managed to bring a non-player entity nano into our game so cool and that was a big achievement but we were left with the problem that we could still see nano through the level walls so we have our mission for today we'll be covering pen stamping drawing to and from lists and creating a depth sorted list oh my word finally though we'll fill our world with cloned entities to make things a lot more fun so save a fresh copy of your episode 3 scripts and let's get scratching this is episode four the problem we are facing is that nano as a scratch sprite will never appear behind a wall drawn using the pen they just can't the pen layer is permanently sat behind all sprites and that's the way it is the only way to overcome this is to use the pen stamp block stamping a copy of our sprite onto the pen layer now we can move the original sprite away and the stamped layer remains what's more we can now continue to draw more pen over the top of the stamped sprite and voila that is how we achieve the result we are after our next problem is working out when to stamp nano as some walls appear behind them and others are in front of them at present we draw the entire raycast scene in one go a nano appears pasted on the top so we will have to split up the raycasting to draw the further away walls first then nano and then anything closer to the player last but to raycast and draw later on requires us to store the results of the raycast in some way and that means using scratch lists we'll need to store each ray's x position distance to the wall and the wall color right then that's where we will begin click into the player sprite and find our define initialize raycaster script this runs before each raycast now we make the three new lists draw x to store the x positions for all sprites draw dist to store the distances again for all sprites and lastly draw type now i'm using this to mean wall color and it's again for all sprites we want to begin each raycasting sweep with our lists empty so delete all of draw dist type and draw x excellent a fresh start click into the raycaster sprite okay now what's the plan here rather than directly painting the level as we raycast we want to instead record all the information gathered from our raycasting such that we can draw the scene later on as such we'll move all the pen drawing scripts out of this sprite and into the aptly named pen sprite down here for later therefore under the when i receive raycast separate off these three green pen blocks these are setting up the pen ready to draw drag them into the pen sprite and then delete them from this sprite altogether let's just check they made it in there shall we yeah there they are in the pen sprite great so click back into the raycaster sprite again next up is the define raycast custom block nope this doesn't draw anything with the pen so we can move on to the define single ray script up here the first part is the ray casting we need to keep that the same but now we are into the pen drawing separate these scripts off starting at the if touching level color block the only exception is these two set distance blocks they should remain with the raycasting scripts there did you get that right we are ready to start pushing values into the lists we could just add them right in but to make things easier going forward we'll make a new custom block specifically for this job name it draw with a numeric input of type then a label at x and a matching input variable x then pop in the label dist for distance and the matching numeric input test now please be double sure to tick the run without screen refresh here otherwise you'll get bugs later on as we change things up a bit so we make use of the block right away but what data do we pass into it well the x is easy that's the variable x the distance yes we have that too it's this distance variable but the type that was to be the wall color right so that comes from this if-else block here the first color was 58 so let's fill that out but we still need this if condition so how about we just drop the draw block in there in place of the set pen color then we can duplicate the draw block into the else and enter the second color number that's 53 for me like that and again remove the actual set pen color block excellent that will do the job right we are almost there so although we call this custom block draw what it is really doing is saying this is where we want to draw and instead stuffs the values into our list for later so under the define draw script we need three add to list blocks and we'll add each of these three input variables to the three lists just make sure to add the type input to the draw type list the x to the draw x list and the dist input variable to the draw dist list cool that should cause our list to be filled up nicely we can take the remaining pen drawing script over to the right and then drop it safely into the pen sprite along with the other pen scripts then as before we can discard these ones from here hooray click into the pen sprite first job is to tidy things up bring the copied scripts into some free space that's better now usually while we code i like to stop regularly so that we can test some things are working as expected the best we can do at this point is to make our three new lists visible on the stage tick those boxes and then run the project now this is interesting see how the lists appear empty you'd be forgiven for thinking that we'd mess something up but hit the stop button and aha now the lists are suddenly full of data what gives all i can say is don't worry about it right now it's just to do with the order scratches running our scripts and it won't cause us any major issues well since the data is now visible what can we make from it each list has the same number of items that's good as we are adding data to each one for each scan line to be drawn i can see the x list appears to be filled with expositions ordered from negative 240 to 240 as expected that's a good sign the draw distances look to be all set and the type column is showing the correct two color codes that i added perfect so we can move on just hide the lists again right to draw the scene we need to work through our lists a row at a time but we need to draw quickly so let's make a custom block call it draw and tick the run without screen refresh and here we go drop the draw block at the end of the when i receive paint block first we must reset the pen canvas ready for our drawing and we have the array scripts here so bring them in the other script is for painting a scanline of the level but first we want to loop through the lists a repeat block will do as well but how many times do we repeat well that depends on how many items there are in the list so a length of list block and well the draw x list is as good as any as we loop around we need to keep track of which item or row number in the list we are up to make a new variable naming it row and then the hash is a shorthand for the word number so this is row number we'll begin at row one so set row hash to one then within the loop we'll change row hash by one to take us through each item in the list in order from first to last okay then awesome now we must draw a scanline of the level make another new custom block naming it draw row run without screen refresh it's a great idea to break code up into these custom blocks so that we can name things not only does this make it easier to know what a script is meant to do but it also makes it easier to find the right script later on pop it in as the first block in our repeat loop before we change to row 2 3 and 4 etc right exciting now we get to code the drawing scripts define draw row then our aim is to be able to use the painting scripts here but they require an x variable and a height variable and neither of these are yet set in this script no at present these values are still in our lists but before even that we don't have a type variable at all making a new variable type for this sprite only and set type 2 to get an item of our list we use the item of list block and choose the draw type list we just need to say which item we want and that of course we get from the row hash variable this way each time we draw a row we will get the values from the next item in the list the x and height variables are already created for us so we can duplicate the set block and switch it to be set x just ensure to switch over the list to match the variable so that should now be draw x just one more then for the draw dist list and the matching variable distance very good can we plug the painting scripts in oh boy yes drag them together getting excited and now we can run the project and hallelujah we have success we should be seeing the level drawing once more that sure is a relief this is a public announcement grief patch has noted during editing that he forgot to set the pen color from the lists and as such we have temporarily lost the wall coloring many apologies for this it will be rectified before the end of the video perhaps it was because he got distracted by oh wowzers nano is going haywire though they are certainly not ending up in the intended position from the last episode that's okay though it's super easy to fix scroll up to the when i receive paint and just drag the draw block up to the top of the stack that then allows nano to be positioned after we paint the 3d scene leaving nano positioned correctly afterwards once more there nano restored but gosh what has this actually achieved remember the goal to find out which walls are behind and in front of nano okay so take a look at this here is our scene as we have it now i've taken the liberty of drawing an oval shadow under nano so that we can easily see where his feet touch the ground now it's pretty obvious that this left wall should be drawn in front of nano so let's watch this scene draw in the order that scratch is drawing it essentially we are drawing from left to right the same order we are raycasting and then nano is popped on top bad they need to be drawn behind the wall so we might try drawing again until we reach nano stamp them and then continue to draw the level well no that doesn't help either because the next walls should have been painted behind nano now they are in front no good so what we need to do instead is paint everything behind nano first then paint nano and then paint the remaining scene in front of them that will guarantee everything is drawn in the correct order and order is the answer to how this needs to be done we must take the data we add to our lists and sort it ordering it by ray distance the distance to the wall the items at the top of the list should be the furthest away so they draw first and the items at the bottom of our lists being the closest walls and so they draw last that is perhaps a bit of a scary thought ordering a list in scratch but fear not it's not so bad if we take it a step at a time since our lists start empty we will assume the list is always in order then each time we want to add to the list instead of adding to the end like before we find the right position in the list to insert the new row that will keep the list in order this we repeat over and over until we are done and the list is guaranteed to be and stay fully ordered this is called insertion sort so let's begin click with me into the player sprite and find the define initialize raycaster script i'm going to begin by adding a dummy value to our empty raycasting lists and add to our draw distance list the value 999.999 wow this represents a distance that is far far away much further than any wall we'll ever actually draw this little trick will help simplify our scripts as it guarantees an upper limit is already in place now add a blank item to the other two lists the draw type list and the draw x list to keep things balanced sweet next we make a new variable naming it draw index or draw idx for short for all sprites we will use this to keep track of the position in the list we are inserting into but rather than starting at 1 set draw idx to 2. we never want to insert anything in place of item 1 the dummy boundary row cool and now the real fun begins click into the raycaster sprite and yeah we need to update the define draw script previously we were always adding new items to the end of the list but now to keep the list ordered we need to search up and down the draw distance list to find where the new distance should be inserted we begin by looking above the current item if it is closer than our new distance then we move up the list so repeat until greater than item of draw distance draw index subtract 1 that's the item above us in the list and compare it to dist input variable then in the repeat loop we change draw index by -1 okay what so we are repeatedly moving up the list a row at a time until we find a row above us that is further away than the distance we are trying to insert cool but what if our new distance was already closer not further away then we would need to search down the list instead so repeat until and this time use a less than operator item of draw distance but another change just use the draw index variable without the subtract one and compare to dist and we change draw index by positive one yes so we are repeatedly looking down the list until we find a draw distance closer to the player than the new distance great stuff because at this point we have found where to insert the new slice of wall we can't use the add to list block we need to use three new insert item at blocks instead these give us the control over where to insert into the list make sure to switch them to the draw type draw x and draw dist lists then move over the matching input variables and finally we say where we want to insert into and that is the value of our draw index variable three times over oh gosh wow that was some serious scripting i hope you are all still following along okay do we dare give this project a test hopefully everything is still working oh yeah cool the level is still there the question is can we tell if it's drawing ordered from back to front luckily there is a quick test we can do stop the project click into the pen sprite and then single click on the draw custom block now the stage will redraw slowly in the order the items are set out in our lists and yes that's certainly not from left to right but instead drawing from back to front that is so awesome to see and weldon you if you've managed to get this far now we are truly coding so let's take stock our level is now drawing from back to front check we have our nicely positioned entity nano check our entities are being correctly drawn behind walls fail and of course not for they are not part of our ordered list to draw nano in the correct layer we need to shuffle them into this list too keeping them all nicely in order all together well okay then click into the raycasting sprite and we'll take our beautiful define draw script and copy it into the entity sprite that's right just drag it straight in then click into our entity sprite and move it into some free space like so we need to find the define rotate view script here it is up here and drop in the awesome draw block we are going to insert nano into the list now what type shall we assign to nano this is not going to be a colour so perhaps we can use their costume number instead costume 1. as a side note if you are using 1 as your wall colour then go back and add 201 to that number so 202 and that will fix this potential conflict now the x position ah the x position stored in here is the perspective adjusted x position we need to therefore do the perspective correction on our vx variable before we add it to the list do you remember how to do this multiply the x position that is vx by dv divided by v y that's the distance cool the last input is just the distance itself and that was v y brilliant oh i have one little optimization we can make when v y is less than zero the sprite is behind us there's no point drawing or even sorting one that is behind us so surround the draw block with an if and check that v y is greater than zero that is it's in front of the camera and on we go click into the pen sprite let's work out how to stamp this entity now that they are sorted into our draw list so here is where we previously positioned the entity sprite no longer just attach that script leaving the single draw costume block to draw the 3d scene next we use a hide block to ensure the actual nano sprite is hidden this won't stop us from stamping copies of them onto the pen canvas though great bring up the define draw row script so coming in here we now need to consider how to deal with a type of one it means we are drawing an entity with a costume of one not a wall as we would have previously been the case we should split the script so that we can handle both scenarios detach the set pen block we just need to save this set height block though as this is needed for both walls and entities to adjust for perspective keep that but the rest of the scripts are for drawing walls so put them with set pen here and now we check the type if less than if type is less than say 10 that will let us use costumes one to nine for entities which we'll do fine for now okay time for a new custom block to handle the entity painting name it stamp entity run without screen refresh just attach that to the old entity scripts for starters and we'll revisit that in a mo we want to use the new block right away in our if condition but we also need a stop this script afterwards to prevent the rest of the scripts from drawing a wall too now you may prefer to have used an if else but i do have a habit of trying to avoid lots of scripts nested inside each other where possible so out of habit here we go right let's look at the stamp entity script hmm actually there isn't much in here that we're going to need to keep we've now already calculated both distance and height so bin them set size two oh yes we need that that's all good then we have the go to x y and this is wrong we can chuck the x maths blocks and in this place we simply place the x variable remember how we already made the perspective adjustments before adding it to the list just now so cool and so finally with the entity sized and positioned we stamp marvellous because that means can you believe it we can finally test this out and i'm dead excited to see the entity finally integrated into our scene and here we are there's nano looking a bit more pixely than before and that's no bad thing as it fits nicely into the style of the pen drawn level and next shuffling around the side of them to view them from behind a wall oh here we go and yes guys look fantastic half of nano has been obscured by this front wall amazing hey i know let's drag the 2d nano entity around the level this really shows things off i can move them back and forth and behind the wall and they are hidden perfectly that is so cool isn't it and i should be able to bring them right in front of the same wall too yeah there we go and how about this wall we can have them in front and take them all the way around the back hold on to see things at their best let's set all the ghost effects back to 100 to hide the player and the level sprites ah and we'll also need to add a new set ghost effect to the entity sprite set ghost effect to 100. there oh yes doesn't that look good you know i could play with this all day but you'd soon get bored of me so come on let's keep going one thing we haven't yet addressed is getting the entities to fade to black as they move off into the distance to match our walls for this click into the pen sprite and find the stamp entity script now we can't use the pen brightness block for this we need to use the set effect block from the looks category and we use set brightness to and drop it in before we stamp this works a little differently to the pen brightness maths a brightness of zero means normal brightness and negative numbers get darker so we need a subtract operator on the left enter 40 and on the right drop in a divide operator block we can divide distance by 1.5 you can play with these values to find out the ones you like but this value works good for me let's take a look oh wow that's already really creepy is that you nano oh phew yes it's you very cool that definitely integrates nano into the scene far more naturally and i love it but nano he looks so lonely just him alone in the shadows oh how about we give him some company this was never supposed to be about just a single entity after all we should click into the entities sprite and here we are setting up one single nano entity well if we want more we'll do well to use clones and to create them fast we'll need a custom block name it spawn with a numeric input count followed by a text label of and finally another numeric input type run without screen refresh use the block right away and will spawn that is clone 25 entities of type 1. costume 1 is the nano costume in my project wow this is going to be so cool drag the define block into some free space first thing we'll do is show this sprite we'll need this for the collision detection with the level don't forget that although we are drawing this in 3d at the end of the day they are also 2d scratch sprites in a 2d costume level so collision detection is completely possible and useful just like we have for our player sprite now create a variable type for this sprite only and set type to the type input variable we just passed in all of the resultant clones will then be set to this type a 1 for nano then we repeat to create each clone the number of clones we want is given by the count input and that was 25 nanos right yeah next we position the clones i want this to be a random position around the map so use a go to random position block but hold on what if a nano ends up randomly positioned on top of a wall of the level or even starts on top of another nano entity we don't want either of these to occur so repeat until not then pop in an ore the first thing to check is touching level that's the easy one so not touching level or touching another entity but nope scratch won't let us choose entity in this touching block pants okay fine let's work around that throw it away and click into another sprite bring in the touching block again and now select entities then we drop that back into the entity sprite right click back into the entity sprite here's our touching entities block that we needed pop it ruefully into the or block okay until we are not touching the level or another entity go to a different random position and that will keep going around and around until the entity lands happily in some free space once there just create a clone of myself make sure that's done outside of the inner repeat loop but within the outer repeat count loop wow we are nearly there guys at the bottom of the script to keep things tidy set type back to the empty value and then hide this sprite oh man this is it time to run the project look at that a herd of wild nanos has appeared what's so cool is that you can see they are layered correctly from back to front if we hit the green flag again they randomly spawn in different locations around the level let's have a wander around oh hello another nano over there i wonder where the rest are hiding yeah they are everywhere so fun it is surprising how many of these little entities we can add without overly slowing down the game which is a good thing because we will surely have a lot of fun with these going forward we are now drawing to a close on this episode but before i go i'm suddenly far too conscious that i broke the two-wall color system of our level ever since we moved to using lists we've got to fix that so click into the pen sprite and find the define draw row script what is missing is the set pen color block we never brought that over from the ray casting sprite so drop a new one in before we set pen brightness set pen color 2 and that is simply the type variable oh yeah wow there you go so much better i knew something was missing but i just couldn't place what it was until now the game looks far better with the wall colours restored wow i am so pleased we made at this point i didn't intend to teach entity placement in this series at all it was started just as a quick and crazy easy way of creating 3d levels in scratch but since you guys were so keen to keep on going here we are now and i have to tell you there's still more to come from here it's not a big step to creating collectibles level progression different entities and enemies we can look at how to make these enemies move around and chase us and could even add projectiles wow wouldn't that be something do fill the chat below with your comments i'd love to hear how you're getting along don't forget to submit your projects to the scratch studio linked under this video too if you've enjoyed this tutorial then please smash the like button and make sure to subscribe to the channel yep subscribe now there's no time to lose and that way you won't miss the next exciting episode if you feel you could support me more in making these videos especially if you're an educator then please consider joining the channel membership a huge thank you to my channel members and a special shout out to emperor aurora 55 code nerd scratch mail 1835 and sean higgins for their tremendous support okay that's it from me thanks for watching have a great week ahead and scratch on guys [Music]
Info
Channel: griffpatch
Views: 342,031
Rating: undefined out of 5
Keywords: scratch coding, scratch programming, scratch game, scratch 3, griffpatch, Pen, Stamping, Tutorial, Help coding, scratch coding games, scratch, scratch tutorial, scratch tutorials, how to scratch, coding for beginners, scratch 3d, scratch games, scratch 3d games, scratch 3d tutorial, scratch raycasting, scratch enemies, scratch 3d enemies, game development, programming, sprite sorting, scratch sort
Id: Q4cDDNCXfHA
Channel Id: undefined
Length: 31min 55sec (1915 seconds)
Published: Mon Feb 07 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.