Advanced Platformer Physics

Материал из Поле цифровой дидактики
Описание Как мы имитируем физические свойства внутри Scratch
Область знаний Физика, Game design
Область использования (ISTE)
Возрастная категория 14


Поясняющее видео
Близкие рецепту понятия
Среды и средства для приготовления рецепта: Scratch

A platformer is a type of game distinguished by jumping across platforms and avoiding obstacles. In order to make the game realistic, more advanced scripting must be used.

Y movement

Because advanced simulations for platformers take more blocks of code, condensing it to a single custom block can simplify the script. A custom block, ticked run without screen refresh is needed.

define Platforming Scripts: Jump Height (J.H) max speed: (M.S) Acceleration: (A) friction: (F) Wall Jump X: (W.J.X) Wall Jump Y: (W.J.Y)

To make for realistic gravity, the amount the player moves down in will increase the longer the player is in the air. 1 variable is needed to store the value the player will move down by :

(Yvel)//This stores the speed the player will move down by.
define Platforming Scripts: Jump Height (J.H) max speed: (M.S) Acceleration: (A) friction: (F) Wall Jump X: (W.J.X) Wall Jump Y: (W.J.Y)
change y by (Yvel)
change [Yvel v] by (-2)
if <(Yvel)<[-22]> then
set [Yvel v] to (-22) // this caps the player's max speed to -22
end

Y-Collisions

In order for the player to collide with another entity like the level, the player needs to be pushed out of the level one pixel at a time until the player is out of the collision. To determine if the player collided with a ceiling, the player must check if the collision occurred during a jump, or when the "Yvel" variable is positive. If it is a ceiling collision, the player will be pushed out of the level downwards:

define Platforming Scripts: Jump Height (J.H) max speed: (M.S) Acceleration: (A) friction: (F) Wall Jump X: (W.J.X) Wall Jump Y: (W.J.Y)
change y by (Yvel)
change [Yvel v] by (-2)
if <(Yvel)<[-22]> then
set [Yvel v] to (-22)
end
if <touching [level v]> then
repeat until <not<touching [level v]>>
change y by ((([abs v] of (Yvel))/(Yvel))*(-1)) // this slowly pushes the player out of the collision on the y-axis.
end
set [Yvel v] to (0) // Sets the speed back to 0

Jumping

Coding Jumping for the player requires the Yvel variable to be set to a positive value. However, the player must only jump when it collides the level.

define Platforming Scripts: Jump Height (J.H) max speed: (M.S) Acceleration: (A) friction: (F) Wall Jump X: (W.J.X) Wall Jump Y: (W.J.Y)
change y by (Yvel)
change [Yvel v] by (-2)
if <(Yvel)<[-22]> then
set [Yvel v] to (-22)
end
if <touching [level v]> then
repeat until <not<touching [level v]>>
change y by ((([abs v] of (Yvel))/(Yvel))*(-1)) // this slowly pushes the player out of the collision on the y-axis.
end
set [Yvel v] to (0)
if <<key [up arrow v] pressed?> or <key [w v] pressed?> > then
set [Yvel v] to (J.H) // Jump height can be set to any positive value
end

Fixing the stick to the ceiling bug

When the player collides with the ceiling and is still jumping, the player has a tendency to stick to the ceiling. To fix this, the player must only jump when the player is falling. A variable is needed to describe the direction the player is moving on the y-axis:

(Ydir)

Integrate the "Ydir" variable in the platforming script:

define Platforming Scripts: Jump Height (J.H) max speed: (M.S) Acceleration: (A) friction: (F) Wall Jump X: (W.J.X) Wall Jump Y: (W.J.Y)
change y by (Yvel)
change [Yvel v] by (-2)
set [Ydir v] to (([abs v] of (Yvel))/(Yvel)) // this quantifies the direction the player is moving on the y-axis
if <(Yvel)<[-22]> then
set [Yvel v] to (-22)
end
if <touching [level v]> then
repeat until <not<touching [level v]>>
change y by ((([abs v] of (Yvel))/(Yvel))*(-1)) // this slowly pushes the player out of the collision on the y-axis.
end
set [Yvel v] to (0)
if <<<key [up arrow v] pressed?> or <key [w v] pressed?>> and <(Ydir)<[0]> > then // Checks if the player is moving down when jumping
set [Yvel v] to (J.H) // Jump height can be set to any positive value
end

X movement

The movement along the x-axis requires more code, as acceleration, friction, and side collisions are needed. The velocity of the player moving on the x-axis will be stored as a variable, called "Xvel":

Hitboxes

Шаблон:Main

If your player, avatar, etc. has arms, they will catch on the platforms (if your player is a smooth rectangle you can skip this). The answer to that is a hitbox. Create a new costume for your sprite and make it a filled rectangle about the size of your normal costume (the one it's showing). Then update your scripts like this:

when gf clicked
forever
switch costume to (hitbox v)
... //other scripts
switch costume to (regular v)
end

Walking Momentum

To simulate momentum, it needs a gliding effect - after you stop pressing the left/right key, it "glides" to a stop instead of stopping right away. First, update the "move" block - replace the "change x" block with a "change speed x" block

define move (dist)
change [speed x v] by (dist) //replace with this
... //the other scripts

Then, after the "check ground touch" block, add:

when gf clicked
forever
switch costume to (hitbox v)
change [speed y v] by [-1]
change y by (speed y)
check ground touch::custom
set [speed x v] to ((speed x)*(0.8)) //add this!
change x by (speed x) //and this!
...
end

What this does is slowly (but not too slowly) speed up when you are pressing the key, and slowly lose speed when you let go.

See Also