Yet another simple gravity simulation. Click to spawn particles.
Created
June 16, 2015 02:29
-
-
Save srajagop/bc460ad814911f464154 to your computer and use it in GitHub Desktop.
Attraction, ladies and gents!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<canvas id="canvas"></canvas> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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