フロントエンド開発Blog

オレには鈍器がある

JavaScript , enchant.js , map , random , rot.js

オレには鈍器がある 作成途中のコードです。
前回からの違いは以下の通りです。

実装機能:
・Ondrej Zara様のrot.jsによるランダムダンジョン生成を実装しました
・ランダム生成されたダンジョンから衝突判定を持たない座標(床)にランダムでplayerを配置するよう変更しました

http://jsdo.it/oredon/qSJV

ランダムマップの生成について取り上げてご紹介いたします。このランダムマップ生成にはrot.js(rot.js is (C) 2012-2014 Ondrej Zara)という、素敵すぎるライブラリを利用させていただきました。

rot.js is (C) 2012-2014 Ondrej Zara

公式サイトに書いて有るとおりに実装すれば良いだけですが、それでは記事が書けないので少し説明をさせてください。

function createFloorMap(){
	var col = [];
	var map = [];
	
	for( var x=0; x < MAP_HEIGHT; x++ ){
		col[x] = [];
		for( var y=0; y < MAP_WIDTH; y++ ){
			col[x][y] = null;
		}
	}
	
	var floorMap = new ROT.Map.Digger(MAP_WIDTH, MAP_HEIGHT, 
					{roomWidth:[MAP_MIN_ROOM_WIDTH, MAP_MAX_ROOM_WIDTH], 
					roomHeight:[MAP_MIN_ROOM_HEIGHT, MAP_MAX_ROOM_HEIGHT], 
					corridorLength:[MAP_MIN_ROAD_LENGTH,MAP_MAX_ROAD_LENGTH], 
					dugPercentage:0.3});
	
	while(true){
		floorMap.create(function(x,y,type){
			col[y][x] = type;
		});
		var rooms = floorMap.getRooms();
		if(rooms.length >= MAP_MIN_ROOM_NUM && rooms.length <= MAP_MAX_ROOM_NUM){
			break;
		}
	}
	
	for( var x=0; x<MAP_HEIGHT; x++ ){
		map[x] = [];
		for( var y=0; y<MAP_WIDTH; y++ ){
			if(col[x][y]){
				if(x != MAP_HEIGHT -1 && col[x+1][y]){
					map[x][y] = MAPIMG_WALL;
				}else{
					map[x][y] = MAPIMG_WALL2;
				}
			}else{
				map[x][y] = MAPIMG_ROAD;
			}
		}
	}
	
	return {collisionData:col, mapData:map, mapObj:floorMap, rooms:rooms};
	
}

rot.jsの公式ページで紹介されているとおり、ROT.Map.Diggerをnewしてインスタンス化します。そしてcollisionDataを生成し、そのデータを元にmap画像用に別途map配列を生成します。これだけです。本当に便利すぎて泣きました。

今回は「Digger」という種類のマップを生成しましたが、公式ページを見るとまだまだたくさんの種類のマップがあります。色々調べてみると面白そうですね。

それから、ランダムマップに変更したらPlayerの初期配置位置も生成されたマップに追従させる必要がでてきます。

ランダムマップにはいくつかのroomというデータがありますが、このroomの中から1つ選択肢、そのroom内のどこかの座標にPlayerをセットするロジックを追加しました。

function calcRandOffsetByRoom(rooms){
	var ret = [];
	var roomsNum = rooms.length;
	
	//ランダムに部屋を指定
	var targetRoomNum = randChois(0,roomsNum-1);
	
	//部屋の構造
	/**
	 * 
	 * (x1,y1)            (x2,y1)
	 *    +------------------+
	 *    |                  |
	 *    |                  |
	 *    +------------------+
	 * (x1,y1)            (x2,y2)
	 * 
	 */
	ret[0] = (16 * randChois( rooms[targetRoomNum]._x1 , rooms[targetRoomNum]._x2 ) ) - 8;
	ret[1] = (16 * randChois( rooms[targetRoomNum]._y1 , rooms[targetRoomNum]._y2 ) ) -16;
	
	return ret;
}
function randChois(min,max){
	return Math.floor( Math.random()*(max-min+1) ) + min;
}

ランダムマップ生成時に作ったroomsデータを受け、ランダムにroom内のどこかのx,y座標を配列で返します。これで壁に埋まった状態でスタートするというヘンテコな状況は避けられます。

今回はランダムマップ生成についての記事を書こうとしたらなんだかrot.jsの紹介記事になってしまった感があり、反省しております。しかし、それだけ本当に完成度の高いライブラリのため、ランダムマップなゲームを作りたい時はrot.jsを使わせていただくことを視野にいれるのも良いのではと思います。

ページトップへ

関連ページ

ページトップへ