Python Pyxel でプログラミング練習 第2回(前編)

Pyxelでじゃんけんゲームを作る(前編)

 Python向けレトロゲームエンジン「Pyxel(ピクセル)」を使ったゲーム制作を通してプログラミングを学習します。
 今回作成するゲームで,画面のクリック判定,乱数の使用,効果音の再生の仕方を紹介します。

 【前回の記事】Pyxelの準備とドット絵を表示するプログラム
 Python Pyxel でプログラミング練習 - 勉強ボックス管理者ブログ

 【後編】Pyxelでじゃんけんゲームを作る(後編)
 Python Pyxel でプログラミング練習 第2回(後編) - 勉強ボックス管理者ブログ

ゲームの内容を考える

 作りたいじゃんけんゲームのイメージと初めの段階で思いつく処理を書き出しました。(COMはコンピューター 対戦相手です)
 
 
 

ドット絵の作成

 画像のサイズを16×16と決めたので,さっそくドット絵を作成しましょう。
 リソースファイルの名前を rps_game.pyxres とします。
 
 <エディタの起動手順>

  1. エクスプローラーでプログラムを作成しているフォルダを表示する。
  2. フォルダ内の何もない所を「Shiftキーを押しながら右クリック」して,メニューを表示する。
  3. メニューから「PowerShell ウィンドウをここで開く(S)」を選択する。
  4. PowerShellウィンドウで「pyxel edit rps_game」を入力してEnterキーを押す。

 <エディタでドット絵を描く>
 グー(0,0) ,チョキ(16,0) ,パー(32,0) を描きます。プログラムから座標を指定するので例と同じ開始位置になるようにしてください。(色や形は自由に変えてもよいです)
 

 ドット絵のイメージ
 
 
 
 ※作成後は保存を忘れずに

 

プログラムの作成

 ソースコードを記述していきます。ファイル名は任意です(最後まで同じファイル名で問題ありません)。

 ※本記事では「ソースコードを書く」→「実行して確認」→「ソースコードに処理を追加」→「実行して確認」→・・・を繰り返します。各ステップでのソースコード変更部分は,下記pdfファイルに赤文字で示しましたので参考にしてください。
Pyxel_じゃんけんゲーム_ソース確認用.pdf - Google ドライブ

01 ドット絵を表示する

 list04_01.py

import pyxel

pyxel.init(80,64,title="rock paper scissors")
pyxel.load("rps_game.pyxres")
pyxel.mouse(True)

def update():
    return

def draw():
    pyxel.cls(0)

    # コンピューターの手を描画
    pyxel.text(4,10, "COM",7)
    pyxel.blt(32,10, 0, 0,0, 16,16, 0)

    # プレーヤーの手を描画
    pyxel.text(4,32, "YOU",7)
    pyxel.blt(16,32, 0,  0,0, 16,16, 0)
    pyxel.blt(32,32, 0, 16,0, 16,16, 0)
    pyxel.blt(48,32, 0, 32,0, 16,16, 0)
    
    return

pyxel.run(update, draw)

 実行結果
 
 ドット絵が表示できました。また,画面上にマウスポインタが表示されています。

・pyxel.init(80,64,title="rock paper scissors")
 引数 title で実行時のウィンドウに表示されるタイトルを指定できます。

・pyxel.mouse(True)
 画面上のマウスポインタ表示を指定する命令です。(Trueで表示あり。デフォルトはFalse指定で非表示)

 

02 クリック判定処理を追加する

 update()関数にマウスクリック判定を追加します。
 クリックされたときに,乱数を使ってコンピューターの手を決めてみましょう。また,クリックされるまでコンピューターの手のドット絵を切り替える演出も合わせて作ります。

 【ゲームの仕様】じゃんけんの手をプログラムから扱いやすくするために数値で表すことにします。「グーを0,チョキを1,パーを2」としましょう。

 list04_02.py
 前のプログラムからの変更箇所は 確認用pdfファイル の2ページを参照してください。

import pyxel

pyxel.init(80,64,title="rock paper scissors")
pyxel.load("rps_game.pyxres")
pyxel.mouse(True)

com_hand = 0
def update():
    global com_hand
    if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT) :
        com_hand = pyxel.rndi(0,2) # クリックされたら手を決める
    else:
        # クリック前は次々手を変える
        com_hand = int(pyxel.frame_count / 5) % 3
        
    return

def draw():
    pyxel.cls(0)

    # コンピューターの手を描画
    pyxel.text(4,10, "COM",7)
    pyxel.blt(32,10, 0, com_hand*16,0, 16,16, 0)

    # プレーヤーの手を描画
    pyxel.text(4,32, "YOU",7)
    pyxel.blt(16,32, 0,  0,0, 16,16, 0)
    pyxel.blt(32,32, 0, 16,0, 16,16, 0)
    pyxel.blt(48,32, 0, 32,0, 16,16, 0)
    
    return

pyxel.run(update, draw)

 実行結果
 
 コンピューターの手の表示が切り替わるようになりましたが,クリックしても絵が変わり続けています。期待した動作にはなりませんでした。

・pyxel.btnp(key, [hold], [repeat])
 btnp()命令は,keyで指定したキーが押されたかどうかがわかる命令です。
 そのフレーム(自動で繰り返されている処理の単位のこと)でキーが押されていればTrue,押されていなければFalseが返ります。例では key にマウスの左ボタン pyxel.MOUSE_BUTTON_LEFT を指定しているので,マウスがクリックされたら True になります。

・pyxel.rndi(a, b)
 rndi()命令は,a以上b以下のランダムな整数を返します。
 pyxel.rndi(0,2) で,0,1,2のどれかの値になるようにしています。

・com_hand = int(pyxel.frame_count / 5) % 3
 pyxel.frame_count の値は経過フレーム数です。Pyxel公式サンプルコード「01_hello_pyxel.py」でも文字色を変更する仕組みに使われています。
 「%演算子」を使うと剰余(割り算の余り)を求めることができます。
 例えば num = 7 % 2 では7を2で割った余りの 1 が変数 num に代入されます。
 公式サンプルコードの
  pyxel.text(55, 41, "Hello, Pyxel!", pyxel.frame_count % 16)
 では,pyxel.frame_count % 16 割られる数がどんどん大きくなっていきますが,余りは割る数を超えることがないので文字色の指定はパレット番号の範囲内(0~15)の値を繰り返します。
 じゃんけんゲームの手の表示では切り替えスピードを下げるために pyxel.frame_count を5で割っています(5フレームごとに絵が変わる)。

 

03 状態を管理する変数を追加して,クリック後の処理と分岐させる

 クリックされる前とされた後を区別できれば処理を分けることができそうです。状態を管理する変数を追加してクリック時に状態を変更するように改造します。

 list04_03.py
 前のプログラムからの変更箇所は 確認用pdfファイル の3ページを参照してください。

import pyxel

pyxel.init(80,64,title="rock paper scissors")
pyxel.load("rps_game.pyxres")
pyxel.mouse(True)

com_hand = 0
status = 0
def update():
    global com_hand, status
    if status == 0:
        if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT) :
            com_hand = pyxel.rndi(0,2) # クリックされたら手を決める
            status = 1
        else:
            # クリック前は次々手を変える
            com_hand = int(pyxel.frame_count / 5) % 3
    elif status == 1:
        pass # 今は何もしない
    
    return

def draw():
    pyxel.cls(0)

    # コンピューターの手を描画
    pyxel.text(4,10, "COM",7)
    pyxel.blt(32,10, 0, com_hand*16,0, 16,16, 0)

    # プレーヤーの手を描画
    pyxel.text(4,32, "YOU",7)
    pyxel.blt(16,32, 0,  0,0, 16,16, 0)
    pyxel.blt(32,32, 0, 16,0, 16,16, 0)
    pyxel.blt(48,32, 0, 32,0, 16,16, 0)
    
    return

pyxel.run(update, draw)

 実行結果
 
 画面をクリックするとコンピューターの手の表示変化が止まるようになりました。

・追加した変数 status は初期値 0 (クリック前の状態)で,update()関数の処理をstatusが0の場合と1の場合で分け,クリックされたら1(クリック後の状態)を代入して,以降のフレームのupdate()処理でcom_handの値が変わらないようにしています。

・pass文
 statusが1の場合の処理※はもう少し後で作ります。(※クリックされたらstatusを0に戻す)
 何も処理がないelifのブロックがあると,Python実行時にエラーになるため何もしない処理「pass」を記述しておきます。


 後編の記事へ続きます。
 kinutani.hateblo.jp