LoginSignup
6
6

More than 5 years have passed since last update.

第8話 次郎!ダンジョン見つけたyo!

Posted at

知らない人の家に勝手に入ってはいかん!

今日も、太郎と次郎は街を徘徊していたんですが、そのとき、太郎がダンジョンを発見した様子をコード化しました。

canvas.png

今回は、Three.jsを使って発見したダンジョンを表示したいと思います。

構成

マインクラフトみたいにCubeで構成してみます。Cubeは壁、扉、天井、床の4種類を用意します。そのCubeを3層(天井、自分のいる階層、床)で並べます。

hoge.js
var mapData = {
  ceiling : [
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■"
  ],
  wall : [
    "■■■■■■■■■■",
    "■   ■    ■",
    "■   ■□■■ ■",
    "■■□■■  ■ ■",
    "■■ ■■  ■ ■",
    "■■ ■■■□■ ■",
    "■      □ ■",
    "■■■■■■■■■■"
  ],
  floor : [
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■■■■■■■■■■",
    "■ ■■■■■■■■",
    "■■■■■■■■■■"
  ]
};

■ と □ の部分にCubeを配置します。それぞれの層に合わせて ■ の部分にそれぞれの層に合わせたCubeを配置します。

Cubeの作成準備

形状(Geometry)を決めて、その表面素材(Material)を用意し、これを使って物体(Mesh)を作成するという手順になります。

hoge.js
var blockSize = 10;
var geometry = new THREE.CubeGeometry(blockSize, blockSize, blockSize);

これで、1辺の長さが10の立方体の形状が出来上がります。今回はすべてCubeなので、形状は1つだけ作成しておきます。

今度は、それぞれのCubeが壁、扉、天井、床に見えるように素材を用意します。これについて、今回はpng画像を使います。
まず、png画像を読み込みます。そのあと、素材の作成になります。

hoge.js
var textureFile = {
  wall    : "img/wall.png",
  door    : "img/door.png",
  ceiling : "img/ceiling.png",
  floor   : "img/floor.png",
};
var loader = new THREE.TextureLoader();
var texture = {
  wall   :loader.load(textureFile.wall),
  door   :loader.load(textureFile.door),
  ceiling:loader.load(textureFile.ceiling),
  floor  :loader.load(textureFile.floor)
};
var material = {
  wall   : new THREE.MeshPhongMaterial({map:texture.wall, bumpMap:texture.wall, bumpScale: 0.05}),
  door   : new THREE.MeshPhongMaterial({map:texture.door, bumpMap:texture.door, bumpScale: 0.08}),
  ceiling: new THREE.MeshPhongMaterial({map:texture.ceiling, bumpMap:texture.ceiling, bumpScale: 0.09}),
  floor  : new THREE.MeshPhongMaterial({map:texture.floor, bumpMap:texture.floor, bumpScale: 0.09})
};

今回の画像が岩肌っぽいので、バンプマッピングで凸凹感を出します。

さて、形状の定義と素材の準備ができました。構成で示したようにCubeを並べていきます。

シーン

作成したCubeをどこに並べるかというと、空間(Scene)に並べます。なので、空間を作っておく必要があります。

hoge.js
var scene = new THREE.Scene();

Cubeの配置

配置データを参照しつつ、空間に配置します。
壁の配置はこんな感じになります。

hoge.js
for (y = 0; y < mapData.wall.length; y++) {
  for (x = 0; x < mapData.wall[y].length; x++) {
    if (mapData.wall[y].charAt(x) == "") {
      var cube = new THREE.Mesh(geometry, material.wall);
      cube.position.set(blockSize * x, 0, blockSize * y);
      scene.add(cube);
    }
  }
}

あとは、こんな感じでしょうか...

hoge.js
// 扉の配置
if (mapData.wall[y].charAt(x) == "") {
  var cube = new THREE.Mesh(geometry, material.door);
  cube.position.set(blockSize * x, 0, blockSize * y);
  scene.add(cube);
}
// 天井の配置
if (mapData.ceiling[y].charAt(x) == "") {
  var cube = new THREE.Mesh(geometry, material.ceiling);
  cube.position.set(blockSize * x, blockSize, blockSize * y);
  scene.add(cube);
}
// 床の配置
if (mapData.floor[y].charAt(x) == "") {
  var cube = new THREE.Mesh(geometry, material.floor);
  cube.position.set(blockSize * x, -blockSize, blockSize * y);
  scene.add(cube);
}

太郎と次郎

配置データの上を北向きとして、下図の位置に二人がいるとします。
map.png

hoge.js
// 方角
var direction = {
  north : 0,
  west  : 1,
  south : 2,
  east  : 3
};
// プレイヤー情報
var Player = {
  x : 6,
  y : 1,
  direction : direction.west,
};

場所とどっち向いてるかを記憶しておきます。
さて、Cubeを空間に配置して、二人の位置が決まったので、実際にどう見えるのか?が問題です。
これが、カメラです。カメラから見たCubeの配置が投影されるわけで、このカメラは二人の目です。

hoge.js
// カメラ用パラメータ
var cameraParams = {
  fov : 95,
  aspect : 1.8,
  near : 1,
  far : 50
};
var camera = new THREE.PerspectiveCamera(
  cameraParams.fov, cameraParams.aspect, cameraParams.near, cameraParams.far
);
camera.position.set( Player.x * blockSize, 0, Player.y * blockSize );
camera.rotation.y = rotationAngle[Player.direction];

3Dっぽく見えるように透視投影のカメラを作ります。カメラには、画角(fov)とアスペクト比(aspect)、見える範囲(near~far)を指定します。場所と向きをさっき記憶した情報から取得して、カメラの位置と向きを設定します。

描画

表示サイズを決めて、rendererを作成し、描画します。

hoge.js
// 表示サイズ
var mazeScreen = {
  width : 480,
  height : 270
};
var canvas = document.getElementById("game");
var renderer = new THREE.WebGLRenderer();
renderer.setSize( mazeScreen.width, mazeScreen.height );
canvas.appendChild( renderer.domElement );
var render = function(){
  renderer.render(scene, camera);
};
var animate = function(){
  render();
  requestAnimationFrame( animate );
};
animate();

いや、真っ暗だし...

光源

はい、人もそうですけど、光ないと何も見えませんw
空間に光を追加します。太陽の光は入ってこない設定なので、懐中電灯とかが頼りです。今回はスポットライト的な懐中電灯ではなく、ろうそく的な感じで光を追加します。

hoge.js
var lightParams = {
  point   : 0xffffff
};
var light = new THREE.PointLight( lightParams.point, 3, 10, 1 );
light.position.copy( camera.position );
light.position.z -= 1;
scene.add( light );

ろうそく(点光源)を空間に追加します。位置はカメラのちょっと前ぐらいで。光の色、明るさ、光の届く範囲、減衰率を指定します。光の届く範囲を0にすると、無限に光が届きますw

これで見えますよね。ぅん。
しかし、ブラウザのレンダリング能力ってすごかったんですね...

いよいよ、次回最終回は、このダンジョンを徘徊してみますw

こんな感じ(デモ)で...

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6