This tutorial shows how to make a simple physics engine where the sprite is not controlled by the arrow keys, as in Platformers, but rather interacts like dropping and pushing the Sprite in real life would.
Make Variables
First make the following Variables 'for this sprite'
(X Velocity)//The velocity of the sprite on the X axis (Y Velocity)//The velocity of the sprite on the Y axis (Direction::variables)//The speed at which the sprite is turning (Slope)//Used for slope detection in collisions
Next make two sprites, one will be the one that uses the physics, and the other will be the one will be the ground that the sprite interacts with. In this tutorial, all the scripts are used in the main sprite and the ground sprite is called 'ground'.
Collision Detection
First, collision detection needs to be made. The collision detection that will be used is similar to ones used in platformers, however, this script does not use any controls to move the player.
define Physics (friction) (stiffness)//Run without screen refresh if <not<touching (ground v)?>> then change [Y velocity v] by (-1) end change y by (Y velocity) if <touching (ground v)?> then repeat ([abs v] of ([ceiling v] of (Y velocity))) change y by ((([abs v] of (Y velocity))/(Y velocity)) * (-1)) end end set [Y velocity v] to (1) change x by (X Velocity) if <touching (ground v)?> then set [slope v] to (0) repeat until <<(slope) = (-8)> or <not<touching (ground v)?>> change [slope v] by (-1) change y by (1) end if <(slope) = (-8)> then change y by (slope) repeat ([abs v] of ([ceiling v] of (X Velocity))) change x by ((([abs v] of (X Velocity))/ (x Velocity))*(-1) end set [X Velocity v] to (0) end end
Turning When Hitting a Slope
This script will make the sprite fall toward the ground and not go through it, however, this does not give a realistic physics look because the sprite does not turn or move on slopes. To add turning and sliding down slopes, another custom block needs to be made, called Turn:
define Turn//Run without screen rfefresh change x by (10)//Move to the right and detect if still touching the ground, if not, turn and slide to the right a little bit. if <not<touching (ground v)?>> then change [Direction v] by (3) change [X Velocity v] by (.3) end change x by (-20)//-20 this time because it is now needed to undo the movement from moving to the right and then move to the left, so the equivalent of moving to the left twice. if <not<touching (ground v) ?>> then//Do the opposite this time. change [Direction v] by (-3) change [X Velocity v] by (-.3) end change x by (10) turn cw (2) degrees if <not<touching (ground v)?>> then change [Direction v] by (1) end turn ccw (4) degrees if <not<touching (ground v)?>> then change [Direction v] by (-1) end turn cw (12) degrees if <not<touching (ground v)?>> then change [Direction v] by (2) end turn ccw (20) degrees if <not<touching (ground v)?>> then change [Direction v] by (-2) end turn cw (10) degrees
Now that the turning custom block has been created, it needs to be used:
define Physics (friction) (stiffness)//Run without screen refresh if <not<touching (ground v)?>> then change [Y velocity v] by (-1) end change y by (Y velocity) if <touching (ground v)?> then repeat ([abs v] of ([ceiling v] of (Y velocity))) change y by ((([abs v] of (Y velocity))/(Y velocity)) * (-1)) end end set [Y velocity v] to (1) change x by (X Velocity) if <touching (ground v)?> then set [slope v] to (0) repeat until <<(slope) = (-8)> or <not<touching (ground v)?>> change [slope v] by (-1) change y by (1) end if <(slope) = (-8)> then change y by (slope) repeat ([abs v] of ([ceiling v] of (X Velocity))) change x by ((([abs v] of (X Velocity))/ (x Velocity))*(-1) end set [X Velocity v] to (0) end end turn cw (Direction::variables) degrees set [Direction v] to ((Direction::variables) * (stiffness::custom)) set [X Velocity v] to ((X velocity) * (friction::custom)) Turn::custom
Implementing Code
The turning and collision detection has been created, so the only thing left to do is to use it.
When green flag clicked go to x: (0) y: (0)//Where the sprite will start (coordinates can be different) set [Direction v] to [0]//Setting variables to avoid bugs set [X Velocity v] to [0] set [Y Velocity v] to [0] forever//using our code! Physics (0.95)(.6)::custom ...::grey//Other code can be placed in here for the controls of the sprite, e.g. allow it to be dragged, moved by the arrow keys, etc. end
Final Code
Note: | Make sure to check the code for any bugs that may be encountered. |
Here is the final code for the physics engine:
define Physics (friction) (stiffness)//Run without screen refresh if <not<touching (ground v)?>> then change [Y velocity v] by (-1) end change y by (Y velocity) if <touching (ground v)?> then repeat ([abs v] of ([ceiling v] of (Y velocity))) change y by ((([abs v] of (Y velocity))/(Y velocity)) * (-1)) end end set [Y velocity v] to (1) change x by (X Velocity) if <touching (ground v)?> then set [slope v] to (0) repeat until <<(slope) = (-8)> or <not<touching (ground v)?>> change [slope v] by (-1) change y by (1) end if <(slope) = (-8)> then change y by (slope) repeat ([abs v] of ([ceiling v] of (X Velocity))) change x by ((([abs v] of (X Velocity))/ (x Velocity))*(-1) end set [X Velocity v] to (0) end end turn cw (Direction::variables) degrees set [Direction v] to ((Direction::variables) * (stiffness::custom)) set [X Velocity v] to ((X velocity) * (friction::custom)) Turn::custom define Turn//Run without screen rfefresh change x by (10)//Move to the right and detect if still touching the ground, if not, turn and slide to the right a little bit. if <not<touching (ground v)?>> then change [Direction v] by (3) change [X Velocity v] by (.3) end change x by (-20)//-20 this time because it is now needed to undo the movement from moving to the right and then move to the left, so the equivalent of moving to the left twice. if <not<touching (ground v) ?>> then//Do the opposite this time. change [Direction v] by (-3) change [X Velocity v] by (-.3) end change x by (10) turn cw (2) degrees if <not<touching (ground v)?>> then change [Direction v] by (1) end turn ccw (4) degrees if <not<touching (ground v)?>> then change [Direction v] by (-1) end turn cw (12) degrees if <not<touching (ground v)?>> then change [Direction v] by (2) end turn ccw (20) degrees if <not<touching (ground v)?>> then change [Direction v] by (-2) end turn cw (10) degrees When green flag clicked go to x: (0) y: (0)//Where the sprite will start (coordinates can be different) set [Direction v] to [0]//Setting variables to avoid bugs set [X Velocity v] to [0] set [Y Velocity v] to [0] forever Physics (0.95)(.6)::custom ...::grey//Other code can be placed in here for the controls of the sprite, e.g. allow it to be dragged, moved by the arrow keys, etc. end