Skip to content

Instantly share code, notes, and snippets.

@vkobel
Last active September 18, 2015 14:45
Show Gist options
  • Save vkobel/82faf7151cb88b9b04ed to your computer and use it in GitHub Desktop.
Save vkobel/82faf7151cb88b9b04ed to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>UHF Live Flow</title>
<style type="text/css">
*{
margin:0;
padding:0;
overflow:hidden;
}
html, body{
background: #000;
height:100%; width:100%;
}
#display{
width:100%;
min-height:100%;
}
</style>
</head>
<body>
<canvas id="display"></canvas>
<script type="text/javascript">
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
/* SOUND */
var expl = new Audio("exp.wav");
expl.preload = 'auto';
expl.load();
function boom(){
var boom = expl.cloneNode();
boom.play();
}
/* GLOBAL */
var particles = [];
var f = 0;
var display = document.getElementById('display');
var size = {
width: window.innerWidth || document.body.clientWidth,
height: window.innerHeight || document.body.clientHeight
}
display.width = width = size.width;
display.height = height = size.height;
var ctx = display.getContext('2d');
var particles = [];
var GRID_SIZE = 15;
var leftRate = 0;
var rightRate = 0;
/*function preShake() {
ctx.save();
var dx = Math.random()*400;
var dy = Math.random()*400;
ctx.translate(dx, dy);
}
function postShake() {
ctx.restore();
}*/
function Particle(x, y, isLtoR){
this.x = this.oldX = x;
this.y = this.oldY = y;
this.speedX = getRandom(2,4) / 50000 ;
this.speedY = 0;//getRandom(2,5) / 5000;
this.isLtoR = isLtoR;
//this.color = colors[getRandom(0, colors.length)];
this.color = isLtoR ? '#FFA200' : '#00C3FF';
this.eject = false;
// Grid - broad collision detection
this.gridIndex = [x / GRID_SIZE | 0, y / GRID_SIZE | 0];
}
Particle.prototype.integrate = function(){
var velocityX = (this.x - this.oldX) * 0.995;
var velocityY = (this.y - this.oldY) + (this.eject ? (Math.random() * f % 2 - 1) * 100 : 0);
this.oldX = this.x;
this.oldY = this.y;
this.x += velocityX;
this.y += velocityY;
this.eject = false;
}
Particle.prototype.attract = function(x, y){
var dx = x - this.x;
var dy = y - this.y;
this.x += dx * this.speedX;
this.y += dy * this.speedY;
this.gridIndex = [this.x / GRID_SIZE | 0, this.y / GRID_SIZE | 0];
}
Particle.prototype.draw = function() {
ctx.strokeStyle = this.color;
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(this.oldX, this.oldY);
ctx.lineTo(this.x, this.y);
ctx.stroke();
};
function drawCircle(x, y){
ctx.beginPath();
ctx.arc(x, y, getRandom(3, 15), 0, 2 * Math.PI, false);
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
ctx.fill();
}
function drawRect(){
ctx.beginPath();
ctx.rect(0,0,width,height);
ctx.fillStyle = "rgba(255, 255, 255, 0.06)";
ctx.fill();
}
function isColliding(p1, p2){
var radius = 15;
var dx = p1.x - p2.x;
var dy = p1.y - p2.y;
var dist = Math.sqrt(dx * dx + dy * dy);
return dist < radius;
}
/* EVENTS */
window.addEventListener("keydown", function(e){
if(e.keyCode == 65)
leftRate = 3;
if(e.keyCode == 76)
rightRate = 3;
});
window.addEventListener("keyup", function(e){
if(e.keyCode == 65)
leftRate = 0;
if(e.keyCode == 76)
rightRate = 0;
});
function frame(){
requestAnimationFrame(frame);
ctx.clearRect(0, 0, width, height);
f++;
document.title = particles.length;
// create new particles
//if(f % 2 == 0)
for(var i=0; i < leftRate; i++){
particles.push(new Particle(0, getRandom( (height/2) - 150, (height/2) + 150 ), true));
}
for(var i=0; i < rightRate; i++){
particles.push(new Particle(width, getRandom( (height/2) - 150, (height/2) + 150 ), false));
}
var LtoRParticles = particles.filter(function(p){ return p.isLtoR });
// update particle position
for(var i = 0; i < particles.length; i++){
var current = particles[i];
if(!current) continue;
if(current.isLtoR)
current.attract(width, current.y);
else
current.attract(0, current.y);
//preShake();
current.integrate();
current.draw();
//postShake();
// delete if out of sight
if(current.toDelete || current.x > width || current.y > height || current.x < 0 || current.y < 0){
particles.remove(i);
}
// Collide only with opposite particles
if(!current.isLtoR && current.x < width / 10 * 9){
var collisions = LtoRParticles
.filter(function(p){ return p.x > width / 10
&& current.gridIndex[0] == p.gridIndex[0]
&& current.gridIndex[1] == p.gridIndex[1]
})
.filter(function(p){ return isColliding(current, p) });
for(var c=0; c < collisions.length; c++){
var collision = collisions[c];
if(getRandom(0,2)){
collision.color = '#FFF';
collision.eject = true;
//collision.toDelete = true;
}else{
current.color = '#FFF';
current.eject =true;
//current.toDelete = true;
}
drawCircle(collision.x, current.y);
drawRect();
//boom()
}
}
}
}
requestAnimationFrame(frame);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment