Pythonのクラスを習得した記念にゲームを作る


はじめに

初学者を脱しつつある者を襲う贅沢な悩み

クラスについて学ぼうと多くの解説サイトを訪れたが、ほとんどの解説サイトは私を満足させなかった。
Flaskの学習をしたときも同様だった。Pythonを一から学ぶ人向けの教材ならともかくFlaskやクラスを学ぼうとしている人にHello worldレベルのプログラムを見せられても物足りなさを感じてしまうのは当然のことだ。
何とかしっくり来たのはこちらの個人サイトだった。

クラスの利便性に気付く

夏休みの自由研究としてディープラーニングを駆使したアプリを作った。仕様を充実させていくにつれ関数に送る引数がどんどん増えていき、収拾がつかなくなってしまった。複数の変数を一つの辞書に登録することも考えたが、どうも違う。こんなとき先達たちはどうしていただろうか。

そう考えて思い出したのがクラスだった。

九割方できていたコードをほとんど見直すことになってしまいそちらの完成は延期となった。そのかわりクラスを意識したちょっとしたプログラムをゼロから作った。

クラスの実装と改良

作ったゲームはこんな感じ。なぜこんなのを作ったかは今となってはわからない。
最初は「ちょっとしたプログラム」だから隕石なんて赤丸でいいじゃんと思っていたのだが、スプライト関数を自作しておいてそれを使わないなんてとんでもない!とどんどん凝っていってしまった。

game_anim.gif

改善前

最初はスコープの扱いがよくわからず、次のようなグローバル変数頼みのコードを書いていた。

before
class Game():
    def __init__(self):
        BeamとMeteorを扱うのでクラス内でグローバル変数beamとmeteorsが使われている 

class Beam():
    def __init__(self):
        GameとMeteorを扱うのでクラス内でグローバル変数gameとmeteorsが使われている

class Meteor():
    def __init__(self):
        Gameを扱うのでクラス内でグローバル変数gameが使われている

def main():
    ループ内で
        meteors.append(Meteor())
        など

# ここ、グローバル
game = Game()
beam = Beam()
meteors = []

if __name__ == "__main__":
    main()

改善後

だが、それでは駄目だと考え直し、次のように作り直した。これによりグローバル変数を使うことなく、またクラス間の主従関係(?)もわかりやすくなった。
ここに至るまでに4~5回は全体的なコードを書き直している。これもまた経験だ。

after
class Game():
    def __init__(self):
        self.meteors = []
        self.beam = Beam(self)

class Beam():
    def __init__(self, game):
        

class Meteor():
    def __init__(self, game):
        

def main():
    game = Game()
    ループ内で
        game.meteors.append(Meteor(game))
        など

if __name__ == "__main__":
    main()

もう一つの課題

きれいなコードを書きGitHubに公開することも夏休みの課題の一つだった。だから今回はいろいろがんばったのだが、肝心のGitHubへのコミットがうまくいかなかった。もう一度一から勉強しなおさなくては。
無理やっこアップロードしたのがこちら。

終わりに

「ちょっとしたプログラム」に1か月以上かかってしまった。夏休みに作っていたメインの作品の完成はいつになるのだろう。