java制作烟花源码,canvas制作的烟花效果

最近感觉canvas挺有意思的,在业余时间没事研究了一下,参考过网上一些思路,话不多说,开始啦。

图片效果如下:(右上角能显示FPS,是时候看看你电脑的性能了哈哈~)

9f25d0b9150b6edd3a9638b160690c13.png

先说一下思路吧,其实很简单,烟花分为两个部分:1.窜天猴。2.爆炸效果。  当穿天猴的竖直方向的速度为0的时候,让它爆炸。

下面是一些常量,后面类中会用到的

1 const canvas = document.getElementById('canvasNode');2 const ctx = canvas.getContext('2d');3 canvas.width =window.innerWidth;4 canvas.height =window.innerHeight;5 const CANVAS_WIDTH =canvas.width;6 const CANVAS_HEIGHT =canvas.height;7 const GRAVITATIONAL = 2.5; //模拟重力加速度

8 const AIR_RESISTANCE = 1; //模拟空气阻力

9 const EVERY_FIREWORK_TIME = 3; //每个烟花的持续时间,单位:秒

10 const FRAME = 60;

class FlyingMonkey{ //窜天猴,发射升空的,目前只能垂直发射

constructor(x,y,speedX,speedY){this.x = x; //x,y 是窜天猴的位置坐标

this.y =y;this.speedX =speedX;this.speedY =speedY;this.opacity = 1;this.count = 50; //窜天猴和其尾巴由这50个圆绘制而成

for(let i=0;i

}

}

createCircle(i) {//创建窜天猴的圈圈尾巴

ctx.beginPath();

ctx.save();

ctx.globalCompositeOperation= 'lighter';

ctx.fillStyle= `rgba(245,123,63,${this.opacity})`;

ctx.arc(this.x + (Math.random()-0.5) * i/10 + i/this.count * this.speedX, this.y + i/this.count * this.speedY ,8 - (6 * i/this.count),0,2 *Math.PI);

ctx.fill();

ctx.restore();

ctx.closePath();

}

}

上面是窜天猴类,就是最开始向上发射的烟花,下面烟花类

class Firework { //烟花,爆炸的

constructor(x,y,speedX,speedY){this.x =x;this.y =y;this.speedX =speedX;this.speedY =speedY;this.opacity = 1;this.count = 500; // 烟花的爆炸效果由500个点组成this.AllFireworks =[];this.createAllFirework();

Launch.arrFirework.push(this);

}

createAllFirework(){

let r= Math.floor(Math.random()*256), g = Math.floor(Math.random()*256) , b =Math.floor(Math.random()*256);for(let i=0;i

r,g,b,

x:this.x,

y:this.y,

opacity:1,

speedX:this.speedX * i/this.count*10 *(Math.random()-0.5),

speedY:this.speedY * i/this.count*10 *(Math.random()-0.5)

});

}this.updateAllFirework();

}

updateAllFirework(){for(let i=0;i

let {r,g,b,x,y,speedX,speedY,opacity}= this.AllFireworks[i];this.AllFireworks[i].y = y - speedY/FRAME;

this.AllFireworks[i].x = x - speedX/FRAME;

this.AllFireworks[i].opacity = opacity - 1/ FRAME /EVERY_FIREWORK_TIME;this.AllFireworks[i].speedY = speedY -GRAVITATIONAL;if(Math.abs(speedX)>3/FRAME) { // 速度<= 3/FRAME 认为停止了

this.AllFireworks[i].speedX = speedX - (speedX>0?AIR_RESISTANCE:(AIR_RESISTANCE*(-1)));

}else{this.AllFireworks[i].speedX = 0;

}

ctx.beginPath();

ctx.save();

ctx.globalCompositeOperation= 'lighter';

ctx.fillStyle= `rgba(${r},${g},${b},${this.AllFireworks[i].opacity})`;

ctx.arc(this.AllFireworks[i].x , this.AllFireworks[i].y ,2,0,2 *Math.PI);

ctx.fill();

ctx.restore();

ctx.closePath();

}

}

}

下面是start类,用来发射窜天猴

class Start{

constructor(x,y,speedX,speedY){

Launch.arrFlyingMonkey.push(this);this.x =x;this.y =y;this.speedX =speedX;this.speedY =speedY;this.begin();

}

begin(){this.y = this.y - this.speedY/FRAME; // 速度减小

this.x = this.x - this.speedX/FRAME;

this.speedY = this.speedY -GRAVITATIONAL;new FlyingMonkey(this.x, this.y, this.speedX, this.speedY);

}

}

下面是发射类,是用【requestAnimationFrame】来渲染的动画

class Launch{ //发射

constructor(){this.fps=0;this.sum=0;//帧数计数器 60帧一循环

this.draw = this.draw.bind(this);this.draw();

}

draw(){

ctx.clearRect(0,0,CANVAS_WIDTH,CANVAS_HEIGHT);this.updateFps();

Launch.arrFlyingMonkey.forEach((item,i)=>{

item.begin();if(item.speedY < 0){

Launch.arrFlyingMonkey.splice(i,1);new Firework(item.x,item.y,7*7,5*7); //烟花宽高比:7:5

}

});

Launch.arrFirework.forEach((item,i)=>{

item.updateAllFirework();

});if(Launch.arrFirework.length>5){ //清理arrFirework,避免占用过多内存,其实还可以通过 EVERY_FIREWORK_TIME 和 Launch.timer 更及时清理。length > EVERY_FIREWORK_TIME/Launch.timer

Launch.arrFirework.shift();

}

requestAnimationFrame(this.draw);

}

updateFps(){if(this.sum++>=60){this.sum = 0;

let nowTime= newDate().getTime();this.fps = 60/(nowTime - Launch.lastTime) *1000;

Launch.lastTime =nowTime;

}

ctx.save();

ctx.fillStyle= 'red';

ctx.font="20px Arial";

ctx.fillText(`FPS: ${~~this.fps}`,CANVAS_WIDTH - 100,50);

ctx.restore();

}

}

然后添加Launch静态属性

/** 添加Launch静态属性*/Launch.arrFlyingMonkey=[];

Launch.arrFirework=[];

Launch.timer= setInterval(()=>{new Start(CANVAS_WIDTH * (Math.random() * 0.8 + 0.1),CANVAS_HEIGHT * 0.9,0,300 *(Math.random()*0.5 + 1));

},1500);

Launch.lastTime= new Date().getTime();

最后在  new Launch(); 就能发射出去啦。

代码还有好多可以优化的地方,在一些手机浏览器上会出现fps越来越低得到情况,画面会变卡,以后可能的话要在进行优化一下,也可以和大家讨论一下如何优化会更好,可以在评论区指导一下呀,感谢大家提出宝贵的意见~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Canvas可以实现很多有趣的特效,包括烟花特效。下面是一个简单的Canvas烟花特效制作步骤: 1. 创建Canvas画布和一个数组,用来存储烟花粒子。 ```javascript const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const particles = []; ``` 2. 定义一个Particle类,用来创建烟花粒子。注意每个粒子都有一个随机的颜色。 ```javascript class Particle { constructor(x, y) { this.x = x; this.y = y; this.vx = Math.random() * 5 - 2.5; this.vy = Math.random() * 5 - 2.5; this.color = `rgb(${Math.round(Math.random() * 255)}, ${Math.round(Math.random() * 255)}, ${Math.round(Math.random() * 255)})`; this.radius = 3; this.life = 100; } draw() { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = this.color; ctx.fill(); } update() { this.x += this.vx; this.y += this.vy; this.vx *= 0.97; this.vy *= 0.97; this.radius -= 0.05; this.life--; } } ``` 3. 创建一个函数,用来在点击Canvas时创建一个烟花。 ```javascript function createFirework(x, y) { for (let i = 0; i < 50; i++) { particles.push(new Particle(x, y)); } } ``` 4. 在Canvas上监听鼠标点击事件,并在点击时创建一个烟花。 ```javascript canvas.addEventListener('click', (e) => { createFirework(e.clientX, e.clientY); }); ``` 5. 创建一个动画循环函数,用来更新和绘制所有的烟花粒子。 ```javascript function loop() { ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < particles.length; i++) { particles[i].draw(); particles[i].update(); if (particles[i].life <= 0) { particles.splice(i, 1); i--; } } requestAnimationFrame(loop); } ``` 6. 最后启动动画循环函数。 ```javascript loop(); ``` 现在你就可以在Canvas上看到一个简单的烟花特效了。你可以根据需要调整粒子的数量、速度、颜色和寿命等参数,以创建更多的烟花效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值