C#RPG開発日記

最新記事へ

#1 2011/2/1

C#でRPGを開発する。
目的は以下の通り。

また、いつかの日経ソフトウェアか何かに「開発日記つけろ」的なことが書いてあったため、この日記をつけることにする。

簡易フローチャート

「まずはフローチャート書け」と高校の授業で習った気がするので、簡単に書いてみる。
てか普通科のごく普通な進学校のたった1単位の情報の授業だったのに、よく考えてみるとすげー事教わってるな。
そんな事教えてる暇があったら未履修問題解決しろよとか思わなくもないが、まあ"こっちが立てばあっちが立たず"なんだろうな。

シーン
データベース
クラス
書き始めて気づいたがこれはフローチャートではない
というかプログラムのフローチャートではなく、開発のフローチャートだ。
ゾーマを倒したいのに、ゾーマの行動ローテーションではなくゾーマ城までの攻略フローチャートを教えられた気分だ。
ちなみにドラクエ3はやった事が無い。

最初の一歩

rpgomi1

バトルシーンの基礎の基礎を作成した。
コントロール群にそれらしいバーがあったので付けてみた。
もちょっとカスタマイズとかできたら十分採用できるな。

今はボタンクリックのイベントハンドラ(?)に、アクター/エネミー行動やら死亡判定やら
画面更新やら全部突っ込んだスパゲッティ状態なので、ここから整理してゆく。
キャラクタークラスを作成し、アクターとエネミーをそのインスタンスとする。
行動判定は各々のクラスのインスタンスメソッド(?)に。HPとかはインスタンス変数(?)に。
それとは別にシーン管理プログラムを書く。戦闘処理中はプレイヤーの入力をウェイトするために、
ボタンを消して物理的にウェイトをかける。これは今思いついた。

プロジェクトを一度閉じて、過去の作品や解説書のサンプルを覗いた後もう一度プロジェクトを開いてみると、
なんとVisual Studio 2010がフリーズ。プロジェクトが開けない。やれなんだなんだ。
ファイル同期ソフトの指定から外して、何度か試してみたら開けた。何だったんだろうか。

#2 2011/2/2

この日記をweb上にアップロードし公開することにした。
後にこのテキストが、少しでも誰かの役に立つことがあれば幸いである。

開発は進まず。机上で画面レイアウトを少し練った。
あとは言語学習。C#に触れるのはほぼ半年ぶりで経験も浅いため、実はあまりよく分かっていない。
ゆとり似非プログラマーな私にとって、変数の型宣言とかメソッドの復帰型宣言とか、
性的静的言語と言うのだろうか、こう言う堅苦しいのはどうも馴染まない。
そもそもセミコロンが慣れない。
幸いにもVisual Studioがやたら頭良いお陰で、上記のようなミスは片っぱしから御指摘してくれるので、
私のようなゴミデベロッパでも開発可能なわけだが。

#3 2011/2/3

クラスをいくつか定義した。まだまだ序の口。

VSが開けない問題が再発。プロジェクトのプロパティを先に開いておかないと、
コードを開いた時点でフリーズする。なんだそれ。
幸いVSは、一度起動に失敗すると、次回起動時は読み込み失敗したドキュメントは放置してプロジェクトを開いてくれる。
この機能のお陰で先回りでプロパティが開けるわけだ。それにしても意味不明だ。
そんな機能付けるぐらいなら、読み込み失敗した原因ぐらい教えて欲しいものである。
vs2010.PNG
↑この様である。何の言い訳もなく突然の終了。

先日書いた「ボタンを消して物理的にウェイトをかける」方法だが、
当時は面白い発想だと自負したが、今日読んだ解説書に当然のごとく書いてあった。そんなものだ。
ゲーム制作だって似たようなものだ。思いついた直後は「このゲームすげー面白いんじゃね?」と夢と希望でいっぱいになるが、
いざ作ってみると想像以上のつまらなさに落胆するものである。
市販ゲームと比べはじめると目も当てられない。

#4 2011/2/4

昨日定義したクラスを処理に組み込んでみた。
攻撃ボタンのイベントハンドラを比較してみよう。以下の通り。

変更前(#1)のコード


変更後(#4)のコード


「ダメージ計算→ダメージ処理→出力」というフローから
「アクション作成→アクション適用→出力」というフローに置き換わった。
シーンクラスを定義していないため、まだあんまり短くなっていないのが残念。

ダメージ数値を直接扱っていたのを、アクションクラスへ
バトラーHPを直接扱っていたのを、バトラークラスへ
計算とかが全部外部クラスで行われるようになったため、コードが読みやすくなったし、
なにより今後の調整が非常に楽になる。
こういう所がオブジェクト指向プログラミングの醍醐味らしい。
生まれて以来オブジェクト指向の言語にしか触れていない私にとってはあまりよくわからないが。

上記の変更前コードで目を引く一行
「text = System.String.Format("主人公の攻撃 モンスターは{0}のダメージ", damage);」
が、変更後に消えているが、実はコレに相当する処理は変更後のコードには存在しない。
「action.makeAct()」内に書こうとしたのだが、このactionのClassActAttackクラスはフォームクラスの外部にあるため、
フォーム内のコントロールにうまくアクセス出来ない。
引数として渡したり、適当な所にpublic変数で置いたりするのではなく、
何かスマートな方法は無いだろうか。

インターフェース(C#)

インターフェースを初めて使ってみた。
しかしこれは何の意味があるんだろう。普通にクラス継承させれば良くね?
メソッドとかの定義のし忘れミスを防ぐため、としか思えない。
まあ大規模なプログラムになって来ると、そんなんでも十分有意義なのかも知れない。

多重継承?
・・・・・・見なかったことにする。

バトルシーン関連の開発

以上が完成したら、バトルシーン関連はほぼ終わったも同然。
次はダンジョンシーン開発に取り掛かる。

書いてなかったが、作成するのはハック&スラッシュライクの
コマンドベースバトル・ダンジョンアタックRPG。そんなジャンルがあるのかは知らないが。
出力系統は基本文字のみ。「Windowsフォームアプリケーションスキル習得」と最初に掲げたが、
GUIにする意味は無いかもしれない。それでも私はフォームアプリをやめない。

#5 2011/2/6

ちょっとだけスタイルシートをいじった。
iphoneにも対応させようと思ったが、面倒だったので途中でやめた。

バトルシーンクラスがひと通り動くようになった。
これでフォームのクラスは随分とすっきりした。
昨日掲載した攻撃ボタンのイベントハンドラは、以下のようになった。

今日(#5)のコード


これだけだとあんまりなので、ここで呼んでいる
ClassSceneBattle#setActionメソッドをみてみると、こうなっている。

引数iの使い道はまだ考えていないなど、まだまだアレ。

最初は「アクションの実行」「HPバーの更新」「エネミーの行動を決める」「死亡判定」などが
すべてフォームのbuttonAtk_Clickに含まれていたが、これらはそれぞれ専用のクラスメソッドとなり、
上記の最後に書いてあるClassSceneBattle#updateから状況に応じて呼ばれるようになった。
このupdateメソッドがバトルシーンのメインルーチンであり、原則としてボタンをクリックする毎に実行される。

ちなみに途中の「form1.writeInfo("your action setted");」が、前回問題となってたポイント。
結局フォームは、シーンのコンストラクタに引数で渡した。
HPバーの更新とかもシーン側からしたいし。

バトルシーン関連の開発

タスクがひとつ減った。
バトルシーンは残りふたつ。先にデータベースをやる。
XMLを使おうと思うが、XMLは1ミリも触れたことがないので不安。

本開発は、読んで分かるとおり
「先に原型をスパゲッティコードで記述」
→「拡張性のある記法で書き換える」(いまここ)
→「実際の機能を実装する」
というステップで開発を行なっている。
最初は効率的な開発手順だと思ったが、開発が進むに連れて
1ステップあたりの負担が大きくなっているのを感じる。
この方法は失敗だったのだろうか。

rpgomi5
スクショ撮ってもあまり代わり映えがしないのも残念。
開発用に出力をたくさん見たいがために、縦に引き伸ばした。

#6 2011/2/8

一応、LINQtoXMLでデータを引き出すのに成功した。
初めて使う技術でまだ右も左も分からんので、詳細をメモしておこう。
なおXMLファイルの作成にはXMLEditor.NETを利用した。

使用するXMLファイル(抜粋)


この中からブレイブのhp「123」を取ってきて、アクターのインスタンス変数hpMaxに代入しよう。
なおClassActorのインスタンス変数とコンストラクタは、以下のように定義されている。

ClassActorの定義(抜粋)


上記で呼んでいるClassActor#calcHPメソッドを、これから定義する。

LINQtoXML

まずコード冒頭に「using System.Xml.Linq;」の1行を追加する。「using System.Linq;」だけではアカンのね。
ここからのステップは3つ。
  1. XMLデータをロードする
  2. XMLデータの中から、条件に一致する要素(?)を選ぶ
  3. 選んだ要素のhpの値をhpMaxに代入する
「条件」とは、ここではジョブのidがアクターのjob.idに一致することとする。
つまりidが1のジョブを取って来ればいいわけだ。

1.XMLデータをロードする
まずXMLファイルを読み込むには、「class System.Xml.Linq.XElement」のメソッド「Load」を利用する。
名前忘れたけど謎の技術によって「XElement.Load」と呼び出すことができる。
さらにここから、すべての<ジョブ>要素を取り出すために、「Elements」メソッドを使う。

コレでXMLファイルを読める。XMLファイルのパスがアレだが、特に意味はない。


さて既に訳がわからなくなってきたが、こうして取り出したデータは「IEnumerable<XElement>」という型になる。
なんかくっついてるし。なんだよ< >って。何このデータ型。

とにかく黙ってこう書けば、読みだしたXMLデータが変数dataJobに代入される。
2.条件に一致するのを選ぶ
さてこのdataJobの中には、まだ「ブレイブ(id 1)」「パラディン(id 2)」の二種類のジョブの情報が入っている。
このうち今回利用するブレイブのデータを抜き出す。


とりあえず「IEnumerable<XElement>」から条件を満たすのを取るには「Where」メソッドを用いる。
<ジョブ>の要素<id>「ジョブ.Element("id")」で拾えるらしい。これは分かりやすいな。
つまり「id」=「1」、という条件式は「(int)ジョブ.Element("id") == 1」と書けばいいわけだ。うんうん。

コレをWhereメソッドの引数に渡し・・・

・・・「ジョブ =>」という謎の記号が出現した。
これはラムダ式とか言って、こう書かないといけないらしいが、
この謎の記号について解説サイトを調べまわったところどこもかしこも宇宙語しか書いてなかったため、
そういうもんだと割りきって使うことにする。

Whereを使って拾ったモノも「IEnumerable<XElement>」のままであるため、こう書ける。
3.必要な値を代入する
さて、これでブレイブのジョブデータを拾えたわけである。
最後のステップとして、この中からhpの値を抜き出してhpMaxに代入する。
先程と同様「Element("hp")」と書けば良さそうだが、ひとつ問題がある。
さっき取ってきたデータは「idが1のジョブ」であり、コレクションなのである。
要するにこう書く。

これだと「idが1のジョブ」が複数あるとき予測せぬ動作をすることになるが、
そんなデータ作らなければいいだけの話だと思うので、ひとまずこれで良しとする。
idを一意的なデータ(主キー?)にするとか何かすればうまく書けると思うが、データベースはさっぱりなので妥協。

さて、コレにてひと通り必要な処理が完成した。

ClassActor#calcHPの定義


訳のわからない技術だったが、いざコードを書いてみるとこれほど簡潔に終わるとは。

LINQtoXMLで検索しても「LINQが実装される前のコードはこんなに長くて大変だったんだよ」という
先輩方のありがたいお話(棒読)ばかりヒットして肝心の解説は宇宙語だったのだが、
これだけの記述でデータを読んで利用できるとは、確かに素晴らしい技術かもしれない。

さて、ようやくバトルらしくなってくるぞ・・・。
プログラム技術面だけでなく、ダメージ計算式などの仕様も考えていかねば。

#7 2011/2/12

試しに戦闘曲を作ってみた。
作曲は、その時の調子に完成度が左右される、いわば運ゲみたいなものなので、出来る時に一気にやっておかないといけない。
ちなみに私はカデンツしか知らないので、1曲ならいいけどこのまま作り続けると似たような曲ばかりになる。
コード理論も勉強しないといかんな・・・。

rpgomi7.PNG

で、wmpコントロールを使って、BGMが鳴るようになった。
スクショでは分からないが、バトルっぽい雰囲気が出てきた。
こういうどうでも良さそうな所が、モチベーション維持のために重要だったりする。
非商用の開発だし、作ってて楽しいのが一番だ。


先日書いたデータ引き出しのプログラムも、使いやすいように書き換えた。

しかし今日のように少ししか進まなくても、結構時間は過ぎるんだな・・・。
4月に入ると時間が取れなくなるので、それまでに完成させたいが。
グライガーの厳選なんてしてる場合ではない。

#8 2011/2/13

初演作品を聴いてきた。やはりプロの作曲は格が違うわ。
本当にいいものを聴いた。曲もいいが奏者も素晴らしかった。
しかし初演曲は3日前に楽譜が届いたと聞いていたが本当なのだろうか。
こんなスレが立つぐらいだから・・・。

移動時間に開発しようとノートパソコン持って行ったがVS2010がインストールされてなかった。
何やってんだ。
仕方ないのでXMLデータをひたすら打ち込む。
XMLエディタぐらい、iphoneや携帯電話アプリに無いのだろうか。

これだけの日記ではどうしようもないので、今日見たエラーを紹介。

警告 1 'IWMPGraphEventHandler.NotifyAcquireCredentials' の引数のうち
少なくとも 1 つをランタイム マーシャラーでマーシャリングできません。
したがってこのような引数はポインターとして渡され、アンセーフ コードの使用が必要になります。

日本語でおk

#9 2011/2/15


UIが固まってきた。
画面上部の主人公とモンスターの部分は、デバッグ用に残してあるだけ。
右上の四角が実際のモンスターの表示位置になる。

今日使った新技術は、コード内からのコントロール手動生成。
VisualStudioは、GUIでコントロールを直感的に配置することで、コードも自動生成してくれる素晴らしい開発環境である。
しかし上記のように、例えばパーティの一人ひとりのステータスにコントロールを結び付けたい場合、
コード内でループでも回して生成した方が手軽だし、可読性も上がる。


実際の戦闘開始時に呼ぶステータス描画部分のプログラムは以下のようになっている。

パーティステータス描画メソッドの定義


長いものの似たような単純な文の繰り返しであり、分かりやすいと思う。
「nameLabel1」「nameLabel2」・・・等と4*6=24個のコントロールを配置し、
いちいち値を対応させていくのに比べれば簡単な方法だと思う。


しかし4人パーティぐらいだったら、コントロールをVSに自動生成してもらって進めるのも十分現実的な話である。
その場合、生成されたコントロールをパーティメンバーに応じて分類したコレクションを定義すれば上手く行くと思う。
この方法の利点は、コードではなくGUIでコントロールを配置できるため、
単純に一列に並べるだけでなく凝ったレイアウトも簡単な点だろう。

ちなみに"キャスト"を用いた型の非暗黙な変換も、地味に初めて使ったと思う。
これまではそんな方法知らずに、メソッドを親クラスにコピペしたり色々無茶していた。

私は今まで、プログラミングは一晩二晩かけて徹夜で一気に終わらせる方法をとってきた。
間を開けてしまうと今までのことを忘れてしまうため、なるべくノンストップで終わらせたかったから。
それで完成するような小規模な開発しかした事がなかったのもある。


しかし今回は将来使える実用的な開発スキルの習得を目的としているため、あえて日々少しずつ開発を進めている。
いや、その方が楽しいというのが一番だろう。前述の方法で、VBAで40時間開発をしたことがあるのだが、あれは苦痛だった。

#10 2011/2/16

4Gamer:「Sid Meier's Civilization IV」のテーマソング「Baba Yetu」がグラミー賞を受賞


ゲーマー合唱人としてスルー出来ない話題なので紹介。
しかしいまさらCiv4とは何故だろうか。
これを機に過去のゲームミュージックの再評価が進んだり、ゲーム合唱曲のブームになったりするといいなあ・・・
ならないだろうけど。

#11 2011/2/22

移動時間にノートパソコンでちょっとずつ開発中。
パーティバトルを無事に実装。
あとはスキルを作ったりダメージ計算式など細かいバトルの仕様を書けば、バトルシーンは終わり。
まあ、そこが長いというのもあるが。

次はダンジョンシーン。
本開発では開発簡略化のためHTMLのテーブルを用いてダンジョンを記述するつもり。
しかしマリオとかのアクションゲームのマップデータ形式って、いったいどうなっているんだろう。

#12 2011/2/23

ボス曲を途中まで作ってみた。今日はこれ以上作曲は無理。
RPGの作曲難易度って戦闘曲<町曲<ダンジョン曲だと思う。

メモ
スーパークラスのコンストラクタは、サブクラスのコンストラクタよりも先に呼ばれるらしい。
この場合、actorは「guard==false」、enemyは「guard==true」となる。試してないけど(ぇ

メモその2
要素数を最初に決めないと定義できない配列の頭の固さにうんざりしたり、
先日扱った謎の型「IEnumerable<XElement>」は配列に毛が生えた程度だと思っていたらlengthプロパティが無かったり、
知識不足が開発に支障をきたしてきたので、ちゃんと調べてみた。


参考…テクヤン - マインドフリー .NET カフェ:C#のコレクションまとめ
わかりやすいサイトが見つかった。
何かと謎だった「IEnumerable<なんとか>」は、 配列とかそういう風なデータ型(コレクションと言う)たちのスーパークラス。
それも、genericという比較的新しい機能(?)を搭載しており、 よくわかんないけどたぶん動的な記述ができるってことだと思う。
「<なんとか>」の部分がジェネリックの鍵らしいけどまあいいや。
そして、こいつのサブクラスである「IList<なんたら>」というのが 可変長配列として利用可能だという。ktkr
しかしRubyだったら、配列とハッシュ覚えるだけで良かったのに・・・

メモその3

Windowsによる開発の何が面倒って、フォントが自由に選べないことだ。

#13 2011/2/24

smileboom:BASICが走るニンテンドーDSiウェア『プチコン』
何がすごいって発表されたのが3DS発売2日前である点だ。


携帯電話にすら携帯BASICというものがあり、 まだ我が家にパソコンが無い頃に遊んだことがあった。
そう思うと「スマートフォン」とは何なのかと思う。
よく「携帯電話」と「ノートパソコン」の良い所取りをしただの言われるが、 開発環境がない時点で携帯電話以下ではないだろうか。
というわけで次はVisualStudio for iPhoneをだな・・・

ダンジョンシーン開発

ダンジョンマップ表示システムの基礎が完成。
マウスカーソルを撮り忘れたのだが、オンマウスで座標の書いてあるラベルがポップするようになっている。

本来はWebブラウザコントロールを用いて、 HTMLで書かれたダンジョンデータを専用CSSを用いて直接表示しようと目論んでいた。
しかしWebブラウザ上のテーブルに対して、どうマウスイベントを発生させるか謎だったのでやめた。
msdnライブラリ チュートリアル 2: 迷路の作成 をヒントに、ラベルコントロールを量産してマップ画面を作った。
以前取り上げた「コード内からのコントロール生成」技術で500個のラベルを生成している。


ここで気になるのが、そんな事して処理は間に合うのかという問題である。
普段はオーバースペック気味なデスクトップPCで開発を行っているのだが、 たまに書くようにノートパソコンを使うこともある。
今回はこのノートパソコンで簡単にテストしてみた。

テスト
500個のラベルに対してMouseEnterでイベントハンドラを呼んで、マウスの下にあるラベル(アクティブラベル)を青で塗ろう
このためのイベントハンドラを二種類用意した。
テスト1:すべてのラベルを白く塗る→アクティブラベルを青く塗る。
テスト2:前のアクティブラベルだけを白く塗る→新しいアクティブラベルを青く塗る。
実行したときの見た目的には同じである。
それぞれに対して、ラベル上でマウスを激しく動かし、イベントハンドラを呼びまくって、 その時のCPU使用率を見てみた。


コード書いてる時:だいたい30%
テスト1:だいたい80%
テスト2:だいたい60%


ずいぶん適当なテストだったが、とりあえずCPU負荷20%の軽減に成功!
もちろん他のソフトを切ったり厳密なテスト環境を作っている訳ではないので、何とも言えないのだが。
少なくともVisualStudio2010が軽快に動く環境なら、このゲームが重すぎて止まるようなことはないだろう。
なおラベルを生成するのは一度だけで、いったん生成すればダンジョンを出るまで破棄しない。 戦闘中もマップウィンドウは閉じない。
500個のラベルに対して行うのは、色を変更するだけである。



マップデータはHTMLを使う予定だったが、Excelデータも良いような気がしてきた。
どちらもほとんど手間無しにGUIでダンジョンデータを作成できるという利点を持つ。

HTMLは形式が簡易で軽量だが、Excelデータの方がC#から楽に取り扱えそう。

#14 2011/3/6

多忙のためしばらくは進展なし。3月中旬くらいまでこんな感じ。
2月末までにもうちょっと進めておきたかったが、特に急ぐ理由もないのでゆっくり進めていこうと思う。
この1週間でArrayをIListで書き換えたぐらい。IListのIって何だろうか。

ちなみに北米では、プロのゲーム開発者の為のイベント「Game Developers Conference」なるものが開催されていた。
数ある記事の中で目を引いたのがこれ。
4gamer:フリーゲーム「洞窟物語」の作者 天谷大輔氏による講演
Game Watch:個人開発者の天谷大輔氏が「洞窟物語」で講演
プロの開発者向けのイベントで何故フリーゲームの講演が行われているかは謎だが、私にとって参考になる話なので構わない。
あれか、海外版PC用フリーウェアは非公式で、wii Ware版が公式だから、コンシューマーゲーム扱いなのか。


しかし洞窟物語はもう6年も昔の話なのか(私がこの作品を知ったのはだいぶ後だが)。
懐かしいな。あれは素晴らしいゲームだった。
こういう所でVisual Studioとか出てくると嬉しくなる。

#00 2011/3/11


東北地方太平洋沖地震 被災者の方々の無事を心よりお祈り申し上げます。
Google Crisis Response


多忙につき停止していた開発は、3月13日より再開予定です。
以上

#14 2011/3/14

ダンジョンデータ読み出しを作る予定だったが、 リファレンスの類が手元に無い環境で新しい技術を使うのは無理だった。

という訳でバトルシーンの仕上げ。
ターゲットの選択を実現するために色々と書き換え。操作系も手入れして、キーボードのみで快適に進められるように。
バトルシーンは完成が見えてきた。

#15 2011/4/24

5月末までは開発時間が取れそうにないので停滞中。

隙を見てダンジョンのBGMを作ってみたが、こんなノリで良いのかは甚だ謎。
同主調転調後の安っぽいCsus4が聴きどころ。

#00 2011/6/7

不慮の事故とかによりだいぶ遅れたが、開発再開。
そしていきなりだが、事情により今月中はJavascriptによるリズムゲームを開発することにし、
C#RPGの開発は一時停止する。

JSリズムゲーム開発日記

#00 2011/7/22


もう少々お待ちください…

#00 2011/7/24

C#RPG開発日記