代码如下:
// Vector2.js
Vector2 = function(x, y) { this.x = x; this.y = y; };
Vector2.prototype = {
copy : function() { return new Vector2(this.x, this.y); },
length : function() { return Math.sqrt(this.x * this.x + this.y * this.y); },
sqrLength : function() { return this.x * this.x + this.y * this.y; },
normalize : function() { var inv = 1/this.length(); return new Vector2(this.x * inv, this.y * inv); },
negate : function() { return new Vector2(-this.x, -this.y); },
add : function(v) { return new Vector2(this.x + v.x, this.y + v.y); },
subtract : function(v) { return new Vector2(this.x - v.x, this.y - v.y); },
multiply : function(f) { return new Vector2(this.x * f, this.y * f); },
pide : function(f) { var invf = 1/f; return new Vector2(this.x * invf, this.y * invf); },
dot : function(v) { return this.x * v.x + this.y * v.y; }
};
Vector2.zero = new Vector2(0, 0);
代码如下:
var position = new Vector2(10, 200);
var velocity = new Vector2(50, -50);
var acceleration = new Vector2(0, 10);
var dt = 0.1;
function step() {
position = position.add(velocity.multiply(dt));
velocity = velocity.add(acceleration.multiply(dt));
ctx.strokeStyle = "#000000";
ctx.fillStyle = "#FFFFFF";
ctx.beginPath();
ctx.arc(position.x, position.y, 5, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
start("kinematicsCancas", step);
修改代码试试看 |
代码如下:
// Particle.js
Particle = function(position, velocity, life, color, size) {
this.position = position;
this.velocity = velocity;
this.acceleration = Vector2.zero;
this.age = 0;
this.life = life;
this.color = color;
this.size = size;
};
代码如下:
//ParticleSystem.js
function ParticleSystem() {
// Private fields
var that = this;
var particles = new Array();
// Public fields
this.gravity = new Vector2(0, 100);
this.effectors = new Array();
// Public methods
this.emit = function(particle) {
particles.push(particle);
};
// ...
}
代码如下:
function ParticleSystem() {
// ...
this.simulate = function(dt) {
aging(dt);
applyGravity();
applyEffectors();
kinematics(dt);
};
// ...
// Private methods
function aging(dt) {
for (var i = 0; i
p.age += dt;
if (p.age >= p.life)
kill(i);
else
i++;
}
}
function kill(index) {
if (particles.length > 1)
particles[index] = particles[particles.length - 1];
particles.pop();
}
// ...
}
代码如下:
function ParticleSystem() {
// ...
function applyGravity() {
for (var i in particles)
particles[i].acceleration = that.gravity;
}
function kinematics(dt) {
for (var i in particles) {
var p = particles[i];
p.position = p.position.add(p.velocity.multiply(dt));
p.velocity = p.velocity.add(p.acceleration.multiply(dt));
}
}
// ...
}
代码如下:
function ParticleSystem() {
// ...
this.render = function(ctx) {
for (var i in particles) {
var p = particles[i];
var alpha = 1 - p.age / p.life;
ctx.fillStyle = "rgba("
+ Math.floor(p.color.r * 255) + ","
+ Math.floor(p.color.g * 255) + ","
+ Math.floor(p.color.b * 255) + ","
+ alpha.toFixed(2) + ")";
ctx.beginPath();
ctx.arc(p.position.x, p.position.y, p.size, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
}
// ...
}
代码如下:
var ps = new ParticleSystem();
var dt = 0.01;
function sampleDirection() {
var theta = Math.random() * 2 * Math.PI;
return new Vector2(Math.cos(theta), Math.sin(theta));
}
function step() {
ps.emit(new Particle(new Vector2(200, 200), sampleDirection().multiply(100), 1, Color.red, 5));
ps.simulate(dt);
clearCanvas();
ps.render(ctx);
}
start("basicParticleSystemCanvas", step);
修改代码试试看 |
代码如下:
// ChamberBox.js
function ChamberBox(x1, y1, x2, y2) {
this.apply = function(particle) {
if (particle.position.x - particle.size
particle.velocity.x = -particle.velocity.x;
if (particle.position.y - particle.size
particle.velocity.y = -particle.velocity.y;
};
}
代码如下:
var ps = new ParticleSystem();
ps.effectors.push(new ChamberBox(0, 0, 400, 400)); // 最重要是多了这语句
var dt = 0.01;
function sampleDirection(angle1, angle2) {
var t = Math.random();
var theta = angle1 * t + angle2 * (1 - t);
return new Vector2(Math.cos(theta), Math.sin(theta));
}
function sampleColor(color1, color2) {
var t = Math.random();
return color1.multiply(t).add(color2.multiply(1 - t));
}
function step() {
ps.emit(new Particle(new Vector2(200, 200), sampleDirection(Math.PI * 1.75, Math.PI * 2).multiply(250), 3, sampleColor(Color.blue, Color.purple), 5));
ps.simulate(dt);
ctx.fillStyle="rgba(0, 0, 0, 0.1)";
ctx.fillRect(0,0,canvas.width,canvas.height);
ps.render(ctx);
}
start("collisionChamberCanvas", step);
代码如下:
var ps = new ParticleSystem();
ps.effectors.push(new ChamberBox(0, 0, 400, 400));
var dt = 0.01;
var oldMousePosition = Vector2.zero, newMousePosition = Vector2.zero;
function sampleDirection(angle1, angle2) {
var t = Math.random();
var theta = angle1 * t + angle2 * (1 - t);
return new Vector2(Math.cos(theta), Math.sin(theta));
}
function sampleColor(color1, color2) {
var t = Math.random();
return color1.multiply(t).add(color2.multiply(1 - t));
}
function sampleNumber(value1, value2) {
var t = Math.random();
return value1 * t + value2 * (1 - t);
}
function step() {
var velocity = newMousePosition.subtract(oldMousePosition).multiply(10);
velocity = velocity.add(sampleDirection(0, Math.PI * 2).multiply(20));
var color = sampleColor(Color.red, Color.yellow);
var life = sampleNumber(1, 2);
var size = sampleNumber(2, 4);
ps.emit(new Particle(newMousePosition, velocity, life, color, size));
oldMousePosition = newMousePosition;
ps.simulate(dt);
ctx.fillStyle="rgba(0, 0, 0, 0.1)";
ctx.fillRect(0,0,canvas.width,canvas.height);
ps.render(ctx);
}
start("interactiveEmitCanvas", step);
canvas.Onmousemove= function(e) {
if (e.layerX || e.layerX == 0) { // Firefox
e.target.style.position='relative';
newMousePosition = new Vector2(e.layerX, e.layerY);
}
else
newMousePosition = new Vector2(e.offsetX, e.offsetY);
};