Discuss Scratch
- Discussion Forums
- » Help with Scripts
- » More accurate object collisions
- BaconLettuceMayo
-
Scratcher
16 posts
More accurate object collisions
I'm working on a platformer game, and recently I've made a forum post about moving objects. I have gotten that fixed, but I've realized it can be done better.
I'm using the code below:
Jokes aside, the nearest space is above the slope, where you usually expect the square to move.

However, because I'm using the script above, the square instead moves to the space most adjacent to it on exactly its x or y axis.

I've tried to make a script on my own, but I'm not really the best at trigonometry.
The square only moves under the slope in this case.

So, does anybody know a good and efficient script which finds the nearest empty space?
I'm using the code below:
define detect collision
set [dist v] to [1]
if <not <touching [level v]?>> then
stop [this script v]
end
repeat (300)
change y by (dist)
if <not <touching [level v]?>> then
stop [this script v]
end
change y by (() - ((dist)* (2))
if <not <touching [level v]?>> then
stop [this script v]
end
change y by (dist)
change x by (dist)
if <not <touching [level v]?>> then
stop [this script v]
end
change x by (() - ((dist)* (2))
if <not <touching [level v]?>> then
stop [this script v]
end
change x by (dist)
change [dist v] by (1)
end
if <script [doesn't v] work?> then
cry myself to sleep
end
Jokes aside, the nearest space is above the slope, where you usually expect the square to move.

However, because I'm using the script above, the square instead moves to the space most adjacent to it on exactly its x or y axis.

I've tried to make a script on my own, but I'm not really the best at trigonometry.
define circle collision detect
if <not <touching [level v]?>> then
stop [this script v]
end
set [dist v] to (0.2)
set rotation style [don't rotate v]
repeat (100)
point in direction (90)
change y by (dist)
repeat (45)
turn cw (8) degrees
move (dist) steps
if <not <touching [level v]?>> then
stop [this script v]
end
end
change y by (() - (dist))
change [dist v] by (0.5)
end
The square only moves under the slope in this case.

So, does anybody know a good and efficient script which finds the nearest empty space?
- MultiTasker801
-
Scratcher
100+ posts
More accurate object collisions
this problem is actually rather complex, you probably can't do anything performant for this in scratch.
for a quick solution, i do rather like your rotation based solution, aside from the not working. i think that issue comes from an error in the amount moved in the change y, but i am far too lazy to calculate the missing coefficient
i made a script to do this but i can't be bothered to write it in scratchblocks so here's a project link instead: https://scratch.mit.edu/projects/606110711/
edit: “performant” is a kinda cloudy word, especially on scratch. chances are this is just fine for what you're doing
i realize it appears that my script is massively more complex and possibly slower, but i used an approach that should ideally require fewer average iterations each time. it's also always exactly equally as fast each time you run it, in a hand-wavey kind of way. in other words it's O(1) instead of O(n)
for a quick solution, i do rather like your rotation based solution, aside from the not working. i think that issue comes from an error in the amount moved in the change y, but i am far too lazy to calculate the missing coefficient
i made a script to do this but i can't be bothered to write it in scratchblocks so here's a project link instead: https://scratch.mit.edu/projects/606110711/
edit: “performant” is a kinda cloudy word, especially on scratch. chances are this is just fine for what you're doing
i realize it appears that my script is massively more complex and possibly slower, but i used an approach that should ideally require fewer average iterations each time. it's also always exactly equally as fast each time you run it, in a hand-wavey kind of way. in other words it's O(1) instead of O(n)
Last edited by MultiTasker801 (Nov. 1, 2023 03:31:05)
- BaconLettuceMayo
-
Scratcher
16 posts
More accurate object collisions
this problem is actually rather complex, you probably can't do anything performant for this in scratch.Your project gives me an idea.
for a quick solution, i do rather like your rotation based solution, aside from the not working. i think that issue comes from an error in the amount moved in the change y, but i am far too lazy to calculate the missing coefficient
i made a script to do this but i can't be bothered to write it in scratchblocks so here's a project link instead: https://scratch.mit.edu/projects/606110711/
edit: “performant” is a kinda cloudy word, especially on scratch. chances are this is just fine for what you're doing
i realize it appears that my script is massively more complex and possibly slower, but i used an approach that should ideally require fewer average iterations each time. it's also always exactly equally as fast each time you run it, in a hand-wavey kind of way. in other words it's O(1) instead of O(n)
It's a bit complex to explain, so I'll make a remix rq.
Created something: https://scratch.mit.edu/projects/917252642/
Last edited by BaconLettuceMayo (Nov. 1, 2023 04:11:25)
- MultiTasker801
-
Scratcher
100+ posts
More accurate object collisions
i decided to benchmark the approaches and figured out that mine is drastically slower than the old circle detect (interestingly, the grid and your old circle detect were about the same speed! weird), so i decided to figure out what exactly was missing from the old one in order to make it work
this boils down to finding the radius of the regular polygon formed by equal length line segments connected at congruent angles, which is a classic solved problem.
the formula goes: L/2*sin(180°/n) where L is the length of a side and n is the number of sides
the script does 45 rotations of 8 degrees, so n is 45. L is just the dist variable.
we can precalculate the denominator to save processing time:
2*sin(4°)
~2*0.069756
~0.13951
now we just have to change the old script from
after this change, our implementations differ by very little, except in extremely rare cases where there are two closest positions, where sometimes one of our scripts will differ from the other (mine chooses the one further clockwise relative to the starting angle). mine is technically more precise, but slightly slower
this boils down to finding the radius of the regular polygon formed by equal length line segments connected at congruent angles, which is a classic solved problem.
the formula goes: L/2*sin(180°/n) where L is the length of a side and n is the number of sides
the script does 45 rotations of 8 degrees, so n is 45. L is just the dist variable.
we can precalculate the denominator to save processing time:
2*sin(4°)
~2*0.069756
~0.13951
now we just have to change the old script from
change y by (dist)to
...
change y by ([] - (dist))
change y by ((dist) / [0.13951])
...
change y by ((dist) / [-0.13951]) // dividing by a negative saves one block, neat!
after this change, our implementations differ by very little, except in extremely rare cases where there are two closest positions, where sometimes one of our scripts will differ from the other (mine chooses the one further clockwise relative to the starting angle). mine is technically more precise, but slightly slower
- BaconLettuceMayo
-
Scratcher
16 posts
More accurate object collisions
i decided to benchmark the approaches and figured out that mine is drastically slower than the old circle detect (interestingly, the grid and your old circle detect were about the same speed! weird), so i decided to figure out what exactly was missing from the old one in order to make it workI'm really just looking for something that can be used smoothly. Permission to use your script?
this boils down to finding the radius of the regular polygon formed by equal length line segments connected at congruent angles, which is a classic solved problem.
the formula goes: L/2*sin(180°/n) where L is the length of a side and n is the number of sides
the script does 45 rotations of 8 degrees, so n is 45. L is just the dist variable.
we can precalculate the denominator to save processing time:
2*sin(4°)
~2*0.069756
~0.13951
now we just have to change the old script fromchange y by (dist)to
...
change y by ([] - (dist))change y by ((dist) / [0.13951])
...
change y by ((dist) / [-0.13951]) // dividing by a negative saves one block, neat!
after this change, our implementations differ by very little, except in extremely rare cases where there are two closest positions, where sometimes one of our scripts will differ from the other (mine chooses the one further clockwise relative to the starting angle). mine is technically more precise, but slightly slower
- BaconLettuceMayo
-
Scratcher
16 posts
More accurate object collisions
Actually nevermind. The grid and circle scripts make the engine buggier.
- Discussion Forums
- » Help with Scripts
-
» More accurate object collisions

