|This article has links to websites or programs not trusted by Scratch or hosted by Wikipedia. Remember to stay safe while using the internet, as we cannot guarantee the safety of other websites.|
|This article or section may not have content matching Scratch Wiki editing standards. Please improve it according to Scratch Wiki:Guidelines and Scratch Wiki:Editing Conventions. (May 2020)|
This tutorial will teach how to make sprites detect and sense other sprites.
The tutorial assumes users are comfortable with making projects that;
- Use keyboard input to move sprites,
- Send and receive broadcasts,
- Include custom blocks and
- Use Game Loops to control and sequence projects.
If a refresher is needed, these tutorials can be followed.
Make three variables:
(delta x) (delta y) (raycast result)
Make one custom block:
raycast () () () ()::custom
Make one broadcast:
broadcast (sensed v)
What Does Sprite Detection Mean?
Creating realistic characters in games starts with giving them the ability to sense their surroundings.
To make games more realistic, the sensing sprite can be created with senses. By sensing other sprites before it touches them, behaviors can be programmed so that the sensing sprite runs towards a certain sprite and away from the other sprite.
How is it Applied in Projects?
Using Sensor Edges
Some games draw invisible circles that are centered around a sprite, called sensor edges, to help implement character senses. They are as wide as the sprite can sense (hear, see or smell), and that is why it is called an edge.
When the sensor edge is touched by another sprite, the sensing sprite can react. It can run away from one sprite, or towards another.
One complication is that the sensing sprite knows when a sprite is at the edge of its senses, but it does not know in which direction. For it to know in what direction the sprites are, a second step is needed.
Casting Lines to Sense Direction and Location
This process may be called raycasting. This raycasting is when a straight line (like a ray of light) is cast in a possible direction. If the sensing sprite casts a ray in the direction it is looking (called a line of sight) and that line touches a certain sprite, the sensing sprite can process what to do based off of that information.
Putting It All Together
Using a sensor edge allows the sensing sprite to sense a sprite, then it can use raycasting to look around for a certain sprite.
How Can This be Done in Scratch?
In Scratch, the following two things need to be done.
Collision Detection and Sensor Rings
The sensor ring is a separate sprite. This sensor ring sprite can send messages to the sensing sprite whenever another sprite touches it. It also makes sure to always stay at the same position as the sensing sprite, so whenever that sprite moves, so does the sensor edge sprite. It follows the sensing sprite, and it uses the ghost effect so it is not seen by players in the game, but it still runs its code. Here is the script:
set [ghost v] effect to (100) forever if <touching (sprite v)?> then broadcast (sense v) end go to x: ([x position v] of (sensing sprite v)) y: ([y position v] of (sensing sprite v)) end
Casting Lines With Raycasting
When the sensing sprite receives a message (from the sensor ring sprite) telling it another sprite is close, the sensing sprite starts looking for the touching sprite. It uses trigonometry to work out the direction of the touching sprite, so it can turn away from it or, to be exact, turn 180 degrees away.
when I receive [sensed v] raycast ([x position v] of (sprite v)) ([y position v] of (sprite v)) (0) (180) point in direction (raycast result) broadcast (sensed v) define raycast (target x) (target y) (offset a) (offset b) set [delta y v] to ((target x) - (y position)) set [delta x v] to ((target y) - (x position)) if <(delta y) = (0)> then if <(delta x) < (0)> then point in direction (-90) end else point in direction (90) if <(delta y) < (0)> then set [raycast result v] to ((offset a::custom) + ([atan v] of ((delta x) / (delta y))) else set [raycast result v] to ((offset b::custom) + ([atan v] of ((delta x) / (delta y))) end end