見出し画像

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

今回はpythonの制御文から「for」を取り上げてみます。

この「for」文は「繰り返し処理」を行う際に使います。実際の使い方としては「配列から要素を取り出して処理」「既定の回数まで処理」があるので順番に書いていきます。

# -*- coding: utf-8 -*-

import pyxel

class APP:
  def __init__(self):
      pyxel.init(128, 128, title="pyxel")
      
      self.num_list = [1, 2, 3, 4, 5, 6, 7, 8]
      
  
      
      pyxel.run(self.update, self.draw)
     
  def update(self):
      pass
   
  def draw(self):
      pyxel.cls(0)
      
      for n in self.num_list:
          
          pyxel.text(20, 10 + 10 * n, str(n), n)
      
APP()

▲最初のコード。self.num_listに1から8までの数字を配列で持たせています。その後draw関数のfor文で配列から要素を取り出して描画します。

      for n in self.num_list:
          
          pyxel.text(20, 10 + 10 * n, str(n), n)

▲for部分のみを抜き出すとこんな感じ。「num_listから1個取り出して処理→次の1個を取り出して処理…」みたいなことですね。せっかくなのでカラーコードも変えてみました。

▲実行した結果です。num_listの中身が繰り返し処理で描画されました。

では同じような形で文字のリストを処理してみます。

# -*- coding: utf-8 -*-

import pyxel

class APP:
  def __init__(self):
      pyxel.init(128, 128, title="pyxel")
      
      self.str_list = ["A", "B", "C", "D", "E", "F", "G", "H"]
      
  
      
      pyxel.run(self.update, self.draw)
     
  def update(self):
      pass
   
  def draw(self):
      pyxel.cls(0)
      
      for s in self.str_list:
          
          pyxel.text(20, 10 + 10 * s, str(s), s)
      
APP()

▲num_listをstr_listに変えて中身を文字にしただけ。
これを実行すると…。

TypeError: unsupported operand type(s) for +: 'int' and 'str'

▲エラーになってしまいました。もともとはカラーコードや座標にnum_listの中身を使っていましたが内容が数字だから大丈夫だったわけです。今回のstr_listの中身は文字ですから「10 + 10 * s」のような指定はできません。

ではどうするか。

# -*- coding: utf-8 -*-

import pyxel

class APP:
  def __init__(self):
      pyxel.init(128, 128, title="pyxel")
      
      self.str_list = ["A", "B", "C", "D", "E", "F", "G", "H"]
      
  
      
      pyxel.run(self.update, self.draw)
     
  def update(self):
      pass
   
  def draw(self):
      pyxel.cls(0)
      
      for s in range(8):
          
          pyxel.text(20, 10 + 10 * s, str(self.str_list[s]), s + 1)
      
APP()

▲改良したコードです。「str_listから1つ取り出して処理」を繰り返すという事は、「str_listの中身の個数分処理を繰り返す」で同じようなことができます。

      for s in range(8):
          
          pyxel.text(20, 10 + 10 * s, str(self.str_list[s]), s + 1)

▲for部分です。range(8)とすることで8回繰り返してくれます。str_listのデータ個数は8なのでこれで大丈夫でしょう。この形にするとsには「0~7」の数字が入ります(1~8ではない)
数字なので座標計算にもカラーコードにも使えます。ただpyxelのカラーコード0は黒で背景と同じなのでs + 1の指定にしておきましょう。

▲実行結果です。きちんと表示されました。

それではstr_listから”H"を消して再度実行してみましょう。
すると…。

IndexError: list index out of range

▲エラーになってしまいました。str_listの中身の個数とfor文の繰り返しの回数が合っていないのが原因です。これだとstr_listの中身を変えたら追加でfor文も直さないと動きません。
そんなの中身の個数を見て良い感じにしてくれよ。という事でちょっと直します。

# -*- coding: utf-8 -*-

import pyxel

class APP:
  def __init__(self):
      pyxel.init(128, 128, title="pyxel")
      
      self.str_list = ["A", "B", "C", "D", "E", "F", "G", "H"]
      
  
      
      pyxel.run(self.update, self.draw)
     
  def update(self):
      pass
   
  def draw(self):
      pyxel.cls(0)
      
      for s in range(len(self.str_list)):
          
          pyxel.text(20, 10 + 10 * s, str(self.str_list[s]), s + 1)
      
APP()

lenと併せて使うと解決できます。lenはリストの中身が何個あるかを教えてくれるもの(リストに限らず色々なものを対象にできますがここでは割愛)。
「range(len(self.str_list))」と指定することで中身が9個なら「range(9)」と同じになり、5個なら「range(5)」となります。

▲str_listの中身を増やしてもきちんと表示されます。
▲もちろん減らしても大丈夫。

このようにしておけば変数部分の修正がほかの場所に与える影響を減らすことができます。何より「range(8)」のような数字決め打ちだと後で「この8は何の数だっけ?」となるので、こちらのやり方がお勧めです。

# -*- coding: utf-8 -*-

import pyxel

class APP:
  def __init__(self):
      pyxel.init(128, 128, title="pyxel")
      
      self.speed = [4, 4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5,]
      
      self.pos = [120, 120, 120, 120, 120, 120, 120, 120, 120, 120, ]
      
      self.start = False
      
      pyxel.run(self.update, self.draw)
     
  def update(self):
      if pyxel.btnp(pyxel.KEY_S):
          self.start = True
          
      if pyxel.btnp(pyxel.KEY_R):
          self.pos = [120, 120, 120, 120, 120, 120, 120, 120, 120, 120, ]      
          self.start = False
          
      if self.start == True:
          for p in range(len(self.pos)):
              self.pos[p] -= self.speed[p]
   
  def draw(self):
      pyxel.cls(0)
      
      for i in range(len(self.pos)):
          pyxel.rectb(5 + 12 * i, self.pos[i], 5, 5, i + 2)
      
APP()

▲さてfor文を使ったへんてこプログラムを1つ作ってみました。Sキーを押すとself.speedで指定した速さで四角が進んでいきます。Rキーでリセット。

▲実行するとこんな感じ。0.5刻みですが結構差が出ています。

内容は単純でforの繰り返しを使って座標を計算しているだけです。
でもシューティングゲームの弾とか敵の処理に使えそうな感じもなくもないかも…?
speedの値を変えると進む速さも変わります。

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

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