見出し画像

【pyxel 1.5】pyxelでpython勉強帳(5)

さて、前回まではpythonのデータ型をいろいろとみていましたが、今回からは制御文やpyxel特有の機能について書いていこうと思います。

ということで、制御文といえば「IF」。ifというと「もしも」という意味ですが、プログラムでも「もしも○○したら××する」というように処理を分ける際に使います。
今回は、条件分岐で使われるif文を使って、簡単なゲームを作ってみました。

▲格ゲーのコマンド入力ゲーム。
→↓→Pで昇竜拳。

pyxelの命令を使ってキー入力を検知して、コマンドの完成を判定します。

コード全体は以下の通りです。

import pyxel

class APP:
  def __init__(self):
      pyxel.init(128, 128, title="pyxel")
      
      self.frame = 0
      self.f_limit = 10
      self.cmd = 0
      
      pyxel.run(self.update, self.draw)
     
  def update(self):
      if pyxel.btn(pyxel.KEY_R):
          self.frame = 0          
          self.cmd = 0
          
      if self.cmd == 0 and pyxel.btn(pyxel.KEY_RIGHT):
          self.cmd += 1
          
      if self.cmd == 1 and pyxel.btn(pyxel.KEY_DOWN):
          self.cmd += 1
          self.frame = 0

      if self.cmd == 2 and pyxel.btn(pyxel.KEY_RIGHT):
          self.cmd += 1 
          self.frame = 0

      if self.cmd == 3 and pyxel.btn(pyxel.KEY_P):
          self.cmd += 1 
          self.frame = 0
          
      if self.cmd != 0:          
          if self.cmd == 4:
              pass
          else:
              self.frame += 1
              if self.frame > self.f_limit:
                  self.frame = 0
                  self.cmd = 0
   
  def draw(self):
      pyxel.cls(0)
      pyxel.text(10, 10, str(self.frame), 7)
      
      if self.cmd == 1:
          pyxel.text(10, 20, "RIGHT!", 7)
          
      if self.cmd == 2:
          pyxel.text(10, 30, "DOWN!!", 7)          

      if self.cmd == 3:
          pyxel.text(10, 40, "RIGHT!!!", 7)                    
          
      if self.cmd == 4:          
          pyxel.text(10, 50, "SYO-RYU-KEN!!!!", pyxel.frame_count % 16)            
      
      
      
APP()

順々に見ていきますが、今回は僕の趣味全開で作ってしまったので、格闘ゲームをやらない方には分かりにくい内容になってしまいました…。できるだけ丁寧に書こうと思いますが、申し訳ない。

  def __init__(self):
      pyxel.init(128, 128, title="pyxel")
      
      self.frame = 0
      self.f_limit = 10
      self.cmd = 0
      
      pyxel.run(self.update, self.draw)

▲まずはinit部分。3つの変数を用意します。
「self.frame」は経過フレーム数を格納。格ゲーのコマンドは一定時間内に連続でキー入力を行うので、前の入力からどれくらい経ったかを判別するのに使います。
「self.f_limit」は猶予フレームの設定用。制限時間みたいなものですね。この値内で次のキー入力を行います。
「self.cmd 」はコマンドがどこまで進んだかを示す値。今回は昇竜拳なので右・下・右・パンチというコマンドになります(パンチはPキーに割り当て)。これがどこまで進んでいるかを示します。

次に、実際にif文を使うupdate関数に進んでいきます。

  def update(self):
      if pyxel.btn(pyxel.KEY_R):
          self.frame = 0          
          self.cmd = 0
          
      if self.cmd == 0 and pyxel.btn(pyxel.KEY_RIGHT):
          self.cmd += 1
          
      if self.cmd == 1 and pyxel.btn(pyxel.KEY_DOWN):
          self.cmd += 1
          self.frame = 0

      if self.cmd == 2 and pyxel.btn(pyxel.KEY_RIGHT):
          self.cmd += 1 
          self.frame = 0

      if self.cmd == 3 and pyxel.btn(pyxel.KEY_P):
          self.cmd += 1 
          self.frame = 0
          
      if self.cmd != 0:          
          if self.cmd == 4:
              pass
          else:
              self.frame += 1
              if self.frame > self.f_limit:
                  self.frame = 0
                  self.cmd = 0

▲update関数です。if文とpyxel.btnを使ってキー入力を判定しています。

      if pyxel.btn(pyxel.KEY_R):
          self.frame = 0          
          self.cmd = 0

▲基本の形はこんな感じ。「if」の後に条件を書いて「:」でふさぎます。
条件に合致した際には下の行の処理を行います。この時インデント(段落)をきちんと下げていないとエラーになってしまうので注意。
pyxel.btnは引数で与えられたキーが押されたかを判定するpyxelの命令文です。この部分はRキーを押すと各変数をリセットするコードですね。

      if self.cmd == 0 and pyxel.btn(pyxel.KEY_RIGHT):
          self.cmd += 1
          
      if self.cmd == 1 and pyxel.btn(pyxel.KEY_DOWN):
          self.cmd += 1
          self.frame = 0

      if self.cmd == 2 and pyxel.btn(pyxel.KEY_RIGHT):
          self.cmd += 1 
          self.frame = 0

      if self.cmd == 3 and pyxel.btn(pyxel.KEY_P):
          self.cmd += 1 
          self.frame = 0

▲コマンド入力を検知する部分。self.cmdの値とキー入力で分岐します。各if文で正しいキー入力が行われた場合は「self.cmd += 1」でコマンドを進めて、「self.frame = 0」で猶予フレームをリセットします。

      if self.cmd != 0:          
          if self.cmd == 4:
              pass
          else:
              self.frame += 1
              if self.frame > self.f_limit:
                  self.frame = 0
                  self.cmd = 0

▲ここのif文はちょっと複雑になっています。
まず「if self.cmd != 0:」の条件が来てますね。これはself.cmdが0でなかったらという意味です。==!=のような比較に使う記号はいろいろあるので、ここではすべては取り上げません。
下のインデントに行くと、そこにもifがあります。if文はこのように何重にもすることができます(が、あまりにも階層が深くなるのは推奨されません)
「if self.cmd == 4:」はself.cmdが4の状態を判定。これはコマンドが完成した状態で、昇竜拳が出ている場合です。この時は何もしたくないので「pass」を書いています。
「else」は「以外の場合」の意味です。これは上のifと対になります。今回でいうと「self.cmdが4でない場合」ということになります。コマンドが完成していない間は猶予フレームを消費したいので「self.frame += 1」で進めます。
ここまで来てまたifが出てきます。「if self.frame > self.f_limit:」で経過フレームが猶予フレームを超えてしまったらという条件になります。ここに合致するとself.frameとself.cmdが0になって最初からになってしまいます。

  def draw(self):
      pyxel.cls(0)
      pyxel.text(10, 10, str(self.frame), 7)
      
      if self.cmd == 1:
          pyxel.text(10, 20, "RIGHT!", 7)
          
      if self.cmd == 2:
          pyxel.text(10, 30, "DOWN!!", 7)          

      if self.cmd == 3:
          pyxel.text(10, 40, "RIGHT!!!", 7)                    
          
      if self.cmd == 4:          
          pyxel.text(10, 50, "SYO-RYU-KEN!!!!", pyxel.frame_count % 16)           
      

▲draw関数はself.cmdの値によって文字表示を変えているだけなので割愛します。

▲制限時間内にコマンドを入れるとクリアです。
時間切れになると最初からになります。

ちなみにself.f_limitをいじると猶予フレームを操作できます。「1」にすると猶予1フレの超難易度の出来上がり。

▲猶予1フレーム。これはなかなか難しい。

と思いきや、このゲームには攻略法があります。pyxel.btnはキー押しっぱなしでの入力も「入力あり」として検知するので、右キーを押し続けながら下とPをパチパチって感じで簡単に出ます。

▲かんたんだなぁ。欠陥ゲームだよ、これ。

これはpyxel.btnの仕様による攻略法ですが、これへの対処策もあります。pyxel.btnではなくpyxel.btnpを使うときちんとキーを「押下」しないと入力となりません。押しっぱなしを許容するかで使い分けると良い感じ。例えばシューティングゲームで押し続けて連射するかどうかとかですかね。

今回はここまで。
うまく使えば簡易版太鼓の達人みたいなゲームも作れそう。
次回はもう1つの制御文の巨頭、「for」を使ってみます。

読んでいただきありがとうございました。


ここまで読んでいただきありがとうございます!