Rope Physics are the physics of a real rope, or the way one acts. It is very difficult to accomplish in Scratch, but it is possible.

## Spring Based Ropes

Ropes can be thought of as a series of springs, with each point trying to get to each other. It does not allow for swinging, but it does allow for a simple representation of ropes. Note: The ideas expressed here can also be used to make a spring instead of a rope.

### Variables and Lists

First, each rope joint is going to need two velocity variables to keep track of its speed:

• X Velocity
• Y Velocity

As well as two it's mass and a few properties:

• Mass
• Dampening
• Stiffness
• Gravity

Stiffness makes the rope shorter and stiffer. Dampening makes forces travel more slowly.

For computational reasons, a few more variables are needed:

• Force X
• Force Y
• True Force X
• True Force Y
• # of Rope Joints Made
• Joint ID

As well as a list to keep track of spring joints:

• Rope Joints

### Some Background

In a spring, the end of the spring is always trying to get to the top of the spring. It can not though because of gravity or because it's running into another section of spring:

Here, the top of the spring will be at (x1, y1) with the bottom being at (x2, y2). Since the bottom is trying to get to the top, the force that the bottom of the spring experiences becomes:

Force along the x-axis = x2-x1
Force along the y-axis = y2-y1

Since object's do not automatically go where they want to, some stiffness is at play:

Force X = (x2-x1) * stiffness
Force Y = (y2-y1) * stiffness

Since energy needs to be distributed over an object's mass, that needs to be factored in:

Force X = ((x2-x1) * stiffness) / mass
Force Y = ((y2-y1) * stiffness) / mass

That then is added to the bottom spring's velocity. The last factor that needs to be added is friction, which is done by:

X Velocity = (X Velocity + Force X) * dampening
Y Velocity = (Y Velocity + Force Y) * dampening

### Coding

A two-jointed roped will be created connected to the mouse. To start, one needs a cloning base:

```當 @greenflag 被點擊

分身 [自己 v] 建立
end

. . . // The physics will go here, as well as rendering.
```

Next, the ropes need to be rendered and they need to add themselves to Rope Joints so that other clones can look at their position:

```當 @greenflag 被點擊

分身 [自己 v] 建立
end

新增項目 (0) \( [Rope Joints v] \)
end

替換第 [1 v] 項於 [Rope Joints v] 成 (滑鼠游標的 x) // This is how the rope will look at the mouse's position
替換第 ((0) + (2)) 項於 [Rope Joints v] 成 (滑鼠游標的 y)
筆跡清除 // Clears the screen of old rope drawings
end

render :: custom
替換第 ((Rope ID) + (2)) 項於 [Rope Joints v] 成 (x 座標) // So that other joints can look at this joint's position
替換第 ((Rope ID) + (3)) 項於 [Rope Joints v] 成 (y 座標)
end

```

Here's when the physics are added:

```當分身產生

physics :: custom
render :: custom
替換第 ((Rope ID) + (2)) 項於 [Rope Joints v] 成 (x 座標) // So that other joints can look at this joint's position
替換第 ((Rope ID) + (3)) 項於 [Rope Joints v] 成 (y 座標)
end

x 改變 (X Velocity)
y 改變 (Y Velocity)
```

### Final Product

This should be the code to make a two-jointed rope that's connected to the mouse:

```當 @greenflag 被點擊

分身 [自己 v] 建立
end

新增項目 (0) \( [Rope Joints v] \)
end

替換第 [1 v] 項於 [Rope Joints v] 成 (滑鼠游標的 x) // This is how the rope will look at the mouse's position
替換第 ((0) + (2)) 項於 [Rope Joints v] 成 (滑鼠游標的 y)
筆跡清除
end

physics :: custom
render :: custom
替換第 ((Rope ID) + (2)) 項於 [Rope Joints v] 成 (x 座標) // So that other joints can look at this joint's position
替換第 ((Rope ID) + (3)) 項於 [Rope Joints v] 成 (y 座標)
end

x 改變 (X Velocity)
y 改變 (Y Velocity)
```

## Pendulum-Spring Based Ropes Note: This tutorial uses (distance) as a variable name, so whenever the variable (distance) is used, it will appear purple. Do not confuse it with the LEGO WeDo block version of (distance).

### Variables and Lists

First, each rope joint is going to need two velocity variables to keep track of its speed:

• X Velocity
• Y Velocity

Next, a list will be needed to keep track of every rope:

• Rope Joints

As well as two variables so that ropes can figure out where they are in order:

• Joint ID

And the length of each rope segment:

• Segment Length

Another list will be needed to keep track of the quality of ropes being created:

• ChainCreateList

As well as a list to keep track of deleted rope joints:

• Removed Rope Joints

And a variable is needed to keep track of if a rope joint is at the end of a rope or not:

• Joint Type

And the gravity:

• Gravity

As well as several computational variables:

• Distance
• Difference in X
• Difference in Y
• Rope Tension
• Force X
• Force Y
• i
• Joint Point ID 2

And two variables for the player's sprite's velocity:

• Player X Velocity
• Player Y Velocity

### Some Background

In this rope simulation, the spring, unlike with a Spring-based rope, heads for a minimum distance away from its swing point. This leads to some pendulum-like characteristics:

The top will be labeled x1, and y1. The bottom (and free part) of the spring will be labeled x2, and y2. A few variables need to be initiated first:

Difference in X = x2 - x1
Difference in Y = y2 - y1
Distance = √((Difference in X)^2 + (Difference in Y)^2)

Then, an intermediate variable is used to find the ratio of the force to the rope length:

Rope Tension = (((Distance) - (Segment Length))/(Distance))

Which is then backtracked to find the individual forces themselves:

ForceX = ((-1) * ((Rope Tension) * (Difference in X)))
ForceY = ((-1) * ((Rope Tension) * (Difference in Y)))

### Coding

#### ChainCreateList

For the purpose of the code, there shall be three types of rope joints:

• 1 - A rope joint with rope joint above and below.
• 0 - A rope joint that attaches to an object. For this tutorial, it will be the player sprite.
• -1 - A rope joint that only attaches to one other rope joint.

An example rope might be constructed from the following rope joints:

1, 1, 1, 0

This rope is four lengths long, and the player is attached at the end.

Meanwhile, ChainCreateList will be styled in this order:

• x座標 of Rope Joint 1
• y 座標 of Rope Joint 1
• Type of Rope Joint 1
• x座標 of Rope Joint 2
• y 座標 of Rope Joint 2
• Type of Rope Joint 2
• Etc.

#### Rope Creation (Custom Blocks)

To create a rope, two custom blocks will be used. One custom block records the information for each rope joint being created, and the other custom block actually creates the rope. The blocks are shown below:

```定義 Add Rope Joint at x: (xPos) y: (yPos) Type: (Type) //Run without screen refresh!

分身 [Ropes v] 建立 // Ropes is the sprite that will render the ropes.
end
```

#### Creating Rope Joints

To make things easy to handle, each rope joint will be a clone of Ropes. The following scripts should be added to Ropes:

```當 @greenflag 被點擊

新增項目 (Joint Type) \( [Rope Joints v] \)

新增項目 (1) \( [Rope Joints v] \)
. . . // If the Joint Type is 0 or -1, then two rope joints will be made.
. . . // This is the first rope joint. It isn't the end of the rope, so its type is 1.
. . . // The second rope joint though is the end of the rope.
. . . // Remember, each clone draws a line between joints.
. . . // So if there are 5 rope joints, only 4 clones are needed.
. . . // Because of that, the last rope clone add two rope joints to (Rope Joints) instead of one.
end

. . . // The next block will figure out where the clone is in the list (Rope Joints).

. . . // The next if block creates a second rope joint.
. . . // Look at the large comment chain above for more information.

新增項目 (清單第 [1 v] 項項目\( [ChainCreateList v] \) :: list) \( [Rope Joints v] \)
新增項目 ((清單第 ((0) + (2)) 項項目\( [ChainCreateList v] \) :: list) - (Segment Length)) \( [Rope Joints v] \)
新增項目 (Joint Type) \( [Rope Joints v] \)
變數 [Rope Joints Made v] 改變 (3)
end
. . . // The next three blocks delete the rope from (ChainCreateList) since it is already created.

. . . // Rope Physics go in here.
end
```

The code inside of the forever block is actually surprisingly simple. All it consist of are two custom blocks and two 清单类积木 to update (Rope Joints) with the position of the rope joint. This is what the code looks like with forever block filled in:

```當 @greenflag 被點擊 // Ropes will be drawn in this color.

新增項目 (Joint Type) \( [Rope Joints v] \)

新增項目 (1) \( [Rope Joints v] \)
end

新增項目 (清單第 [1 v] 項項目\( [ChainCreateList v] \) :: list) \( [Rope Joints v] \)
新增項目 ((清單第 ((0) + (2)) 項項目\( [ChainCreateList v] \) :: list) - (Segment Length)) \( [Rope Joints v] \)
新增項目 (Joint Type) \( [Rope Joints v] \)
變數 [Rope Joints Made v] 改變 (3)
end

Apply Chain Physics of x: (清單第 ((Joint ID) + (3)) 項項目\( [Rope Joints v] \) :: list) y: (清單第 ((Joint ID) + (4)) 項項目\( [Rope Joints v] \) :: list) :: custom
. . . // The next two blocks update (Rope Joints) with the new position of the rope joint.
替換第 ((Joint ID) + (3)) 項於 [Rope Joints v] 成 (x 座標)
替換第 ((Joint ID) + (4)) 項於 [Rope Joints v] 成 (y 座標)
Draw Rope Segment original: (x座標) (y 座標) :: custom
end

. . . // To be implemented in the section called "Adding Physics to the Rope Joints"

. . . // To be implemented in the section called "Rendering a Rope"
```

#### Adding Physics to the Rope Joints

The first half of the physics is just like the section above called "Some Background"

```定義 Apply Chain Physics of x: (xPos) y: (yPos) //Run without screen refresh!
. . . // Look above at the section "Some Background" for an explanation of the physics.

變數 [TempX v] 設為 ((清單第 (Joint ID) 項項目\( [Rope Joints v] \) :: list) - (xPosition))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (1)) 項項目\( [Rope Joints v] \) :: list) - (yPosition))

變數 [TempX v] 設為 ((清單第 (Joint ID) 項項目\( [Rope Joints v] \) :: list) - ([x 座標 v]\([Player Sprite v]\))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (1)) 項項目\( [Rope Joints v] \) :: list) - ([y 座標 v]\([Player Sprite v]\)))
end

變數 [Rope Tension v] 設為 (((Distance) - (Segment Length)) / (Distance))
變數 [ForceX v] 設為 ((Rope Tension) * (TempX))
變數 [ForceY v] 設為 ((Rope Tension) * (TempY))

變數 [ForceX v] 設為 (0)
變數 [ForceY v] 設為 (-1) // Applying gravity.
end

. . . // Since rope joints of type 0 are attached to the player, it makes sense to apply forces to the player.
. . . // That's what the three blocks below do.
定位到 x: ([x座標 v] \( [Player Sprite v] \)) y: ([y 座標 v] \( [Player Sprite v] \))
變數 [Player X Velocity v] 改變 (ForceX)
變數 [Player Y Velocity v] 改變 ((ForceY) - (3))
end
. . . // More code to be added here.

變數 [X Velocity v] 設為 (((X Velocity) + (ForceX)) * (0.65))
變數 [Y Velocity v] 設為 ((((Y Velocity) + (ForceY)) * (0.61)) - (3))
x 改變 (X Velocity)
y 改變 (Y Velocity)
end
```

The problem with this model of physics is that if an entire rope was completely still, but it's end was twitching around frantically, then the only part of the rope affected would be the end. In reality, some of the twitching end's force would travel up the rope. To combat this, the script will reapply the physics, but instead of having a rope joint try to get to the one above it, it will try to get to the one below it. The reason why this works is because gravity always keeps a rope joint just below the threshold of a segment length.

```定義 Apply Chain Physics of x: (xPos) y: (yPos) //Run without screen refresh!

變數 [TempX v] 設為 ((清單第 (Joint ID) 項項目\( [Rope Joints v] \) :: list) - (xPosition))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (1)) 項項目\( [Rope Joints v] \) :: list) - (yPosition))

變數 [TempX v] 設為 ((清單第 (Joint ID) 項項目\( [Rope Joints v] \) :: list) - ([x 座標 v] \( [Player Sprite v] \)))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (1)) 項項目\( [Rope Joints v] \) :: list) - ([y 座標 v] \( [Player Sprite v] \)))
end

變數 [Rope Tension v] 設為 (((Distance) - (Segment Length)) / (Distance))
變數 [ForceX v] 設為 ((Rope Tension) * (TempX))
變數 [ForceY v] 設為 ((Rope Tension) * (TempY))

變數 [ForceX v] 設為 (0)
變數 [ForceY v] 設為 (-1) // Applying gravity.
end

定位到 x: ([x 座標 v] \( [Player Sprite v] \)) y: ([y 座標 v] \( [Player Sprite v] \))
變數 [Player X Velocity v] 改變 (ForceX)
變數 [Player Y Velocity v] 改變 ((ForceY) - (3))
end

變數 [TempX v] 設為 ((清單第 ((Joint ID) + (6)) 項項目\( [Rope Joints v] \) :: list) - (xPosition))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (7)) 項項目\( [Rope Joints v] \) :: list) - (yPosition))
變數 [Distance v] 設為 (([sqrt v] 數值 (((TempX) * (TempX)) + ((TempY) * (TempY)))))
如果 <(Segment Length) < (Distance)> 那麼
變數 [Rope Tension v] 設為 (((Distance) - (Segment Length)) / (Distance))
變數 [ForceX v] 設為 (((Rope Tension) * (TempX)) * (0.6))
變數 [ForceY v] 設為 (((Rope Tension) * (TempY)) * (0.5))
end
end // New Content

變數 [X Velocity v] 設為 (((X Velocity) + (ForceX)) * (0.65))
變數 [Y Velocity v] 設為 ((((Y Velocity) + (ForceY)) * (0.61)) - (3))
x 改變 (X Velocity)
y 改變 (Y Velocity)
end
```

#### Rendering a Rope

Rendering a rope is pretty simple. It draws a line between two rope joints and adds a dot at each rope joint to look like a knot.

```定義 Draw Rope Segment original: (xPosition) (yPosition)

x 改變 (0.4) // This block makes sure that something's drawn.

. . . // Since the pen is down, simply going from one rope joint to another makes a line.

```

#### Deleting a Rope

Deleting a rope requires three scripts. The first two scripts remove all deleted rope data from the list (Rope Joints), and the other script is for deleting those rope joint clones, and if needed, altering other rope joint's data. The first two scripts are shown below.

The custom block's variable (Joint Point ID) should be a multiple of three and will not take any other values.

Also, remember that the list Removed Rope Joints is used to keep track of the (Clone ID)'s of the rope joints deleted.

```定義 Destroy Rope containing Rope Joint: (Joint Point ID) //Run without screen refresh!

. . . // This repeat deletes all rope joints ahead of (Joint Point ID) until it meets the end of the rope.
Destroy Rope Joint at: (Joint Point ID)
新增項目 (((Joint Point ID) + ((i) * (3))) - (2)) \( [Removed Rope Joints v] \)
變數 [i v] 改變 (1) // Delete next rope joint.
end

. . . // This repeat deletes all rope joints behind (Joint Point ID).
Destroy Rope Joint at: (Joint Point ID 2)
新增項目 ((Joint Point ID 2) - (2)) \( [Removed Rope Joints v] \)
變數 [Joint Point ID 2 v] 改變 (-3) // Delete next rope joint.
end

. . . // The next block deletes the tail of the rope.
Destroy Rope Joint at: (Joint Point ID 2)

```

The third script, as said above, just deletes the deleted rope joint clones, and alters other rope joint clone's data so that they point towards the right spot in (Rope Joints).

```當收到訊息 [Destroy Ropes v]

. . . // This checks if the rope joint was deleted, and if it was, it completes the process.
分身刪除
end

. . . // This checks if the rope joint is in a higher spot in the list (Rope Joints) then the remove joints.
. . . // If that is true, then the rope joints needed
變數 [Joint ID v] 改變 ((-3) * (清單 [Removed Rope Joints v] 的項目數 :: list))
end

. . . // If (Joint Type) equals -2, then this is the original Rope sprite.
. . . // All it does it decrease (Rope Joints Made) by the amount of rope joints deleted
. . . // It also resets the list (Removed Rope Joints).
變數 [Rope Joints Made v] 改變 ((-3) * (清單 [Removed Rope Joints v] 的項目數 :: list))
等待 (0) 秒
刪除第 [全部 v] 項 \( [Removed Rope Joints v] \)
end
```

#### Miscellaneous

To delete all ropes, the next script is needed in Ropes:

```當收到訊息 [Rope Clear v]

刪除第 [全部 v] 項 \( [Rope Joints v] \)
變數 [Rope Joints Made v] 設為 (1)
end

```

To test if code was copied correctly, it would be helpful to make a rope. Below is some code to make a wavering rope with a player attached to the end. Note, it needs a variable called (X Acceleration) and another variable called (j).

```當 @greenflag 被點擊

Add Rope Joint at x: (0) y: (80) Type: (1) :: custom
Add Rope Joint at x: (0) y: (55) Type: (1) :: custom
Add Rope Joint at x: (0) y: (30) Type: (1) :: custom
Add Rope Joint at x: (0) y: (5) Type: (0) :: custom
Initiate Rope Length #: (4) :: custom

變數 [X Acceleration v] 設為 (-2.2)
重複無限次
變數 [j v] 設為 (0)
重複直到 <(j) = (40)>
變數 [j v] 改變 (1)
變數 [Player X Velocity v] 改變 (X Acceleration)
變數 [X Acceleration v] 改變 (0.11) // Pushing the player slightly right.
end
變數 [j v] 設為 (0)
重複直到 <(j) = (40)>
變數 [j v] 改變 (1)
變數 [Player X Velocity v] 改變 (X Acceleration)
變數 [X Acceleration v] 改變 (-0.11) // Pushing the player slightly left.
end
end
end

. . . // This blocks definition is above.

. . . // This blocks definition is above.
```
##### The Player Sprite

The player sprite, like in a regular platformer, needs the following scripts run constantly:

• Gravity
• A script to change x by (Player X Velocity)
• A script to change y by (Player Y Velocity)
• A script to decrease (Player X Velocity) because of friction. Multiplying (Player X Velocity) by 0.65 is good.
• A script to decrease (Player Y Velocity) because of friction. Multiplying (Player Y Velocity) by 0.65 is good.

### Final Product

Ignoring the player sprite and the test code, all of the required code is shown below.

The next two scripts can be put in any sprite:

```定義 Add Rope Joint at x: (xPos) y: (yPos) Type: (Type) //Run without screen refresh!

分身 [Ropes v] 建立 // Ropes is the sprite that will render the ropes.
end
```

The next series of scripts need to be in the Ropes sprite:

```當 @greenflag 被點擊 // Ropes will be drawn in this color.

新增項目 (Joint Type) \( [Rope Joints v] \)

新增項目 (1) \( [Rope Joints v] \)
end

新增項目 (清單第 [1 v] 項項目\( [ChainCreateList v] \) :: list) \( [Rope Joints v] \)
新增項目 ((item ((0) + (2)) of [ChainCreateList v] :: list) - (Segment Length)) \( [Rope Joints v] \)
新增項目 (Joint Type) \( [Rope Joints v] \)
變數 [Rope Joints Made v] 改變 (3)
end

Apply Chain Physics of x: (清單第 ((Joint ID) + (3)) 項項目\( [Rope Joints v] \) :: list) y: (清單第 ((Joint ID) + (4)) 項項目\( [Rope Joints v] \) :: list)
替換第 ((Joint ID) + (3)) 項於 [Rope Joints v] 成 (x 座標)
替換第 ((Joint ID) + (4)) 項於 [Rope Joints v] 成 (y 座標)
Draw Rope Segment original: (x座標) (y 座標)
end

變數 [TempX v] 設為 ((清單第 (Joint ID) 項項目\( [Rope Joints v] \) :: list) - (xPosition))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (1)) 項項目\( [Rope Joints v] \) :: list) - (yPosition))

變數 [TempX v] 設為 ((清單第 (Joint ID) 項項目\( [Rope Joints v] \) :: list) - ([x座標 v] of [Player Sprite v]))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (1)) 項項目\( [Rope Joints v] \) :: list) - ([y 座標 v] of [Player Sprite v]))
end

變數 [Rope Tension v] 設為 (((Distance) - (Segment Length)) / (Distance))
變數 [ForceX v] 設為 ((Rope Tension) * (TempX))
變數 [ForceY v] 設為 ((Rope Tension) * (TempY))

變數 [ForceX v] 設為 (0)
變數 [ForceY v] 設為 (-1) // Applying gravity.
end

定位到 x: ([x座標 v] \( [Player Sprite v] \)) y: ([y 座標 v] \( [Player Sprite v] \))
變數 [Player X Velocity v] 改變 (ForceX)
變數 [Player Y Velocity v] 改變 ((ForceY) - (3))
end

變數 [TempX v] 設為 ((清單第 ((Joint ID) + (6)) 項項目\( [Rope Joints v] \) :: list) - (xPosition))
變數 [TempY v] 設為 ((清單第 ((Joint ID) + (7)) 項項目\( [Rope Joints v] \) :: list) - (yPosition))
變數 [Distance v] 設為 ([sqrt v] \( (((TempX) * (TempX)) + ((TempY) * (TempY))) \))
如果 <(Segment Length) < (Distance)> 那麼
變數 [Rope Tension v] 設為 (((Distance) - (Segment Length)) / (Distance))
變數 [ForceX v] 設為 (((Rope Tension) * (TempX)) * (0.6))
變數 [ForceY v] 設為 (((Rope Tension) * (TempY)) * (0.5))
end
end

變數 [X Velocity v] 設為 (((X Velocity) + (ForceX)) * (0.65))
變數 [Y Velocity v] 設為 ((((Y Velocity) + (ForceY)) * (0.61)) - (3))
x 改變 (X Velocity)
y 改變 (Y Velocity)
end

x 改變 (0.4) // This block makes sure that something's drawn.

分身刪除
end

變數 [Joint ID v] 改變 ((-3) * (清單 [Removed Rope Joints v] 的項目數 :: list))
end

變數 [Rope Joints Made v] 改變 ((-3) * (length of [Removed Rope Joints v] :: list))
等待 (0) 秒
刪除第 [全部 v] 項 \( [Removed Rope Joints v] \)
end
```

The following two scripts can be put in any sprite:

```定義 Destroy Rope containing Rope Joint: (Joint Point ID) //Run without screen refresh!

. . . // This repeat deletes all rope joints ahead of (Joint Point ID) until it meets the end of the rope.
Destroy Rope Joint at: (Joint Point ID)
新增項目 (((Joint Point ID) + ((i) * (3))) - (2)) \( [Removed Rope Joints v] \)
變數 [i v] 改變 (1)
end

. . . // This repeat deletes all rope joints behind (Joint Point ID).
Destroy Rope Joint at: (Joint Point ID 2)
新增項目 ((Joint Point ID 2) - (2)) \( [Removed Rope Joints v] \)
變數 [Joint Point ID 2 v] 改變 (-3)
end

. . . // The next block deletes the tail of the rope.
Destroy Rope Joint at: (Joint Point ID 2)

```

## Simple rope physics

A restricted, but simpler method of rope physics is also available. It consists of the rope's starting location, the ending location, a sprite representing a person, and a sprite used to draw the rope.

This method represents a person ziplining to either side of the rope, and the rope sagging to the person's weight.

Firstly, position the sprites that represent the starting and ending position of the rope.

Secondly, add this script to the sprite in charge of drawing the rope.

```當 @greenflag 被點擊

筆跡清除
定位到 [Rope End Left v] 位置
下筆
定位到 [Person v] 位置
定位到 [Rope End RIght v] 位置
停筆
圖層上移至頂層
end
```

Thirdly, script the person such that it follows the path of the rope. For example, if the rope goes horizontally, you may wish to add this script into the person:

```當 @greenflag 被點擊

如果 <[向右 v] 鍵被按下？> 那麼
x 改變 (5)
如果 <[向左 v] 鍵被按下？> 那麼
x 改變 (-5)
end
end
end
```

Be sure to position the person just below the rope for a more realistic effect.

Rope Physics on Scratch is an example project showing this method.