おはようこんにちはこんばんは。
初めてインフルエンザを体験して泣いてた
“みたらし”でございます(´・ω…:.;::..
第6回目は第5回に続き、
Canvasのアニメーションを弄っていきましょう。
(`・ω・´)
下準備
前回作ったものをちょっと改良して、
今回改良するためのサンプルを用意しましょう
<!DOCTYPE html>
<html>
<head>
</head>
<body>
[HTML5を知ろう] Canvasでアニメーションする!②
<div>
<canvas width="300" height="300" id="sumple" style="background-color:rgba(0, 0, 0, 1);"></canvas>
</div>
<script>
function test() {
var canvas = document.getElementById('sumple');
var circle = canvas.getContext('2d');
var circle_w = canvas.width;
var circle_h = canvas.height;
var x = 150;
var y = 20;
var z = 20;
(function circle_animation() {
circle.clearRect(0, 0, circle_w, circle_h);
circle.beginPath();
circle.arc(x, y, z, 0, 2*Math.PI, false);
circle.fillStyle = 'white';
circle.fill();
if (y >= (canvas.height-z)) {
y = 20;
}
y += 2;
requestAnimationFrame(circle_animation);
})();
}
test();
</script>
</body>
</html>
上記のような感じでhtmlファイルを用意して下さい。
真ん中から円が下に落ちていき、一番下に到達すると一番上に戻り、また落ちていきます。
今回はこの円が黒い枠の中を縦横無尽にバインバインするように作り替えていきましょう(`・Д・)
壁に当たったら跳ね返るようにする
前回までと同様で<script>タグの中身を書き換えて動きを変えていきます。
最初の状態だと一定速度のまま、一番下から上にワープしている状態なので、
これを一番下に到達したら移動する向きが逆になり、
跳ね返るようにしたいと思います。
function test() {
var canvas = document.getElementById('sumple');
var circle = canvas.getContext('2d');
var circle_w = canvas.width;
var circle_h = canvas.height;
var x = 150;
var y = 20;
var z = 20;
var reverse_flag_y = false;
(function circle_animation() {
circle.clearRect(0, 0, circle_w, circle_h);
circle.beginPath();
circle.arc(x, y, z, 0, 2*Math.PI, false);
circle.fillStyle = 'white';
circle.fill();
if (!reverse_flag_y) {
if (y >= (canvas.height-z)) {
reverse_flag_y = true;
}
} else {
if (y <= z) {
reverse_flag_y = false;
}
}
if (reverse_flag_y) {
y = y - 2;
} else {
y += 2;
}
requestAnimationFrame(circle_animation);
})();
}
test();
<script>タグの中身を全て上記のような感じに書き換えてみて下さい。
これをブラウザで表示すると…
上下移動するようになりました(`・ω・´)
“reverse_flag_y”というフラグを用意して、
これが false だったら通常通り y に 2 が加算され続け下へ移動しますが、
y の値が canvas.height(黒い枠の縦の長さ)を越えたらフラグが true になり、
y から 2 が減算され続けます。
そしてまた y が 0 に近づくと、フラグが false になり…
ということを繰り返しています。
※canvas.heightからz(円の半径)を引いているのは枠の外に円がはみ出さないようにするためです
等倍速の移動なら、跳ね返させるのは簡単ですね( =ω=)
だんだん早くなるように移動する
等倍速だと面白くないので、重力の影響を受けているかのような、
だんだん早くなるように移動させてみます。
function test() {
var canvas = document.getElementById('sumple');
var circle = canvas.getContext('2d');
var circle_w = canvas.width;
var circle_h = canvas.height;
var x = 150;
var y = 20;
var z = 20;
var speed_y = 0;
var gravity = 1;
var reverse_flag_y = false;
(function circle_animation() {
circle.clearRect(0, 0, circle_w, circle_h);
circle.beginPath();
circle.arc(x, y, z, 0, 2*Math.PI, false);
circle.fillStyle = 'white';
circle.fill();
if (!reverse_flag_y) {
if (y >= (canvas.height-z)) {
reverse_flag_y = true;
speed_y = speed_y - gravity;
}
} else {
if (y <= z) {
reverse_flag_y = false;
speed_y = 0;
}
}
if (reverse_flag_y) {
y = y - 2;
} else {
y += speed_y;
speed_y += gravity;
}
requestAnimationFrame(circle_animation);
})();
}
test();
<script>タグの中身を全て上記のような感じに書き換えてみて下さい。
これをブラウザで表示すると…
ちょっとわかりずらいですが下に移動するときに速度が変わるようになりました(っ゚Д゚;)っ
“speed_y”, “gravity”という変数を用意し、
これを用いて下に移動する処理で単純に y に 2 を加算していたのを、
『前回 y に加算した値』+『重力に見立てた値』
の合計を y に加算し、だんだん1回で加算される値が大きくなるため、
円の移動が速くなるようにしています。
この時、移動の向きが変わった後”speed_y”を初期化せず放置すると、
下へ移動する速度が上がり続け、そのうち見えない速さになります(´・ω・`)
だんだん遅くなるように移動する
重力の影響を受けているように移動させるには、
上に移動している時もだんだん速度が遅くなるようにしないと不自然なので、
さっきとは逆のことをしてあげるとそんな感じになります。
function test() {
var canvas = document.getElementById('sumple');
var circle = canvas.getContext('2d');
var circle_w = canvas.width;
var circle_h = canvas.height;
var x = 150;
var y = 20;
var z = 20;
var speed_y = 0;
var gravity = 1;
var reverse_flag_y = false;
(function circle_animation() {
circle.clearRect(0, 0, circle_w, circle_h);
circle.beginPath();
circle.arc(x, y, z, 0, 2*Math.PI, false);
circle.fillStyle = 'white';
circle.fill();
if (!reverse_flag_y) {
if (y >= (canvas.height-z)) {
reverse_flag_y = true;
speed_y = speed_y - gravity;
}
} else {
if (speed_y <= 0) {
reverse_flag_y = false;
speed_y = 0;
}
}
if (reverse_flag_y) {
y = y - speed_y;
speed_y = speed_y - gravity;
} else {
y += speed_y;
speed_y += gravity;
}
requestAnimationFrame(circle_animation);
})();
}
test();
<script>タグの中身を全て上記のような感じに書き換えてみて下さい。
これをブラウザで表示すると…
バウンドするようになりました!(`・ω・´)
やっていることは先程の逆版で、
壁に当たって跳ね返った後は”speed_y”の値はそのままにし、
y から減算する前に”speed_y”から”gravity”を引き、
y から引かれる値がだんだん小さくなるようにしています。
これで縦方向の移動はバッチリ完成しました!( ・`ω・´)
横方向にも移動するようにする
黒い枠の中を縦横無尽にバインバインするようにしたいので、
横方向にも移動するようにします。
function test() {
var canvas = document.getElementById('sumple');
var circle = canvas.getContext('2d');
var circle_w = canvas.width;
var circle_h = canvas.height;
var x = 150;
var y = 20;
var z = 20;
var speed_x = 5;
var speed_y = 0;
var gravity = 1;
var reverse_flag_x = false;
var reverse_flag_y = false;
(function circle_animation() {
circle.clearRect(0, 0, circle_w, circle_h);
circle.beginPath();
circle.arc(x, y, z, 0, 2*Math.PI, false);
circle.fillStyle = 'white';
circle.fill();
if (!reverse_flag_x) {
if (x >= (canvas.width - z)) {
reverse_flag_x = true;
}
} else {
if (x <= z) { reverse_flag_x = false; } } if (reverse_flag_x) { x = x - speed_x; } else { x += speed_x; } if (!reverse_flag_y) { if (y >= (canvas.height-z)) {
reverse_flag_y = true;
speed_y = speed_y - gravity;
}
} else {
if (speed_y <= 0) {
reverse_flag_y = false;
speed_y = 0;
}
}
if (reverse_flag_y) {
y = y - speed_y;
speed_y = speed_y - gravity;
} else {
y += speed_y;
speed_y += gravity;
}
requestAnimationFrame(circle_animation);
})();
}
test();
<script>タグの中身を全て上記のような感じに書き換えてみて下さい。
これをブラウザで表示すると…
縦横無尽にバインバインするようになりました!(`・Д・´)
コードは長くなっちゃいましたが、
やったことは一番最初の上下に向きが変わるようにした時と同じことをしただけです。
横移動は等倍速ですが、縦が等倍速ではないので結構変わった動きに見えますね。
工夫次第でさらに複雑な動きとかもできそうです。
Canvasすごいねぇ( `・ω・´)
そんなこんなでみたらしのCanvasシリーズはこれで終わりです。
皆さんも気が向いたら、遊んでみて下さいね。
おまけ
重力っぽい移動をさせるプロトタイプ版です。
重力の計算っぽく”乗算”でやっていた時に不思議な副産物ができてしまいました。
どんな動きかは…下記コードを実際に動かしてみて下さい(´・ω・`)
function test() {
var canvas = document.getElementById('sumple');
var circle = canvas.getContext('2d');
var circle_w = canvas.width;
var circle_h = canvas.height;
var x = 150;
var y = 20;
var yg = 1;
var z = 20;
var g = 1.2;
var reverse_flag = false;
(function circle_animation() {
circle.clearRect(0, 0, circle_w, circle_h);
circle.beginPath();
circle.arc(x, y, z, 0, 2*Math.PI, false);
circle.fillStyle = 'white';
circle.fill();
if (!reverse_flag) {
if (x >= canvas.width-20 || y >= canvas.height-20) {
if (yg < 1) { yg = 0; } else { reverse_flag = true; yg = yg * -1; } } } else { if (yg > -1) {
reverse_flag = false;
yg = yg * -1;
}
}
if (reverse_flag) {
yg = yg / g
y += yg;
} else {
yg = yg * g;
y += yg;
}
requestAnimationFrame(circle_animation);
})();
}
test();