Simulating gravity, or at least the effect of gravity in Scratch can be difficult, but due to trigonometric blocks in Scratch, it is possible.

Note Tip: You should always adjust the scripts shown in this tutorial as necessary to fit your project.

Creating Gravity Using Trigonometry

This section is designed to teach you how to simulate gravity's pull on an object around a center-point. This is similar to how the gravity of a star affects the motion of a planet.

The script below is based on a simple trigonometric identity which states that sin2x + cos2y = 1.

Below are the scripts you will need to put into the object that you want to rotate:

when flag clicked
set [Distance v] to [100]
set [Rotation v] to [0]
forever
  repeat (360)
    go to x: ((([sin v] of (Rotation)) * (Distance::variables)) + ([x position v] of (Sprite2 v))) y: ((([cos v] of (Rotation)) * (Distance::variables)) + ([y position v] of (Sprite2 v)))
    point in direction (([direction v] of (Sprite2 v)) + (90))
  if <[359] < (Rotation)> then
    set [Rotation v] to [0]
  end
  if <[-359] > (Rotation)> then
    set [Rotation v] to [0]
  end
  if <not <touching (Sprite2 v)?>> then
    change [Distance v] by (-1.5)
  end
  end

If you want the person playing the game to control the rotation you can use this script:

when flag clicked
forever
  if <key (right arrow v) pressed?> then
    change [Rotation v] by (2)
    switch costume to (costume3 v)
  end

when flag clicked
forever
  if <key (up arrow v) pressed?> then
    repeat (10)
      change [Distance v] by (5)
    end
    wait until <touching (Sprite2 v)?>
  end

when flag clicked
forever
  if <key (left arrow v) pressed?> then
    change [Rotation v] by (-2)
    switch costume to (costume4 v)
  end

For the "Planet" or other object that is being rotated about you will want to use this script:

when flag clicked
forever
  point towards (planet v)

Make sure you set the "Planet" or other object's rotation to "do not rotate".

Using trigonometry is a smooth and effective way for more experienced Scratchers to simulate gravity. With some more advanced scripts you can even rotate about non-circular objects.

An example of trigonometric gravity can be seen here.

Creating Gravity Using Rotation

Archive.png 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.

  1. Change the sprite's center to the center of the planet. Paint Editor With Sprite Center in Center.png
  2. Repeat Step 1 for every single sprite of that character.
  3. 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:

Newton's Law of Universal Gravity.png

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:

Simulating Gravity in Scrollers

Gravity can be replicated on Scratch to be used in Scrollers and other projects where an object is forced downward. Listed below are several methods that you can use.

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)
forever
change y by (Y Velocity)
set [Y Velocity v] to ((Y Velocity) * (0.98))
when flag clicked
forever
if <not<touching [Ground v]?>> then
change [Y Velocity v] by (-0.1)
end
when flag clicked
forever
if <touching [Ground v]?> then
set [Y Velocity v] to [0]
end
wait until <not<touching [Ground v]?>>

Click here to see an example.

Direct Movement Method

Direct movement is more simple than the Velocity Method, but far less efficient at what it does. Not only does the jump look unrealistic, but it is far less practical in almost all situations. 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)
end
end

when flag clicked
forever
if <key [up arrow v] pressed?> then
repeat (10)
change y by (10)
end
end
wait until <touching [Ground v]?>

Examples

Simulating Gravity on Flying Objects

With the right backdrop and scripts, programming a sprite to "fly" may be fairly simple, but adding gravity helps with making platformers as well as jetpack games. The following script can help with the gravity implementation in a flying engine:[problematic]

when green flag clicked
forever
  if <key [space v] pressed?> then//You're flying
    glide (0.4) secs to: x: (x position) y: ((y position) + (40))
  else//You're falling
    glide (0.4) secs to: x: (x position) y: ((y position) - (40))

Or you can simply use Velocity:

when green flag clicked
forever
  if <key [space v] pressed?> then
    change [Y Velocity v] by (0.1)
  else
    if <(Y Velocity) > (-8)> then//Maximum falling speed
      change [Y Velocity v] by (-0.1)//Gravity
    end
    if <touching [ground v]?> then //A ground sprite
      set [Y Velocity v] to (0)
    end
  end
  change y by (Y Velocity)

Example Projects

The following projects are examples of the above or a similar engine:

See Also

Cookies help us deliver our services. By using our services, you agree to our use of cookies.