Last active
September 18, 2015 14:45
-
-
Save vkobel/82faf7151cb88b9b04ed to your computer and use it in GitHub Desktop.
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
<!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