canvasで少しずつ作るブロック崩し(2/5)
前回はマウスで動くバーを作成しました。今回はボールを打てるようにしていきます。
目次
バーとボール
追加要素
ボールの描画と座標の更新処理、壁、床・天井、バーと接触時にボールを反発させる処理を追加しました。
var BALL = {
'X' : 0, // ボールのX座標
'Y' : 0, // ボールのY座標
'Vx' : 100, // ボール速度(X成分)
'Vy' : 0, // ボール速度(Y成分)
'Vy0' : 100, // ボールの最低速度
'E' : 0.7, // 床の反発係数
'E0' : 10, // 反発時のバタつき防止
'RADIUS' : 5, // ボールの半径
};
var FIELD = {
'GRAVITY' :588, // 重力加速度(0.9 * FPS)
'FPS' : 60, // frame per second
};
// ボールの座標更新
function calcBallPosition() {
// 縦計算
BALL.Vy += FIELD.GRAVITY * (1/FIELD.FPS);
BALL.Y += BALL.Vy * (1/FIELD.FPS);
// 床・天井接触
if (BALL.Y <= 0 || height <= BALL.Y) {
if (BALL.Y <= 0) {
BALL.Y = BALL.E0;
BALL.Vy = BALL.Vy * BALL.E * (-1)
} else {
BALL.Y = height-BALL.E0;
BALL.Vy = BALL.Vy * BALL.E * (-1) - BALL.Vy0;
}
}
// 横計算
BALL.X += BALL.Vx * (1/FIELD.FPS);
// 壁接触
if (BALL.X <= 0 || width <= BALL.X) {
if (BALL.X <= 0) {
BALL.X = BALL.E0;
} else {
BALL.X = width - BALL.E0;
}
BALL.Vx = BALL.Vx * (-1);
}
// バー接触
if (BAR.X <= BALL.X && BALL.X <= BAR.X + BAR.WIDTH) {
if (Math.abs(BALL.Y - (height - BAR.UNDER)) <= BAR.HEIGHT) {
BALL.Y += - BALL.E0;
BALL.Vy = BALL.Vy * (-1) - BALL.Vy0;
}
}
};
// ボールの描画
function drawBall() {
// ボールの座標更新
//calcBallPosition()
ctx.save();
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, width, height);
// 円の描画設定
ctx.beginPath();
ctx.arc(BALL.X, BALL.Y, BALL.RADIUS, 0, 2*Math.PI, true);
ctx.closePath();
// 色設定
hue += 0.5;
ctx.strokeStyle = 'hsl(' + hue + ', 50%, 50%)';
ctx.fillStyle = 'hsl(' + hue + ', 50%, 50%)';
ctx.shadowColor = 'hsl(' + hue + ', 50%, 50%)';
ctx.shadowBlur = 10;
// 描画実行
ctx.stroke();
ctx.fill();
ctx.restore();
};
ソースコード
後はブロックを作ればひとまず形になりそう。
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript">
(function() {
var canvas;
var ctx;
var width;
var height;
var mouseX;
var mouseY;
var BAR = {
'HEIGHT' : 10, // バーの高さ
'WIDTH' : 50, // バーの幅
'UNDER' : 20, // バーのY座標(床からの高さ)
'X' : 0, // バーのX座標
};
var BALL = {
'X' : 0, // ボールのX座標
'Y' : 0, // ボールのY座標
'Vx' : 100, // ボール速度(X成分)
'Vy' : 0, // ボール速度(Y成分)
'Vy0' : 100, // ボールの最低速度
'E' : 0.7, // 床の反発係数
'E0' : 10, // 反発時のバタつき防止
'RADIUS' : 5, // ボールの半径
};
var FIELD = {
'GRAVITY' :588, // 重力加速度(0.9 * FPS)
'FPS' : 60, // frame per second
};
// 初期化処理
function initialize() {
canvas = document.getElementById('canvas');
if(!canvas && !canvas.getContext) {
return false;
}
ctx = canvas.getContext('2d');
width = ctx.canvas.width ;
height = ctx.canvas.height;
// バーの初期位置は中心
mouseX = width/2;
BAR.X = mouseX;
// ボールの初期位置は中心
BALL.X = width/2;
BALL.Y = height/2;
canvas.addEventListener('mousemove', getMousePosition, false);
setInterval(drawBar, 1000/FIELD.FPS);
setInterval(drawBall, 1000/FIELD.FPS);
setInterval(calcBallPosition, 1000/FIELD.FPS);
};
// マウス座標の更新
function getMousePosition(e) {
var rect = e.target.getBoundingClientRect();
mouseX = Math.floor(e.clientX - rect.left);
mouseY = Math.floor(e.clientY - rect.top);
};
// ボール位置計算
function calcBallPosition() {
// 縦計算
BALL.Vy += FIELD.GRAVITY * (1/FIELD.FPS);
BALL.Y += BALL.Vy * (1/FIELD.FPS);
// 床・天井接触
if (BALL.Y <= 0 || height <= BALL.Y) {
if (BALL.Y <= 0) {
BALL.Y = BALL.E0;
BALL.Vy = BALL.Vy * BALL.E * (-1)
} else {
BALL.Y = height-BALL.E0;
BALL.Vy = BALL.Vy * BALL.E * (-1) - BALL.Vy0;
}
}
// 横計算
BALL.X += BALL.Vx * (1/FIELD.FPS);
// 壁接触
if (BALL.X <= 0 || width <= BALL.X) {
if (BALL.X <= 0) {
BALL.X = BALL.E0;
} else {
BALL.X = width - BALL.E0;
}
BALL.Vx = BALL.Vx * (-1);
}
// バー接触
if (BAR.X <= BALL.X && BALL.X <= BAR.X + BAR.WIDTH) {
if (Math.abs(BALL.Y - (height - BAR.UNDER)) <= BAR.HEIGHT) {
BALL.Y += - BALL.E0;
BALL.Vy = BALL.Vy * (-1) - BALL.Vy0;
}
}
};
var hue = 0.5;
function drawBall() {
// ボールの座標更新
//calcBallPosition()
ctx.save();
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, width, height);
// 円の描画設定
ctx.beginPath();
ctx.arc(BALL.X, BALL.Y, BALL.RADIUS, 0, 2*Math.PI, true);
ctx.closePath();
// 色設定
hue += 0.5;
ctx.strokeStyle = 'hsl(' + hue + ', 50%, 50%)';
ctx.fillStyle = 'hsl(' + hue + ', 50%, 50%)';
ctx.shadowColor = 'hsl(' + hue + ', 50%, 50%)';
ctx.shadowBlur = 10;
// 描画実行
ctx.stroke();
ctx.fill();
ctx.restore();
};
function drawBar() {
var delay = 1;
BAR.X = (mouseX + delay * BAR.X) / (delay+1);
ctx.save();
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)';
ctx.fillRect(0, 0, width, height);
// 色設定
ctx.fillStyle = 'rgb(255,255,0)';
// 円の描画設定
ctx.fillRect(BAR.X, height-BAR.UNDER, BAR.WIDTH, BAR.HEIGHT);
// 描画実行
ctx.stroke();
ctx.fill();
ctx.restore();
};
// 初期化イベント
window.addEventListener('load', initialize, false);
} ) ();
</script>
</head>
<body>
<canvas id='canvas' width=500 height=300></canvas>
</body>
</html>
関連ページ
canvasで少しずつ作るブロック崩し(1/5) – Segmentation Fault
canvasで少しずつ作るブロック崩し(3/5) – Segmentation Fault
canvasで少しずつ作るブロック崩し(その4) – Segmentation Fault
canvasで少しずつ作るブロック崩し(5/5) – Segmentation Fault
コメント