もどる

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

python2026.3.15

4-5. 火力増強:変数の状態で変化する3WAY弾

実践:火力増強
3WAY弾

1. 3秒でわかるまとめ

プレイヤーの「パワーアップ状態」を 変数で管理 し、その状態によって弾の撃ち方(1WAY弾/3WAY弾)を変えられるようにします。

2. パワーアップ状態を管理する変数を用意する

前回の記事 実践:救援物資アイテム! では、敵を倒すとボムアイテムが出現し、取得するとボムの数が増える機能を実装しました。今回はこれに加えて「パワーアップアイテム」を追加し、取得すると自機の攻撃力がアップする仕組みを作っていきます。

まず、プレイヤーのパワーアップ状態を管理するための新しい変数を用意しましょう。

# --- 変数の初期化 ---
# (中略)

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

# パワーアップ & ボム
power_level = 1 # ★追加: パワーアップレベル。初期値は1 (通常弾)
power_timer = 0 # ★追加: パワーアップの残り時間
num_bombs = 1
is_bomb_active = False
bomb_radius = 0

power_level は現在のパワーアップ段階を示し、初期値は 1 で通常の状態を意味します。
power_timer はパワーアップの効果が持続する時間をカウントダウンするための変数です。特定のフレーム数まで効果が続き、時間切れになると power_level が初期値に戻るようにします。

補足だよ

変数の初期化は、ゲームが始まる前に一度だけ行われる大切な処理です。ここでゲームの土台となる状態を設定します。

3. パワーアップアイテムの出現と取得ロジック

次に、敵が倒されたときにパワーアップアイテムがドロップするようにします。
update 関数内の、敵が破壊された後の処理を見てみましょう。

# --- 4. オブジェクト更新 ---
# (中略)

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

        if hit:
            spawn_particles(e['x'], e['y'], 5, e['color'])
            score += e['score']
            
            dice = random.random() # ★変更: アイテムドロップの判定
            if dice < 0.08: drop_item(e['x'], e['y'], 'bomb')
            elif dice < 0.18: drop_item(e['x'], e['y'], 'power') # ★追加: パワーアップアイテムのドロップ
            continue
        
        surviving_enemies.append(e)
    enemies = surviving_enemies

前回のコードでは、敵が破壊されたときに random.random() < 0.08 の確率でボムアイテムをドロップしていました。
今回は、dice という変数でランダムな値を生成し、その値によってドロップするアイテムの種類を分岐させています。
dice < 0.08 ならボムアイテム、dice < 0.18 (つまり 0.08〜0.18 の間) ならパワーアップアイテムをドロップするようにしました。これにより、パワーアップアイテムのドロップ率は10%となります。

次に、プレイヤーがパワーアップアイテムを取得したときの処理を追加します。
update 関数内のアイテム更新部分を変更します。

# --- 4. オブジェクト更新 ---
# (中略)

    # アイテム更新
    surviving_items = []
    for item in items:
        item[1] += 1
        ix, iy, kind = item
        
        # プレイヤーとの当たり判定
        if check_collision(player_x, player_y, PLAYER_W, PLAYER_H, ix, iy, 4, 4):
            if kind == 'power': # ★変更: アイテムの種類によって処理を分岐
                power_level = 2 # パワーアップレベルを2に設定
                power_timer = 300 # パワーアップ効果を300フレーム継続
            elif kind == 'bomb':
                num_bombs += 1
            continue # 取得したのでリストに追加しない (消える)

        if iy <= SCREEN_HEIGHT:
            surviving_items.append(item)
    items = surviving_items

ここでは、if kind == 'power': という条件文を使って、取得したアイテムが 'power' だった場合にのみ特別な処理を実行しています。

  • power_level = 2: パワーアップレベルを 2 に設定します。
  • power_timer = 300: パワーアップ効果が 300 フレーム(約5秒)持続するようにタイマーを設定します。

そして、update 関数の冒頭にある「システム更新」セクションに、power_timer を管理するロジックを追加します。

# --- 2. システム更新 (ボム & パワーアップ) ---
    if is_bomb_active:
        bomb_radius += 4
        if bomb_radius > 200:
            is_bomb_active = False
            bomb_radius = 0
            
    if power_timer > 0: # ★追加: パワーアップタイマーの更新
        power_timer -= 1 # 毎フレーム1ずつ減らす
        if power_timer <= 0: # 0になったら
            power_level = 1 # パワーアップレベルを1に戻す (通常状態)

これで、power_timer0 より大きい間はカウントダウンが続き、0 以下になったら power_level1 (通常状態)に戻るようになりました。

4. パワーアップ状態による3WAY弾の実装

いよいよメインの機能です。update 関数内の弾の発射処理を power_level の値に応じて分岐させます。

# --- 3. プレイヤー操作 ---
# (中略)

    # 弾の発射
    if pyxel.btnp(pyxel.KEY_SPACE):
        # 通常弾
        if power_level == 1: # ★変更: power_levelが1なら通常弾
            bullets.append([player_x + 3, player_y - 4, 0, -5])
        # パワーアップ弾 (3方向)
        elif power_level >= 2: # ★変更: power_levelが2以上なら3WAY弾
            bullets.append([player_x + 3, player_y - 4, 0, -5]) # 中央
            bullets.append([player_x + 3, player_y - 4, -2, -4]) # 左斜め
            bullets.append([player_x + 3, player_y - 4,  2, -4]) # 右斜め
  • if power_level == 1: の条件では、これまで通り中央にまっすぐ進む弾を1発だけ発射します。[0, -5] はX方向の速度が0、Y方向の速度が-5(上方向)を意味します。
  • elif power_level >= 2: の条件が追加され、power_level2 以上であれば3方向に弾を発射します。
    • 中央の弾はこれまでと同じ [0, -5] です。
    • 左斜めの弾は [-2, -4] で、X方向にもわずかに左に移動しながら上昇します。
    • 右斜めの弾は [2, -4] で、X方向にもわずかに右に移動しながら上昇します。

このように、弾の速度を調整することで、様々な方向に弾を撃ち分けることができます。

豆知識

弾の速度 `[vx, vy
` の値を変更することで、弾の角度や速さを自由に調整できます。例えば、`[-3, -3]` や `[3, -3]` にすると、もっと斜めに、そして少し遅めの弾になります。]

5. パワーアップ中の見た目の変化

最後に、パワーアップ状態が分かりやすいように、プレイヤーの描画色を変化させましょう。

# 毎フレーム実行される描画処理 (結果を画面に表示する。計算はしない)
def draw():
    pyxel.cls(COL_BLACK)
    
    # (中略)
        
    # プレイヤー
    col = COL_ORANGE # ★変更: 色を管理する変数を追加
    if power_level >= 2: # ★追加: power_levelが2以上の場合
        # パワーアップタイマーが残り少ない時は点滅させる
        if power_timer < 90 and pyxel.frame_count % 4 < 2: col = COL_ORANGE
        else: col = COL_CYAN # 通常のパワーアップ中はシアン色
    pyxel.rect(player_x, player_y, PLAYER_W, PLAYER_H, col) # ★変更: col変数を使用
    pyxel.rect(player_x+3, player_y-2, 2, 2, COL_YELLOW)

    # 弾
    for b in bullets:
        pyxel.rect(b[0], b[1], 2, 4, COL_L_GREEN)

    # 敵
    # (中略)

    # アイテム
    for item in items:
        char = "P" if item[2] == 'power' else "B" # ★変更: アイテムの種類によって表示文字を変える
        col  = COL_YELLOW if item[2] == 'power' else COL_CYAN # ★変更: アイテムの種類によって表示色を変える
        pyxel.text(item[0], item[1], char, col) # ★変更: charとcol変数を使用

    # UI
    pyxel.text(5, 5, f"SCORE:{score}", COL_WHITE)
    pyxel.text(120, 5, f"BOMB:{num_bombs}", COL_CYAN) # ★変更: BOMBS -> BOMB
  • プレイヤーの描画:
    • player_x, player_y, PLAYER_W, PLAYER_H の色を直接指定するのではなく、col という変数に一旦色を代入するように変更しました。
    • power_level >= 2 の場合、colCOL_CYAN(水色)に変更します。
    • さらに、power_timer が残り 90 フレーム(約1.5秒)を下回ると、点滅してパワーアップ終了が近いことを示します。pyxel.frame_count % 4 < 2 は、4フレームごとに2フレームだけ色を変えることで点滅を表現しています。
  • アイテムの描画:
    • アイテムの種類 (item[2]) が 'power' なら P を、それ以外 ('bomb') なら B を表示するようにしました。
    • 同様に、色も 'power' なら COL_YELLOW'bomb' なら COL_CYAN に分けて表示しています。
  • UIの修正:
    • ボムの表示が BOMBS と複数形になっていたのを、BOMB に修正しました。

これで、プレイヤーのパワーアップ状態が視覚的にもわかりやすくなり、ゲームプレイがさらに楽しくなりましたね!

実際に動かしてみましょう!

これまでの変更をすべて適用したコードで、3WAY弾の爽快感を体験してください。
パワーアップアイテムを取得して、敵を一掃してみましょう!

  <div class="my-16 max-w-full">
    <div class="bg-gradient-to-br from-purple-50 to-blue-50 border-4 border-purple-200 rounded-2xl p-6 md:p-8 shadow-xl">
      <div class="flex items-center gap-3 mb-6">
        <img src="/icons/icon-denkyu.png" alt="" class="w-8 h-8 flex-shrink-0" />
        <h4 class="font-black text-purple-900 text-xl">実際に動かしてみよう!</h4>
      </div>
      <div class="bg-white rounded-xl overflow-hidden border-2 border-purple-100 shadow-inner">
        <iframe 
          src="/dev-snapshots/run/4-5_3way_shot"
          class="w-full aspect-[4/3] border-0"
          title="Pyxel Game: 4-5_3way_shot.py"
          loading="lazy"
        ></iframe>
      </div>
      <p class="text-sm text-purple-700 font-bold mt-4 text-center">
        矢印キーで移動、スペースキーでショット、ZキーまたはBキーでボム発動。

パワーアップアイテムを取ると3WAY弾に!



次の記事では、いよいよ強大な敵「ボス」が登場します!お楽しみに!
実践:巨大戦艦接近遭遇

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