Gravity could be described as the force that pulls objects together. There are many different ways gravity can be simulated in Scratch, with varying complexity.
| You can adjust the scripts shown in this tutorial as necessary to fit your project. |
Pulling Objects Downwards
The following are methods are of relevance to many 2D projects such as platformers. The examples given move sprites along the y axis.
Velocity Method
The Velocity Method is a great method for creating gravity and is highly effective and adaptable for multiple situations. Here is an example script—please note, this script will have the sprite inside the ground, rather than on top of it. This script will be placed into the Sprite that is being affected by gravity:
when flag clicked go to x: (0) y: (0) set [y velocity v] to [0] forever change [y velocity v] by (-0.1) // acceleration downwards change y by (y velocity) // move sprite by its current velocity if <touching [ground v]?> then // collision detection change y by ((0) - (y velocity)) // move sprite out of ground set [y velocity v] to [0] end end
Example Projects
- How to make a platforming script by djpro
- Scratch Cat's Adventure by StarWarsFan02
- Cross Sections by poose
Direct Movement Method
This method is simpler and less realistic than the Velocity Method as it pulls the sprite downwards at a constant speed. Nonetheless, the script works and is a good starting point for beginners:
when flag clicked forever if <not <touching [ground v]?>> then change y by (-1) // pull sprite downwards end end when flag clicked forever if <key [up arrow v] pressed?> then // jump detection repeat (10) change y by (10) end end wait until <touching [ground v]?> // can't jump again until you fall back to the ground
Example Projects
- Direct Movement Example by dazman_test
- First Project: Blob Advanced by Blobzer22
Glide Block Method
This is similar to the Direct Movement Method but with less control over movement.
when [space v] key pressed // jump glide (0.4) secs to: x: (x position) y: (40) glide (0.4) secs to: x: (x position) y: (0)
Example Projects
- Jetpack+ by StarWarsFan02
Pulling Objects Towards a Point
This method is similar to those shown in Pulling Objects Downwards. Instead of moving a sprite along the y axis, the sprite is moved towards or away from a point in 2D. This is easy to implement if the position of the sprite is stored as a direction and distance from the point.
when flag clicked point in direction (90) // sprite's direction also represents its direction from the point set [distance v] to [100] // the distance from the point set [velocity v] to [0] forever change [velocity v] by (-0.1) // acceleration downwards change [distance v] by (velocity) if <(distance::variables) < [100]> then // collision detection set [distance v] to [100] // stop falling set [velocity v] to [0] end go to x: (([cos v] of (direction)) * (distance::variables)) y: (([sin v] of (direction)) * (distance::variables)) // set sprite position based on distance end
An example can be seen here.
Creating Gravity Using Rotation
| This article or section documents something not included in the current version of Scratch (3.0). It is only useful from a historical perspective. |
Another method of simulating gravity is to change the center of a sprite so when you rotate it, it appears to be pulled by gravity. This method is much more simple, but far more difficult to achieve. Note the center change is no longer supported in 3.0. You will have to move the costumes for it to work. You can download the Scratch 2.0 offline editor for it.
- Change the sprite's center to the center of the planet.

- Repeat Step 1 for every single sprite of that character.
- Write scripts for each sprite for every different situation:
when flag clicked show go to x: (0) y: (0) point in direction (0) forever if <not <<key (space v) pressed?> or <<key (right arrow v) pressed?> or <key (left arrow v) pressed?>>>> then if <touching (Sprite1 v)?> then switch costume to (costume1 v) end end end when flag clicked forever wait until <key (up arrow v) pressed?> play sound (jump v) repeat (20) switch costume to (costume4 v) move (1.5) steps end repeat (10) switch costume to (costume4 v) move (1) steps end repeat (10) switch costume to (costume4 v) move (-1) steps end repeat (10) switch costume to (costume4 v) move (-1.5) steps end switch costume to (costume1 v) go to x: (0) y: (0) end when flag clicked forever if <<key (right arrow v) pressed?> and <not <key (up arrow v) pressed?>>> then turn cw (5) degrees switch costume to (costume2 v) wait (0.05) secs turn cw (5) degrees switch costume to (costume3 v) wait (0.05) secs end if <<key (right arrow v) pressed?> and <key (up arrow v) pressed?>> then turn cw (5) degrees switch costume to (costume4 v) wait (0.05) secs turn cw (5) degrees switch costume to (costume4 v) wait (0.05) secs end end when flag clicked forever if <<key (left arrow v) pressed?> and <not <key (up arrow v) pressed?>>> then turn cw (-5) degrees switch costume to (costume5 v) wait (0.05) secs turn cw (-5) degrees switch costume to (costume 6 v) wait (0.05) secs end if <<key [left arrow v] pressed?> and <key [up arrow v] pressed?>> then turn cw (-5) degrees switch costume to (costume4 v) wait (0.05) secs turn cw (-5) degrees switch costume to (costume4 v) wait (0.05) secs end end
One example of rotational gravity can be seen here.
Creating Gravity Using Physics
One advanced technique for simulating gravity involves Newton's law of universal gravity:
Variables and Lists
From this equation and Newton's 2nd Law of Motion (which states that F = ma) we can solve for the change in velocity of an object as: a = (Gm2)/(r2)
This describes the acceleration of one object due to the gravity of another (with mass = m2)
In the equation above, three variables can be seen to be needed:
- G (Newton's universal law of gravity)
- m2(mass of the other object)
- r (the distance the objects are from each other)
G is a universal constant and can often lead to masses and distances that seem very awkward or unintuitive. To simplify the equation and allow you to use easier/friendlier numbers, we can actually ignore G. When you choose your relative masses you will be factoring it in. If the project involves very large (e.g. Moon-sized) masses and large (e.g. low-orbital level) distances, use 6.67*10−11 for G.
Along the mass of object two and its distance, the speed of the moving object (object one) will need to be stored:
- X Velocity
- Y Velocity
Also, to turn the acceleration into its x and y components, a ratio will be used (this is based on the idea that the x and y forces form a right triangle similar to that formed by the objects themselves)
- Ratio
Finally, a variable will be used to iterate through every mass and every object's x and y position:
- i
Those masses will be stored in a list:
- Masses
As well as the x and y positions:
- X Positions
- Y Positions
Scripting
This demo simulates the trajectory of an object based on multiple stationary masses.
To begin, a custom block is needed that will iterate through every object in the project:
define Check Objects // make sure this runs without screen refresh!
set [i v] to (1) // the beginning of the list
repeat (length of [Masses v]) // each object takes up two items in the list
... // this is where the calculations will go
change [i v] by (1)//moving onto the next object
end
To note, the custom block needs to run without a screen refresh. After the custom block is created, the distance between the sprite and an object needs to be computed:
define Check Objects
set [i v] to (1)//the beginning of the list
repeat (length of [Masses v])
set [Dist. v] to ([sqrt v] of ((((item (i) of [X Positions v]) - (X Position))*((item (i) of [X Positions v]) - (X Position))) + (((item (i) of [Y Positions v]) - (Y Position))*((item (i) of [Y Positions v]) - (Y Position))))
change [i v] by (1)
end
Next, the overall acceleration is needed:
define Check Objects
set [i v] to (1)//the beginning of the list
repeat (length of [Masses v])
set [Dist. v] to ([sqrt v] of ((((item (i) of [X Positions v]) - (X Position))*((item (i) of [X Positions v]) - (X Position))) + (((item (i) of [Y Positions v]) - (Y Position))*((item (i) of [Y Positions v]) - (Y Position))))
set [Acceleration v] to ((item (i) of [Masses v]) / ((Dist.) * (Dist.)))// equation we found above
change [i v] by (1)
end
Next, the force is needed to turn into its x and y components. To achieve this, the force will be compared to the distance, and that ratio, when compared to the horizontal/vertical distance between the sprite and an object, will achieve just that:
define Check Objects
set [i v] to (1)//the beginning of the list
repeat (length of [Masses v])
set [Dist. v] to ([sqrt v] of ((((item (i) of [X Positions v]) - (X Position))*((item (I) of [X Positions v]) - (X Position))) + (((item (i) of [Y Positions v]) - (Y Position))*((item (i) of [Y Positions v]) - (Y Position))))
set [Acceleration v] to ((item (i) of [Masses v]) / ((Dist.) * (Dist.)))//equation we found above
set [Ratio v] to ((Acceleration) / (Dist.))
change [X Velocity v] by ((Ratio) * ((item (i) of [X Positions v]) - (X Position)))//x component of the force vector
change [Y Velocity v] by ((Ratio) * ((item (i) of [Y Positions v]) - (Y Position)))//y component of force vector
change [i v] by (1)
end
The script is now done, though the variables X Velocity and Y Velocity need to have some use:
when gf clicked set [X Velocity v] to (0) set [Y Velocity v] to (0) forever Check Objects change x by (X Velocity)//applying the velocities change y by (Y Velocity) define Check Objects . . .//refer above for the coding
To control the object, add this script:
when gf clicked forever if <key (left arrow v) pressed?> then change [X Velocity v] by (-1) end if <key (right arrow v) pressed?> then change [X Velocity v] by (1) end if <key (up arrow v) pressed?> then change [Y Velocity v] by (1) end if <key (down arrow v) pressed?> then change [Y Velocity v] by (-1) end end
Final Product
Once the steps above have been followed, this should be the final coding:
define Check Objects
set [i v] to (1)//the beginning of the list
repeat (length of [Masses v])
set [Dist. v] to ([sqrt v] of ((((item (I) of [X Positions v]) - (X Position))*((item (i) of [X Positions v]) - (X Position))) + (((item (i) of [Y Positions v]) - (Y Position))*((item (i) of [Y Positions v]) - (Y Position))))
set [Acceleration v] to ((item (i) of [Masses v]) / ((Dist.) * (Dist.)))//equation we found above
set [Ratio v] to ((Acceleration) / (Dist.))
change [X Velocity v] by ((Ratio) * ((item (i) of [X Positions v]) - (X Position)))//x component of the force vector
change [Y Velocity v] by ((Ratio) * ((item (i) of [Y Positions v]) - (Y Position)))//y component of force vector
change [i v] by (1)
end
when gf clicked
set [X Velocity v] to (0)
set [Y Velocity v] to (0)
forever
Check Objects
change x by (X Velocity)//applying the velocities
change y by (Y Velocity)
Examples
The following projects are examples of the above or a similar engine:
