Skip to content

Instantly share code, notes, and snippets.

@srajagop
Created June 16, 2015 02:29
Show Gist options
  • Save srajagop/bc460ad814911f464154 to your computer and use it in GitHub Desktop.
Save srajagop/bc460ad814911f464154 to your computer and use it in GitHub Desktop.
Attraction, ladies and gents!

Attraction, ladies and gents!

Yet another simple gravity simulation. Click to spawn particles.

A Pen by Phis on CodePen.

License.

<canvas id="canvas"></canvas>
function PlanetManager(maxPlanets, marginX, marginY) {
this.maxPlanets = !maxPlanets ? 10 : maxPlanets;
this.planets = [];
this.margin = {
x: !marginX ? 0 : marginX,
y: !marginY ? 0 : marginY
};
}
PlanetManager.prototype.addRandomPlanet = function(w, h, maxSize, maxV) {
if (this.planets.length < this.maxPlanets) {
var xSign = Math.random() >= 0.5 ? 1 : -1;
var ySign = Math.random() >= 0.5 ? 1 : -1;
var x = xSign > 0 ? this.margin.x + 1 : w + this.margin.x - 1;
var y = ySign > 0 ? this.margin.y + 1 : h + this.margin.y - 1;
var size = Math.random() * maxSize;
var vx = Math.random() * maxV * xSign;
var vy = Math.random() * maxV * ySign;
this.planets.push(new Planet(x, y, size, undefined, vx, vy));
}
}
PlanetManager.prototype.add = function(planet) {
if (this.maxPlanets > this.planets.length)
this.planets.push(planet);
};
PlanetManager.prototype.update = function(w, h) {
for (var i = 0; i < this.planets.length; i++) {
if (this.planets[i].isOutOfSpace(w, h, this.margin.x, this.margin.y)) {
this.planets.splice(i, 1);
i--;
} else {
this.planets[i].update();
}
}
};
PlanetManager.prototype.draw = function(ctx) {
ctx.fillStyle = ctx.strokeStyle = "rgba(255, 255, 255, 0.3)";
for (var i = 0; i < this.planets.length; i++)
this.planets[i].draw(ctx);
};
function Planet(x, y, size, gravity, vx, vy, ax, ay) {
this.x = x;
this.y = y;
this.size = !size ? 1 : size;
this.gravity = !gravity ? this.size : gravity;
this.vx = !vx ? 0 : vx;
this.vy = !vy ? 0 : vy;
this.ax = !ax ? 1 : ax;
this.ay = !ay ? 1 : ay;
}
Planet.prototype.update = function() {
this.vx *= this.ax;
this.vy *= this.ay;
this.x += this.vx;
this.y += this.vy;
};
Planet.prototype.draw = function(ctx) {
var halfsize = this.size / 2;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(this.x + halfsize, this.y + halfsize, this.size, 0, Math.PI + Math.PI);
ctx.stroke();
};
Planet.prototype.getForce = function(particle) {
var halfsize = this.size / 2;
var fx = particle.x - this.x - halfsize;
var fy = particle.y - this.y - halfsize;
var hyp = Math.sqrt(fx * fx + fy * fy);
var fApplied = this.gravity / (hyp * hyp) * 0.3;
return {
x: fx * fApplied,
y: fy * fApplied
};
};
Planet.prototype.isOutOfSpace = function(w, h, marginX, marginY) {
var xRight = this.x + this.size;
var xLeft = this.x;
var yTop = this.y;
var yBottom = this.y + this.size;
return xRight < 0 - marginX || xLeft > w + marginX ||
yTop < 0 - marginY || yBottom > h + marginY;
}
function ParticleManager(maxParticles) {
this.maxParticles = !maxParticles ? 100 : maxParticles;
this.particles = [];
}
ParticleManager.prototype.add = function(particle) {
if (this.maxParticles > this.particles.length)
this.particles.push(particle);
};
ParticleManager.prototype.update = function(w, h, planets) {
for (var i = 0; i < this.particles.length; i++) {
if (this.particles[i].isOutOfBorder(w, h)) {
this.particles.splice(i, 1);
i--;
} else {
this.particles[i].update(planets);
}
}
};
ParticleManager.prototype.draw = function(ctx) {
for (var i = 0; i < this.particles.length; i++)
this.particles[i].draw(ctx);
};
function Particle(x, y, size, vx, vy, ax, ay, color) {
this.x = x;
this.y = y;
this.xOld = x;
this.yOld = y;
this.size = !size ? 1 : size;
this.vx = !vx ? 0 : vx;
this.vy = !vy ? 0 : vy;
this.ax = !ax ? 0 : ax;
this.ay = !ay ? 0 : ay;
if (!color)
this.setColor();
else
this.color = color;
}
Particle.prototype.setColor = function(r, g, b) {
if (!r || !g || !b) {
r = Math.floor(Math.random() * 255);
g = Math.floor(Math.random() * 255);
b = Math.floor(Math.random() * 255);
}
this.color = "rgb(" + r + "," + g + "," + b + ")";
};
Particle.prototype.update = function(planets) {
this.vx *= this.ax;
this.vy *= this.ay;
if (planets) {
var forceTotal = {
x: 0,
y: 0
};
for (var i = 0; i < planets.length; i++) {
var force = planets[i].getForce(this);
forceTotal.x += force.x;
forceTotal.y += force.y;
}
this.vx -= forceTotal.x;
this.vy -= forceTotal.y;
}
this.xOld = this.x;
this.yOld = this.y;
this.x += this.vx;
this.y += this.vy;
};
Particle.prototype.isOutOfBorder = function(w, h) {
return this.x < 0 || this.y < 0 || this.x > w || this.y > h;
};
Particle.prototype.draw = function(ctx) {
var halfsize = this.size / 2;
ctx.lineWidth = halfsize;
ctx.beginPath();
ctx.fillStyle = ctx.strokeStyle = this.color;
ctx.moveTo(this.xOld, this.yOld);
ctx.lineTo(this.x, this.y);
ctx.stroke();
//ctx.fillRect(this.x - halfsize, this.y - halfsize, this.size, this.size);
};
function init() {
for (var i = 0; i < 5; i++) {
var size = planetConstraints.maxSize;
var x = Math.random() * width;
var y = Math.random() * height;
var vx = Math.random() * (Math.random() > 0.5 ? 1 : -1) * 0.25;
var vy = Math.random() * (Math.random() > 0.5 ? 1 : -1) * 0.25;
planets.add(new Planet(x, y, size, undefined, vx, vy));
}
spawnRandomParticle(20);
}
function run() {
update();
requestAnimationFrame(run);
}
function update() {
if (spawnParticle)
addParticle(mouseX, mouseY);
//draw
ctx.fillStyle = "rgba(0, 0, 0, " + fading + ")";
ctx.fillRect(0, 0, width, height);
ctx.strokeStyle = "white";
planets.draw(ctx);
particles.draw(ctx);
//update
planets.update(width, height);
particles.update(width, height, planets.planets);
planets.addRandomPlanet(width, height, planetConstraints.maxSize, planetConstraints.maxV);
time++;
}
function spawnRandomParticle(amount) {
color = createRandomColor();
for (var i = 0; i < amount; i++) {
var size = 5; //Math.random() * 5 + 1;
var x = Math.random() * width;
var y = Math.random() * height;
var vx = Math.random() * 4 * (Math.random() > 0.5 ? 1 : -1);
var vy = Math.random() * 4 * (Math.random() > 0.5 ? 1 : -1);
particles.add(new Particle(x, y, size, vx, vy, 1, 1, color));
}
}
function addParticle(x, y) {
var size = 5;
var vx = Math.random() * 4 * (Math.random() > 0.5 ? 1 : -1);
var vy = Math.random() * 4 * (Math.random() > 0.5 ? 1 : -1);
particles.add(new Particle(x, y, size, vx, vy, 1, 1, color));
}
//vars
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = ctx.canvas.width = window.innerWidth;
var height = ctx.canvas.height = window.innerHeight;
var particles = new ParticleManager(1000, 50, 50);
var planets = new PlanetManager(5);
var mouseStartX, mouseStartY, mouseDragX, mouseDragY, spawnParticle;
var blubb = 0; //debug var
var fading = 0.2;
var time = 0;
var color;
var planetConstraints = {
maxSize: 60,
maxV: 2
};
function createRandomColor() {
var r, g, b;
r = Math.floor(Math.random() * 255);
g = Math.floor(Math.random() * 255);
b = Math.floor(Math.random() * 255);
return "rgb(" + r + "," + g + "," + b + ")";
}
canvas.addEventListener("mousedown", function(e) {
e.preventDefault();
mouseX = e.pageX;
mouseY = e.pageY;
color = createRandomColor();
spawnParticle = true;
addParticle(mouseX, mouseY);
}, false);
canvas.addEventListener("mousemove", function(e) {
mouseX = e.pageX;
mouseY = e.pageY;
}, false);
canvas.addEventListener("mouseup", function(e) {
spawnParticle = false;
}, false);
init();
run();
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
canvas{
width: 100%;
height: 100%;
background: black;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment