Discuss Scratch

SourSkittlezzz7
Scratcher
3 posts

how do i somewhat convincingly replicate the physics of a ball in scratch? from a top down perspective (ex, Hockey)

this might be a somewhat complicated question, and I have a rudimentary and buggy system in place.

So! I have a small character who I want to be able to interact with a ball, I made it so each direction the player is moving in is captured.
when green flag clicked
forever

if <key [ w] pressed?> then


set [ UP] to [1]

else
set [ UP] to [0]
end
end
I use this system to also implement sprinting or walking over slow terrain by multiplying or dividing the variable when in the respective scenario.

Then, I have a ball. My current method is to take the captured movement values of the character, have a new variable called “Ball UP”, capture the player's Up value, and multiply it by 1.5 (in order to simulate a kick), and slowly divide the variable by 0.75 until it reaches a very small decimal, in which it is rounded to 0 to stop the script from dividing forever.

The problem is that, on paper, it seems alright, but in practice, its very janky. If the player hits the ball while going backwards, the ball captures that speed, the ball clips into the player, then clips around inside of them, making a ruckus and eventually squeezing its way out once you move enough. Since it captures the player's speed, if the player isn't moving, it stays stuck. It also just doesn't make for very convincing movement.

Is there a mathematic principle I can follow that would help me get a better start? Or is there a simpler solution someone can start me out with? I don't know, just looking for somewhere else to start.

Last edited by SourSkittlezzz7 (March 17, 2026 21:53:39)

g6g6g66g6g
Scratcher
100+ posts

how do i somewhat convincingly replicate the physics of a ball in scratch? from a top down perspective (ex, Hockey)

Are you able to share the project? It would make it a lot easier to see the exact issue.

Do you interact with the ball by running into it or by pressing an interaction key? How would you like the ball to move on interaction? By matching the movement of the player, moving away from the player, or like a circle-circle physics collision?

The issue with the ball moving into the player can probably be solved with some maths to bounce the ball off the player, assuming the player has a circular hitbox. I can explain further if you'd like.
SourSkittlezzz7
Scratcher
3 posts

how do i somewhat convincingly replicate the physics of a ball in scratch? from a top down perspective (ex, Hockey)

https://scratch.mit.edu/projects/1044175647/ is the project I'm referring to, it's a little project where I'm testing a few things, hence the name.

Yup! you just run into the ball to interact with it, and the character is a circle.

P.S. Code is a mess, like most games you've probably remixed. Haven't touched this project (or scratch in general) for over a year so some of my information might not be accurate to what I said.

play sound [Thanks!]

Last edited by SourSkittlezzz7 (March 18, 2026 05:02:13)

g6g6g66g6g
Scratcher
100+ posts

how do i somewhat convincingly replicate the physics of a ball in scratch? from a top down perspective (ex, Hockey)

For starters, it is not necessary to use 2 different variables to register speeds in opposite directions. Typically movement is split into horizontal velocity or xvel, and vertical velocity or yvel. Check the demo below to see how they're used.

Since we're working with circles, we don't need to use <touching sprite?> and instead use the faster and more consistent
if <(distance to [player v]) < [29]> then

end
29 is around the amount where you'll be touching the player. You can find it by adding the width of the player with the width of the ball, then dividing by 2.

From there, move the ball out of the collison range.
if <(distance to [player v]) < [29]> then
point towards [player v]
move ((distance to [player v]) - (29)) steps
point in direction (90 v)
end
Since the first thing this does is separate the player and ball, it is a lot less likely for them to get stuck together.

From there, you can set the speed of the ball in several ways. The first is just by using a multiplier of the player's velocity:
set [ball xvel v] to ((player xvel) * (1.5))
set [ball yvel v] to ((player yvel) * (1.5))

The second is an accurate physics bounce between two circles:
  1. first, imagine the player is completely still and only the ball is moving
  2. Get the player normal vector, which is the vector pointing away from the surface on the spot where the ball contacts it.

  3. Take the ball's velocity and get the amount that is moving in the same direction as the normal vector. We do this by getting the dot product between the normalized normal vector and the ball movement vector. The dot product only outputs an amount, not a direction, so you have to multiply it with the normalized normal vector to get its direction.

  4. Then reflect that velocity in the opposite direction. An easy way to do that is by adding 2x of the negative of the vector.
  5. This is how it would bounce if only the ball was moving. Since the player is also moving, we first need to shift the view of the world so the player is completely still, like if it was at the center in a scrolling game. To do this, imagine subtracting the player's velocity from both the player and the ball. We only need to actually do this to the ball. Then apply the bounce, then add back the player's velocity to bring it back to the regular world.
    change [ball xvel v] by ((0) - ((player xvel) * (kick power)))
    change [ball yvel v] by ((0) - ((player yvel) * (kick power)))
    bounce code ::custom
    change [ball xvel v] by ((player xvel) * (kick power))
    change [ball yvel v] by ((player yvel) * (kick power))
  6. You can try this and it'll work, but controlling where the ball goes will be inconvenient when it's purely physics based, so what we can do is bias the normal vector so that it faces slightly in the direction that you're moving. To do that, get both the normalized normal vector and player movement vector, blend them together, renormalize them and use that as the normal vector

  7. As a final fix, with the way it currently is, it would still have the bug where the ball can get stuck if it hits the backwards moving player. This is because of the force caused by the kick multiplier. Since the player is moving backwards, the extra force goes into pushing the ball even more toward the player. To fix this, we only apply the kick multiplier when the ball is “in front of the player”, which we determine with dot products again. If the ball is behind the player, then it's just treated as a regular bounce which is handled completely fine.


I know I've left quite a bit unexplained so if there's any part you want me to expand on just let me know. The demo below isn't completely bug free so my apologies for that, I'm not very advanced with physics collisions. A lot of what I've talked about is covered in Griffpatch's How to make Physics in Scratch.

DEMO

Powered by DjangoBB