Cara Cara

untung99.homes: Raycaster Scratch Wiki


Untung99 menawarkan beragam permainan yang menarik, termasuk slot online, poker, roulette, blackjack, dan taruhan olahraga langsung. Dengan koleksi permainan yang lengkap dan terus diperbarui, pemain memiliki banyak pilihan untuk menjaga kegembiraan mereka. Selain itu, Untung99 juga menyediakan bonus dan promosi menarik yang meningkatkan peluang kemenangan dan memberikan nilai tambah kepada pemain.

Berikut adalah artikel atau berita tentang Harian untung99.homes dengan judul untung99.homes: Raycaster Scratch Wiki yang telah tayang di untung99.homes terimakasih telah menyimak. Bila ada masukan atau komplain mengenai artikel berikut silahkan hubungi email kami di koresponden@untung99.homes, Terimakasih.

A raycaster is a project that renders a 3D world based on a 2D map. This is a working example. A raycaster in Scratch is usually single frame and low resolution, to prevent lag.

Raycasting should not be mistaken with raytracing, which renders rays with more physical accuracy, catering to reflection and refraction of light rays, and traces rays in two dimensions rather than one dimension like in a raycaster.

Concept

A visual representation of the raycasting process

Raycasting works by casting “rays” to measure the distance to the nearest wall, hence the term “raycaster”. The program sends out rays starting from the player, moving forward until it hits an object, at which point it takes the distance it has traveled and colors the pixel based on the distance. The rays are sent in different directions. After all rays have been sent, the complete picture will be seen.

Sprite Based vs List Based vs SDF Based

This page explains two types of raycaster that can be programmed: the sprite-based method, the list-based method, and the SDF based method. Each has their own advantages and disadvantages:

Sprite Based List Based SDF Based
Degree of Difficulty Easy Hard Hard
Framerate Low High Low
Knowledge Required Basic Scratch Programming Scratch Programming; Trigonometry; Array Scratch Programming; Trigonometry
How Map is Stored As a Sprite; each map/world is a Costume As an Array (grid of numbers); each map is a separate array As a group of My Blocks
Sprites Needed 1 or more, depending on setup At least 1 (renderer) At least 1 (renderer)
Other Advantages Can be used for making worlds with curved walls Can easily generate random worlds Can easily generate shapes such as spheres, toruses, and cones

For beginners, it is recommended to start by making the sprite-based method, as it is easy and not complicated. For more advanced programmers and those who have made a sprite-based raycaster, it is recommended to make an array based raycaster, which is faster but more complicated, or an SDF based raycaster, which is slower and more complicated, but more flexible.

Sprite-Based Raycaster

The necessary components of a raycaster are:

  • A “map”
    • The map shows the layout of the level.
  • A “sensor”
    • The sensor will compute distances from the player to each wall.
  • A “renderer”
    • The renderer draws each wall based on the distance given by the “sensor”.

This tutorial will use four sprites to accomplish these three requirements. If someone is stuck at any time,
here is a finished example.

Map

Make a map sprite with walls, preferably 480×360. Floor space should be “clear” colored.

Then, add the following script to it:

when gf clicked
go to x: (0) y: (0)
set [ghost v] effect to (100)

Person

Next, a person sprite that walks around the map will be made.

Make a person sprite that has a one pixel by one pixel costume. The costume should be centered on the pixel. This is important.

Before diving into the sprite’s scripts, note that all (speed) should be replaced with how fast the player needs to move.

Put these scripts in the “person” sprite:

when gf clicked
go to x: (0) y: (10) // Or wherever you want the sprite in the map.
set [ghost v] effect to (100)
broadcast (sense v) and wait
forever
  if  then
    turn cw (3) degrees // This can be adjusted to rotate faster, to fight lag.
  else
    if  then
      turn ccw (3) degrees // This can be adjusted to rotate faster, to fight lag.
    end
  end
  if  then
    move (speed)::custom
  else
    if  then
      move ((-1) * (speed))::custom
    end
  end
  broadcast (sense v) and wait
end
define move (speed)
move (speed) steps
if  then // Wall sensing
  move ((-1) * (speed)) steps
end

A map has now been created that can be walked around in

Distance sensing

This is where it starts to build up to 3D raycasting.

In the real world, the more distant an object is, the smaller it appears.

A gif showing off “distance sensing” in slow-motion action. The red “blob” is the person sprite.

You will make a sensing script that measures the distance from the player to the walls around them. You need to do this for 96 different angles. All of this will happen when the “sense” broadcast is called.

Make a “distance sensing” sprite that has a one pixel by one pixel costume. The costume should be centered on the pixel.

Then, add this script:

when gf clicked
set [ghost v] effect to (100)

when I receive [sense v] // Used in "person"
sense
broadcast (draw v) and wait

define sense// Important: Make this custom block run without screen refresh.
. . .
delete all of [distances v]
set [distance v] to [0]
set [angle offset v] to [-48]
repeat (96)
  set [distance v] to [0]
  go to (person v)
  point in direction (([direction v] of (person v)) + (angle offset))
  repeat until < or <(distance::variables)>>
    move (1) steps
    change [distance v] by (1)
  end
  add (distance::variables) to [distances v] // We hit a wall. Let's keep track of the distance.
  change [angle offset v] by (1) // Let's test a new angle...
end

Drawing

Here is the information generated by “distance sensing” it taken and drawn. Remember, the more distant an object is, the smaller it is.

Make a “drawing” sprite with this script:

when I receive [draw v]
draw

define draw// Important: Make this custom block run without screen refresh.
. . .
go to x: (-237.5) y: (180)
set pen size to (5)
set pen color to [#7AF] // Pick the color that you want.
erase all // Prepare the screen for drawing!
pen up
set [column v] to (1)
repeat (length of [distances v])
  set pen (brightness v) to ((50) + ((item (column) of [distances v]) * ((50) / (80)))) // Fade to white
  set y to ((-1200) / (item (column) of [distances v])) // Adjust -1200 to make walls larger or smaller.
  pen down
  set y to ((1200) / (item (column) of [distances v])) // Adjust 1200 to make walls larger or smaller.
  pen up
  change x by (5)
  change [column v] by (1)
end

The project is now finished. The project will be slow when it is run in Scratch, unfortunately.

Jumping (optional)

Although it is impossible to add true vertical movement to the project, it is possible to create the illusion of jumping. It works by drawing the walls at a lower height when the player is jumping. Walls closer to the player will move downwards more to simulate parallax. To add the option to jump, first add the script below to any sprite or background:

when gf clicked
forever
if < and <(variable)>> then
 set [variable v] to (900)
 broadcast (sense v) and wait
 set [variable v] to (750)
 broadcast (sense v) and wait
 set [variable v] to (675)
 broadcast (sense v) and wait
 set [variable v] to (650)
 broadcast (sense v) and wait
 set [variable v] to (650)
 broadcast (sense v) and wait
 set [variable v] to (675)
 broadcast (sense v) and wait
 set [variable v] to (750)
 broadcast (sense v) and wait
 set [variable v] to (900)
 broadcast (sense v) and wait
 set [variable v] to (1200)
 broadcast (sense v) and wait
end
end

Now, modify the script that draws the walls to the following:

define draw
go to x: (-237.5) y: (180)
set pen size to (5)
set pen color to [#7AF] // Pick the color that you want.
erase all
pen up
set [column v] to (1)
repeat (length of [distances v])
  set pen (brightness v) to ((50) + ((item (column) of [distances v]) * ((50) / (80))))
  set y to (((variable) - (2400)) / (item (column) of [distances v])) //This is what creates the illusion of jumping.
  pen down
  set y to ((variable) / (item (column) of [distances v])) //This is what creates the illusion of jumping.
  pen up
  change x by (5)
  change [column v] by (1)
end

Speed Optimization

There are several ways to reduce lag:

  • Set the “person” sprite’s rotation style to “don’t rotate”.
  • In the “distance sensing” sprite, check for walls every 2 steps instead of 1.
  • Instead of drawing 96 columns, draw fewer. 60 is a good amount, assuming that in “distance sensing”, the sprite is rotated 2 degrees instead of 1 and the pen size is 8.
  • Replace the code in the forever loop in the “Player” sprite with this:
turn cw (( - ) * (5)) degrees
move (( - ) * (speed)) :: custom
broadcast (sense v) and wait
  • Make the sensing both sense and draw
  • Replace all broadcast (sense v) and wait with wait (0) seconds and make the sensing and drawing always sense and draw

The main speed bottleneck with a sprite-based raycaster is that the “distance sensing” sprite has to do lots of sensing.

List-Based Raycaster

A list-based raycaster relies on a map stored as a list and coordinates, such as that of the player and the ray, stored as variables. This method of raycasting is very virtual, all data is stored as numbers and there are no actual sprite costumes used. The only sprite required is a moving pen to draw the walls. If you want an example map, one is downloadable here. An example is available here.

A screenshot from a game that uses the list-based raycasting tutorial. Note that the frame per second counter is not low for a 3D Scratch project.

This tutorial will teach you how to make a simple list-based raycaster. It uses custom blocks to make editing easier. Make sure to check off “run without screen refresh” box.