YaneuraoGameScript2001でRPGプログラミング【マップ表示編】

初心者歓迎!プロのゲームプログラマによる、×××ツクールでは物足りない人のためのゲーム制作入門!

written by やねうらお
やねうらおのホームページ


 §1.RPGは、すべてのゲームの基本です

働けど働けどわが暮らし、楽にならず..ですが、みなさん24時間、馬車馬のように働いてますかー?(笑)
などと、のっけから無茶なことを言ってやまない、やねうらおです。

今回は、RPG型のゲームの作り方をいってみよう..とは言っても、いきなり全体を作っていくことは出来ないので、いくつかのステップに分割して取り組んでいきます。

まずは、古典的な、ドラクエタイプのRPGを思い浮かべてください。広大なマップ(世界地図のようなものですね)をさ迷いながら、敵を倒して主人公を成長させつつ、目的(?)を達するために旅をする―――まあ、そんな感じでしょうか。今回は、このうち、マップの移動という部分に焦点を当てて探っていきます。

マップの移動というのは、単純そうで、結構奥深い意味があるんです。これは、シューティングゲームなど、背景が移動するタイプのゲームすべてに共通して必要となるテクニックですんで、これを機に習得してしまいましょう。

今回がはじめて、という方は、私のホームページのほうで過去の記事が読めますので、そちらのほうも合わせてご覧ください。私も毎回、同じことを書いて行数を稼ぐと顰蹙を買いますので(笑)

あと、今回メインで使っていくプログラミングツール、YaneuraoGameScript2001、これはこの講座では略してygsと呼ぶことにします。

 §2.マップとは何か?
マップ(map)―――日本語に訳すると「地図」のことなのですが、画面上にはその地図の一部分しか映りません。主人公が歩くと、それに応じて、マップが移動していきます。この移動のことをスクロール、と呼ぶこともあります。スクロール(scroll)とは巻物のことです。画面が、巻物が巻かれていくときのように見えるからです。
マップについて、簡単に説明を書いてみましたが、「主人公が歩くと、それに応じて、マップが移動」するにはどうしたら良いか?だとか、マップはどうやって表示するのか?だとか、座標はどうやって管理するのか?だとか、わからないことだらけなのではないかと思います。
まずは、世界地図を想像してください。
えっ?この落書きは何かって?? 姉さん、これは世界地図ですよ!世界地図!(;´Д`)  右上の部分がなんだか犬に見えなくも無いですが、そういう心理テストではございません(笑)
こほん、こほん。気をとりなおしまして、この中央の赤い四角は、北海道のところを囲ったつもりなのですが、実際に画面に表示されるのは、この赤い四角のエリアだけだとします。つまり、この赤の四角は、一画面のサイズ、640×480ドットの大きさがあると。ここに主人公がいて、主人公が左下のほうに移動していけば、主人公を画面内に収めるために、画面は左下にスクロールしていき、本州が表示されたりもしますが、そのときは、この赤い四角(画面に表示されている部分)が、左下に移動したということになります。俳優を追いかけるテレビカメラにも似てますね。
この赤い四角(実際の画面での表示される部分)の左上の頂点が、この世界地図のどの位置にあるかを座標で表してみましょう。この世界地図の左上の座標を原点 (0,0) 、右下の座標は、少しややこしいですが、仮にひとつの画面が横640×縦480のサイズがあったとして、この世界地図が縦と横10画面分ずつの広さがあるとすれば ( 6400,4800) となります。この座標系を、ワールド座標だとかグローバル座標と呼びます。それに対して、この画面に表示されている範囲を表す、赤い四角の左上の点の座標を (0,0)と考える座標系を、スクリーン座標だとかローカル座標と呼びます。
ワールド座標とスクリーン座標は、相互に変換できますので、主人公や敵の居る座標をどちらで管理しても良いのですが、主人公が「九州に到達したら」というような地形に対する条件を判定するためには、ワールド座標のどこそこ、という条件でなければいけないので、RPGなどではワールド座標で扱うほうが、良いと思います。
それでは、まずは、マップをどうやって用意するのか考えてみましょう。パソコンのメモリには限りがあります。メモリ上には 640×480ドットのグラフィックは、せいぜい数枚程度しか入らないと考えて設計したほうが良いでしょう。そうなってくると、縦横10画面分、すなわち10画面×10画面で、全体としては100画面分の大きさがあることになりますが、こんな大きな画面は、メモリ上に収まらないことになります。
そこで、どうするのか、というのがひとつの課題になってくるのです。世界地図をいくつのかのエリアに分割して、エリアごとに、ハードディスクから読みなおす、というのも一つの方法だと思います。つまり、主人公が北海道から本州に飛び立つときに、いったん画面を暗くして、本州のグラフィックを読み込むのです。これでも悪くはありません。
しかし、ここでは、もっと融通の利く方法を考えていくことにしましょう。
 §3.特定のパーツから構成されるマップの場合

いま、マップが、いくつかのパーツから構成されているとしましょう。たとえば、野原と砂地と森と山と海の5つしか無いとします。各パーツは、それぞれ32×32ドットの大きさだとします。このパーツのことを、ここでは、マップチップと呼ぶことにします。また、マップチップを集めたビットマップを、マップバンク、あるいは単にバンクと呼ぶことにします。

マップバンクには、この5つのチップだけを用意すれば良いだけなので、32×32が5つ、横に並べて配置するならば160×32ドットのビットマップだけで済みますので、これならほとんどメモリを消費しません。

マップは、このマップチップを、ジグソーパズルのように敷き詰めていくと考えてください。一画面は、640×480ドットですから、32×32ドットのチップを敷き詰めるのならば、横に20、縦に15チップ、計 20×15 = 300チップを敷き詰めることになります。

すなわち、
マップ = マップチップを並べたもの
ということになります。
さきほどの「野原と砂地と森と山と海」の5つのチップの場合ならば、0番から順番に番号を振っておきます。すなわち、野原ならば0、砂地ならば1、森ならば2、山ならば3、海ならば4というようになります。そして、マップの左上から順番に、そこにはどのチップを使うのか、この0〜4の数字で指定していきます。1チップを1つの数字で表すのならば、300チップ分ですから、300の数字で済むことになります。

仮に100画面としても、300×100 = 30,000 チップ。すなわち、1つの数字が1バイトだとすれば、30,000バイト(30 KB)ですね。フルカラーの640×480ドットのビットマップが900KB程度であることを考えると、100画面分がたった30KBというのは、驚異的な小ささであることがわかるでしょう。

ここでは、この方法で制作を進めていくことにしましょう。

 §4.マップの作成
マップチップを敷き詰めて、マップを構成すると言っても、実際は、どうやって、そのデータを用意すれば良いのでしょうか?
実は、そのへんがまず一つ目の難関(?)であったりするのです。
ゲームをやるごとに新しいマップが自動生成されるタイプのRPGもありますが、ほとんどのゲームは事前に用意されたマップでしょう。普通、プロの方が制作する場合は、まずは、おおまかに紙の上で設計して、それを元に、専用のツールで配置していきます。マップをエディット(編集)するためのツールですから、通常、マップエディタと呼ばれています。
ところが、そのマップエディタを作るのが、また結構大変だったりするのです。下手すると、簡単なゲームを作るぐらいの手間がかかります。通例、プログラマが5人ぐらいで、1つのゲームをプログラムする場合は、そのうち、ひとりかふたりが、そういったツールの制作に回ります。それほど面倒なのです。
また、必要とされるマップエディタというのは、ゲームによって異なります。汎用的なマップエディタというのは、なかなか難しいのです。なぜなら、ゲームごとに必要とされる機能が微妙に違うからです。たとえば、地形の属性(主人公が歩ける歩けないだとか、見える見えないだとか、体力が回復するだとか、そういう情報)として、どんな情報を持たせるかは、ゲームによって異なるからです。
ここでは、特別なツールを使わずに済ませる方法をいくつか考えてみましょう。
1.手で直接入力する
一番原始的な方法ですが、有力です。方眼紙のような紙の上で、完全にマップを仕上げてしまい、それを数値として入力していきます。プログラムに直接データとして埋め込むような形にしても良いですが、通例、ゲームのプログラムを組む人と、マップの入力をする人とは作業を分担したい意味もあって、マップ用のテキストファイルにテキストエディタで入力して行くことになるでしょう。
数字の羅列をテキストファイルから読み込んでそれを配列に格納する処理が必要となるわけですが、これは、過去の記事でやっているので、そちらを参考にしてください。
2.ビットマップから変換する
案外、盲点かも知れませんが、ビットマップからマップデータに変換する方法もあります。ビットマップならば、ビットマップエディタが使えます。これには、Windows付属のペイントでも良いですし、PhotoShop等の市販のソフトでも良いです。ご自分の使い慣れているもので良いのです。さきほどの「野原と砂地と森と山と海」の5つのチップの場合ならば、野原ならば緑、砂漠ならば黄色、森ならば黒、山ならば白、海ならば青というように色を決めておき、その色をドット(ひとつの点)として配置していくのです。あとは、これを読み出して、データに変換するプログラムを書きます。ygs2kならば、importライブラリのGDIライブラリを使えば、ピクセルの色が取得できますので、比較的簡単ではないかと思われます。


このどちらも、実際に、私は経験したことがありますが、ある程度の規模になってくると、さすがにやる気が失せてくるのが欠点です(笑) ただ、マップエディタを自作するとなると、それもまた大きな作業で、マップエディタを作るが良いのか悩むところで、作り始めたら作り始めたで、自分はゲームを作っているのか、ゲーム制作ツールを作っているのか、さっぱりわからなくなってきます。プログラムって、往々にしてそういうことがあります。数学や物理の教科書を紐解いたり、全然違う分野の本を読んだり..はたから見ていて、ゲームを作っているようには見えないです。そういうときは、本人も、ゲームを作っている気にはなっていないのですが(笑)
そこで、そんな不毛な事態を打開すべく、今回、私の会社が開発したマップエディタをここで公開することにします。これは、(株)ウエストサイド様から依頼されて開発したものですが、(株)ウエストサイド様のご好意により、一般公開することが可能となりました。この場を借りて感謝の意を表する次第です。
余談ですが、私が一番最初にマップエディタを作ったのは、Waffleの『盗撮マニア』というゲームを作ったときなのですが、突貫工事で1日で作ったため、非常に使いにくいものでした。その後も『夜這いマニア』、『Revolution』でも、その使いにくいマップエディタを使い続け、ゲームデザイナーや、グラフィッカーの苦情も何のその(笑) いや、笑いごとじゃないんですけど。
それから、約2年の時を経て、素晴らしいマップエディタを私の会社のバイト君に作ってもらいました。(笑) 自分で使うプログラムだと、これくらいでいいやと、変に妥協をしてしまうため、あまり完成度の高いものが出来ないのです。人に作ってもらうなら、「これ、こうなってないと使いにくいでしょ」とか、いろいろ自分勝手な要望を出して、いいものを作ることが出来ます(笑) ゲームの現場でも、少人数でやっていて、プログラムを組む人とプランナーが同じ人だと、自分でゲームのアイデアを考えているときに「あー、こんな処理のプログラム書くの大変だなー」とか考えて、どんどんゲームの規模が小さくなっていくことが多々あります。あっ、、いえ、、うちのゲームのことでは無いんですけれども。^^;
 §5.マップエディタ

それでは、さっそく、マップエディタを使っていくことにしましょう。これを右クリックして、「対象をファイルに保存」してください。

解凍したあと、exeというフォルダのなかのMapEditorという実行ファイルを実行すれば、マップエディタが起動します。使いかたは、添付のテキスト(「操作説明.txt」です)を参照していただくとして、簡単に用語だけ解説しておくことにします。

まず、以下のようなダイアログが存在するはずです。


このマップエディタは、クォータービューと言って、斜め上から見下ろしているような特殊な視点や、高さ属性を持つチップをサポートするため、少し操作が煩雑ですが、そのへんは、実はまだ未完成の部分もあるので、無視していただくとして(笑)、必要なの下レイヤ・中レイヤ・上レイヤという部分です。

レイヤ(layer)とは何かというと、層のことです。PhotoShopをご存知のかたは、PhotoShopのレイヤを想像していただくとわかりやすいかと思います。一番下の層が、下レイヤ。そのひとつ上が中レイヤ。一番上が上レイヤということになります。ゲームによっては、こんなレイヤ分けは不要なのですが、私がここで想定しているゲームでは、主人公の手前に表示されるようなマップ(例、橋の下をくぐる)等も考慮しているため、このようなレイヤ分けが必要になってくるのです。具体的には、上レイヤは、主人公(ゲーム上のキャラクター)より、手前に描画されます。このとき、主人公は見えません。下レイヤは、主人公より背面に描画されます。

中レイヤは、この上レイヤと下レイヤの中間に属するもので、ちょっと説明するのが難しいのですが、たとえば、この図で、赤がマップの障害物青丸が主人公だとしましょう。

この主人公が、この障害物より下のほうに居る場合は、この中央の図の前後関係のようになります。つまり、主人公のほうが手前に表示されます。ところが、主人公が、この障害物の背面にまわりこむと、障害物のほうが前面に表示されます。このようになるのが、中レイヤです。

また、RPGタイプのゲームでは、キャラクターは、身長が違うものが居たりします。普通、キャラクターなどを描画するときは、描画先の左上の点(座標)を指定するのですが、上のように地形との前後関係を考慮しなければなりません。あるいは、キャラクター同士の前後関係を考慮しなければなりません。

普通は、このような前後関係が発生するときは、描画するキャラクターすべてをY座標でソート(並び替え)を行ない、Y座標の小さいものから順番に表示していきます。そうすれば、正しい前後関係で描画されます。ところが、キャラクター同士の前後関係のことを考えてみればわかると思うのですが、身長が違うキャラクターが混在している場合は、少しマズイのです。

たとえば、身長が100ドットあるキャラクターと、身長が10ドットしか無いキャラクターが居て、前者を (0,0) に描画し、後者を (0,10) に描画するときのことを考えてみると、Y座標は、後者のほうが大きいので、上の方法だと、後者を前面に表示してしまうことになります。前者を赤丸、後者を青丸で示すと下の左図のようになります。

これは、違うのです。右図のような前後関係になって欲しいことは、おわかりでしょう。どうすれば良いかというと、キャラクターの足元を基準(=ベースライン)として考え、そのベースラインのY座標が小さいものから順番に描画すれば正しい前後関係になるのです。このベースラインという考えかたは、この後、キャラクターパターンを定義するときに必要になってきますので覚えておいてくださいね。
このように、キャラクターは、ベースラインを定義してやる必要がある(あるいは、足元の座標で管理すべき)という理由がわかったところで、マップエディタの説明は終了です。
なお、表示箇所・編集箇所として、「下レイヤ」「中レイヤ」「上レイヤ」の選択が出来ます。初期状態では、「表示箇所」は、すべて表示するようになっていますが、上レイヤに正しく配置出来ているかなどを確認するときには、「下レイヤ」と「中レイヤ」を一時的に非表示にすると良いです。
また、主人公等の動くキャラクターは、マップとは異なるものですので、マップエディタ上では編集はできません。特定のゲーム専用のマップエディタならば、マップ上に敵キャラを配置したり出来るものを作ったりすることもありますが、あくまでこのマップエディタは、汎用性のあるものを目指して作ってありますので、ゲームに依存するような部分はなるべく用意していないのです。このマップエディタ自体のソース(プログラム)はすべて公開してありますので、Visual C++の使えるかたは、自分なりのマップエディタにカスタマイズしてみると良いかも知れませんね。
あと、私のホームページのほうで、マップ関係のツールをこのあと、いろいろリリースする予定があるので、よかったらそちらもチェックしてみてください。
 §6.マップデータフォーマット

マップエディタの使いかたがわかったところで、このマップエディタによって、どんなデータが作成されるかを、一応簡単に解説しておきます。

詳しいことは、マップエディタのexeフォルダのなかのファイルフォーマット.txtというテキスト文章に詳しい仕様が書いてあります。ygs2kは直接使わないという人も、マップエディタだけ使ってみる、ということも出来るはずです。

特に難しいところは無いと思うのですが、ygsを使っている方には、いくつか知らない用語が出てくると思いますので、この場をお借りして、簡単に解説します。

まず、ヘッダ部分のヘッダというのは、headerと綴ります。headというのはのことですから、頭にあるデータのことを言います。マップは、「どこにどのチップがあるのかという情報」だけでは無いのです。マップのサイズであるだとか、どのバンクを使用しているかだとか、そういう情報も含まれます。そういう、マップについての情報を、このヘッダ部分に収めます。このヘッダに対して、(マップの)本体部分は、人間の体にたとえて、ボディ(body)と呼ばれることもあります。

そして、

4バイト  このマップレイヤの形式で表す文字列
"TMA4"(0x544D4134)が入っています。
と書かれています。バイトというのは、メモリーの単位です。パソコンを買ったときに256MBだとか書いてありますね。このMBは、メガバイト、つまり1024×1024バイトのことです。ygsの変数は、1つが4バイトを必要とするので、バイト単位のデータを扱うときは、多少注意が必要です。それというのも、インテル系のプロセッサ(Pentiumおよび、その互換プロセッサ)では、ちょっと困ったことになるのです。
バイトが2つで、ワード(WORD)と呼びます。ワードが2つで、ダブルワード(DWORD)と呼びます。つまり、DWORDとは、4バイトのことなのですが、WORDもDWORDも、上位、下位、逆順で格納されるのです。具体的には、0x12345678(最初の0xは16進数表記を表します。16進数表記で2桁は1バイトに相当します。よって、この数字は4バイトの長さがあることになります。すなわちDWORDデータです)という数字ならば、これは、0x78 , 0x56 , 0x34 , 0x12という順番でメモリに格納されています。これを、エンディアン(endian)の問題というのですが、「エンディアン嘘つかない」んではなかったんですか、とか思ってしまいます(笑) まあ、自前でファイルを読み込むときは、そのへんにだけ注意してもらえれば良いかな、と。
ただ、ygsからこのマップデータを扱うときは、このマップデータを自前で読み出す必要は無いので、これ以上詳しい解説は割愛します。(既に、そういう機能がそなわっていますので)
先頭に、このように、マップを識別するための文字列を埋め込んでいるのは、他のファイルを間違って読み込ませたときに、“これは明らかに違うデータである”と即座に判定することが出来るようにするためです。たとえば、圧縮で有名なlzh形式ならば、先頭付近に「lh」という文字があり、これで判別が出来るようになっています。
 §7.ygs2001でマップ描画も楽々!

それでは、さっそく、マップエディタで編集したマップを表示してみることにしましょう。ygs2001の最新版を右クリックして、「対象をファイルに保存」してください。

いつも通り、ygs2001の実行ファイルが存在するフォルダにscriptというフォルダを作成し、そのフォルダのなかに、gamestart.cという名前のテキストファイルを作成し、そこにプログラムを書いていけばokです。

基本的な使いかたは、ygs2kのときと同じなので、今回から読まれている方は、私のホームページのほうから以前の記事を閲覧することが出来ますので、そちらをご覧くださいね。ygs2001の新しい機能については、前回の講座にありますので、そちらも合わせてご覧ください。
今回は、ygs2001ver1.10で用意された、マップ描画機能についての解説です。
何か良いサンプルデータがあれば良かったんですけど、最近、マップ使ったゲーム作ってない、やねうらおにとっては、適当なサンプル素材自体がありませんでした^^; そこで、サンプルデータ自体はつけることが出来なかったんですけども、プログラムを書いてみたので、見てください。
void main(){
 int x,y; // マップの表示位置。ワールド座標で指定する

 // マップレイヤーを設置
 MapLayerOn();

 // マップの読み込み
 MapLoad("test.map");

 // マップの表示箇所は(0,0)から
 x = 0; y = 0;

 loop {
 // マップの描画
  MapOnDraw(x,y,0);

 // 斜めにスクロールしてみる
  x++; y=y+2;

  halt;
 }

 // マップレイヤーを除去
 MapLayerOff();
}
どうでしょうか?簡単ですね。たったこれだけで、マップの表示が出来てしまうなんて!!実行すると、右斜め下にゆっくりスクロールしていくばずです。マップデータは、マップエディタで用意しておく必要があります。ygs2001の実行ファイルが存在するフォルダに、bankというフォルダを用意し、そのなかにバンクのビットマップデータを用意しておく必要があります。(マップデータを用意する方法については、マップエディタの使用方法を参照してください。上のプログラムは、ygs2001の実行ファイルと同じフォルダ内に存在するtest.mapというマップのファイルを読み込むときのプログラムです)
プログラムをよく見るとわかるかも知れませんが、これ、前回のシナリオ画面の描画方法と同じなんです。まずレイヤをOnにして、Loadでファイルを読み込んで、OnDrawで描画、そして使い終わればレイヤーをオフ。ygs自体、このように拡張性を備えていますので、どんどん新しい機能を取り込むことが出来ます。(このような拡張はVisual C++の使える人に限定されてしまいますけど)
上ので、ひとつだけ注意が必要なのは、MapOnDrawの引数です。ひとつ目とふたつ目は、マップ描画したい場所を、ワールド座標で指定するんですけど、3つ目は、どのレイヤを描画するかを指定します。この数字が0ならば、すべてのレイヤ、2は下レイヤ、3は中レイヤ、4は上レイヤということになっています。普通は、0を指定しておけば良いのですが、下レイヤを描画したのち、主人公を描画して、そのあと上レイヤを描画というときは、呼び出しを分割してやる必要があります。つまり、MapOnDraw( x , y , 2); のようにしたのちに、主人公を描画する部分は、自前で行ない、そのあと MapOnDraw( x , y , 4); だとかやります。このように、描画する順序を調整してやることにより、主人公より手前(前面)に描画される上レイヤを描画することが出来ます。
ここまで読んで、あれ?と思われた方もおられるでしょう。本当は、キャラクターの前後関係は、プログラムの処理順序とは無縁なものであるはずです。敵の移動処理を主人公の移動処理よりも先にやるからと言って、主人公を敵より手前に描画するわけでも無いでしょうし、敵を主人公より手前に描画するわけでも無いでしょう。しかし、描画のプライオリティ(重ね合わせの優先順位)は、描画した順番と逆順になってしまいます。わかりやすく言えば、あとから描画したほうが手前に表示されてしまうという、当たり前のような、当たり前で無いような事実があります。この問題を回避するために、描画のプライオリティを属性として持ち、それに従って描画するような描画プログラムを書いてやる必要があるのですが、今回の講座の範囲を超えてしまいますので、背面に表示したい下レイヤは先に、前面に表示したい上レイヤは後から描画処理を行なう、とだけ覚えておいてください。
あと言い忘れてましたがマップの全体サイズは、次のようにして取得できます。
// MapLoad後、マップ全体のドット数を取得できる
  MapGetSize(&x,&y);
これでマップに関しては完璧ですねヽ(´▽`)ノ
 §8.マップのスクロール位置の調整

キャラクターを画面に表示して、それに対して、画面を動かす―――ほとんどのゲームは、そういう作りになっているでしょう。主人公を追いかけて画面がスクロールしないといけませんから。

キャラクターの座標も、ワールド座標で保持することにしましたから、キャラクターの座標から、どこのマップを表示するかを決定してやる必要があります。

いま主人公の座標を、ワールド座標の( mx , my )に居るとします。この座標は、本当は主人公の足元、それも、ちょうど左右方向のど真ん中の座標なのですが、便宜上、主人公の大きさについては加味しないことにしましょう。

画面サイズは、640×480ドットです。主人公を画面のちょうど中央、スクリーン座標で言う(320,240)に来るように、画面を表示したいとしましょう。このとき、画面の左上(スクリーン座標 (0,0))の座標( sx , sy ) は、ワールド座標の( mx - 320 , my - 240)であれば良いのです。このように、調整します。

ところが、マップの端ではどうなるのでしょうか?世界地図の場合、上下と左右は繋がっているような気もしますが、ゲームで使用するマップの端はたいていは繋がっていないので、それ以上行けないわけです。それ以上行けないのに、主人公を画面の中央に表示しようとすると無理が生じてしまいます。たとえば、主人公がワールド座標の(0,0)に居るときは、主人公に対して右下にしかマップは無いわけで、そこより上とか、左とかは暗黒宇宙なわけです。そこを表示しようとしてはいけません。そのときは、主人公を画面中央に表示するのをやめて、主人公を左上のほうに表示するようにしてやるべきです。

この方法は、意外と簡単です。画面左上(スクリーン座標 (0,0))のワールド座標 ( sx , sy ) が、マップが正しく表示される範囲でなければ、範囲内に戻す補整処理をすれば良いのです。sxがゼロ未満の数字ならば、ゼロに。syも同様に。sxがマップの横端より大きければ、マップの端の横幅に。syも同様に。ただ、このとき、実際は画面サイズも考慮して、sx > マップの横幅 - 640  のときに sx を マップの横幅 - 640 という処理にしなければなりません。 sy についても同様で、 sy > マップの縦幅 - 480  のときに sy を マップの縦幅 - 480です。

これで、主人公が1キャラの場合の表示位置を調整する方法はわかりました。次に、主人公が複数キャラ居る場合の表示位置を確定させる方法について考えていきます。

まず、一般的な方法としては、平均を使います。たとえば2キャラ居て、それぞれの座標がワールド座標において ( mx1 , my1) と ( mx2 , my2 ) だとすれば、( (mx1 + mx2)/2 , (my1 + my2)/2 )の座標に主人公がひとりだけ居ると考えて、上記の方法で画面位置を確定させます。複数いるときも、同様です。こうしておけば、ある程度、うまくいきます。

この方法で、うまくいかないケースというのは、いずれかのキャラクターが画面からはみ出してしまう場合です。スクリーン座標において画面端に行ってしまったものを画面内に押し戻すような処理が必要だったりするのか、それとも、メインキャラのほうを画面は追いかけるようにするべきなのか、そのへんはゲームによって異なるでしょうから、一般的な話としては、ここまでとします。

あと、主人公は、常に画面中央に表示する場合を考えてきましたが、実際のゲームでは、主人公は常に画面中央では無いほうが良いのです。これは少し実践的な問題なのですが、主人公が移動して、画面の3分の2ぐらいの位置に来たときに初めてスクロールを開始するようにしたほうが、パニング(カメラ移動)が安定するのです。これは、主人公が細かく動いたときに、それに応じて画面が細かく動きつづけると非常に見辛いという意味です。この処理は、それほど難しくないので、考えてみてください。

 §9.まとめ
ygs2001によるマップ描画はいかがでしたでしょうか。マップエディタも、まだ作りたてなので、いろいろ不備があるかも知れませんが、私のホームページのほうでウキウキサポートしてますので、よろしくお願いします。ご意見、ご希望などもお待ちしております。
最近、ygsから始めて、そのあとVisual C++を勉強し、yaneSDK2ndを使ってプロとして仕事をされている方から感謝のメールをいただくことがあります。ygsだけでやるには、確かに限界があります。ygsを卒業という方は、yaneSDK2ndで新たなステップを目指し、頑張ってください。
次回は、キャラターのアニメーションについて詳しく書いていきたいと思います。

ページデザイン協力:さ〜