煙のようなパーティクルシステム。Daniel ShiffmanによるNature of Codeより。
particle system texture smoke
Simulate Physics
View Source Code
/*
* @name SmokeParticles
* @arialabel White circle gives off smoke on the middle of the bottom of the screen. The smoke blows in the direction of the user’s mouse as it moves side to side. There is a white arrow on the top that also points to the side where the user’s mouse is
* @description a port of Dan Shiffman's SmokeParticleSystem example originally
* for Processing. Creates smokey particles :p
*/
// texture for the particle
let particle_texture = null;
// variable holding our particle system
let ps = null;
function preload() {
// particle_texture = loadImage("assets/particle_texture.png");
particle_texture = loadImage("../../../../p5js-website-legacy-examples/assets/particle_texture.png");
}
function setup() {
//set the canvas size
// createCanvas(640, 360);
createCanvas(windowWidth, windowHeight);
//initialize our particle system
ps = new ParticleSystem(0, createVector(width / 2, height - 60), particle_texture);
}
function draw() {
background(0);
let dx = map(mouseX, 0, width, -0.2, 0.2);
let wind = createVector(dx, 0);
ps.applyForce(wind);
ps.run();
for (let i = 0; i < 2; i++) {
ps.addParticle();
}
// Draw an arrow representing the wind force
drawVector(wind, createVector(width / 2, 50, 0), 500);
}
/**
* This function draws an arrow showing the direction our "wind" is blowing.
*/
function drawVector(v, loc, scale){
push();
let arrowsize = 4;
translate(loc.x, loc.y);
stroke(255);
rotate(v.heading());
let len = v.mag() * scale;
line(0, 0, len,0);
line(len, 0, len-arrowsize, +arrowsize / 2);
line(len, 0, len-arrowsize, -arrowsize / 2);
pop();
}
//========= PARTICLE SYSTEM ===========
/**
* A basic particle system class
* @param num the number of particles
* @param v the origin of the particle system
* @param img_ a texture for each particle in the system
* @constructor
*/
let ParticleSystem = function(num, v, img_) {
this.particles = [];
this.origin = v.copy(); // we make sure to copy the vector value in case we accidentally mutate the original by accident
this.img = img_
for(let i = 0; i < num; ++i){
this.particles.push(new Particle(this.origin, this.img));
}
};
/**
* This function runs the entire particle system.
*/
ParticleSystem.prototype.run = function() {
// cache length of the array we're going to loop into a variable
// You may see <variable>.length in a for loop, from time to time but
// we cache it here because otherwise the length is re-calculated for each iteration of a loop
let len = this.particles.length;
//loop through and run particles
for (let i = len - 1; i >= 0; i--) {
let particle = this.particles[i];
particle.run();
// if the particle is dead, we remove it.
// javascript arrays don't have a "remove" function but "splice" works just as well.
// we feed it an index to start at, then how many numbers from that point to remove.
if (particle.isDead()) {
this.particles.splice(i, 1);
}
}
}
/**
* Method to add a force vector to all particles currently in the system
* @param dir a p5.Vector describing the direction of the force.
*/
ParticleSystem.prototype.applyForce = function(dir) {
let len = this.particles.length;
for(let i = 0; i < len; ++i){
this.particles[i].applyForce(dir);
}
}
/**
* Adds a new particle to the system at the origin of the system and with
* the originally set texture.
*/
ParticleSystem.prototype.addParticle = function() {
this.particles.push(new Particle(this.origin, this.img));
}
//========= PARTICLE ===========
/**
* A simple Particle class, renders the particle as an image
*/
let Particle = function (pos, img_) {
this.loc = pos.copy();
let vx = randomGaussian() * 0.3;
let vy = randomGaussian() * 0.3 - 1.0;
this.vel = createVector(vx, vy);
this.acc = createVector();
this.lifespan = 100.0;
this.texture = img_;
}
/**
* Simulataneously updates and displays a particle.
*/
Particle.prototype.run = function() {
this.update();
this.render();
}
/**
* A function to display a particle
*/
Particle.prototype.render = function() {
imageMode(CENTER);
tint(255, this.lifespan);
image(this.texture, this.loc.x, this.loc.y);
}
/**
* A method to apply a force vector to a particle.
*/
Particle.prototype.applyForce = function(f) {
this.acc.add(f);
}
/**
* This method checks to see if the particle has reached the end of it's lifespan,
* if it has, return true, otherwise return false.
*/
Particle.prototype.isDead = function () {
if (this.lifespan <= 0.0) {
return true;
} else {
return false;
}
}
/**
* This method updates the position of the particle.
*/
Particle.prototype.update = function() {
this.vel.add(this.acc);
this.loc.add(this.vel);
this.lifespan -= 2.5;
this.acc.mult(0);
}
License
Source code is available on GitHub p5.js website legacy.
All examples are licensed under CC BY-NC-SA 4.0.