第10回 エフェクトと演出
3 / 4 戦闘イベントへのエフェクト接続
このステップの目的
弾の命中時やプレイヤーの被弾時にエフェクトを発生させ、視覚と聴覚が連動した手応えのある演出を完成させます。
命中位置でのエフェクト発生
Game::ResolveCollisions()内で、弾が敵に命中した瞬間、および敵弾がプレイヤーに命中した瞬間に、接触位置を中心としてエフェクトを生成します。
Game.cppcpp
void Game::ResolveCollisions()
{
// プレイヤーの弾は最初に重なった敵だけに命中させる
for (PlayerShot& playerShot : playerShots.GetAll())
{
if (!playerShot.IsActive())
continue;
for (Enemy& enemy : enemies.GetAll())
{
if (!enemy.IsActive())
continue;
if (!playerShot.GetHitbox().Overlaps(enemy.GetHitbox()))
continue;
enemy.TakeDamage(tuning::playerShot::Damage);
playerShot.Deactivate();
effects.Spawn(enemy.GetHitbox().GetCenter());
if (!enemy.IsActive())
++score;
sounds.PlaySe(SoundId::Hit);
break;
}
}
for (EnemyShot& enemyShot : enemyShots.GetAll())
{
if (!enemyShot.IsActive())
continue;
if (!enemyShot.GetHitbox().Overlaps(player.GetHitbox()))
continue;
enemyShot.Deactivate();
effects.Spawn(enemyShot.GetHitbox().GetCenter());
if (player.TryTakeDamage())
sounds.PlaySe(SoundId::Damage);
}
for (Enemy& enemy : enemies.GetAll())
{
if (!enemy.IsActive())
continue;
if (!enemy.GetHitbox().Overlaps(player.GetHitbox()))
continue;
enemy.Deactivate();
effects.Spawn(enemy.GetHitbox().GetCenter());
if (player.TryTakeDamage())
sounds.PlaySe(SoundId::Damage);
}
}効果音(sounds.PlaySe)とエフェクト(effects.Spawn)を同じ場所で呼び出している点に注目してください。
自機や敵などのEntityごとに演出の処理を持たせず、Gameで出来事の成立をまとめて扱います。処理が各所に散らばらず、演出を追加・変更しやすくなります。
描画レイヤーの順序
ゲーム画面のすべての要素を描画するGame::DrawPlaying()において、描画順序は重要です。
Game.cppcpp
void Game::DrawPlaying() const
{
// 描画順はプレイヤー、プレイヤーの弾、敵、敵の弾とし、エフェクトを最後に重ねる
player.Draw(images);
playerShots.Draw(images);
enemies.Draw(images);
enemyShots.Draw(images);
effects.Draw();
DrawHud();
}エフェクトは敵や弾より手前、UIのすぐ奥に描きます。爆発や火花がキャラクターを覆うように広がり、迫力のある画面になります。
チェックリスト
- 敵に弾が当たった位置を中心としてエフェクトが発生することを確認できる
- プレイヤーが被弾した際、当たった位置にエフェクトが発生することを確認できる
- 音声(SE)とエフェクトが同一の判定ブロック内で同期して呼び出されている
- 描画順序において、エフェクトがキャラクターよりも手前に正しく重ねられている