CanvasAPIを使った爆破エフェクトイメージです。
実際にゲームに利用した例
ソースコード
エフェクトはEffect.jsとEffectOpacity.jsの2種類あります。
基本的に同じ作りですが、EffectOpacity.jsはパーティクルがだんだん消えていきます。
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="Functions.js" type="text/javascript"></script>
<script src="Effect.js" type="text/javascript"></script>
<script src="EffectOpacity.js" type="text/javascript"></script>
<script src="main.js" type="text/javascript"></script>
<title>爆破エフェクト</title>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
</body>
</html>
style.css
/* style.css */
@charset "utf-8";
*{
margin: 0;
padding: 0;
}
function.js
// 指定範囲の乱数を生成する関数(min~max)
function randInt(min, max){
return Math.floor(Math.random() * (max+1-min)+min);
}
// オブジェクトを消去
function deleteObjects(){
// エフェクト
for(let i in effects){
if(!effects[i].isAlive) effects.splice(i, 1);
}
}
// 多角形を描画する関数(頂点の数、中心x座標、中心y座標、半径、線幅、傾き、色)
const drawPolygon = function(n, cx, cy, r, lineWidth, tilt, color){
const p = Math.floor(360 / n)
let theta = -90 + tilt; // 角度修正(キャンバスでは3時方向が0度扱いのため12時方向を0度とする)
let polygon = [];
while(theta<360-90){ // 全ての頂点を求める
const pos = {
x: r * Math.cos(theta*Math.PI/180) + cx,
y: r * Math.sin(theta*Math.PI/180) + cy,
};
polygon.push(pos);
theta += p; // 次の点の位置
}
//console.log({polygon});
// 多角形を描画する
g.strokeStyle = color;
g.lineWidth = lineWidth;
g.beginPath();
for(let i=0; i<polygon.length; i++){
if(i==0){
g.moveTo(polygon[i].x, polygon[i].y);
}
else{
g.lineTo(polygon[i].x, polygon[i].y);
}
}
g.closePath(); // パスを閉じる
g.stroke();
}
Effect.js
/* Effect.js : エフェクトクラス*/
class Effect{
// コンストラクタ(x座標, y座標, 発射角度, 速度, 色)
constructor(x, y, angle, speed, color){
this.x = x; // x座標
this.y = y; // y座標
this.angle = angle; // 発射角度
this.speed = speed; // 速度
this.color = color; // 色
this.isAlive = true;
// 発射角度と速度からxy方向の速度計算
this.vx = this.speed * Math.cos(this.angle / 180 * Math.PI);
this.vy = this.speed * Math.sin(this.angle / 180 * Math.PI);
}
// 移動メソッド
move(){
this.x += this.vx;
this.vy += 0.1;
this.y += this.vy;
// 画面から消えたら消去
if(this.y < 0 || this.y > canvas.height || this.x < 0 || this.x > canvas.width){
this.isAlive = false;
}
}
// 描画メソッド
draw(){
// □を描画
drawPolygon(4, this.x, this.y, 3, 1, 0, this.color);
}
// 更新処理
update(){
this.move();
this.draw();
}
}
EffectOpacity.js
/*
EffectOpacity.js
だんだん消える
*/
class EffectOpacity{
// コンストラクタ(x座標, y座標, 発射角度, 速度, 色)
constructor(x, y, angle, speed, color){
this.x = x; // x座標
this.y = y; // y座標
this.angle = angle; // 発射角度
this.speed = speed; // 速度
this.rgbColor = color; // RGB色
this.opacity = 1.0; // 透過度
this.isAlive = true;
// 発射角度と速度からxy方向の速度計算
this.vx = this.speed * Math.cos(this.angle / 180 * Math.PI);
this.vy = this.speed * Math.sin(this.angle / 180 * Math.PI);
}
// 移動メソッド
move(){
this.x += this.vx;
this.vy += 0.1;
this.y += this.vy;
this.opacity -= 0.02;
// 画面から消えたら消去
if(this.y < 0 || this.y > canvas.height || this.x < 0 || this.x > canvas.width){
this.isAlive = false;
}
else if(this.opacity < 0.0){
this.isAlive = false;
}
}
// 描画メソッド
draw(){
// □を描画
this.color = `rgba(${this.rgbColor[0]}, ${this.rgbColor[1]}, ${this.rgbColor[2]}, ${this.opacity})`; // 色
drawPolygon(4, this.x, this.y, 3, 1, 0, this.color);
}
// 更新処理
update(){
this.move();
this.draw();
}
}
main.js
// main.js
let canvas = null;
let g = null;
let effects = []; // エフェクト格納用配列
let frameCount = 0; // フレーム数
// 描画更新処理
function mainLoop(){
// 一定間隔でエフェクトを生成
if(frameCount % 60 == 0){
// エフェクト生成
for(let angle of [0, 30, 60, 90, 120, 150, 180, -30, -60, -90, -120, -150]){
// Effect
const effect = new Effect(100, 100, angle, 3, "#555");
effects.push(effect);
// EffectOpacity
const effectOpacity = new EffectOpacity(400, 100, angle, 3, [50, 50, 50]);
effects.push(effectOpacity);
}
}
// キャンバスクリア
g.fillStyle = "#eee";
g.fillRect(0, 0, canvas.width, canvas.height);
// エフェクト描画を更新
for(let effect of effects){
effect.update();
}
// オブジェクト消去
deleteObjects();
// フレームカウント
frameCount++;
// フレーム毎に再帰呼び出し
requestAnimationFrame(mainLoop);
}
window.addEventListener("load", ()=>{
// キャンバス取得
canvas = document.getElementById("canvas");
g = canvas.getContext("2d");
frameCount = 0;
// 描画更新処理を開始
mainLoop();
});
コメント