Skip to content
第14回 調整できるプレイヤー表示と操作

3 / 4 左右入力による移動と画面端での境界制限

このステップの目的

入力抽象化クラス Input から左右キーの状態を取得し、同時押しの相殺と画面端での境界制限を組み込んだ移動処理を実装します。

アクション列挙型(Key)による入力抽象化

DXライブラリの物理キーコードをゲーム内の各クラスへ直接書き込むと、キー配置の変更が困難になります。
本作では、すべての操作を抽象的な列挙型 Key で管理します。

Input.hcpp
namespace dxgame::platformer
{
    enum class Key
    {
        Left,           // 左移動
        Right,          // 右移動
        Jump,           // ジャンプ・決定
        Debug,          // デバッグ表示トグル(F1)
        Escape,         // ゲーム終了
        Count
    };
}

Input クラスは、キーの状態を以下の3つの判定関数で提供します。

  • IsHeld(key): 現在キーが押し続けられているか(移動などに使用)
  • IsPressed(key): 前フレームでは離されていて、今フレーム押された瞬間か(ジャンプや画面切り替えに使用)
  • IsReleased(key): 今フレーム離された瞬間か(可変ジャンプの高度制御などに使用)

同時押しと1回の移動量

プレイヤーの移動更新処理 Player::Update() では、左右の押し続け状態(IsHeld)を調べます。

Player.cppcpp
void Player::Update(const Input& input, float deltaTime)
{
    float direction = 0.0f;
    if (input.IsHeld(Key::Left) && !input.IsHeld(Key::Right))
        direction = -1.0f;
    else if (input.IsHeld(Key::Right) && !input.IsHeld(Key::Left))
        direction = 1.0f;

    position_.x += direction *
        tuning::player::MoveSpeed * deltaTime;

    const float minX = -tuning::player::Hitbox.x;
    const float maxX = dxgame::config::ScreenWidth -
        tuning::player::Hitbox.x - tuning::player::Hitbox.width;
    position_.x = std::clamp(position_.x, minX, maxX);
}

左右同時押しの相殺と実時間移動

左右キーが同時に押された場合は direction = 0.0f となり、その場に静止します。
この作品はdeltaTimeに固定の1/60秒を渡します。毎秒60回更新できると、MoveSpeedで指定した距離を1秒で進みます。処理が間に合わず毎秒30回になると、実時間1秒で進む距離も半分になります。

画面端での境界制限(クランプ処理)

プレイヤーが画面の外へはみ出さないよう位置を制限する際、画像の描画枠ではなく命中矩形(Hitbox)の端を基準にします。
画像の余白ではなく判定矩形を基準にすることで、グラフィック素材の余白サイズに左右されず、常に一定の移動境界を維持できます。

チェックリスト
  • Input::IsHeld() を用いてキーの継続的な押下状態を取得できている
  • 左右のキーが同時に押された際、移動が相殺されて静止することを確認できる
  • MoveSpeedに固定1/60秒を掛け、1回の移動量を求めている
  • 画面の左右両端において、命中矩形が画面外へはみ出さないよう正しく制限されている

ゲームプログラミング実践