同人ゲームやフリーゲームはもちろん、ゲームデザイナーを目指す人、これからゲームを作りたい人、今もゲームを作っているがなかなかうまくいかない人向けの、ゲーム開発に関するブログ。
2024/11/21 (Thu)
[PR]
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
2016/06/10 (Fri)
オブジェクト指向、私の解釈と説明
ゲームに限らずプログラミングに触れるようになると必ず「オブジェクト指向」という単語を耳にします。どうやら便利な物らしいという事で調べると、良くわからない解説やたとえ話にぶつかって結局全く理解できないって言う経験、多分あるあるだと思います。
wikipediaだとこう書かれています。
……日本語でおk
オブジェクト指向に限った話でもないのですが、プログラムの用語を調べると良く数式に遭遇することがあり、そんな物は求めていないと毎回感じてたりします。説明不足を指摘するプレイヤーが求めているのは説明ではない説と全く同じで、使い方を求めているんであって、説明は求めていない訳ですね。
だがしかし、使い方の実例と言う物はこれまた少なく、出てきたとしてもソースコードでして。違うそうじゃない。
と言う訳でない物は作れ。カス子で培ったフロンティアスピリッツで、間違えていると言う指摘覚悟で自分なりの理解を、整理もかねて記述したいと思います。間違ってると思った方は、より間違ってないであろう説明をご自身の手で作ってもらえれば幸いです。
オブジェクト指向を理解するには、同じ挙動をするものでオブジェクト指向のものとそうでないものを見比べると良いと思います。と言う訳で例題。
例題1:面構成
ツクールでアクションゲームを作った。この時各面の遷移をどう管理するか。全8面。用意したMAPも8つ。検討した結果、以下のようなものにしようと考えた。
ぱっと思いつくのは、適当な変数、便宜上「面構成配列」としますが、この面構成配列に[6,8,1,2,10,9,4,2]と配列を代入するものです。
式
面構成配列 = [6,8,1,2,10,9,4,3]
これはオブジェクト指向でしょうか、それともオブジェクト指向とは違うスパゲティコード予備軍でしょうか?
自分の理解では、面構成配列に配列を代入したものはオブジェクト指向ではありません。オブジェクト指向の場合はどう記述するかというと以下のように設定します。
次の面のIDを各マップのメモ欄辺りに記述して、クリア時にこいつを読み込むという手法を取ります。
処理の違いを見てみましょう。例えばゲームクリアをした際、面構成配列を採用した場合は以下の物が必要となります。
次の面ID = 面構成配列[クリア面数]
要するに、クリア面数を代入している変数が新たに必要となります。対してオブジェクト指向だとこうなります。
次の面ID = 次の面ID@メモ欄
クリア面数を代入している一行が削れただけですが、意外にこの一行がエラーの元になっていたりします。
さて、ここでステージの構成を入れ替える事になったとしましょう。4面と8面を入れ替える事になりました。どうするか。配列の数字を入れ替えるだけですね。
式
面構成配列 = [6,8,1,3,10,9,4,2]
こういう場合は、オブジェクト指向よりも面構成配列を採用したほうが数が少ないから、まだぱっと解ります。ですが、もっと増えたらどうでしょう?
また、テストプレイ中に今触っている面のIDが何番かというのは判断しづらく、難易度が高いからこの面は入れ替えようとなった際にはまずマップ画面を探すはずです。オブジェクト指向を採用していた際、マップ画面はその画面を開いているのでメモ欄に次のステージを新たな物に書き換え、前のステージなどを変更すればよいのですが、配列を使ていた場合、IDを見直す手間が発生します。視覚的に解りにくいんですね。
面構成配列を採用していた場合はもう一つ、どこにその変数を用意したか探すのが面倒になる場合が有ります。また修正中にカンマを間違えて消してしまったり、気が付いたらステージ数が7になっていたりという事も発生します。そういった凡ミスをオブジェクト指向は防ぐことが出来ます。
もちろん、オブジェクト指向でも凡ミスは発生します。ステージのつながりがおかしかったりエラーで終了したりもします。が、問題は今、その時プレイしていたステージにあるため、エラーの出たMAPIDの把握という工数が一つ減ります。
まだ面構成の話なので、オブジェクト指向の便利さと言う物はこの文章では伝わりにくいと思います。オブジェクト指向がどういう物なのかについては何となく伝わったら嬉しいです。
要は、極力一括で管理しないで、出来るだけオブジェクト単位、アイコンだったり、キャラクターだったりに設定を持たせましょう、というのがオブジェクト指向という理解です。
例題2:装備に応じて立ちグラフィックを変更する
装備品によって立ちグラフィックが変化するゲームです。まぁエロ同人ではド定番ですし、3Dグラフィックを使うゲームでも定番の機能です。これをどう処理して実装するか、何も考えずに作るとしたらこうなります。
if アクター1が、頭部にヘルメットを装備しているとき、ピクチャ4に「ヘルメット装備画像」を表示
if アクター1が、頭部に帽子を装備しているとき、ピクチャ4に「帽子装備画像」を表示
if ・
if ・
if ・
if アクター1が、武器に弓を装備しているとき、ピクチャ5に「弓装備画像」を表示
と、条件式を作って、全てのパターンを用意すると言うものです。単純作業で量も多いが実装は不可能ではありません。もちろん、これはオブジェクト指向ではありません。
オブジェクト指向ではどうするかというと、アクターに以下のように設定していきます。(うちで提供しているRPGツクール VX aceの汎用タグスクリプトを使用した前提です)
<立ち:ヘルメット "ヘルメット装備画像">
<立ち:帽子 "帽子装備画像">
・
・
・
<立ち:弓 "弓装備画像">
そして、立ち画像を表示する際にはこのように実装します。
アクター1の頭部の装備を確認
⇒アクターのメモ欄から<立ち:装備品 "画像">を取得して対応するものを表示。
ざっくり解説しますと、条件式を一切合切カットしています。ソースコードがすっきりするのはもちろんですが、単純に条件式のみで実装した場合、ピクチャ番号を間違える場合があります。また、数が増えれば増えるほどソースコードは長くなり、間違えた場所を探すのが難しくなります。
対してオブジェクト指向であれば、少なくともピクチャ番号が装備部位では統一される。間違えたとしても、特定の装備だけ間違えるという事はありません。その場合、5か6行のなかから一つを修正してやれば修正が完了します。
デバッグも1つの装備がきちんと表示されれば、ファイル名の間違いが無い限りはきちんと表示されるためいちいち全部を確認する必要がありません。(後々あらためて一通り確認はするべきですが)
例えば弓を装備した際にエラーが発生したのであれば、 <立ち:弓 "弓装備画像">が間違っているか、保存しているファイル名が間違っているのかのどちらかで、原因の特定が楽です。
例題ではアクターは一人でしたが、実際に作られるゲームでは2,3人、多ければもっと増えるでしょう。実際自分のように人員整理が上手く出来なければ20何人という事も有ります。(RAVAGE)
全員分の着せ替えを条件式で作っていくとなると、装備品が各5種類、部位が5か所アクター3人としても、条件式は75行必要となります。一行に1分かかったとしても一時間以上かかる計算です。この単純作業に耐えられるかどうかという問題と同時に、どこか間違えたとき、75行から探さなければならず、この修正作業がまた時間がかかってしまいます。メンテナンスのしにくさ、という意味でも条件式のみで作るよりは、オブジェクト指向で作成したほうが楽です。
SAVAGEがちょうど過渡期でして、オブジェクト指向ではない物からオブジェクト指向へと処理を変更していっている所なので、実例としてこんなことをしてました。
例題3:特定のアイテムを所有している場合にイベントが有る、という通知を行う
SAVAGEでは特定の拠点を解放した際、特定のカードを持っていると掛け合いのイベントが発生するようになっています。イベントが発生している場合、フキダシアイコンを表示させているのですが、この管理をコモンイベントで行っていました。
まず、所持しているアイテムをチェックして該当するものが有れば「イベントがあるかもスイッチ」をonにしています。
つづいて、有るかもスイッチがonの時、実際に該当するイベントを精査して、どの一度も発生していないイベントが一つでもあれば、通知をonにし、発生通知がonの時、特定の拠点にフキダシを表示させています。
実際にフラグが立てれるかをチェックして
フラグが立っていたら吹き出しを表示
こういう処理の仕方をしていると、イベントの新規追加が難しくなります。なので、次はこういう風に変更してみました。
すごくスッキリしてます。
見比べてみて欲しいのですが、コモンイベントを3つまたいでいたものがわずか3つの命令で済んでいます。ややこしい条件式も要らないし、なによりもイベントの追加がこれによって非常に容易になりました。
追加のしやすさ、メンテナンスのしやすさがオブジェクト指向を採用する利点で、規模が大きくなればなるほどその恩恵は大きくなります。
もちろん、オブジェクト指向はいくつかのデータを効率よく扱うために検討と設計が必要なので、小規模なもの、例えば3つ4つの分岐程度であれば、オブジェクト指向で組んだ方が時間の無駄になる可能性も有ります。
よって、無暗に最初からオブジェクト指向を視野に入れず、条件式だけでぱぱっと組んでしまっていいと思います。同じ処理を何度も繰り返したり、数が多くて面倒になりそうだ、という場合は今組んだ条件式から省けそうな物を省くにはどうしたらいいだろうか、と検討してみて実装していくと言う手順が学習の流れとしては良いと思います。
以上、自分なりのオブジェクト指向の解釈をでした。株式会社とかの例を出されるよりかは解りやすいんじゃないかと個人的には思います。もし違和感を感じたら各自で解説を作ってみてもらいたいです。色んな例えが有った方が解りやすいと思いますので。理解の一助になれば幸いです。
wikipediaだとこう書かれています。
オブジェクト指向プログラミングとは、オブジェクトと呼ばれる機能の部品でソフトウェアを構成させるものであり、一般的に以下の機能や特徴を活用したプログラミング技法のことをいう。
……日本語でおk
オブジェクト指向に限った話でもないのですが、プログラムの用語を調べると良く数式に遭遇することがあり、そんな物は求めていないと毎回感じてたりします。説明不足を指摘するプレイヤーが求めているのは説明ではない説と全く同じで、使い方を求めているんであって、説明は求めていない訳ですね。
だがしかし、使い方の実例と言う物はこれまた少なく、出てきたとしてもソースコードでして。違うそうじゃない。
と言う訳でない物は作れ。カス子で培ったフロンティアスピリッツで、間違えていると言う指摘覚悟で自分なりの理解を、整理もかねて記述したいと思います。間違ってると思った方は、より間違ってないであろう説明をご自身の手で作ってもらえれば幸いです。
オブジェクト指向とそうでない物
オブジェクト指向を理解するには、同じ挙動をするものでオブジェクト指向のものとそうでないものを見比べると良いと思います。と言う訳で例題。
例題1:面構成
ツクールでアクションゲームを作った。この時各面の遷移をどう管理するか。全8面。用意したMAPも8つ。検討した結果、以下のようなものにしようと考えた。
面 | マップID |
1 | 6 |
2 | 8 |
3 | 1 |
4 | 2 |
5 | 10 |
6 | 9 |
7 | 4 |
8 | 3 |
ぱっと思いつくのは、適当な変数、便宜上「面構成配列」としますが、この面構成配列に[6,8,1,2,10,9,4,2]と配列を代入するものです。
式
面構成配列 = [6,8,1,2,10,9,4,3]
これはオブジェクト指向でしょうか、それともオブジェクト指向とは違うスパゲティコード予備軍でしょうか?
自分の理解では、面構成配列に配列を代入したものはオブジェクト指向ではありません。オブジェクト指向の場合はどう記述するかというと以下のように設定します。
マップID | 次の面ID@メモ欄 |
1 | 2 |
2 | 10 |
3 | 0 |
4 | 3 |
6 | 8 |
8 | 1 |
9 | 4 |
10 | 9 |
次の面のIDを各マップのメモ欄辺りに記述して、クリア時にこいつを読み込むという手法を取ります。
処理の違いを見てみましょう。例えばゲームクリアをした際、面構成配列を採用した場合は以下の物が必要となります。
次の面ID = 面構成配列[クリア面数]
要するに、クリア面数を代入している変数が新たに必要となります。対してオブジェクト指向だとこうなります。
次の面ID = 次の面ID@メモ欄
クリア面数を代入している一行が削れただけですが、意外にこの一行がエラーの元になっていたりします。
手直しが発生した場合
さて、ここでステージの構成を入れ替える事になったとしましょう。4面と8面を入れ替える事になりました。どうするか。配列の数字を入れ替えるだけですね。
式
面構成配列 = [6,8,1,3,10,9,4,2]
こういう場合は、オブジェクト指向よりも面構成配列を採用したほうが数が少ないから、まだぱっと解ります。ですが、もっと増えたらどうでしょう?
また、テストプレイ中に今触っている面のIDが何番かというのは判断しづらく、難易度が高いからこの面は入れ替えようとなった際にはまずマップ画面を探すはずです。オブジェクト指向を採用していた際、マップ画面はその画面を開いているのでメモ欄に次のステージを新たな物に書き換え、前のステージなどを変更すればよいのですが、配列を使ていた場合、IDを見直す手間が発生します。視覚的に解りにくいんですね。
面構成配列を採用していた場合はもう一つ、どこにその変数を用意したか探すのが面倒になる場合が有ります。また修正中にカンマを間違えて消してしまったり、気が付いたらステージ数が7になっていたりという事も発生します。そういった凡ミスをオブジェクト指向は防ぐことが出来ます。
もちろん、オブジェクト指向でも凡ミスは発生します。ステージのつながりがおかしかったりエラーで終了したりもします。が、問題は今、その時プレイしていたステージにあるため、エラーの出たMAPIDの把握という工数が一つ減ります。
まだ面構成の話なので、オブジェクト指向の便利さと言う物はこの文章では伝わりにくいと思います。オブジェクト指向がどういう物なのかについては何となく伝わったら嬉しいです。
要は、極力一括で管理しないで、出来るだけオブジェクト単位、アイコンだったり、キャラクターだったりに設定を持たせましょう、というのがオブジェクト指向という理解です。
メンテナンス性の高さ
数が増えれば増えるほど、オブジェクト指向はその真価を発揮するようになります。例えば以下のような処理をさせたい場合はどうでしょうか。例題2:装備に応じて立ちグラフィックを変更する
装備品によって立ちグラフィックが変化するゲームです。まぁエロ同人ではド定番ですし、3Dグラフィックを使うゲームでも定番の機能です。これをどう処理して実装するか、何も考えずに作るとしたらこうなります。
if アクター1が、頭部にヘルメットを装備しているとき、ピクチャ4に「ヘルメット装備画像」を表示
if アクター1が、頭部に帽子を装備しているとき、ピクチャ4に「帽子装備画像」を表示
if ・
if ・
if ・
if アクター1が、武器に弓を装備しているとき、ピクチャ5に「弓装備画像」を表示
と、条件式を作って、全てのパターンを用意すると言うものです。単純作業で量も多いが実装は不可能ではありません。もちろん、これはオブジェクト指向ではありません。
オブジェクト指向ではどうするかというと、アクターに以下のように設定していきます。(うちで提供しているRPGツクール VX aceの汎用タグスクリプトを使用した前提です)
<立ち:ヘルメット "ヘルメット装備画像">
<立ち:帽子 "帽子装備画像">
・
・
・
<立ち:弓 "弓装備画像">
そして、立ち画像を表示する際にはこのように実装します。
アクター1の頭部の装備を確認
⇒アクターのメモ欄から<立ち:装備品 "画像">を取得して対応するものを表示。
ざっくり解説しますと、条件式を一切合切カットしています。ソースコードがすっきりするのはもちろんですが、単純に条件式のみで実装した場合、ピクチャ番号を間違える場合があります。また、数が増えれば増えるほどソースコードは長くなり、間違えた場所を探すのが難しくなります。
対してオブジェクト指向であれば、少なくともピクチャ番号が装備部位では統一される。間違えたとしても、特定の装備だけ間違えるという事はありません。その場合、5か6行のなかから一つを修正してやれば修正が完了します。
デバッグも1つの装備がきちんと表示されれば、ファイル名の間違いが無い限りはきちんと表示されるためいちいち全部を確認する必要がありません。(後々あらためて一通り確認はするべきですが)
例えば弓を装備した際にエラーが発生したのであれば、 <立ち:弓 "弓装備画像">が間違っているか、保存しているファイル名が間違っているのかのどちらかで、原因の特定が楽です。
例題ではアクターは一人でしたが、実際に作られるゲームでは2,3人、多ければもっと増えるでしょう。実際自分のように人員整理が上手く出来なければ20何人という事も有ります。(RAVAGE)
全員分の着せ替えを条件式で作っていくとなると、装備品が各5種類、部位が5か所アクター3人としても、条件式は75行必要となります。一行に1分かかったとしても一時間以上かかる計算です。この単純作業に耐えられるかどうかという問題と同時に、どこか間違えたとき、75行から探さなければならず、この修正作業がまた時間がかかってしまいます。メンテナンスのしにくさ、という意味でも条件式のみで作るよりは、オブジェクト指向で作成したほうが楽です。
追加の処理がしやすい
SAVAGEがちょうど過渡期でして、オブジェクト指向ではない物からオブジェクト指向へと処理を変更していっている所なので、実例としてこんなことをしてました。
例題3:特定のアイテムを所有している場合にイベントが有る、という通知を行う
SAVAGEでは特定の拠点を解放した際、特定のカードを持っていると掛け合いのイベントが発生するようになっています。イベントが発生している場合、フキダシアイコンを表示させているのですが、この管理をコモンイベントで行っていました。
まず、所持しているアイテムをチェックして該当するものが有れば「イベントがあるかもスイッチ」をonにしています。
つづいて、有るかもスイッチがonの時、実際に該当するイベントを精査して、どの一度も発生していないイベントが一つでもあれば、通知をonにし、発生通知がonの時、特定の拠点にフキダシを表示させています。
所持アイテムをチェックして……
実際にフラグが立てれるかをチェックして
フラグが立っていたら吹き出しを表示
こういう処理の仕方をしていると、イベントの新規追加が難しくなります。なので、次はこういう風に変更してみました。
オブジェクト指向で組みなおすとこうなる。
すごくスッキリしてます。
- まずイベントの移動ルートに必要なカードと既読かどうかのスイッチ番号を設定
- どれか一つでも実行できそうなら吹き出しを表示
見比べてみて欲しいのですが、コモンイベントを3つまたいでいたものがわずか3つの命令で済んでいます。ややこしい条件式も要らないし、なによりもイベントの追加がこれによって非常に容易になりました。
追加のしやすさ、メンテナンスのしやすさがオブジェクト指向を採用する利点で、規模が大きくなればなるほどその恩恵は大きくなります。
まとめ
自分から実例として表示されるのは以上ですが、少なくともオブジェクト指向ではない処理の仕方と言う物についてはご理解いただけたのではないかなと思います。簡単に言ってしまうと、条件式を多用してしまうのはオブジェクト指向では無い、という事ですね。もちろん、オブジェクト指向はいくつかのデータを効率よく扱うために検討と設計が必要なので、小規模なもの、例えば3つ4つの分岐程度であれば、オブジェクト指向で組んだ方が時間の無駄になる可能性も有ります。
よって、無暗に最初からオブジェクト指向を視野に入れず、条件式だけでぱぱっと組んでしまっていいと思います。同じ処理を何度も繰り返したり、数が多くて面倒になりそうだ、という場合は今組んだ条件式から省けそうな物を省くにはどうしたらいいだろうか、と検討してみて実装していくと言う手順が学習の流れとしては良いと思います。
以上、自分なりのオブジェクト指向の解釈をでした。株式会社とかの例を出されるよりかは解りやすいんじゃないかと個人的には思います。もし違和感を感じたら各自で解説を作ってみてもらいたいです。色んな例えが有った方が解りやすいと思いますので。理解の一助になれば幸いです。
PR
プロフィール
HN:
色々ありすぎでどれを名乗ろうか
Webサイト:
性別:
男性
自己紹介:
素材屋GY.Materialsを運営。
TRPGや同人ゲームなどを制作。イベントプロデュース等。
TRPGや同人ゲームなどを制作。イベントプロデュース等。
カテゴリー
最新記事
(01/23)
(03/14)
(11/01)
(09/01)
(08/23)
P R