Skip to content
第16回 ワールド座標とカメラ

2 / 4 プレイヤーへ追従するCameraを作る

このステップの目的

プレイヤーを画面の中央付近にとらえ続けるカメラ座標の計算方法と、ステージ外側の余白を映さない境界制限(クランプ)を実装します。

プレイヤーを画面中央に見せるカメラ目標位置

横スクロールゲームでは、プレイヤーキャラクターが画面の中央付近に映っている状態が基本となります。
画面幅が 640ピクセルの場合、プレイヤーを画面の中央($X = 320$)に見せるためには、**「プレイヤーのワールドX座標から、目標とする画面X座標(320)を引いた位置」**にカメラを配置します。

GameTuning.hcpp
namespace dxgame::platformer::tuning::camera
{
    // カメラがプレイヤーをとらえる目標画面X座標(画面中央:320ピクセル)
    inline constexpr float TargetScreenX = dxgame::config::ScreenWidth * 0.5f;
}

例えば、プレイヤーが $X = 320$ にいるときはカメラは $320 - 320 = 0$(ステージ左端)となり、プレイヤーが右へ進んで $X = 1000$ に達したときはカメラは $1000 - 320 = 680$ となります。

ステージ両端での見切れを防ぐクランプ処理

この計算結果(desiredX)をそのまま使うと、ゲーム開始直後にプレイヤーが左端付近(例えば $X = 100$)にいる場合、カメラは $100 - 320 = -220$ という負の座標になり、ステージ左側の余白が画面に映ってしまいます。右端(ゴール側)に到達した際も同様です。

これを防ぐため、カメラの移動範囲をステージの左端から右端までの間に制限(クランプ)します。

Camera.cppcpp
void Camera::Update(const dxgame::Vector2& target, int worldWidth)
{
    const int targetX = static_cast<int>(
        target.x - tuning::camera::TargetScreenX);
    const int maxX = std::max(0, worldWidth - dxgame::config::ScreenWidth);
    x_ = std::clamp(targetX, 0, maxX);
}

境界値の計算根拠

  • 最小値(0: ステージの左端です。これより左へカメラが進むことはありません。
  • 最大値(worldWidth - ScreenWidth: カメラの右端がステージの右端に揃う位置です。これより右へ進むとステージ外の余白が見えてしまいます。

この std::clamp により、ステージの端に近づいたときはカメラが停止し、プレイヤーのみが画面端へと進む挙動が実現します。

チェックリスト
  • プレイヤーのワールドX座標から画面中央幅を引いてカメラ位置を求められる
  • カメラの移動可能範囲が 0worldWidth - ScreenWidth である理由を説明できる
  • std::clamp によって、ステージ外側の余白が画面に映り込まないよう制限されている
  • 画面幅より小さなステージであっても負にならないガード(std::max(0, ...))がある

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