この記事は Riot.js Advent Calendar 2016 の最終日の記事です。ギリギリの更新ですみません;
ゲームにも使えるRiot.js
Riot.js、いいですよね。
実用的なアプリで利用されている印象ですが、ゲーム開発にも便利に使えそうだと感じたので、試しに使ってみました。
とりあえず3Dっぽい迷路をうろうろするゲームを作ってみましたが、1フレーム単位でシビアなタイミングが要求されるゲームでなければ非常に実用的だと思います。
デモは↓こちら。
Plunkerでのデモ
簡単な解説
- 迷路データ(0:通路、1:壁、など)を配列に格納
- 移動用のボタンを用意し、押下時に現在地データ(座標と方角)を書き換え
- 現在地データと迷路データをもとに、迷路画像などの表示を切り替え
- Plunker便利(Riot.js関係ない)
ソース
やっつけ感漂うソースですみません。特にsetToView
ファンクションのベタベタ感が……。
index.html
<html>
<body>
<mz-main></mz-main>
<script type="riot/tag" src="mz-main.html"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/riot/3.0.2/riot+compiler.min.js
"></script>
<script>
riot.mount('mz-main',{
current: {
x:2,
y:2,
direction:'E'
},
maze: [
// 0:passageway
// 1:wall
// 9:goal
/*N*/
[1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1],
[1,1,0,0,0,0,0,1,1],
[1,1,1,0,1,0,1,1,1],
/*W*/ [1,1,1,1,1,0,1,1,1], /*E*/
[1,1,1,0,0,0,0,1,1],
[1,1,1,1,1,1,9,1,1],
[1,1,1,1,1,1,1,1,1],
[1,1,1,1,1,1,1,1,1]
/*S*/
],
view: [
[0,0,0],
[0,0,0],
[0,0,0]
],
message: ""
});
</script>
</body>
</html>
mz-main.html
<mz-main>
<img style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/////AP/gXFgRAAAAA3RSTlP//wDXyg1BAAAAJUlEQVRo3u3BAQ0AAADCoPdPbQ43oAAAAAAAAAAAAAAAAAAAvg05MAABhS0NogAAAABJRU5ErkJggg==">
<!--20--><img if="{ opts.view[0][2] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/AP////+5HGLvAAAAA3RSTlP/AP9p7B++AAAAm0lEQVRo3u3YsQ2DQAAEQfQZhVAS/VjOXMCX4MRVugAIQJuhuXyCS3fZwxYYhmEYhmEYhmEYhuEH4d9h8zo+bHwL/hT8Lvg1C94KXgseBS+z4K3gteBR8NXT53greIVhGIZhGIZhGIZhGD7BKTjMgFNkSXknhaUZcIppKeOlgDgDTtE05doboTgl6j0MhmEYhmEYhmEYhmH4QfgPHchQ+/8y2XcAAAAASUVORK5CYII=">
<!--22--><img if="{ opts.view[2][2] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/AP////+5HGLvAAAAA3RSTlP/AP9p7B++AAAAlklEQVRo3u3YsQ3CMAAAQYsdsSKqKJNYjMOUDJAUkb6D+/4W+PEMDRiGYRiGYRiGYRiG4X/E83PqPn6tceo2Pgp+BzwfAW8F7wWvgOcIeCt4L3gFPEfAW8E7DMMwDMMwDMMwDMPwRWk4pNWRJkvbO2kspaWVZlrbeGkgpnWZpmnbtWkUp0V9EQzDMAzDMAzDMAzD8A/hLxZbbLXR08o2AAAAAElFTkSuQmCC">
<!--21--><img if="{ opts.view[1][2] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/AP////+5HGLvAAAAA3RSTlP/AP9p7B++AAAAWklEQVRo3u3YQQ0AIAwAsQWP+EEPKjEAYcl+S+9fAxezUMAwDMMwDMMwDMMwDLfG+1EKr7g2YBiGYRiGYRiGYRiGYRiGYfiPS4s6HwzDMAzDMAzDMAzDcCN8ABfVAM1V0PxpAAAAAElFTkSuQmCC">
<!--10--><img if="{ opts.view[0][1] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/AP////+5HGLvAAAAA3RSTlP/AP9p7B++AAAA7ElEQVRo3u3aoQ0DQQxE0ZWZC3FJ108UlgJcQkiqDDspd8j7ScA3f2CoZ9YBbonFYrFYLBaLt/HnvJ7j8+JN8IvgJ8GPJrgIToKD4NUEF8FJcBA8Df2Li+AkOAgehr7gIjgJDoJnoa+4CE6Cg+BR6BsugpPgIHgS+o6L4CQ4CB6EFovFYrFYLBaLxWKxWCwWi8VisfhvMHqOo7c8KgQaYFSCoPoFFT8NMCq7UM2GCr4GGJWaqE5FRW4DjMprVJujwr4BRiMFNI9Aw4wGGI1R0AwGDXAaYDQ6QnOnjaEVmngd4MRisVgsFovF2/cFpGO+FroQDfoAAAAASUVORK5CYII=">
<!--12--><img if="{ opts.view[2][1] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/AP////+5HGLvAAAAA3RSTlP/AP9p7B++AAAA7UlEQVRo3u3aPUqEMRhG0eAe/QhWwZUEl+Mq/RkZbCcHBOG+/SnS5j7jGW6Ew+FwOBwOh/8OX+/3exy/7HG/h/Gr4DfA1xPgKXgJ3oCvAXgKXoI34GsAnoKX4A3488nneApegjfgrycf4yl4Cd6Av598iqfgJXgDvj35EE/BS/AG/PPkcDgcDofD4XA4HA6Hw+FwOBwOh/8Vps9x+5anIEApgiKI5RcKP5ScKHZZZqPAR2mRoqblVAq5lJApXls2p2BPUwEaKdg8goYZNAmhMYrNYGiAQ9MfGh3Z3ImGVjTx+nXhcDgcDofD4eP7ADDdswa+58hZAAAAAElFTkSuQmCC">
<!--11--><img if="{ opts.view[1][1] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/AP////+5HGLvAAAAA3RSTlP/AP9p7B++AAAAWUlEQVRo3u3aMREAIAwAsR4e8YMeVGKAobSM+T0OPmajgGEYhmEYhj/gneyKV6QaMAzDMAzDMAzDMAzDMAzDMAzDMAzDMAzDMAzDcAW3Fq/3YBiGYRiG4XIHzWHmM1h1cIAAAAAASUVORK5CYII=">
<!--00--><img if="{ opts.view[0][0] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/////AP/gXFgRAAAAA3RSTlP//wDXyg1BAAAA7UlEQVRo3u3bsRECAQwDQZFQxJfo0qiSHtiImXO+weXy7vP77RH8FvwSvBP8CH4LfgmG6En0JHoSPYmeRE+iJ9GT6En0JHoSPYmeRE+iJ9GT6En0JHoSPYmeRE+iJ9GT6En0JHoSPYmeRE+iJ9GT6HA4HA6Hw+FwOBwOh8PhcDgcDofD4XA4HA6Hw+FwOBwO/wGmcRnN2mhQd4BpREjzRRpOHmAai9JMlQayB5hGwTRHpiH0AabxN83OafB+gGnkT+8F9NhwgOmZg95I6IHlANPTDr0L0aPSAabnLHoLo4e0A0xPePT+R4+HkPz5AqMk9H6B56i0AAAAAElFTkSuQmCC">
<!--02--><img if="{ opts.view[2][0] == 1 }" style="position:absolute;top:4px;left:4px;" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwAgMAAABDOwEBAAAACVBMVEUAAAD/AP////+5HGLvAAAAA3RSTlP/AP9p7B++AAAA8ElEQVRo3u3boRGAABADwWsSBkkplE4PrGPyfsX5fMf3OwN8Cb4FP0lykpwkJ8lJcpKcJCfJSXKSnCQnyUlykpwkJ8lJcpKcJCfJSXKSnCQnyUlykpwkJ8lJcpKcJCfJSXKSnCQnyUny8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8I8wjcts1kaDOpry0YjQ5os0nKTJJo1FbaZKA1ma5tIo2ObINISmCTaNv212ToN3mtrTyN/eC+ixgV4q6JnD3kjogYVeZ+hpx96F6FGJXqToOcvewughjV7h6AnP3v/o8fB8AUGcKJHXD01AAAAAAElFTkSuQmCC">
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<div>
({ opts.current.x },{ opts.current.y })
{ opts.current.direction }
{ opts.message }
</div>
<table>
<thead></thead>
<tbody>
<tr>
<td></td>
<td><button onclick={ moveToFront }>↑</button></td>
<td></td>
</tr>
<tr>
<td><button onclick={ turnToLeft }>←</button></td>
<td><button onclick={ turnToBack }>↓</button></td>
<td><button onclick={ turnToRight }>→</button></td>
</tr>
</tbody>
</table>
<script>
this.on('mount', function(){
console.log(this);
this.setToView();
this.update();
});
this.moveToFront = function(e) {
var d = opts.current.direction;
var x = opts.current.x;
var y = opts.current.y;
if (d == 'N') y--;
if (d == 'S') y++;
if (d == 'E') x++;
if (d == 'W') x--;
if (opts.maze[y][x] != null && opts.maze[y][x] != 1) {
opts.current.x = x;
opts.current.y = y;
if (opts.maze[y][x] == 9) {
opts.message = "*GOAL*";
} else {
opts.message = "";
}
this.setToView();
} else {
opts.message = "*OUCH*";
}
}
this.turnToLeft = function(e) {
var d = opts.current.direction;
if (d == 'N') opts.current.direction = 'W';
if (d == 'S') opts.current.direction = 'E';
if (d == 'E') opts.current.direction = 'N';
if (d == 'W') opts.current.direction = 'S';
opts.message = "";
this.setToView();
}
this.turnToRight = function(e) {
var d = opts.current.direction;
if (d == 'N') opts.current.direction = 'E';
if (d == 'S') opts.current.direction = 'W';
if (d == 'E') opts.current.direction = 'S';
if (d == 'W') opts.current.direction = 'N';
opts.message = "";
this.setToView();
}
this.turnToBack = function(e) {
var d = opts.current.direction;
if (d == 'N') opts.current.direction = 'S';
if (d == 'S') opts.current.direction = 'N';
if (d == 'E') opts.current.direction = 'W';
if (d == 'W') opts.current.direction = 'E';
opts.message = "";
this.setToView();
}
this.setToView = function() {
opts.view[1][0] = opts.maze[opts.current.y][opts.current.x];
var d = opts.current.direction;
if (d == 'N') {
opts.view[0][2] = opts.maze[opts.current.y-2][opts.current.x-1];
opts.view[1][2] = opts.maze[opts.current.y-2][opts.current.x];
opts.view[2][2] = opts.maze[opts.current.y-2][opts.current.x+1];
opts.view[0][1] = opts.maze[opts.current.y-1][opts.current.x-1];
opts.view[1][1] = opts.maze[opts.current.y-1][opts.current.x];
opts.view[2][1] = opts.maze[opts.current.y-1][opts.current.x+1];
opts.view[0][0] = opts.maze[opts.current.y][opts.current.x-1];
opts.view[2][0] = opts.maze[opts.current.y][opts.current.x+1];
}
if (d == 'S') {
opts.view[0][2] = opts.maze[opts.current.y+2][opts.current.x+1];
opts.view[1][2] = opts.maze[opts.current.y+2][opts.current.x];
opts.view[2][2] = opts.maze[opts.current.y+2][opts.current.x-1];
opts.view[0][1] = opts.maze[opts.current.y+1][opts.current.x+1];
opts.view[1][1] = opts.maze[opts.current.y+1][opts.current.x];
opts.view[2][1] = opts.maze[opts.current.y+1][opts.current.x-1];
opts.view[0][0] = opts.maze[opts.current.y][opts.current.x+1];
opts.view[2][0] = opts.maze[opts.current.y][opts.current.x-1];
}
if (d == 'E') {
opts.view[0][2] = opts.maze[opts.current.y-1][opts.current.x+2];
opts.view[1][2] = opts.maze[opts.current.y][opts.current.x+2];
opts.view[2][2] = opts.maze[opts.current.y+1][opts.current.x+2];
opts.view[0][1] = opts.maze[opts.current.y-1][opts.current.x+1];
opts.view[1][1] = opts.maze[opts.current.y][opts.current.x+1];
opts.view[2][1] = opts.maze[opts.current.y+1][opts.current.x+1];
opts.view[0][0] = opts.maze[opts.current.y-1][opts.current.x];
opts.view[2][0] = opts.maze[opts.current.y+1][opts.current.x];
}
if (d == 'W') {
opts.view[0][2] = opts.maze[opts.current.y+1][opts.current.x-2];
opts.view[1][2] = opts.maze[opts.current.y][opts.current.x-2];
opts.view[2][2] = opts.maze[opts.current.y-1][opts.current.x-2];
opts.view[0][1] = opts.maze[opts.current.y+1][opts.current.x-1];
opts.view[1][1] = opts.maze[opts.current.y][opts.current.x-1];
opts.view[2][1] = opts.maze[opts.current.y-1][opts.current.x-1];
opts.view[0][0] = opts.maze[opts.current.y+1][opts.current.x];
opts.view[2][0] = opts.maze[opts.current.y-1][opts.current.x];
}
}
</script>
</mz-main>