こんにちは!
ブログ”はやぶさの技術ノート”のマスコットキャラクターもやってるよー☆
そーいえば、最近”はやぶー”@Cpp_Learningの書く記事が真面目過ぎると思いません?
コレとか↓
コレとか↓
こんなんも↓
…じゃなかった!つい本音が!!
昔は”くるる”が主人公な感じの記事も書いてくれてたのに…
コレとか↓
コレとか↓
こんなんも↓
最高かよ(*・ω・)ノ♪
だから”はやぶー”がいない間に、こっそり楽しい記事書くことにした!笑
『pythonでゲーム作りまーす!!』
作り方書いてくねー
以降からオブジェクト指向に関する長ーーーい説明をするので、サクッとゲームのコードを見たい人は目次から「ゲームソフト”Kururu_Game”リリース!」に飛んで下さいね。
Contents
読みやすいソースコードとは?
以下の記事で”はやぶー”が言ってたけど…
じゃあ『読み手のことを想って書いたソースコード』も正解だよね!
ってわけじゃないよね!
オブジェクト指向よく分からないけど、読みやすいソースコードを書こーっと!
作りたいゲームのジャンル
うーん。。
読みやすいソフトウェア設計とかソースコードとか後回しする!笑
まずは作りたいゲームを決めよーっと!
”はやぶー”がロックマンが好きって東京ゲームショー帰りに言ってたな…
つまり、ビームを出して敵を倒しながら進む”アクションゲーム”だね!
アクションゲーム作って”はやぶー”に喜んでもらうよー(*・ω・)ノ♪
勉強すること自体を目標にするより「誰かのため/自分のために何かをやり遂げたい!そのためには勉強しないと!」という考え方が好きだし、挫折しにくいかなーと思ってます。
作成ゲームのイメージと名詞抽出
そもそもゲームって”どんな素材(部品)”があれば作れるのかな?
はっ!そーいえば、”はやぶー”が…
って言ってた!!
ってことか!!歌いながら楽しく『名詞抽出』してみよーっと
作りたいゲームのイメージと『名詞抽出』↓
【抽出した名詞リスト】
- マップ
- ブロック
- 主人公キャラ(くるる)
- 敵キャラ(パイソンくん)
- ショット
- 階段
そーいえば…
って”はやぶー”が言ってたけど抜け漏れはないかな?
うーーーーん。。。
ゲームに限らず作りたいソフト(システム)の全体像が決まったら、あらゆるモノの名前を抽出することが、オブジェクト指向の第1歩です。この時点でクラスを意識する必要はなく、とにかく目に付くもの全ての名前を抽出してください。
オブジェクト図
なんか『名詞抽出』した情報を整理したいな…
って言ってた!つまり、図を描けば良いよね!
オブジェクト図とゲームシナリオ
【抽出した名詞リスト】で”❻階段”って書いたけど…図を描いてみて「階段」=「ブロックの集合体」ってことが分かったから「階段」って名詞はなくした!
あと今回つくるゲームを”Kururu_Game”と名付けたよ!
以上を踏まえて図を描くと…こんな感じ↓
「敵やブロックがいっぱい存在する」ことを「○○_A~○○_Z」と表現をしてみたよ!
次に、関連のある名詞を線で結んでみた!
ショットは”くるる”しか出せないようにした!あと”マップ”は”ゲームの世界”というイメージで…
- マップを構成するブロック
- マップから湧いて出てくる敵キャラ
- マップに召喚された主人公キャラ
って感じ!!
関連を考えると同時にゲームシナリオも考えてみたよ↓
”Kururu_Game”が世界(”マップ”)を創造するとき…
世界のあちこちで”魔物”が誕生し、世界に危機が訪れる!
この危機を何とかするため、世界は救世主”くるる”を異世界から召喚する!
”くるる”は得意技”ショット”で全ての魔物を倒し、世界を平和にできるのか?
”くるる”の壮絶な冒険が始まろうとしていた…
関連をそのままシナリオにした感じ!もしくはシナリオをそのまま関連にした感じ!
フクロウ卵(ニワトリ卵)な関係ってやつ!
リリースはよー
↑で作成したものが「オブジェクト図」と呼ばれるものです。「オブジェクト図」の関連に「集約」・「部品」・「汎化」まで考慮して描く人もいますが、個人的には「オブジェクト図」はクラス図の設計図(設計図の設計図)だと考えているので、関連などをラフに描いています。
クラス図
次は何をするんだっけ??
って”はやぶー”が言ってたな!
”クラス”って設計図のイメージらしいよー↓
- オブジェクトのクラス(設計図)を生成
- クラス(設計図)からモノ(インスタンス)を生成
ゲームを構成するオブジェクトの名詞(部品)まで考えたので…
シンプルに考えると…ブロックや敵キャラなど「○○_A~○○_Z」と表現したオブジェクトは1つのクラス©から生成することができるね♪(クラスには©が付いてます↓)
(もちろん1つのクラス©から1つのインスタンスだけを生成する場合もあるよー)
ただし、クラス(クラス名)を考えるときは以下のポイントがあるよ!
- 抽象化
- 部品化(モジュール化)
- 分かりやすさ(メンテナンス性)
抽象化とは
「抽象的」の反対が「具体的」なので…鳥だとこんな感じ↓
オブジェクト指向とか、クラスを考えるとき
という人がいる!抽象度の高いクラスを作るって、こういうこと↓
鳥の特徴を内包してる”鳥クラス”からは”様々な種類の鳥”を生成することができるよー
また、”鳥クラス”をベースに”猛禽類”専用の設計図”猛禽クラス”を作れば、”くるる”作り放題!
ん?大事なことを忘れているような…
『読み手のことを想ってUML(ソフトウェア設計図)を書くのが正解』
抽象化のメリット・デメリット/部品化/メンテナンス性も確認してからクラスを考えよーっと
抽象化のメリット・デメリット
この前”はやぶー”が抽象化のメリット・デメリットをクッキー作りで例えてくれたよ!
子供たちが色んな形のクッキーを食べたい!と考えていたとする…
丸いクッキー型で大きめの丸いクッキーを作って、後から加工すれば、色んな形のクッキーができます!ただし、加工には手間がかかります!
一方、子供たちが星形のクッキーを食べたい!と考えていたとする…
星形のクッキー型を使えば簡単に★クッキーを作ることができます!ただし、星形から他の形を作ることは出来ません!
ゲームの話に戻すと…『主人公キャラ』と『敵キャラ』がいるよね?
抽象度の高い『Characterクラス』を親クラスとして、子クラスの『主人公キャラ(くるる)クラス』と『敵クラス』を生成する!という考え方もあれば…
『主人公キャラ(くるる)クラス』と『敵クラス』では責務が全然違うので、親を持たないクラスにして、コードの冗長化を回避する!という考え方もできるよー
部品化(モジュール化)-共有部品-
親クラスとか子クラスとか…
抽象度とか…
良い/悪いはない…って言われても判断基準は欲しいよね(*・ω・)ノ♪
さっきは『抽象化』からクラスを考えてみたけど…今度は『部品化(モジュール化)』からクラスを考えてみるよー
復習!クラスは設計図で、そのクラスからインスタンスが生成できる↓
このクラスを別のソフトで使い回すことを考えてみる!
例えば、全ての鳥に共通する部分(特徴)を考えて…
【全ての鳥に共通する部分】
- 身長/体重などのサイズ情報(パラメータ※1)
- 歩くスピード/鳴き声パターン/音量などの個体値(パラメータ※1)
- 歩く/鳴くなどの行動(処理※2)
※1:クラスでいう属性(プロパティ)
※2:クラスでいう操作(メソッド)
↑の情報が書かれた設計図からは、個体差などを考慮してパラメータを設定すれば様々な種類の鳥インスタンスを生成できるね!
あれれー?おかしいぞー?
ってことに気が付いてた?
抽象度を高くして”ニワトリ”や”アヒル”にも共通する鳥の特徴のみを書いたから”飛ぶ”に関する情報がないのだー
”飛べない鳥”のインスタンスを生成するのに↑の親クラスが使えるし、親クラスの情報を継承して”飛ぶ”情報を追加した子クラスを作成すれば”飛ぶ鳥”のインスタンスも作れる!
つまり『抽象度の高い”鳥”クラス』は「”飛べない鳥”を生成したいソフト」と「”飛べる鳥”を生成したいソフト」両方の『共有部品』になれるのだー
抽象度の高いクラスは汎用性も高いので、様々なソフトに採用することができます!『相手を想って様々なところで使える”共有部品”を作りたい!』と考えるのは素敵なことです!
部品化(モジュール化) -専用部品-
クッキー型は丸い方が良い!共有部品を作りたい!という設計思想すごく良い(*・ω・)ノ♪
ただ、”Kururu_Game”の続編”Kururu_Game2”など”飛べる鳥”…より正確には”猛禽類”しか出てこないソフト(ゲーム)ばかり作るなら…
- 猛禽類クラス(猛禽類インスタンスの生成用クラス)
- さらに特化した”くるる”専用クラス
があった方が便利!毎回、親クラスから子クラス生成して…とかやるのは時間がかかる!!
つまり『抽象度の低い”専用”クラス』は、短いシンプルなコードで専用インスタンスを生成できるので、使いやすい『専用部品』になれるのだー
ちなみに”はやぶー”は…
って言ってた!笑
なので、今回は親クラスを持たないシンプルな以下の構造(クラス図)を採用するよー
繰り返すけど…
『読み手のことを想ってUML(ソフトウェア設計図)を書くのが正解』だよ
抽象度の低いクラスは専門性が高いので、簡単に専用インスタンスを生成できます!汎用性は低いですが、同じジャンルのソフトで採用できる場合も多いです。『相手を想ってシンプルかつ便利な”専用部品”を作りたい!』と考えるのは素敵なことです!
分かりやすさ(メンテナンス性)
ソースコードの分かりやすさ(メンテナンス性)って色んな説明があるけど、今回はクラスの命名に焦点を当てて説明するよー
最初に『名詞抽出』しながらオブジェクト図を作成したよね?
「目に見えるもの」や「名前のあるもの」は、そのままオブジェクトとして考えられるけど…
と考えている人いますか?正解!ただし、以下の条件があると考えてみて!
【空を飛ぶ条件】
- ”くるる”はレベル3以上じゃないと空を飛べない
- アイテムを手に入れないと空を飛べない
- お腹が空いてると飛べない
さらにロボットの仲間キャラが登場して、そのロボットも『空を飛ぶ』ことができるとしたら?
『空を飛ぶ』という部分を『共有部品』にできると良いよね?
関数でも良いけど…ある条件で『飛べなくなる』⇒『飛ぶ系インスタンス』の破棄と考えることもできる!
ただし「飛ぶ」は動詞なので、オブジェクト指向の考え方…
つまり『オブジェクト(名詞)からクラス(部品)を考える!』
というコンセプトが崩れちゃう!
飛ぶ⇒部品⇒名詞にしたい⇒『飛行能力クラス』
とすれば、鳥でもロボットでも使える”抽象度の高い”共有部品にもなります!
クラス名を”いい加減”に付けると、どんな部品になるか分からなくなります。
クラス名だけ見てみて、どんな部品か把握できるのが理想的だよ♪
↑の図は”はやぶー”に教えてもらった理想のソフトウェアデザインだよ(*・ω・)ノ♪
つまり、レゴブロックみたいに部品の組み合わせでソフト開発をするのが理想的だって!
ソフトにバグが発生したとき、部品化(クラス化)できていれば、その部品のコードのみを修正すれば良いよ!
完全に独立した部品になっていれば、分散開発もできる!!
さらに、前回作った部品を別のソフトに使い回すことができる!!!
良いクラス名を考えて、部品化(クラス化)できれば、メンテナンス性の高いソフトウェアを開発できる!
適切なクラス名を考え、コードを部品化できれば、ソフトウェアのメンテナンス性が向上します!理想は上記したレゴブロックのようなソフトウェア設計!『相手を想って分かりやすい部品(部品名)を作りたい!』と考えるのは素敵なことです!
クラスの責務
ソフトウェア構造(クラス図)の骨格が決まったので↓
と”はやぶー”が言ってた!「必要ならオブジェクト図に戻っても良い」とも言ってたよ!
『”くるる”が果たすべき役割』⇒『世界を救う』⇒『そのために必要な属性と操作を考える』
ってことは”くるる”クラスはこんな感じかな?
【属性】
- 体力
- すばやさ
- 攻撃力
【操作】
- ■火を吐く
- ■歩く
- ●ショットを出す
- ●空を飛ぶ
【備考】
■は”くるる”だけが使える操作で、●は”くるる”インスタンスを生成できるれば、簡単に使える操作だよ!また、体力が無くなると空を飛べなくなるようにしたよ!(内緒だけど、くるる長い距離飛ぶの苦手なの…)
「ショットを出す」や「空を飛ぶ」という操作は『共有部品』にしてみた!
”はやぶさ”のいない間に、こっそり記事を書く!という当初の予定は、ここにきて完全に崩壊する!笑
でも問題なし!!
ソフトウェアの設計~実装まで、どうしても一人で実施しないといけない現場もあります。。でも、メンター等の頼れる人がいるなら、遠慮なく頼って良いよ!!どんな質問をしても良いよ!ただ、今回の”くるる”ちゃんみたいに、具体的な内容だとアドバイスしやすいね(*・ω・)ノ♪
クラスの責務 -添削結果-
”くるる”ちゃんからクラスの添削依頼が!ポイントは…
だよ!先に私が修正してクラス図を紹介するね↓
属性について
まずは属性から…
とのこと…すごくプリチーで良いと思う!ただ、体力がミスリードになってたかも!
例えば『飛ぶ』を『連続ジャンプ(空中でもジャンプ可)』として、ジャンプ回数やジャンプ力に制約を持たせれば、『体力が無くて飛べない』を表現できる!(体力という表現だとパラメータの設定に悩んじゃうね)
『すばやさ』はもっと具体的に『移動速度』としても良かったと思う!
また『攻撃力』の情報は”くるる”ではなく、”ショット”クラスや”敵”クラスが何回まで攻撃に耐えられるか?というHPで表現しても良かったと思う!
ショットの『攻撃力』=『敵を貫通』とかね!
あとは、”くるる”クラスに限らず『位置(座標)』や『状態(何かに衝突している)』の情報は必要だったと思うよ!
操作について
というのは、相手を想って考えているので、非常に良いね!!
ただ、責務を忘れてないかな?
そんな”くるる”のインスタンスを気軽に生成して良いのかな?
『飛ぶ』については、飛ぶ系の責務をもつ『飛行能力クラス』でも良かったと思うし…『飛ぶ』がフクロウ”くるる”のアイデンティティなら、いっその事 『飛ぶ』という操作を公開しないのも良いと思う!
”ショット”については、オブジェクトがあるので、当然クラスもあるはず!
”ショット”の責務が『前方に飛んで、衝突する対象次第で状態が変化する』だとすると↓
- ”ショット”が”ブロック”と衝突⇒”ショット”インスタンス消滅
- ”ショット”が”敵”と衝突⇒貫通(”敵”インスタンス消滅)
などが考えられる!
なので、”くるる”は”ショット”インスタンスを生成すれば、あとは”ショット”が責務に従い勝手に前方に飛んでいき敵を倒してくれる。
上記を「ショットを出す」という操作で表現しても良いし、単に「”ショット”インスタンス生成」と考えることもできる。(インスタンス生成自体は操作に現れてこない)
”くるる”の責務について
『”くるる”の責務は世界を救うこと』という考え方は、すごく良かったと思う!
ただ『世界を救うのはプレイヤーで”くるる”はプレイヤーの指示に従う勇敢な戦士』という考え方もできる!
考え方が変われば、オブジェクト図や責務が変わり、責務が変われば「属性」・「操作」が変わります…難しいねー
また、操作に『火を吐く』とあるけど、きっと責務から連想して考えたんだと思う!そのこと自体はOK!
ただし『雷を出す』・『瞬間移動できる』・『時間を止める』など他にも様々な必殺技(?)の操作を追記したとすると…
操作や属性が多いクラスは『ファット(太った)クラス』と呼ばれています。
また、それらの操作を公開して『共有部品化』すると…
”くるる”クラスが『何でもできる便利ツール』になってしまい、あらゆるクラスと関連を持つ『神様クラス』みたいになってしまいます!
という考え方(設計思想)もあるため、一方的に否定はできませんが…
経験上『ファットクラス』や『神様クラス』の存在するソフトはメンテナンス性が低いです。
それに『世界を救う』が責務だったはずなのに『必殺技が出せる便利なツール』になるのは「責務が違う」あるいは「責務を複数もち過ぎ」と考えられます。
『世界を救う』という抽象的かつ大きい責務でも”ショット”クラスなどを検討することで、クラスとディベロッパーの負担を軽くすることができます。(仮に『神クラス』があったとしてチームの誰が作るかでケンカになりそう…!)
抽象化/部品化/メンテナンス性/責務を考慮して、下記のような理想的なソフトウェアを開発しましょう!
クラス図完成
あーでもない!こーでもない!と言いながら…ついにクラス図が完成したよー
で!いざ実装に入ると…
などの問題は多かれ少なかれ出てきます!その都度チームメンバーで話し合って、みんなが納得の使いやすいor開発しやすいソフトウェアになってるのが理想的です!
今回もクラス図(設計図)とソースコードで一部乖離しています…ただ、致命的ではないので、特に修正はしません。。設計フェーズと実装フェーズで何かあったんだろうなーっと想像してみてください!笑
チームでソフトウェア設計をするときや、誰かのソフトウェア設計図を見る機会があったら…
という考えは常に持っていてくださいね!自分が納得する理想的なソフトウェア設計およびソフトウェア開発を目指しましょう!
ゲームソフト”Kururu_Game”リリース!
パタパタ
そう言い残して”くるる”ちゃんは飛んでいってしまった!
”くるる”ちゃんが頑張って設計したソフトを実装してみますか!
下記の記事でも紹介しているけど…
まずはサンプルソースなど参考になりそうな資料を調査します!
今回は、以下の記事とGitHubのソースコードが大変参考になりました!感謝!!
横スクロールアクションのソフトmap_scrollが丁寧にクラスも作りこんでいたので、そのクラス(部品)を再利用し、足りないクラス(部品)は新規作成してソフトを完成させました!
まさにこんな感じ↓
”はやぶさ”の技術ノート
いつもなら、ソースコードの解説もするのですが、上記した参考資料がPythonのゲーム用ライブラリPygameの使い方も丁寧に説明しているので…
ということで、いきなりソースコードを紹介↓
map_scrollがベースソフトなので、分からないときはmap_scrollを参考にしてみてね!
プレイ動画はこちら↓
まとめ
色々書いたけど、結局伝わったのは『オブジェクト指向は難しい!』ってことだけだったりして(?)
私の力不足/説明不足な部分はあったと思いますが、実践的にソフトウェア設計を学べる記事に仕上げたつもりです。(この記事書くの本当に大変でした( ;∀;))
ソフトウェア設計は色んな”設計思想”があるから難しいけど、本記事で伝えたかったことは…
『読み手のことを想ってUML(ソフトウェア設計図)を書くのが正解』
という一言に尽きます!
そして、私が理想とするソフトウェア開発とは…
『抽象化/部品化/メンテナンス性/責務を考慮して、下記のような理想的なソフトウェアを開発しましょう!』
です!!
ただし、「これが絶対に正しい!」とかいう気は全くありません!あくまで私の理想であり思想です!
『あなたの理想的なソフトウェア設計思想は何ですか?』
本記事をきっかけに考えてみませんか?
本記事が少しでもソフトウェア設計の勉強に役立つと大変嬉しいなぁ
(完)