view source
JavaScript
document.title = 'ボンバーマン';
var style = document.createElement('style');
style.innerText = 'html,body{overflow:hidden;cursor:crosshair;}';
document.getElementsByTagName('head').item(0).appendChild(style);
var canvas = document.createElement('canvas');
var w = document.body.clientWidth;
var h = document.body.clientHeight;
var min = Math.min(w,h);
canvas.setAttribute('width',w);
canvas.setAttribute('height',h);
let demo = document.getElementById('demo');
demo.appendChild(canvas);
var ctx = canvas.getContext('2d');
var cx = w/2;
var cy = h/2;
var t = 0;
var rAry = [];
var grayLine;
var mapAry = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
];
mapAry[1][2] = 2;
var len = mapAry.length;
console.log(len);
var crossAry = [
[0,0],
[-1,0],
[1,0],
[0,-1],
[0,1],
];
var max = mapAry.length;
var iw = Math.floor(min/max);
var ih = Math.floor(min/max);
var mg = Math.floor((w - mapAry.length*iw) /2);
var blockCount = 0;
//https://taira-komori.jpn.org/arms01.html
var se = new Audio('bomb.mp3');
se.volume = 0.2;
//http://blog.pipoya.net/blog-entry-405.html
var imgs = {};
imgFiles = [
'bomb.png',
'bomb-block.png',
'bomb-fire.png',
];
imgFiles.forEach(function(v){
var img = new Image();
img.src = v;
imgs[v] = img;
});
var img = new Image();
img.src = 'bomb.png';
var face = new Image();
face.src = 'homomi.png';
var bombs = [];
var fires = [];
function setBlocks() {
var i = 0;
var j = 0;
mapAry.forEach(function(line){
i=0;
//console.log(line);
line.forEach(function(v){
if(v===0 && Math.random()*9>7){
mapAry[j][i] = 2;
}
i++;
});
j++;
});
}
function draw() {
ctx.clearRect(0, 0, w, h);
ctx.strokeStyle = 'none';
ctx.lineWidth = 0;
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, w, h);
ctx.lineWidth = 1;
var r = 0;
rAry = [];
var i = 0;
var j = 0;
blockCount = 0;
mapAry.forEach(function(line){
i=0;
//console.log(line);
line.forEach(function(v){
if(v===1){
ctx.fillStyle = '#7C787C';
ctx.fillRect(mg+i*iw, j*ih, iw, ih);
ctx.fillStyle = '#3A3A3F';
ctx.fillRect(mg+i*iw, j*ih+ih*9/10, iw, ih/10);
ctx.fillStyle = '#3A3A3F';
ctx.fillRect(mg+i*iw+iw*39/40, j*ih, iw/40, ih);
ctx.fillStyle = '#BEBCBE';
ctx.fillRect(mg+i*iw, j*ih, iw/40, ih);
} else if(v===0 || v === 2){
if((i+j)%2===0){
ctx.fillStyle = '#63AA51';
} else {
ctx.fillStyle = '#7EC160';
}
ctx.fillStyle = '#3F720F';
ctx.fillRect(mg+i*iw, j*ih, iw, ih);
}
if(v===2){
blockCount++;
ctx.drawImage(imgs['bomb-block.png'], 0,0,104,86, mg+i*iw, j*ih, iw, ih);
}
i++;
});
j++;
});
if(blockCount<5 && Math.random()* 99 > 80){
let ii = Math.floor(Math.random()*len);
let jj = Math.floor(Math.random()*len);
if(mapAry[ii][jj] === 0){
//mapAry[ii][jj] = 2;
}
}
bombs.forEach(function(bomb){
bomb.draw();
});
//ctx.drawImage(imgs['bomb-fire.png'], 104*2-2*104,84*2-0*84,104,84, 0, 0, iw, ih);
bombs.forEach(function(bomb, i, ar){
if(bomb.o().isDead){
delete ar[i];
}
});
bombs = bombs.filter(v => v);
fires.forEach(function(fire){
fire.draw();
});
fires.forEach(function(fire, i, ar){
if(fire.o().isDead){
delete ar[i];
}
});
fires = fires.filter(v => v);
}
draw();
function setBomb(x,y) {
//console.log(x);
//ctx.putImageData(grayLine,0,0);
var ii=0;
ctx.strokeStyle = '#ff0000';
ctx.lineWidth = 4;
var ex = -iw;
var ey = -ih;
var i = 0;
var j = 0;
var isSet = false;
for(j=0;j<mapAry.length;j++){
if(y > j*ih && y < j*ih+ih){
ey = j*ih+ih/2;
break;
}
}
for(i=0;i<mapAry.length;i++){
if(x > mg+i*iw && x < mg+i*iw+iw){
ex = mg+i*iw+iw/2;
break;
}
}
//console.log([i,j,mapAry[i][j]]);
if(mapAry[j][i] === 0){//ji逆
isSet=true;
}
if(isSet){
ctx.beginPath();
//ctx.fillStyle = '#000000';
//ctx.arc(ex, ey, iw/3, 0, Math.PI * 2, true);
ctx.fill();
//ctx.drawImage(img, 32,0,32,32, ex-iw/2, ey-ih/2, iw, ih);
bombs.push(new Bomb({i:i,j:j,x:ex-iw/2,y:ey-ih/2}));
}
}
//********************************************
var Bomb = function(_o){
var that = this;
var t = 0;
var x = _o.x;
var y = _o.y;
var i = _o.i;
var j = _o.j;
var isDead = false;
that.o = function(){
return {
x:x,
y:y,
isDead:isDead,
}
}
that.draw = function(){
t++;
sy = 0;
sx = (t % 3)*32;
if(t===30){
isDead = true;
}
if(t===27){
se.currentTime = 0;
se.play();
}
if(t>27){
//ctx.drawImage(imgs['bomb-fire.png'], 0,0,520,424, x-iw*2, y-iw*2, iw*5, ih*5);
} else if(t>29){
//ctx.drawImage(imgs['bomb-fire.png'], 520,0,520,424, x-iw*2, y-iw*2, iw*5, ih*5);
}
if(t===24 && blockCount>0){
setFire({i:i,j:j,x:x,y:y});
}
if(t>25){
sy = 5*32;
sx = (t - 25)*32 +32*3;
} else if(t>21){
sx = (t-21)*32;
sy = 1*32;
}
ctx.drawImage(img, sx,sy,32,32, x, y, iw, ih);
if(t<24){
//ctx.drawImage(face, x+4, y+4, iw-8, ih-8);
}
}
return that;
}
var setFire = function(_o){
var x = _o.x;
var y = _o.y;
var i = _o.i;
var j = _o.j;
crossAry.forEach(function(d){
for(k=1;k<4;k++){
let dx = d[0]*k;
let dy = d[1]*k;
let ii = i+d[0]*k;
let jj = j+d[1]*k;
let isSet=false;
let isEnd=false;
if(ii>0 && jj > 0 && ii< len && jj< len){
if(mapAry[jj][ii] === 2){//ji逆
mapAry[jj][ii] = 0;
}
if(mapAry[jj][ii] === 0){
isSet=true;
}
}
if(isSet){
let fire = new Fire({i:ii,j:jj,x:x+iw*dx,y:y+ih*dy,pos:d,isEnd:isEnd});
fires.push(fire);
} else {
break;
}
if(d[0] === 0 && d[1] === 0){
break;
}
}
});
}
//********************************************
var Fire = function(_o){
var that = this;
var t = 0;
var x = _o.x;
var y = _o.y;
var i = _o.i;
var j = _o.j;
var pos = _o.pos || [0,0];
var isEnd = _o.isEnd;
var isDead = false;
//console.log({x:x,y:y});
that.o = function(){
return {
x:x,
y:y,
isDead:isDead,
}
}
that.draw = function(){
t++;
sx = 104*2-pos[0]*104;
sy = 84*2-pos[1]*84;
if(isEnd){
sx+= pos[0]*104;
sy+= pos[1]*84;
}
if(t<4){
ctx.drawImage(imgs['bomb-fire.png'], sx,sy,104,84, x, y, iw, ih);
} else {
ctx.drawImage(imgs['bomb-fire.png'], sx+104*5,sy,104,84, x, y, iw, ih);
}
//ctx.fillStyle = '#aa0000';
//ctx.fillRect(x, y, iw/2, ih/2);
if(t===5){
isDead = true;
}
}
return that;
}
setBlocks();
setInterval(function(){
draw();
},199);
document.oncontextmenu = function () {return false;}
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
console.table({w:canvas.width, h:canvas.height});
w = document.body.clientWidth;
h = document.body.clientHeight;
cx = w/2;
cy = h/2;
iw = min/max;
ih = min/max;
}
window.onresize = resize;
window.addEventListener('click', function(ev) {
setBomb(ev.clientX,ev.clientY);
console.log(mapAry);
//resize();
//document.body.requestFullscreen();
//draw();
}, false );
window.addEventListener('dblclick', function(ev) {
//draw();
setBlocks();
}, false );
document.addEventListener('fullscreenchange',function(e){
resize();
});
CSS
HTML
ページのソースを表示 : Ctrl+U , DevTools : F12
view-source:https://hi0a.com/demo/-js/js-canvas-grid-bomberman/
ABOUT
hi0a.com 「ひまアプリ」は無料で遊べるミニゲームや便利ツールを公開しています。
プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。
必要な機能の関数をコピペ利用したり勉強に活用できます。
プログラムの動作サンプル結果は画面上部に出力表示されています。
環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。
画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。
動く便利なものが好きなだけで技術自体に興味はないのでコードは汚いです。
途中放置や実験状態、仕様変更、API廃止等で動かないページもあります。