1 / 4 重力で落下させる
Y方向の速度と端数を使い、落下する移動を作ります。
入力と物理更新の準備
第17回では Player::Update() に入力と横移動をまとめました。この回では入力を UpdateInput()、重力と移動を UpdatePhysics() に分けます。ステップ1〜3で各部分を用意し、ステップ4で接続して実行します。
まず Player.h の dxgame::platformer 名前空間内で、Player クラスの前へ以下を追加します。PlayerEvents は、そのフレームにジャンプ・着地したかを記録する値です。Stage の宣言は地形を引数で受け取るために使います。
namespace dxgame::platformer
{
class Stage;
struct PlayerEvents
{
bool jumped = false;
bool landed = false;
};同ファイルの public にある Update() の宣言を次へ置き換えます。
PlayerEvents Update(const Input& input, const Stage& stage, float deltaTime);private に以下の宣言を追加します。参照引数 PlayerEvents& events を使うと、入力処理と物理更新が同じ結果へ書き込めます。
private:
void UpdateInput(const Input& input, float deltaTime, PlayerEvents& events);
void UpdatePhysics(const Stage& stage, float deltaTime, PlayerEvents& events);
void MoveHorizontal(float deltaTime);
void MoveVertical(const Stage& stage, float deltaTime);Player.cpp の第17回の Update() から、左右のキー取得〜X速度の上限を決める std::clamp までを UpdateInput() へ移します。X方向の端数処理と位置更新は MoveHorizontal() へ移します。各関数の引数は上の宣言とそろえてください。Update() の新しい本文と UpdatePhysics() 全体はステップ4で示します。
速度に重力を加える
先に GameTuning.h の namespace player で、摩擦の定数の下へ重力と速度の上限を追加します。
inline constexpr float Friction = 900.0f;
inline constexpr float RiseGravity = 1620.0f;
inline constexpr float FallGravity = 2700.0f;
inline constexpr float MaxFallSpeed = 720.0f;画面の下はYの正方向です。Player::UpdatePhysics() で速度に重力を加えます。上昇中は RiseGravity、落下中は FallGravity を使います。次は新しい関数内に置く重力計算の部分です。
const float gravity = velocity_.y < 0.0f
? tuning::player::RiseGravity
: tuning::player::FallGravity;
velocity_.y += gravity * deltaTime;
velocity_.y = std::min(velocity_.y, tuning::player::MaxFallSpeed);std::min は二つの値の小さい方を返し、落下速度の上限を保ちます。
Y方向にも端数を残す
Player.h の remainderX_ の下へ、Y方向の端数と接地状態を追加します。
float remainderX_ = 0.0f;
float remainderY_ = 0.0f;
bool onGround_ = false;Player::Reset() でも同じ順に初期化します。
remainderX_ = 0.0f;
remainderY_ = 0.0f;
onGround_ = false;新しい MoveVertical() では、第17回のX方向と同じように整数の移動量を取り出し、小数部分を次回へ残します。次はその先頭部分です。
remainderY_ += velocity_.y * deltaTime;
const int pixelMove = static_cast<int>(remainderY_);
remainderY_ -= static_cast<float>(pixelMove);この後に床との位置補正を接続します。速度を制限するのは、大きな移動によるすり抜けを起こしにくくするためです。あらゆる速度で衝突を保証する処理ではありません。続くステップで床の判定とジャンプを加え、ステップ4で落下・着地を確認します。
- 重力を加えるとY方向の速度が増えることを説明できる。
- X方向とY方向の端数を別の変数で保つ。
- 第17回の整数移動をY方向にも使っている。