Pyxel学習日記(4日目)

今日は物をランダムに複数落下させるコードを勉強した。
物を落下させるクラスをつくって、そのクラスからつくられたオブジェクトをそれぞれ落ちてくる1つ1つの
物として扱うと実装しやすい。落下するものを入れ子にするイメージかな?
今回はクラスとコピーメソッドが新しく出てきたので、それも勉強しないといけない。

今日書いたコード

結果:物をランダムに複数落下させる

import pyxel

SCREEN_WIDTH = 160
SCREEN_HEIGHT = 120
STONE_INTERVAL = 30

class Stone:
    def __init__(self, x, y): #座標を表すxとyというインスタンス変数
        self.x = x
        self.y = y

    def update(self):
        if self.y < SCREEN_HEIGHT:
            self.y += 1

    def draw(self):
        pyxel.blt(self.x, self.y, 0, 8, 0, 8, 8, pyxel.COLOR_BLACK)
class App:
    def __init__(self): #イニシャライザー。初期化関数。初期設定を書く
        pyxel.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="はじめてのゲーム") #ゲーム画面の幅と高さとタイトル
        pyxel.mouse(True)
        pyxel.load("my_resource.pyxres") #リソースを読み込む
        self.player_x = SCREEN_WIDTH // 2 #プレイヤーのX座標のデフォルト値
        self.player_y = SCREEN_HEIGHT * 4 // 5
        self.stones = []
        self.is_collision = False
        pyxel.run(self.update, self.draw)

    def update(self): #フレーム更新時に呼び出される処理
        if pyxel.btnp(pyxel.KEY_ESCAPE): #quit関数でesc押下で終了する処理。btnはおされつづけてる、btnpは押した瞬間
            pyxel.quit()

        #プレイヤーが右をおした時。ただし条件として画面の幅より12小さい時
        if pyxel.btn(pyxel.KEY_RIGHT) and self.player_x < SCREEN_WIDTH - 12:
            self.player_x += 1

        #プレイヤーが左をおした時。ただし条件として画面の幅より4大きい時:
        elif pyxel.btn(pyxel.KEY_LEFT) and self.player_x > - 4:
            self.player_x -= 1

        if pyxel.frame_count % STONE_INTERVAL == 0: #pyxel.frame_countは経過フレーム数が(自動)で格納されている
            self.stones.append(Stone(pyxel.rndi(0, SCREEN_WIDTH -8), 0)) #rndiの引数は最小と最大

        #物の落下
        for stone in self.stones.copy():
            stone.update()

            #衝突
            if (self.player_x <= stone.x <= self.player_x + 8 and
                self.player_y <= stone.y <= self.player_y + 8):
                self.is_collision = True

            #画面外に出た物を削除
            if stone.y >= SCREEN_HEIGHT:
                self.stones.remove(stone)

    def draw(self): #描画処理
        pyxel.cls(pyxel.COLOR_DARK_BLUE) #画面を特定の色でクリアするための関数

        for stone in self.stones:
            stone.draw()

        pyxel.blt(self.player_x, self.player_y, 0, 16, 0, 16, 16, pyxel.COLOR_BLACK) #プレイヤー
        #ユーザーからの操作で状態が変化するような値はインスタンス変数として扱い、updateでもdrawでも扱えるようにする

        if self.is_collision:
            pyxel.text(SCREEN_WIDTH // 2 - 20, SCREEN_HEIGHT // 2,
                       "Game Over", pyxel.COLOR_YELLOW)

App() #オブジェクト化