もどる

この記事は「うずら」とAIが協力して作成しました。
なるべく正確さを心がけていますが、最新の公式ドキュメントなどもあわせて確認してみてね!

python2026.3.13

4-3. 起死回生:ボム(衝撃波)炸裂!

起死回生
ボム炸裂

みなさん、こんにちは!世界最高に親切な技術講師、うずらです。
退屈な授業からの脱出! を見てここまで来てくださり、本当にありがとうございます。

激しい敵の攻撃で、画面が敵や弾で埋め尽くされ、絶体絶命のピンチに陥ることもありますよね。
そんな時に役立つのが「必殺技」です!

今回は、画面中の敵を一瞬で吹き飛ばす「ボム(衝撃波)」を実装して、ゲームをさらに盛り上げましょう。

1. 3秒でわかるまとめ

今回の記事では、ゲーム中に貯めておいた「ボム」をキー入力で発動し、画面に広がる衝撃波で敵を一掃する機能を作ります。

プレイヤーの周囲に広がる衝撃波        --> 衝撃波を描画する
敵と衝撃波がぶつかる(当たり判定)    --> 敵を消す
ボムを使った回数を記録しておく        --> ボムの数を管理する

2. ボム実装のための新しい変数たち

ボムの機能を追加するために、いくつかの新しい変数が必要です。
これらの変数は、ボムの状態を管理するために使います。

前回のコード 演出の極意爆砕演出 に、以下の変数を追加してください。

# --- 変数の初期化 ---
# プレイヤー
player_x = SCREEN_WIDTH // 2 - PLAYER_W // 2
player_y = SCREEN_HEIGHT - 20

# ゲームオブジェクト
bullets   = [] # [x, y, vx, vy]
enemies   = [] # Dictionary {'x', 'y', 'type', ...}
particles = [] # Dictionary
stars     = [] # [x, y, speed]

# (中略)

# ゲーム進行状況
score = 0
game_over = False

# パワーアップ & ボム    # ここから追加
num_bombs = 1           # 持っているボムの数
is_bomb_active = False  # ボムが発動中かどうか
bomb_radius = 0         # 衝撃波の半径
  • num_bombs = 1: これは 現在持っているボムの数 を表します。最初は1つ持っている状態に設定しました。
  • is_bomb_active = False: これは ボムが現在発動中かどうか を管理するブール型(真偽値)の変数です。計算と決断if文の魔法 で学んだ True または False の値を取ります。最初は発動していないので False です。
  • bomb_radius = 0: これは 衝撃波の現在の半径 を表します。衝撃波が広がるにつれて、この値が大きくなります。

補足だよ

num_bombs, is_bomb_active, bomb_radius の3つの変数は、それぞれボムの「個数」「状態」「見た目」を制御する大切な役割を担っています。

3. 必殺技「ボム」を発動する関数

次に、ボムを発動するための特別な関数 trigger_bomb() を作りましょう。
この関数は、ボムが使える状態であれば、ボムを1つ消費して発動中の状態に切り替えます。

spawn_particles() 関数の下に、以下の関数を追加してください。

# =========================================================
#  関数定義 (エフェクト生成など)
# =========================================================

# 爆発エフェクトなどを生成する
def spawn_particles(x, y, count, color):
    # (省略)

# ボムを発動する                # ここから追加
def trigger_bomb():             # ボム発動関数を定義
    global num_bombs, is_bomb_active, bomb_radius # グローバル変数を変更可能にする
    
    if num_bombs > 0 and not is_bomb_active: # ボムが残っていて、かつ発動中でない場合
        num_bombs -= 1                      # ボムを1つ減らす
        is_bomb_active = True               # ボムを発動状態にする
        bomb_radius = 5                     # 衝撃波の初期半径を設定

trigger_bomb() 関数の中には、いくつかの重要なポイントがあります。

  • global num_bombs, is_bomb_active, bomb_radius:
    関数の中で、関数の外で定義された変数(グローバル変数)の値を変更したい場合、このように global キーワードを使って明示的に宣言する必要があります。関数で呪文作成 で関数について学んだ際にも少し触れましたね。
  • if num_bombs > 0 and not is_bomb_active::
    この条件分岐は、ボムを発動しても良いかをチェックしています。
    • num_bombs > 0: ボムが1つ以上残っているか。
    • not is_bomb_active: 現在ボムが発動中でないか(二重に発動させないため)。

両方の条件が True の場合のみ、ボムが発動し、num_bombs が減り、is_bomb_activeTrue になり、bomb_radius が初期値に設定されます。

豆知識

globalキーワードは、関数の外で定義された変数を関数内で変更したいときに使います。これによって、関数がプログラム全体の状態に影響を与えられるようになります。

そして、この trigger_bomb() 関数を update() 関数の中で呼び出します。
プレイヤーの操作部分に、ボム発動のキー入力を追加してください。

# 弾の発射
if pyxel.btnp(pyxel.KEY_SPACE):
    bullets.append([player_x + 3, player_y - 4, 0, -5])

# ボム発動                # ここから追加
if pyxel.btnp(pyxel.KEY_Z) or pyxel.btnp(pyxel.KEY_B):
    trigger_bomb()

これで、ZキーまたはBキーを押すとボムが発動するようになります。pyxel.btnp() は、キーが「押された瞬間」だけ True になるので、一度押せば一回だけボムが発動します。

4. 衝撃波の計算と敵の一掃

ボムが発動したら、次は衝撃波を広げ、敵との当たり判定を行います。
これは update() 関数の中で行われる計算処理です。

update() 関数の冒頭に、以下の「システム更新」部分を追加してください。

# 毎フレーム実行される更新処理 (計算などはここで行う。描画は禁止)
def update():
    global player_x, player_y, score, game_over
    global num_bombs, is_bomb_active, bomb_radius # global宣言を追加
    global bullets, enemies, particles

    # --- 1. ゲームオーバー / クリアチェック ---
    if game_over:
        return

    # --- 2. システム更新 (ボム)    # ここから追加
    if is_bomb_active:              # ボムが発動中なら
        bomb_radius += 4            # 半径を徐々に大きくする
        if bomb_radius > 200:       # 画面外まで広がったら
            is_bomb_active = False  # ボムを非発動状態にする
            bomb_radius = 0         # 半径をリセット

is_bomb_activeTrue の間、bomb_radius の値が毎フレーム4ずつ増えていきます。これにより、衝撃波が画面いっぱいに広がっていく様子を表現できます。
bomb_radius200 を超えたら、ボムの発動を終了しています。

次に、この広がる衝撃波と敵との当たり判定を実装します。
update() 関数内の「敵の更新」ループの中で、敵が破壊されるかどうかをチェックする部分に以下のコードを追加してください。

    # 敵の更新
    surviving_enemies = []
    for e in enemies:
        # (省略)

        destroyed = False
        if is_bomb_active: # ボムが発動中であれば
             # ボムの範囲 (中心座標から左上座標を計算)
             # pyxel.circb() は中心座標を使うが、check_collision() は左上座標を使うので変換
             bomb_x = player_x + 4 - bomb_radius
             bomb_y = player_y + 4 - bomb_radius
             bomb_size = bomb_radius * 2 # 半径を直径に変換
             
             if check_collision(bomb_x, bomb_y, bomb_size, bomb_size, e['x'], e['y'], ENEMY_W, ENEMY_H):
                 destroyed = True # 当たっていたら破壊フラグを立てる

        if destroyed:
            spawn_particles(e['x'], e['y'], 5, COL_WHITE) # 爆発エフェクトを生成
            if e['type'] != 'bullet': score += 10 # 弾じゃない敵ならスコア加算
            continue # この敵は消滅させるので、surviving_enemies には追加しない
  • bomb_x = player_x + 4 - bomb_radius の部分では、プレイヤーの中心座標(プレイヤーの幅が8なので player_x + 4)から、bomb_radius を使って四角形の左上座標を計算しています。
    pyxel.circb() は中心座標を使いますが、前回 実践:命中!敵を撃破 で作った check_collision() 関数は左上座標と幅・高さを使うため、変換が必要です。
  • bomb_size = bomb_radius * 2 で、半径からボムのヒット判定用の四角形のサイズ(直径)を求めています。
  • check_collision() 関数を使って、ボムのヒット範囲と敵が衝突しているかを判定します。
  • 衝突していた場合、destroyed = True となり、敵が破壊された時の処理 (spawn_particles() やスコア加算) が実行され、surviving_enemies リストには追加されないため、次のフレームでは消滅します。

5. 炸裂する衝撃波の描画

最後に、広がる衝撃波を画面に描画しましょう。
これは draw() 関数の中で行われる描画処理です。

draw() 関数内の「背景」描画のすぐ後に、以下の「衝撃波」描画部分を追加してください。

# 毎フレーム実行される描画処理 (結果を画面に表示する。計算はしない)
def draw():
    pyxel.cls(COL_BLACK)
    
    # 背景
    for star in stars:
        pyxel.pset(star[0], star[1], COL_WHITE if star[2] > 1 else COL_GRAY)

    # 衝撃波                # ここから追加
    if is_bomb_active:      # ボムが発動中なら
        # 中心 (player_x + 4, player_y + 4) からbomb_radiusの円を描く
        pyxel.circb(player_x + 4, player_y + 4, bomb_radius, COL_WHITE)
        # 少し内側にもう一つ円を描いて、二重円で表現
        pyxel.circb(player_x + 4, player_y + 4, bomb_radius - 2, COL_LBLUE)
  • pyxel.circb(x, y, r, col) は、指定された中心座標 (x, y) と半径 r円の枠線 を描画する関数です。魔法の絵筆描画関数 で学んだ Pyxel の描画関数です。
  • player_x + 4player_y + 4 は、プレイヤーのスプライトの中心座標を計算しています(プレイヤーの幅・高さが8なので中心は4です)。
  • bomb_radius の値が update() 関数で増えているので、draw() 関数では毎フレーム大きくなる円が描画され、衝撃波が広がって見えます。
  • bomb_radius - 2 のように少し小さめの円も描画することで、二重の円となり、より迫力のある衝撃波に見えますね。

補足だよ

pyxel.circb() で円の枠線を描画することで、衝撃波の広がっていく様子を視覚的に表現しています。Pyxelの描画関数をうまく活用すると、シンプルな形で様々なエフェクトが作れます。

最後に、画面右上にボムの残り数を表示するUIを追加しましょう。
draw() 関数内の「UI」描画部分を、以下のように変更してください。

    # UI
    pyxel.text(5, 5, f"SCORE:{score}", COL_WHITE)
    pyxel.text(120, 5, f"BOMB:{num_bombs}", COL_CYAN) # ボムの数を表示

これで、いつでもボムの残り数を確認できるようになりました。

6. 完成!ボムで敵を一掃する爽快感を体験しよう

お疲れ様でした!これで「ボム」機能の実装は完了です。
プログラム全体は以下のようになります。


実際に動かしてみよう!

矢印キーで自機移動、スペースキーで弾発射、ZまたはBキーでボム発動

---

ボムを発動して、画面中の敵を一掃する爽快感をぜひ味わってみてください!
窮地に陥った時にボムを使うタイミングを見極めるのも、ゲームを面白くする要素の一つですね。

次回は、プレイヤーがパワーアップするための「アイテム」を敵が落とすようにしてみましょう!
より戦略的なゲームプレイが楽しめるようになりますよ。お楽しみに!
実践:救援物資アイテム!

最後まで読んでくれてありがとう!🌱
ノートみたいに、いつでも見返してね。