第06回 プレイヤーの被弾と無敵時間
2 / 4 無敵時間の更新と点滅表示
このステップの目的
無敵タイマーを経過時間に応じて減算し、プレイヤーが無敵状態であることを示す点滅演出を実装します。
無敵タイマーの減算処理
設定された無敵時間は、毎フレームのdeltaTime分だけ減算していき、0未満にならないように制限します。
Player::Update()内で発射タイマーshotTimerを減らす行の下に追加します。invincibleTimerの宣言と被弾時の設定は前のステップのものを使います。
Player.cppcpp
shotTimer = std::max(0.0f, shotTimer - deltaTime);
// 無敵タイマーを減算し、0未満には下げない
invincibleTimer = std::max(0.0f, invincibleTimer - deltaTime);タイマーの更新をPlayer::Update()で行うため、Gameクラスでは無敵時間を計算する必要がありません。
点滅表示による視覚的フィードバック
無敵時間中も普段と同じ見た目では、弾に当たってもダメージを受けない理由が分かりません。ゲームでは、状態の変化を見た目で伝えることが非常に重要です。
ここでは、無敵時間中のみ機体を高速で点滅させる演出をPlayer::Draw()に実装します。
Player.cppcpp
void Player::Draw(const ImageManager& images) const
{
constexpr float BlinkRate = 20.0f;
bool blinkOff =
invincibleTimer > 0.0f &&
static_cast<int>(invincibleTimer * BlinkRate) % 2 == 0;
if (blinkOff)
return;
images.Draw(ImageManager::Id::Player, GetDrawRect());
}点滅計算の仕組み
残り時間invincibleTimerは減っていきます。この値にBlinkRateを掛け、整数に変換します。
その整数を2で割った余りにより、非表示と通常描画を切り替えます。フレーム番号の偶奇を調べているわけではありません。
点滅と被弾を分ける
点滅で切り替えるのは描画だけです。ダメージを受け付けるかどうかはTryTakeDamage()で判断するため、非表示の間も判定範囲は残ります。敵との接触は次のステップで接続して確認します。
チェックリスト
- 毎フレーム
invincibleTimerがdeltaTime分だけ正しく減算されている - タイマーが0未満に下がらないようガードされている
- 無敵時間中のみ機体が高速に点滅することを確認できる
- 点滅(見た目の演出)と被弾拒否(ロジック)の責任が混同されずに分離されていることを説明できる