もどる

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

python2026.3.5

3-2. エンジン点火:「もしも(if)」の魔法で自機を動かせ

もしもの魔法
自機移動

皆さん、こんにちは!うずらです。
主人公召喚!は、ついにPyxelの画面にあなたの宇宙船が描画されましたね。

今回は、その宇宙船に「魂」を吹き込みます。そう、キーボードの入力に応じて、自機を自由に動かせるようにするのです!
「もしもキーが押されたら、こう動く」という魔法の呪文「if」を使いこなして、ゲームの世界をあなたの手でコントロールしましょう。

1. 3秒でわかるまとめ

今回のゴールは、Pyxelの pyxel.btn() 関数とPythonの if 文を組み合わせて、キーボードの矢印キー入力に応じて自機を画面内で上下左右に動かせるようにすることです。

2. 動き出す魔法のスイッチ:pyxel.btn()

ゲームを操作するために、まず必要なのは「プレイヤーがどんなキーを押しているか」をコンピュータに伝えることです。Pyxelには、これを簡単に検出できる便利な魔法の呪文があります。それが pyxel.btn() です。

pyxel.btn() の使い方

pyxel.btn() は、「今、指定したキーが押されているか?」を判定する関数です。

pyxel.btn(pyxel.KEY_LEFT) # 左矢印キーが押されているか?
pyxel.btn(pyxel.KEY_RIGHT) # 右矢印キーが押されているか?
pyxel.btn(pyxel.KEY_UP) # 上矢印キーが押されているか?
pyxel.btn(pyxel.KEY_DOWN) # 下矢印キーが押されているか?

pyxel.KEY_LEFT のように pyxel.KEY_ で始まるものは、特定のキーを表すPyxelが決めた「定数」です。
これらの関数は、キーが押されていれば True(真)、押されていなければ False(偽)を返します。この True/False という情報は、Pythonの「もしも(if)」の魔法と相性抜群です。

豆知識

pyxel.btnp()pyxel.btnr() もあります!
pyxel.btn() はキーが「押されている間ずっと」Trueを返しますが、pyxel.btnp() はキーが「押された瞬間」だけTrueを返します。また、pyxel.btnr() はキーが「離された瞬間」にTrueを返します。用途によって使い分けましょう。今回は押しっぱなしで移動させたいので pyxel.btn() を使います。

3. 「もしも」の魔法:if 文で自機を動かす

さあ、いよいよ本題です。計算と決断if文の魔法以前に学習した「if 文」を思い出してください。「もし〇〇ならば、××を実行する」という条件分岐の魔法でしたね。

これを pyxel.btn() と組み合わせることで、「もし左矢印キーが押されたら、自機を左に動かす」という処理が実現できます。

前回のコードから update() 関数の中身を次のように変更します。

# 毎フレーム実行される更新処理 (計算などはここで行う。描画は禁止)
def update():
    global player_x, player_y # これを追加!

    # --- 3. プレイヤー操作 ---
    if pyxel.btn(pyxel.KEY_LEFT):
        player_x = player_x - PLAYER_SPEED # 左に動かす
    if pyxel.btn(pyxel.KEY_RIGHT):
        player_x = player_x + PLAYER_SPEED # 右に動かす
    if pyxel.btn(pyxel.KEY_UP):
        player_y = player_y - PLAYER_SPEED # 上に動かす
    if pyxel.btn(pyxel.KEY_DOWN):
        player_y = player_y + PLAYER_SPEED # 下に動かす

注目すべき点は次の3つです。

  1. global キーワード:
    update() 関数の中で player_xplayer_y の値を変更するために、global キーワードが必要です。関数の中で定義されていない変数を変更する場合、「これは関数の外で定義された変数を使うよ」とPythonに教えてあげる必要があります。

補足だよ

Pythonでは、関数の中で変数を新しく定義すると、その変数はその関数の中でしか使えません。しかし、global 変数名 と書くことで、関数の外(グローバルスコープ)で定義された変数を関数の中から変更できるようになります。これで player_x の値を update() 関数の中で更新できるようになります。
  1. PLAYER_SPEED:
    自機が動く速さを決める定数 PLAYER_SPEED を新しく定義しました。コードの先頭にある「定数設定」の部分に PLAYER_SPEED = 3 のように追加してください。こうすることで、後から移動速度を変えたいときに、この1箇所だけ変更すれば済むようになります。

  2. player_xplayer_y の更新:
    player_x = player_x - PLAYER_SPEED は、現在の player_x から PLAYER_SPEED 分だけ値を減らして、新しい player_x とする、という意味です。これで、フレームごとに自機が左に移動します。
    Pyxelの座標系は、画面の左上が (0, 0) で、右に行くほど x が大きく、下に行くほど y が大きくなることを思い出しましょう。

    • 左に動かす:player_x を減らす
    • 右に動かす:player_x を増やす
    • 上に動かす:player_y を減らす
    • 下に動かす:player_y を増やす

4. 画面からはみ出さない工夫:max()min() 関数

上記のコードで自機は動くようになりますが、このままだと画面の外へ出て行ってしまいます。
これでは困りますね。自機が画面の中にとどまるように、移動範囲を制限する魔法をかけましょう。

ここで登場するのが、Pythonの組み込み関数 max()min() です。

  • max(A, B): AとBのうち、大きい方の値を返します。
  • min(A, B): AとBのうち、小さい方の値を返します。

これを移動処理と組み合わせると、次のようになります。

    # --- 3. プレイヤー操作 ---
    if pyxel.btn(pyxel.KEY_LEFT):
        player_x = max(player_x - PLAYER_SPEED, 0)
    if pyxel.btn(pyxel.KEY_RIGHT):
        player_x = min(player_x + PLAYER_SPEED, SCREEN_WIDTH - PLAYER_W)
    if pyxel.btn(pyxel.KEY_UP):
        player_y = max(player_y - PLAYER_SPEED, 0)
    if pyxel.btn(pyxel.KEY_DOWN):
        player_y = min(player_y + PLAYER_SPEED, SCREEN_HEIGHT - PLAYER_H)

それぞれの行が何をしているか、見ていきましょう。

  • player_x = max(player_x - PLAYER_SPEED, 0)
    左に移動しようとしたとき (player_x - PLAYER_SPEED)、その値が 0 より小さくなる場合は、0 にとどまるようにしています。つまり、左端(x座標が0)よりも左には行かないようにする、ということです。

  • player_x = min(player_x + PLAYER_SPEED, SCREEN_WIDTH - PLAYER_W)
    右に移動しようとしたとき (player_x + PLAYER_SPEED)、その値が SCREEN_WIDTH - PLAYER_W より大きくなる場合は、SCREEN_WIDTH - PLAYER_W にとどまるようにしています。

補足だよ

自機の座標 (player_x, player_y) は、常にキャラクターの「左上隅」の座標を表します。そのため、画面の右端で止める場合は SCREEN_WIDTH から自機の横幅 PLAYER_W を引く必要があります。そうしないと、自機が半分画面外に出てしまうことがあります。同様に、下端も SCREEN_HEIGHT - PLAYER_H となります。

この max()min() の魔法で、あなたの宇宙船は画面内を自由に飛び回れるようになりました!

5. 動く自機を体験しよう!

それでは、ここまでの変更をすべて適用したコードを見てみましょう。
PLAYER_SPEED 定数の追加、update() 関数内の global 宣言、そしてキー入力と画面端制限の処理が加わっています。
draw() 関数に変更はありません。

import pyxel

# =========================================================
#  ASTRO SURVIVOR
#  - 宇宙シューティングゲーム -
# =========================================================

# --- 定数設定 ---
SCREEN_WIDTH = 160
SCREEN_HEIGHT = 120
GAME_TITLE = "ASTRO SURVIVOR"

# キャラクターのサイズ
PLAYER_W = 8
PLAYER_H = 8
PLAYER_SPEED = 3 # 新しく追加

# 色の定義
COL_BLACK = 0
COL_WHITE = 7
COL_RED = 8
COL_ORANGE = 9
COL_YELLOW = 10
COL_CYAN = 12


# --- Pyxelの初期化と音の定義 ---

pyxel.init(SCREEN_WIDTH, SCREEN_HEIGHT, title=GAME_TITLE)

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

# =========================================================
#  メインループ (Update & Draw)
# =========================================================

# 毎フレーム実行される更新処理 (計算などはここで行う。描画は禁止)
def update():
    global player_x, player_y # これを追加しました

    # --- 3. プレイヤー操作 ---
    if pyxel.btn(pyxel.KEY_LEFT):
        player_x = max(player_x - PLAYER_SPEED, 0) # 左端の制限
    if pyxel.btn(pyxel.KEY_RIGHT):
        player_x = min(player_x + PLAYER_SPEED, SCREEN_WIDTH - PLAYER_W) # 右端の制限
    if pyxel.btn(pyxel.KEY_UP):
        player_y = max(player_y - PLAYER_SPEED, 0) # 上端の制限
    if pyxel.btn(pyxel.KEY_DOWN):
        player_y = min(player_y + PLAYER_SPEED, SCREEN_HEIGHT - PLAYER_H) # 下端の制限

# 毎フレーム実行される描画処理 (結果を画面に表示する。計算はしない)
def draw():
    pyxel.cls(COL_BLACK)

    # 背景
    # プレイヤー
    pyxel.rect(player_x, player_y, PLAYER_W, PLAYER_H, COL_ORANGE)
    pyxel.rect(player_x+3, player_y-2, 2, 2, COL_YELLOW)


pyxel.run(update, draw)

上記のコードを実際にブラウザで動かしてみてください。
矢印キーを押して、あなたの宇宙船が画面内を自由に動き回るのを確認しましょう!

実際に動かしてみよう!

矢印キーで宇宙船を操作できます

いかがでしたか? 自分のキー入力でキャラクターが動くのは、プログラミングの大きな喜びの一つですよね。
「もしも」の魔法 if 文が、ゲームの世界でこんなにも強力な力を持つことが実感できたのではないでしょうか。

次回は、宇宙に輝く星々を描いて、ゲームの背景をさらに魅力的にしていきます。リスト魔法星空の実装どうぞお楽しみに!

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