とても間が空いてしまった3回目です。
今回は第1回と第2回の内容を補完しながら、その繋がりを説明します。
1. オブジェクトとクラス第1回でスクリプトの構成として「クラス」と「メソッド」があることを
第2回でコードの一例として変数の代入を紹介し
「変数」と「オブジェクト」があることを説明しました。
ではこれらの関係はどうなっているのか、と言いますと
クラスというのは設計図で、それを元に生成されるのがオブジェクトです。
スクリプトのコードを書いているときは主にクラスの定義をしているわけですが
ゲームの実行中は、そこから作られたオブジェクトが動いているイメージです。
また、このクラスから生成されるものをインスタンスと言い
正確には「オブジェクト = クラスのインスタンス」という定義となりますが
とりあえずはオブジェクトとインスタンスは同じものを指していると理解しましょう。
専門用語が増えてややこしい限りですが、
何となく気分で使い分け単体で見たときはオブジェクトという言い方をして
元のクラスとの関係性で見たときはインスタンスという言い方をします。
2. pコマンドとコンソールさて座学が続いて退屈だと思いますので、そろそろ具体的に手を動かしてみましょう。
まず色々試すために新規プロジェクトを作成して下さい。
スクリプトの触り方は2つあります。
新規のイベントを作って、イベントコマンド「スクリプト」を作成します。
以下のコードを入力して、テストプレイで実行して下さい。
a = 10 #変数aに10を入れる
b = a * 10 #変数bに変数a*10を入れる
p b #コンソールに変数bを表示
コンソールウィンドウ(テストプレイ時に出てくる黒いウィンドウ)の方に
100が表示されたかと思います。
p オブジェクト
でそのオブジェクトをコンソールに表示するコマンドになります。
次にスクリプトエディタを開き
Game_Actor の30行目にある setup メソッドの最後の行に
p @name
を追加します。第1回のパッチ形式で出来ればなお良し。
テストプレイでゲームを起動すると、やはりコンソールに
"エリック"
と表示されるはずです。初期パーティを増やすと名前も増えます。
このpコマンドは最重要です。
・この変数に入っているオブジェクトは何か(整数か小数か文字列か)
・この処理はどのタイミングで実行されているのか
etc.デバッグにも調査にも必須となりますので、使い倒しましょう。
3. オブジェクトのクラスというわけで、オブジェクト = インスタンスは必ず元となるクラスを持っています。
例えば文字列は String というクラスです。
配列だと Array というクラスになります。
数値は少し複雑で細分化されています。(スーパークラスも絡むので説明は次回で)
これらは最も基本的なクラスなので、決められた書き方をすることで
そのインスタンスを直接生成できます。これをリテラルと言います。※第2回参照
a = 10 # Integer クラスのインスタンス 10 を生成して、変数aに代入
b = "あ" # String クラスのインスタンス あ を生成して、変数bに代入
ではリテラルが使えない普通のクラスはどうするかというと
クラスからインスタンスを生成する、全クラス共通の方法を使います。
a = xxx.new # xxx クラスのインスタンスを生成して、変数aに代入
一方、そのオブジェクトがどのクラスのインスタンスなのか調べるには
p オブジェクト.class
というのを使います。これでクラス名が判別できます。
4. 変数の参照に慣れようここまで散々「オブジェクト」と書いてきましたが
例の通り、コード上で実際に指定するのはオブジェクトの入った変数名です。
実際の運用としてもインスタンス生成時に変数に入れて(=名前を付けて)
その変数名=そのオブジェクトとして取り扱う感じになります。
実行時にはその変数の中身のオブジェクトが参照される、置き換わるイメージです。
例えばこんな感じです。
ダメージ = 攻撃力 * 2 #攻撃力の中身は100
→ 100 * 2
→ 200 #ダメージには200が入る
HP = HP - ダメージ #HPの中身は1000
→ 1000 - 200
→ 800 #HPには800が入る(自己代入)
エラーの多くは、この置き換えた結果で、コードが破綻して起こります。
ダメージ = 攻撃力 * 2 #攻撃力の中身は"強い"(文字列)
→ "強い" * 2 #ここで破綻……は実はしない
→ "強い強い" #ダメージには"強い強い"が入る
HP = HP - ダメージ #HPの中身は1000
→ 1000 - "強い強い" #ここで破綻する
→ *error*
上記の例のように、コード自体は同じでも変数の中身によって破綻します。
またその場では成立してしまい、後で破綻してエラー箇所がずれることもあります。
この例だと全然別の、攻撃力に"強い"なんて代入する処理に問題がありますね。
p オブジェクトや p オブジェクト.class を使い
変数の中身のオブジェクトを理解する必要があるのはこのためです。
5. メソッドの呼び出しとselfオブジェクトの取り扱いに慣れてきたところで、もう1つだけ覚えてしまいましょう。
クラスでは一連の処理である「メソッド」を定義していました。※第1回参照
オブジェクト.メソッド名
とすることで、そのオブジェクトのメソッドを呼び出すことができます。
気付きましたかね。実はさっきの オブジェクト.class もメソッドの呼び出しでした。
これによって異なるオブジェクト間で処理のやり取りをすることができます。
例えばアクター、エネミー、スキル、ウィンドウは全部別のクラス=オブジェクトですが
こんな感じでお互いに参照し合ってゲームの流れが形作られています。
一方で、自身のメソッドを呼び出す場合は
self.メソッド名
とします。self は「そのオブジェクト自身」を意味します。
なお self は省略可能です。つまりメソッド名だけ書けば自身のメソッド呼び出しになります。
最後に、 + や & などの「演算子」というのも
実は特殊な形をしているメソッド呼び出しとなっています。
例えば "あいう" + "えお" とすると2つが繋がった文字列"あいうえお"になりますが
これはStringクラスで +メソッドがその様に定義されているためです。
6. スクリプトの処理でやっていることお疲れ様でした。ここまで多くの用語や考え方が出てきて大変だったと思います。
ですが以上を理解した上でスクリプトのコードを眺めてみれば
実はやっていることは以下の4パターンくらいだと分かります。
書いていること やっていること
・変数への代入 = 変数を定義
・(self.)メソッド名 = 自身のメソッド呼び出し
・変数名(.メソッド名) = 他オブジェクトのメソッド呼び出し
・その他 = 制御構文(クラス、メソッドの定義や条件分岐など)
次回からは実例を交えて、より具体的・実践的な内容に行きたいと思います。
まとめ・クラス → インスタンス=オブジェクト
・まずはとにかくpコマンドを使って確認する
・実行時に参照先に置き換わるというイメージに慣れる
[2回]
PR