blog/2007-11-11


Total: 2378 / Today: 1 / Yesterday: 1

GoogleMapsを使いこなせ(第1回)

最近、マビノギ用のGoogleMapsの開発をしている。GoogleMaps APIにはカスタムレイヤーという機能があり、これを用いることによって自分の地図を上書きすることが可能である。これを応用することでゲーム上のマップをGoogleMapに貼り付けることも可能なわけだ。カスタムレイヤーとここでは言っているが、実際はgetTileUrlという関数である。

つまり、既存のGoogleMapに自作画像を貼り付けているだけに過ぎない。GoogleMapに表示されるGoogleのロゴをクリックするとわかるが、画像貼り付けの開始位置に相当する場所は、アラスカ半島の西側の日付変更線の近くである。ここで、問題が発生する。GoogleMapは256ピクセルの倍数で縮尺を決めているが、このときの座標はどうなるかである。

仮に座標の定義をx,y,zとし、zを縮尺とする。ここで、左上を0,0,0と定義するとして、そこの画像の縮尺zを1段階拡大すると0,0,1、0,1,1、1,0,1、1,1,1という画像を用意しなければならなくなる。ここまではいい。問題なのは、そこから1タイル右に移動した、0,1,0の画像の拡大である。先ほどの定義からすると、2,0,1、3,0,1、2,1,1、3,1,1となり、画像を求める事が困難になる。縮尺を拡大するとタイルの量は2乗に比例するので、当然画像の座標のずれも激しくなってくる。いったいどういう命名規則なのだろうか?

結局、これを調べるよりも先にタイル自動生成プログラムを使用することにした。試したのは以下の通り。

1番目は使いにくい。2番目は動作が軽いがJpeg限定。結局3番目を使った。PhotoShopのバッチ処理を使うので信頼できる。画像のマージにもPhotoshop使っているので都合がよかった。さらに良いことに、マビノギの地図のラインは256x256で引かれているのでGoogleMapの規格にも便利だった。(もっとも、たいていのネトゲのマップは32の倍数でマップがかかれているようだが)

カスタムタイルを格納するレイヤーを生成する

var (マップのオブジェクト名) = new GTileLayer(new GCopyrightCollection(""), 0, 5);

次に、タイルの画像を呼び出すスクリプト

var getCustomLayerUri = function(tile, zoom) {
	var x = tile.x;
	var y = tile.y;
	return "(画像格納ディレクトリ)" + z + "_" +x+"_"+y+".png";

カスタムタイルで地球儀をつくるスクリプトはいくつかあった。

1:

function createCustomProjection() {
	var projection = G_NORMAL_MAP.getProjection();
	projection.tileCheckRange = function (tile, zoom, tilesize) {
		var tileBounds = Math.pow(2, zoom);
		if (tile.y < 0 || tile.y >= tileBounds) {
			return false;

2:

function createCustomProjection() {
	var projection = G_NORMAL_MAP.getProjection();
	projection.tileCheckRange = function (tile, zoom, tilesize) {
		var maxTile = Math.floor(this.getWrapWidth(zoom) / tilesize);
		if (tile.x < 0 || tile.x >= maxTile || tile.y < 0 || tile.y >=maxTile) {
			return false;

3:

function createCustomProjection() {
	var projection = G_NORMAL_MAP.getProjection();
	projection.tileCheckRange = function (tile, zoom, tilesize) {
		var mapsize = 256*Math.pow(2,zoom);
		if (tile.y < 0 || tile.y * tilesize >= mapsize) {
			return false;

今回は、1番目を使った。なお、3番目はドラクエで使われているやつ。

レイヤーをマップとする

var (レイヤー)= new GMapType([getCustomLayerUri()], createCustomProjection(), "(レイヤーのタイトル)",{errorMessage:"画像がないか、読み取りに失敗しました。"

描画

var map = new GMap2(document.getElementById("(マップを描画するオブジェクト)"), {mapTypes: [(レイヤー)]

これで、<div id="(マップを描画するオブジェクト)"></div>の位置にマップが表示されるようになった。


Last Modified: 2007-11-13 07:33:45