[Intro] Hello fellow Scratchers, I tell you what,
it’s crazy what I’ve been up to this week! I’ve said it before, but the best breakthroughs
in Scratch coding happen when you are just having fun. You asked me for image scanning,
and texture mapping, and I said – Nah, we can’t do that with a bitmap raycaster… Ha! That was so last
week – This week we are blazing on all cylinders! So how is this suddenly possible? Well, stay with
me, and I’ll reveal all with not one, but two epic breakthroughs in one video, your raycasters
will never have run so fast! Am I excited? You have no idea! Guys – Let’s get Scratching!!!
Right, so load up our raycasting projects. It doesn’t matter if you are still at episode 2
or have made it all the way to episode 5, you can add in the following script
enhancements at any point… So, let’s begin by saving this project as a fresh copy,
for this is episode 6. [FPS]
Ok, so this is all about speed – I have quite a powerful PC here, so this looks to be running
pretty good right? Well, don’t forget we have set the resolution of this project set to 8… That’s
quite chunky – Hold on, if I make that RES slider visible, then we can drop this down to level 4…
Right! Now you can see things are slowing down… I don’t even let us set RES lower than this…
But the level walls do look better for it. It’d be nice if this could run faster right?
Hey, I wonder… How fast… or slow I should say, will it run at even better resolutions.
Oh heck! Looks great, but – not so fast! But better to not be subjective,
what would help is if we added a quick FPS counter so as to get a good measure of the
actual render speed in Frames Per Second. In the player sprite, we need 3 new variables.
“tick30”; this will keep track of the current time in 30ths of a second,
Scratch’s default refresh rate. Make it for this sprite only.
Next up, another variable named “DELTA”, leaving it for all sprites. This will record
the time it takes to render one frame. And finally, “FPS” or Frames Per Second,
also for all sprites. This will be our readout of the final frame rate – Excellent.
We need to initialise these values, Setting DELTA to 1,
and set tick30 to 0. Just pop those in
under the initial green flag script. Ok, scrolling down, here’s our main game loop,
we’ll add our FPS scripts here, but in a new custom block. We’ll name this “FPS”,
and add a nice new input, named “last tick30”. And check that run without screen refresh… why not.
Just pop the new FPS block in at the top of the forever loop,
and the input just takes the current tick30 value, Super.
So, let’s manhandle that into some free space, and code up the FPS counter.
This is nice and easy, We calculate our current game time. Set tick30 to,
the multiple, of timer (that’s the current time), and 30. This value will
now increase by 30 every second keeping in time with our desired frame rate.
Now we calculate the DELTA, that’s the time between the last frame
and this one. Set delta to tick30 subtract the ‘last tick30’ value.
Hey, we can see this working – When the project is running at full speed, this DELTA should read 1.
That’s because it’s taking exactly 1 frame to draw the screen. But… if I up the resolution,
ah… now we can see it’s taking over 4 screen update cycles to draw each screen. Now it’s just
a simple step to convert this to FPS. Set FPS to the round,
of dividing, 30 by DELTA. Sweet. And there, now we have a way
of measuring our games speed. [Fix for Transparent Walls – Oops]
Hold on, did you notice this? At some resolutions, our walls are mysteriously
appearing see through! TO be specific, this happens at a RES of 1, and 3. 3 and 1.
If we hope to work at these resolutions, and I am super optimistic about the fantastic improvement
in speeds we are going to get, then we should fix this. It’s caused by a quirk of the pen extension,
and luckily there is a quick fix. Come into the Raycaster sprite,
and find the define Raycast script. It’s all to do with where we begin our first
vertical line, this x value. The glitch occurs at pen widths less than 4. In these cases we
must begin drawing at only whole numbers of x. So, IF RES is less than 4. Set x to the round of x.
Simple. If we test that now, I’ll get some enemies behind this wall… and wiggle that RES slider… Yep,
solid as… solid as… a solid thing. Smashing! But do you feel we are getting distracted from
making our uber fast raycasting? No.. no not at all, this is all part of the ride,
so hold on tight, there’s just one more nugget of code to fix before we dive into
the meat of this explosive episode! [Framerate independent movement]
When the framerate of our project drops… have you noticed that not only does the screen updates
slow down… but, urgh, the player’s movement also slows down with it… man… it’s like wading through
thick treacle… In any decent 1st person game the players movements have to be completely
independent of the framerate. When my game is running half speed, the DELTA value rises to 2,
this tells us that we should be moving twice as fast to compensate. Useful!!!
So, armed with this value, find with me the define Player Tick script. Here are all our player
movement values. Mostly turns and move blocks. We are just going to multiply all these
values then by, DELTA. Turn left by 3 * DELTA,
Turn right by 3 * DELTA. Move forward by 2 * DELTA
Ok, this one’s negative, Move by -2 * DELTA
Now watch out on these strafing scripts, leave the turn 90s as they are. Just multiply the move
blocks again, 2 * DELTA, and 2 * DELTA. Yay… Let’s give that a test shall we.
Normal movement feels about the same. That’s good. We don’t want any unexpected choppy movement,
or to be moving too fast. Now let’s drop the RES…
So out framerate has indeed dropped, but the player speed is no longer slowed down, but we
keep on running around even so… That’s cool. Of course, you may now feel a bit sorry for
the enemies in the game, as they have not benefitted from the same DELTA speed boost.
If you have enemies, then we can fix this in the same way,
click into the ‘Entities’ sprite, and find the “when I start as clone” script.
And we just replace the move 0.5, with 0.5 multiplied by, DELTA.
So – Standing back… Here they come. And pull down the RES… And do those enemies care? No
they don’t. They remain coming at me at full speed independent of framerate, so good.
[Quick win – reduce number of pixels scanned] But this framerate!!! Come on, guys – I’ve
promised so much, and thus far we are still lagging like bright yellow banana slugs, So
how would you like to see an absurdly quick win? For this we need to be in the raycaster sprite.
If you look in the costumes, you can see we have the single
hitbox costume, and it’s 4x4 pixels in size. This is the costume we fling across the level,
over and over again as we raycast. And each time we ask, are we touching the level? Scratch needs
to check all 4x4, that’s 16 pixels underneath to see if any of them are indeed touching the level.
So, interesting question, what if we reduced the size of this scanner, would
that have a big effect on our raycasting speed? But, forget trying to size this by hand, no no no,
I have an awesome trick that I only just learnt while working on image scanners of all things.
Make a new costume, and we need a large filled rectangle. I’m just going to switch
to bitmap, and fill it all in. I’ll name this costume BIG.
Now, in the code tab, when the flag is clicked, we need a new switch to costume block,
switching to the new BIG costume. Doing this will then let us set the size of the sprite
to 1%. That’s really small. Careful now, drop this script in BEFORE you switch back to the
hitbox costume. Ok, so this will result in our already small hitbox costume being shrunk down
to as absolutely small as possible… And when we use a touching sprite or colour block now,
Scratch will always do just that single pixel check that is so sought after. Genius!
But, does shrinking down the scanner have a positive effect on framerate?
Let’s drop the RES to 4 and see…
Oh wow! Guys, I am still able to maintain 30fps at a RES of 4, that’s bonkers.
And even a RES of 1 is hitting 6 to 7 FPS, this is double what we were getting just moments ago. Now,
does this come at any cost you may ask? And the answer is yes. By shrinking our
raycasting costume, our rays are thinner, but also, if we skip too fast, potentially
gappy. And gaps lead to rendering errors around sharp corners in our level.
BUT THE SPEED… Hold on, the enemies are always getting in the way, I’m going to remove them
temporarily. Just click into the entities sprite, and reduce the SPAWN counts to 0.
Even at a resolution of one… things are not looking absolutely hopeless speed wise. And a
RES of 2 is incredibly playable for me… But, I want it faster! Is that even possible?
Hey look! My famous pillar room is looking different. The pillars are so much thinner than
they used to be. Do you know why? Well, this is actually the correct width of the pillars showing
up for the first time. A side effect of shrinking down the size of the scanning ray costume
is that it can now slip past the edges of the level far more accurately. So that’s a boon.
[Why bitmap raycasting is slow] But where was I… Yes speed! The question is,
what in general makes bitmap raycasting slow? Well, it’s because we are doing so much work…
At resolution 1 we are firing out 480 rays each an every game cycle, and each ray has to travel
100s of pixels… Wow well that’s like 48,000 pixels to scan every game tick!!!
Crazy – no wonder it runs slowly. We previously tried to mitigate this
by casting less rays, using a res of 6 or 8, but that isn’t ideal. The only other option is
to get the rays to travel faster by skipping more pixels, perfect for speed, but alas, resulting in
rays skipping over walls and corrupted rendering of our scene. But, man look at all this wasted
scanning in the middle of rooms and corridors… all this space that we know is empty, and yet we still
have to scan across it all the time. [Proximity Based Ray Skipping]
Well, hold on. What if we just used another sprite costume to highlight areas where nothing
is happening, and then allowed our rays to fast skip across these? If we are careful to guarantee
this area is always at least 10 pixels away from any wall, then we can always move by 10
pixels at a time in this area and never hit a wall… Oh my word that word that sounds amazing!
But drawing this floor area could be time consuming… except no, not at all. How
about we flip the concept, and just add a thick outline to the level costume and that gives us
the very proximity we need! We gotta try this! We start by duplicating the Level sprite (again) –
Name it "Level Proximity"
Then in the Costume Editor, Select all the shapes that make up the level…
You can do that by dragging a box around them, or pressing Ctrl + A on your keyboard.
Now we can simply set the outline width to 20. So, just how wide a perimeter
has this added to each shape? Well, pen outlines are measured in half pixels, so it will be 10
pixels wide… And since it’s 10 pixels across, but the line is centred on the edge of each shape,
then that’s actually only 5 pixel offset to our perimeter,
definitely worth bearing in mind. Great. So into the code.
We can delete this Toggle Map script, no need for that in this sprite.
Now we want to code up the special ray skipping scripts.
Click into the Raycaster sprite, and find our define Single Ray script. Yeah – Here it is,
and this is the simple repeat loop that scans forward, 2 pixels at a time until it hits a wall.
Right! Make a new custom block, and name it “Fast Proximity Ray”.
And we tick, run without screen refresh. Ok, so it’s this little repeat loop we are
replacing, so we’ll pull that out into the new define block, replacing it with a call to Fast
Proximity Ray script itself. Yeah, we can test that to confirm it works just the same as before…
Cool. Time for some fun.
To ensure we get the minimum touching checks, we’ll rework this script using a forever loop.
So the logic is, if the ray is not currently touching our proximity sprite,
then we are safe to move forward by a full 10 pixels. Now, why 10, not 5? Well,
even if we overshoot by 5 pixels, we will still be guaranteed to be within the perimeter of the
actual wall if a collision should occur. Handy. So if we were not touching the proximity sprite,
let’s repeat until we are touching it, that’s right the proximity sprite,
and we continue to move fast, 10 steps at a time – Oh yeah, this is what dreams are made of!
Now finally, this repeat will end when we have hit the proximity sprite, so… what do we do. We
need to back off a little, I’m opting for a move of -6 steps. This is just in case we overshot.
And now we do the detailed scan of the real level, but we must remember it’s possible we won’t find
a wall, we could just be passing by. So, we’ll repeat for a fixed number of tries, say 8 times?
Each time we move forward, we move by just 1 step.
Then check if we are touching the real Level sprite.
And if we are, then splendid, we want to stop this script, we are done.
Now, if after 8 tries we are still not touching the level, we can assume we were just passing by
a wall, and we loop around and start fast skipping across the level again – Yeah,
I really, really like that. I am stoked to give it a test! So off we go!
Looking fine at resolution 8 at a solid 30 FPS, so now dropping the RES down to… 2… Oh wow, are you
seeing this? Amaing, 25 FPS? Is that possible!?! This is madness… If you’d shown me this a
week ago I would have said speeds like this couldn’t be achieved with a bitmap raycaster.
Even at a RES of 1… 15 FPS in Scratch, Wowsers. [Outro]
You see, what’s so great about this, is that not only does it give us much smoother walls,
or the opportunity to run our project on slower PCs at reasonable framerates, But more than that,
it means we have power left over to finally look at adding extra features like texture mapping…
Something that looked impossible just last week, is now looking very, very possible… In fact,
yeah – I’ve already done it! Just look at what we’ve got to look forward to! :D. It looks amazing
in Scratch, which is unbelievable, but you should see it in TurboWarp! Oh yeah, this is insanity!
So yeah, I might have gone a bit too far with the animating textures and floor reflections,
but seriously it’s been just too much fun. Our next step in getting here will be to learn how
to do fast, full colour, image scanning, that’s going to be serious fun! Then,
after that we will be able make episode 7 of the raycaster where we will add in the scan engine,
and implement wall texturing. Yeah, even animating ones if we want ha! What a treat!
Are you excited? Oh yeah! So please smash that like button, don’t forget to subscribe to the
channel so as not to miss the next crazy cool episode, it’s going to be epic! If you want to
catch it early, or need the scripts, then why not consider joining the channel membership
which also include priority replies to comments and the fabulous custom channel emoji.
Well, that’s it from me, thanks for watching, have a great week ahead, and Scratch on Guys!