資料館/CsharpE3D003

Last-modified: 2011-07-05 (火) 15:18:41

第0.5回では、ゲームの流れ、全体像を設計図のように考える事にする。その過程で
どうしても説明しなければならないので、クラス等についても少々の説明する。既に
JavaやC++、もしくはHSPのモジュール機能などに練達した古参兵の諸兄は該当箇所について
適宜読み飛ばすなどして対処してくれ。

ゲーム全体の構成

俺はC#でゲームを作った事はないが、複数のシーンからなるでもプログラムや、WORZ等を勉強しながら頑張って作っている。
なので今回作るシューティングゲームでも、プログラムをシーンごとに区切ってそれぞれでクラスを作っていくことにする。そのためには必要なシーンをまず定義する。その後必要なキャラクター、画像などの素材を考えていく。なるべくこの段階で、ゲームの全体像がかなり具体的に思い浮かんでいた方が後々苦労しなくて済む。可能ならゲーム画面をコンテのような簡単な絵にすると自分の中でよく整理がつく。絵にするというのは大変便利な整理方法なのでこれに限らずやってみて損は無い。

シーンの定義と簡単な説明

  • タイトル画面
    • タイトル画面と、現在のハイスコアを表示し、スタートボタンの入力を受け付ける
    • スタートボタンを押すとゲームシーンに飛ぶ
  • ゲームシーン
    • 実際にゲームを行う
    • 敵を全滅させるとステージカウントを1つ上げ、ゲームクリアシーンに飛ぶ
    • ゲームオーバーになった場合は、タイトルシーンに飛ぶ
  • ゲームクリアシーン
    • ゲームをクリアした旨を表示する。ゲームシーンに飛ぶ
  • 終了シーン
    • 各シーンから飛ぶ事が出来る、ゲームの終了処理を定義したシーンで、E3D.Bye()などを呼ぶ

だいたいこんな感じになるかな。ゲームシーンを各ステージごとにさらに分けてもいいかもしれない。
今回は登場する敵の動きなどを別のファイルとして定義して、ステージ毎に読み込む形を取る予定。
細かく初期化シーンなどを継ぎ足すかもしれないが、それは適宜脳内補完してほしい。これらを遷移させる方法については後で述べる。

キャラクターの定義

次は画面に実際に表示するキャラを考えたい。キャラというのは、自機、敵、弾、爆発エフェクト等の事だ。

  • 自機
    • 言わずもがな自分が操作する愛すべき自機
  • 敵機
    • 語る必要もない。破壊すべき悪
    • 敵、味方共に攻撃する唯一の手段であり、ゲームの花
  • アイテム
    • 敵を殺すと出るパワーアップアイテムとか、スコアアイテムとか、ボムストック増加とか
  • エフェクト
    • 敵および自機の死亡時に爆発エフェクトを出す。弾の命中時に火花を飛ばすのもいいかもしれない。

構成を考えたら、クラスを考える

先ほどからやたらめったら設計図ばかりを作っている気がするが、勘違いしてはいけない。これらは
まだ設計図未満の、妄想を書き連ねた思春期ノート程度の価値しかない。本当はかなり綿密な設計図をおこしてから作業に移るのだが、今回作るぐらいの規模なら経験値補正でなんとかなるだろう。
というわけで、さっきの構成で考えたものをクラスに落とし込んでいく。

クラスについて

以前こんな記事を書いたので一応参考にしてくれ。繰り返しになるが、この講座は全体的に
HSPを触ったことがあって、シューティングゲームくらいは作ったことがあるがC#が初めて、という人が対象なのでモジュール機能のスペシャリストや
JavaやC#、C++等でクラスというものの概念に触れたことがある人はここは読み飛ばして問題ない。

クラスとはそもそも何なのか

Wikipediaを見ても参照に次ぐ参照で何が何だか分からない状態に陥るだろうからここで頑張って説明したい。
C#においてはプログラムはオブジェクトの集合で構成される。クラスはそのオブジェクトの設計図である。クラスには通常、何らかのデータと、何らかの処理が関連付けられているがそれを直接扱うことはできず、外の方に
コントローラーが付いている。これをメソッドと呼ぶ。例えば、二つの数字を使って計算をするクラスがあるとする。

  • 数字を計算するクラス
    • 二つの数字を与えると合計値を返すメソッド
    • 二つの数字を与えると掛け合わせたものを返すメソッド

という風に、二つのメソッドが外側に出ていて、そのメソッドを正しく呼び出すと機能が発揮される。中でどういった計算が行われているのか、まあ
今回は容易に察しが付くが、知らなくても扱える。次のような例を出すとわかるかもしれない。
キャラクターの情報を管理するクラスがある。

  • キャラクター管理クラス
    • 内部に、HP、攻撃力、防御力をデータとしてもっている
    • 敵の攻撃力を入力すると、自分の防御力やその他の補正を計算して、受けるダメージを返すメソッド
    • 最終ダメージを入力すると、現在HPを入力されたダメージ分減らすメソッド
    • HPを出力するメソッド
    • 攻撃力を出力するメソッド
    • 防御力を出力するメソッド

このような構成は通常無いと思うが、例と言う事で。敵の攻撃力を入力すると、内部のデータを利用して演算して、結果を出力する。中でどういう計算をしているかは知る由もない。クラスはオブジェクトの設計図であり、クラスはもともと他人が作ったプログラムを中身を理解しないで安全に利用できるようにしたもの、捕えていいんじゃないかと思う。HSPの場合は例えば誰かが作った、サブルーチン化された機能をコピペする場合、正しい変数名に値を代入し、適切にgosubする必要がある。
コピペの際にミスが発生するかもしれないし、変数名が自分のコードと被っていてバグるかもしれない。C#ではクラスの中と外ではほぼ隔離されている状況で、違うクラスの中にint hpみたいな変数があっても問題は無い。int unitmaxhp:int enemymaxhp といった
いかにも打ち間違いが発生しそうな変数名から解放されるのだ*1

オブジェクトは何なのよ

クラスという設計図から実際に作られるものがオブジェクトになる。例えば、さっきのキャラクター管理クラスの例を使うとこのクラスを用いてキャラクターを複数作ることができる。オブジェクトはそれぞれ独立であり、AのHPを減らすことでBのHPも減る、という事は無い。
ここまで例をあげればわかると思うが、敵キャラをクラスとして定義しておき、それをオブジェクト化して大量発生させればいいという事だ。HPの管理などもそのオブジェクト単位で出来るようになる。

インターフェースや継承など、詳しいことは割愛。そのうち。

必要なデータを考える

実際C#でプログラミングするには、クラスに置き換えたほうが無難だろう。*2
そのために必要なのは、各クラスが持つデータを定義することだ。といっても特に難しくとらえる必要はない。HSPのときだって、『敵には現在座標のx,yと、HP、MAXHPが必要だな』と頭の中で決めていたはずだ。それをソースコードの中で、メインのプログラムではなく、別の場所、キャラクターのところで定義するだけの話だ。こうすると、その座標にはキャラクターのクラスを用いてしかアクセスできなくなる。これは不便だと感じるかもしれないが他のところで変に弄ってしまってバグるという状況を未然に防ぐことができる。

ということで、自分が思いついたキャラクターにどのようなデータが必要か考える作業になる。
こういう時、いきなりコードとして書き込もうとすると頭がパーンしてしまう事が殆どだ。なので、鉛筆と落書き帳を持ち殴り書きでいいのでメモを書こう。隅っこにラクガキなんかしてもいいよな。
少し脱線するが殴り書きのメモは大変に重要だ。よく整理された一生形にならない中二ノートより、殴り書きのメモの方が余程価値がある。漢字わからん、悪筆だとかまるで関係なし。だって誰にも見せねーもん。

memo.jpg
ちなみに俺は敵のデータを定義するときこんなメモを作った。*3この通りにならないかもしれないがメモで整理するとしないとでは大幅に作業効率が違うのでぜひ試してみてほしい。閑話休題。
必要なデータが大体わかったら、それをソースコードに落とし込んで行こう。

たとえば、全ての基本となるキャラクタークラスはこんな風に始まるようにしてみた。

namespace SampleShooting
{
    class Base2DCharacter
    {
        int posx, posy;
        int life;
        public Base2DCharacter()
        {
            posx = 0; posy = 0;
            life = 0;
        }
    }
}

キャラクターのデータをこういう風にどんどん考えていき、ゲームを作りながら必要な機能を追加していこう。
別のファイルとしてどんどん増やしていくと、管理し辛くなるので、ソリューションエクスプローラで
sol.jpg

こんな風にフォルダわけして行くといいかもしれない。
次回はもう少しクラスについて喋りつつ、どうにか戦闘機を画面に表示して動かすあたりまでいきたい。


*1 厳密には変数の名前はわかりやすい方がいいので、aとかbとか適当な変数名をつけてはいけない
*2 正確には、そうでもしなければC#を使う意味がない
*3 流石に恥ずかしいので薄くモザイク。なんかうんことか書いてあるし、よほど機嫌が良かったに違いない