gpt4 book ai didi

javascript - 在已经制作好的 Canvas 上创建轨迹

转载 作者:行者123 更新时间:2023-11-28 04:12:56 24 4
gpt4 key购买 nike

所以我试图在已经绘制的缓慢移动恒星的 Canvas 上实现 meteor 的概念。但我还没有找到办法这样做。我尝试实现一个数组以使其看起来如此,但跟踪效率不高。

这段代码如下:

var canvas = document.querySelector('canvas');
var c = canvas.getContext('2d');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;


var mouse = {
x : innerWidth/2,
y : innerHeight/2
};

var colors = [
'#3399CC',
'#67B8DE',
'#91C9E8',
'#B4DCED',
'#E8F8FF'
];



addEventListener('resize', function () {
canvas.width = innerWidth;
canvas.height = innerHeight;

init();
});

var isClicked = false;
addEventListener('click', function () {
mouse.x = event.clientX;
mouse.y = event.clientY;
isClicked = true;
});



function randomIntFromRange (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}

function randomColor (colors) {
return colors[Math.floor(Math.random() * colors.length)];
}



function Stars (x, y, radius, dy, color) {
this.x = x;
this.y = y;
this.radius = radius;
this.dy = dy;
this.color = color;

this.draw = function () {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
c.shadowColor = this.color;
c.shadowBlur = 15;
c.shadowOffsetX = 0;
c.shadowOffsetY = 0;
c.fillStyle = this.color;
c.fill();
c.closePath();
}

this.update = function () {
if (this.y < -10) {
this.y = canvas.height + 10;
this.x = randomIntFromRange(this.radius, canvas.width);
}
this.y -= this.dy;

this.draw();
}
}

function ShootingStar (x, y, radius) {
this.x = x;
this.y = y;
this.radius = radius;

this.draw = function () {
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);
c.shadowColor = "red";
c.shadowBlur = 15;
c.shadowOffsetX = 0;
c.shadowOffsetY = 0;
c.fillStyle = "red";
c.fill();
c.closePath();
}

this.update = function () {
this.x += 10;
this.y += 10;

this.draw();
}
}



let stars = [];
let shooting_star = [];

function init () {
stars = [];
for (var i = 0; i < 300; i++) {
var stars_radius = randomIntFromRange(2, 3);
var stars_x = randomIntFromRange(stars_radius, canvas.width);
var stars_y = randomIntFromRange(stars_radius, canvas.height);
var stars_dy = Math.random() / 6;
var color = randomColor(colors);
stars.push(new Stars(stars_x, stars_y, stars_radius, stars_dy, color));
}
}

function Explode () {
shooting_star = [];
var shooting_star_radius = 3;
var shooting_star_x = mouse.x;
var shooting_star_y = mouse.y;
for (var i = 0; i < 50; i++) {
shooting_star.push(new ShootingStar(shooting_star_x, shooting_star_y, shooting_star_radius));
if (shooting_star_radius > 0.2) {
shooting_star_radius -= .2;
}
var initiator = randomIntFromRange(-1, 1);
console.log(initiator);
shooting_star_x -= 3;
shooting_star_y -= 3;
}
}

function animate () {
requestAnimationFrame(animate);
c.clearRect(0, 0, canvas.width, canvas.height);

for (var i = 0; i < stars.length; i++)
stars[i].update();
for (var i = 0; i < shooting_star.length; i++)
shooting_star[i].update();

if (isClicked == true) {
Explode();
isClicked = false;
}
}

init();
animate();

这是它的jsfiddle https://jsfiddle.net/qjug4qdz/

我基本上希望 meteor 从随机位置到达我单击鼠标的点,但使用数组很难处理该轨迹。

最佳答案

基本粒子

对于您正在寻找的特定效果,您可以使用基本粒子系统。

当 meteor 移动时,您将掉落一个粒子,该粒子以恒星速度开始,然后减慢并逐渐消失。

粒子

首先从粒子开始。我喜欢用Object.assign创建对象时,您可以使用任何您喜欢的方法,类、new、工厂...

// This defines a particle and is copied to create new particles
const starDust = {
x : 0, // the current position
y : 0,
dx : 0, // delta x,y (velocity)
dy : 0,
drag : 0, // the rate that the particle slows down.
life : 0, // count down till particle is removed
age : 0, // the starting value of life
draw(){ // function to update and draw the particle
this.x += this.dx; // move it
this.y += this.dy;
this.dx *= this.drag; // slow it down
this.dy *= this.drag;
const unitLife = (this.life / this.age); // get the life left as a value
// from 0 to 1 where 0 is end
ctx.globalAlpha = unitLife; // set the alpha
ctx.beginPath();
ctx.arc(this.x,this.y,4,0,Math.PI); // draw the particle


this.life -= 1; // count down
return this.life > 0; // return true if still alive
}

具有内存意识。

创建粒子系统时的一个常见错误是人们忘记创建和销毁对象会给 JavaScript 内存管理增加大量工作。其中最糟糕的是GC(垃圾收集)。 GC 是延迟的主要来源,如果浪费内存,将会影响动画的质量。对于简单粒子来说,它可能不明显,但您可能希望每帧生成数百个复杂粒子。这就是 GC 真正伤害动画的时候。

大多数游戏引擎通过重用对象而不是取消引用和重新创建来减少 GC 影响。一种常见的方法是对象池,其中第二个数组保存不再使用的对象。当需要新对象时,首先检查池,如果有未使用的对象,则使用它,否则创建一个新对象。

这样你就永远不会删除任何粒子,大大减少GC工作量,并防止你的动画丢帧(如果你使用大量粒子)

粒子需要初始化

但是您需要提供一种重新初始化对象的方法。因此添加函数init到将其设置为再次使用的粒子

    init(x,y,vx,vy){ // where x,y and velocity vx,vy of shooting star
this.x = x;
this.y = y;
this.dx = vx;
this.dy = vy;
// give a random age
this.age = (Math.random() * 100 + 60) | 0; // in frames and | 0 floors the value
this.life = this.age; // and set the life countdown
this.drag = Math.random() * 0.01 + 0.99; // the drag that slows the particle down
}
} // end of starDust object.

数组

为了管理所有粒子,我们创建了一个对象,该对象具有用于添加、创建和渲染粒子的数组和方法。在这种情况下,我将其称为 dust

const dust = {
particles : [], // array of active particles
pool : [], // array of unused particels
createParticle(particleDesc){ // creates a new particle from particleDesc
return Object.assign({},particleDesc);
},
add(x,y,vx,vy){ // where x,y and velocity vx,vy
var dust;
if(this.pool.length){ // are there any particles in the pool
dust = this.pool.pop(); // get one
}else{ // else there are no spare particles so create a new one
dust = this.createParticle(starDust);
}
dust.init(x,y,vx,vy); // init the particle
this.items.push(dust); // put it in the active particle array
return dust; // return it (sometimes you want to do something with it)
},
draw(){ // updates and draws all active particles
var i = 0;
while(i < this.items.length){ // iterate each particle in items
if(this.items[i].draw() === false){ // is it dead??
this.pool.push(this.items.splice(i,1)[0]); // if dead put in the pool for later
}else{ i ++ } // if not dead get index of next particle
}
}
}//end of dust object

使用粒子系统

创建粒子的最简单方法是使用随机数并设置每帧创建粒子的机会。

在你的主循环中

 // assuming that the falling star is called star and has an x,y and dx,dy (delta)
if(star) { // only if there is a start to spawn from
// add a particle once every 10 frame (on average
if(Math.random() < 0.1) {
dust.add(star.x, star.y, star.dx, star.dy); // add some dust at the shooting starts position and speed
}
}

dust.draw(); // draw all particles

就是这样。

关于javascript - 在已经制作好的 Canvas 上创建轨迹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46108850/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com