Discuss Scratch

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:
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)

Last edited by MultiTasker801 (Nov. 1, 2023 03:31:05)

BaconLettuceMayo
Scratcher
16 posts

More accurate object collisions

MultiTasker801 wrote:

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)
Your project gives me an idea.
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
change y by (dist)
...
change y by ([] - (dist))
to
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

MultiTasker801 wrote:

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
change y by (dist)
...
change y by ([] - (dist))
to
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
I'm really just looking for something that can be used smoothly. Permission to use your script?
BaconLettuceMayo
Scratcher
16 posts

More accurate object collisions

Actually nevermind. The grid and circle scripts make the engine buggier.

Powered by DjangoBB