Skip to content

Instantly share code, notes, and snippets.

@angus-c
Created January 25, 2015 00:36
Show Gist options
  • Save angus-c/f9d77a5dd216c50eaadc to your computer and use it in GitHub Desktop.
Save angus-c/f9d77a5dd216c50eaadc to your computer and use it in GitHub Desktop.
bouncer // source http://jsbin.com/vodep
<!DOCTYPE html>
<html>
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.22/rx.all.js"></script>
<title>bouncer</title>
</head>
<body>
<svg id="box" class="space" style="border: 1px solid; width: 400px; height: 400px" height="100%"></svg>
<script id="jsbin-javascript">
var svgNS = "http://www.w3.org/2000/svg";
var size = parseInt(document.getElementById('box').style.width);
var ballCount = 25;
var ballSize = 10;
var v = 0;
var xChange = new Rx.Subject();
var yChange = new Rx.Subject();
var subscription = xChange.subscribe(function (data) {
data.ball.xSpeed = data.x;
});
var subscription = yChange.subscribe(function (data) {
data.ball.ySpeed = data.y;
});
var probeOffsets = {
primary: ballSize + 3,
secondary: Math.pow((ballSize*ballSize/2), 0.5) + 2
}
var Ball = function (xSpeed, ySpeed, magic, id) {
this.x = size*Math.random();
this.y = size*Math.random();
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.magic = magic;
this.id = id;
};
function circle(id, x, y, radius, color) {
var c = document.createElementNS(svgNS, "circle");
c.setAttribute('id', id);
c.setAttribute("class", 'ball');
c.setAttributeNS(null, "cx", x);
c.setAttributeNS(null, "cy", y);
c.setAttributeNS(null, "r", radius);
c.setAttributeNS(null, "fill", color || "blue");
document.getElementById("box").appendChild(c);
return c;
}
Ball.prototype.draw = function () {
this.node = circle(this.id, this.x, this.y, ballSize, this.magic ? 'red' : this.color);
};
var balls = [];
for (var i = 1; i <= ballCount; i++) {
balls[i] = new Ball(
1 - 2 * Math.random(),
1 - 2 * Math.random(),
i == 1,
i,
'blue'
);
balls[i].draw();
}
Ball.prototype.move = function () {
this.node.setAttributeNS(null, "cx", this.x += this.xSpeed);
this.node.setAttributeNS(null, "cy", this.y += this.ySpeed);
};
Ball.prototype.registerOpposingX = function(val) {
xChange.onNext({ball: this, x: val});
}
Ball.prototype.registerOpposingY = function(val) {
yChange.onNext({ball: this, y: val});
}
Ball.prototype.checkCollision = function () {
var p = probeOffsets.primary;
var s = probeOffsets.secondary;
var probes = [[p, 0], [-p, 0], [0, p], [0, -p], [s, s], [-s, -s], [s, -s], [-s, s]];
for (var i = 0; i < probes.length; i++) {
var probeLeft = (probes[i][0] < 0);
var probeTop = (probes[i][1] < 0);
var detected = elemAt(this.x + probes[i][0], this.y + probes[i][1]);
if (!detected || !(detected.id)) {
if (probes[i][0]) {
this.registerOpposingX((probeLeft ? 1 : -1) * Math.abs(this.xSpeed));
}
if (probes[i][1]) {
this.registerOpposingY((probeTop ? 1 : -1) * Math.abs(this.ySpeed));
}
} else if(detected.id != 'box') {
if (probes[i][0]) {
this.registerOpposingX((probeLeft ? 1 : -1) * Math.abs(balls[detected.id]['xSpeed']));
balls[detected.id].registerOpposingX((probeLeft ? -1 : 1) * Math.abs(this['xSpeed']));
}
if (probes[i][1]) {
this.registerOpposingY((probeTop ? 1 : -1) * Math.abs(balls[detected.id]['ySpeed']));
balls[detected.id].registerOpposingY((probeLeft ? -1 : 1) * Math.abs(this['ySpeed']));
}
}
}
function elemAt(x, y) {
return document.elementFromPoint(x+8, y+8);
}
if (this.magic) {
//console.log(Object.keys(probe).filter(function(k) {
// return !isAt(probe[k].x, probe[k].y, 'box');
//}));
//console.log('sX', this.xSpeed, 'sY', this.ySpeed);
}
};
function checkCollisions() {
for (var i = 1; i <= ballCount; i++) {
balls[i].checkCollision();
}
}
function moveAll() {
for (var i = 1; i <= ballCount; i++) {
balls[i].move();
}
if (!v) {
requestAnimationFrame(moveAll);
}
}
if (!v) {
moveAll();
} else {
document.body.addEventListener('click', moveAll);
}
setInterval(checkCollisions, 0);
/*
function point(id, x, y, color) {
var c = document.createElementNS(svgNS, "circle");
c.setAttribute('id', id);
c.setAttribute("class", 'probe');
c.setAttributeNS(null, "cx", x);
c.setAttributeNS(null, "cy", y);
c.setAttributeNS(null, "r", 1);
c.setAttributeNS(null, "fill", color || "red");
document.getElementById("box").appendChild(c);
}
*/
</script>
<script id="jsbin-source-html" type="text/html"><!DOCTYPE html>
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.22/rx.all.js"><\/script>
<title>bouncer</title>
</head>
<body>
<svg id="box" class="space" style="border: 1px solid; width: 400px; height: 400px" height="100%"></svg>
</body>
</html></script>
<script id="jsbin-source-javascript" type="text/javascript">var svgNS = "http://www.w3.org/2000/svg";
var size = parseInt(document.getElementById('box').style.width);
var ballCount = 25;
var ballSize = 10;
var v = 0;
var xChange = new Rx.Subject();
var yChange = new Rx.Subject();
var subscription = xChange.subscribe(function (data) {
data.ball.xSpeed = data.x;
});
var subscription = yChange.subscribe(function (data) {
data.ball.ySpeed = data.y;
});
var probeOffsets = {
primary: ballSize + 3,
secondary: Math.pow((ballSize*ballSize/2), 0.5) + 2
}
var Ball = function (xSpeed, ySpeed, magic, id) {
this.x = size*Math.random();
this.y = size*Math.random();
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.magic = magic;
this.id = id;
};
function circle(id, x, y, radius, color) {
var c = document.createElementNS(svgNS, "circle");
c.setAttribute('id', id);
c.setAttribute("class", 'ball');
c.setAttributeNS(null, "cx", x);
c.setAttributeNS(null, "cy", y);
c.setAttributeNS(null, "r", radius);
c.setAttributeNS(null, "fill", color || "blue");
document.getElementById("box").appendChild(c);
return c;
}
Ball.prototype.draw = function () {
this.node = circle(this.id, this.x, this.y, ballSize, this.magic ? 'red' : this.color);
};
var balls = [];
for (var i = 1; i <= ballCount; i++) {
balls[i] = new Ball(
1 - 2 * Math.random(),
1 - 2 * Math.random(),
i == 1,
i,
'blue'
);
balls[i].draw();
}
Ball.prototype.move = function () {
this.node.setAttributeNS(null, "cx", this.x += this.xSpeed);
this.node.setAttributeNS(null, "cy", this.y += this.ySpeed);
};
Ball.prototype.registerOpposingX = function(val) {
xChange.onNext({ball: this, x: val});
}
Ball.prototype.registerOpposingY = function(val) {
yChange.onNext({ball: this, y: val});
}
Ball.prototype.checkCollision = function () {
var p = probeOffsets.primary;
var s = probeOffsets.secondary;
var probes = [[p, 0], [-p, 0], [0, p], [0, -p], [s, s], [-s, -s], [s, -s], [-s, s]];
for (var i = 0; i < probes.length; i++) {
var probeLeft = (probes[i][0] < 0);
var probeTop = (probes[i][1] < 0);
var detected = elemAt(this.x + probes[i][0], this.y + probes[i][1]);
if (!detected || !(detected.id)) {
if (probes[i][0]) {
this.registerOpposingX((probeLeft ? 1 : -1) * Math.abs(this.xSpeed));
}
if (probes[i][1]) {
this.registerOpposingY((probeTop ? 1 : -1) * Math.abs(this.ySpeed));
}
} else if(detected.id != 'box') {
if (probes[i][0]) {
this.registerOpposingX((probeLeft ? 1 : -1) * Math.abs(balls[detected.id]['xSpeed']));
balls[detected.id].registerOpposingX((probeLeft ? -1 : 1) * Math.abs(this['xSpeed']));
}
if (probes[i][1]) {
this.registerOpposingY((probeTop ? 1 : -1) * Math.abs(balls[detected.id]['ySpeed']));
balls[detected.id].registerOpposingY((probeLeft ? -1 : 1) * Math.abs(this['ySpeed']));
}
}
}
function elemAt(x, y) {
return document.elementFromPoint(x+8, y+8);
}
if (this.magic) {
//console.log(Object.keys(probe).filter(function(k) {
// return !isAt(probe[k].x, probe[k].y, 'box');
//}));
//console.log('sX', this.xSpeed, 'sY', this.ySpeed);
}
};
function checkCollisions() {
for (var i = 1; i <= ballCount; i++) {
balls[i].checkCollision();
}
}
function moveAll() {
for (var i = 1; i <= ballCount; i++) {
balls[i].move();
}
if (!v) {
requestAnimationFrame(moveAll);
}
}
if (!v) {
moveAll();
} else {
document.body.addEventListener('click', moveAll);
}
setInterval(checkCollisions, 0);
/*
function point(id, x, y, color) {
var c = document.createElementNS(svgNS, "circle");
c.setAttribute('id', id);
c.setAttribute("class", 'probe');
c.setAttributeNS(null, "cx", x);
c.setAttributeNS(null, "cy", y);
c.setAttributeNS(null, "r", 1);
c.setAttributeNS(null, "fill", color || "red");
document.getElementById("box").appendChild(c);
}
*/
</script></body>
</html>
var svgNS = "http://www.w3.org/2000/svg";
var size = parseInt(document.getElementById('box').style.width);
var ballCount = 25;
var ballSize = 10;
var v = 0;
var xChange = new Rx.Subject();
var yChange = new Rx.Subject();
var subscription = xChange.subscribe(function (data) {
data.ball.xSpeed = data.x;
});
var subscription = yChange.subscribe(function (data) {
data.ball.ySpeed = data.y;
});
var probeOffsets = {
primary: ballSize + 3,
secondary: Math.pow((ballSize*ballSize/2), 0.5) + 2
}
var Ball = function (xSpeed, ySpeed, magic, id) {
this.x = size*Math.random();
this.y = size*Math.random();
this.xSpeed = xSpeed;
this.ySpeed = ySpeed;
this.magic = magic;
this.id = id;
};
function circle(id, x, y, radius, color) {
var c = document.createElementNS(svgNS, "circle");
c.setAttribute('id', id);
c.setAttribute("class", 'ball');
c.setAttributeNS(null, "cx", x);
c.setAttributeNS(null, "cy", y);
c.setAttributeNS(null, "r", radius);
c.setAttributeNS(null, "fill", color || "blue");
document.getElementById("box").appendChild(c);
return c;
}
Ball.prototype.draw = function () {
this.node = circle(this.id, this.x, this.y, ballSize, this.magic ? 'red' : this.color);
};
var balls = [];
for (var i = 1; i <= ballCount; i++) {
balls[i] = new Ball(
1 - 2 * Math.random(),
1 - 2 * Math.random(),
i == 1,
i,
'blue'
);
balls[i].draw();
}
Ball.prototype.move = function () {
this.node.setAttributeNS(null, "cx", this.x += this.xSpeed);
this.node.setAttributeNS(null, "cy", this.y += this.ySpeed);
};
Ball.prototype.registerOpposingX = function(val) {
xChange.onNext({ball: this, x: val});
}
Ball.prototype.registerOpposingY = function(val) {
yChange.onNext({ball: this, y: val});
}
Ball.prototype.checkCollision = function () {
var p = probeOffsets.primary;
var s = probeOffsets.secondary;
var probes = [[p, 0], [-p, 0], [0, p], [0, -p], [s, s], [-s, -s], [s, -s], [-s, s]];
for (var i = 0; i < probes.length; i++) {
var probeLeft = (probes[i][0] < 0);
var probeTop = (probes[i][1] < 0);
var detected = elemAt(this.x + probes[i][0], this.y + probes[i][1]);
if (!detected || !(detected.id)) {
if (probes[i][0]) {
this.registerOpposingX((probeLeft ? 1 : -1) * Math.abs(this.xSpeed));
}
if (probes[i][1]) {
this.registerOpposingY((probeTop ? 1 : -1) * Math.abs(this.ySpeed));
}
} else if(detected.id != 'box') {
if (probes[i][0]) {
this.registerOpposingX((probeLeft ? 1 : -1) * Math.abs(balls[detected.id]['xSpeed']));
balls[detected.id].registerOpposingX((probeLeft ? -1 : 1) * Math.abs(this['xSpeed']));
}
if (probes[i][1]) {
this.registerOpposingY((probeTop ? 1 : -1) * Math.abs(balls[detected.id]['ySpeed']));
balls[detected.id].registerOpposingY((probeLeft ? -1 : 1) * Math.abs(this['ySpeed']));
}
}
}
function elemAt(x, y) {
return document.elementFromPoint(x+8, y+8);
}
if (this.magic) {
//console.log(Object.keys(probe).filter(function(k) {
// return !isAt(probe[k].x, probe[k].y, 'box');
//}));
//console.log('sX', this.xSpeed, 'sY', this.ySpeed);
}
};
function checkCollisions() {
for (var i = 1; i <= ballCount; i++) {
balls[i].checkCollision();
}
}
function moveAll() {
for (var i = 1; i <= ballCount; i++) {
balls[i].move();
}
if (!v) {
requestAnimationFrame(moveAll);
}
}
if (!v) {
moveAll();
} else {
document.body.addEventListener('click', moveAll);
}
setInterval(checkCollisions, 0);
/*
function point(id, x, y, color) {
var c = document.createElementNS(svgNS, "circle");
c.setAttribute('id', id);
c.setAttribute("class", 'probe');
c.setAttributeNS(null, "cx", x);
c.setAttributeNS(null, "cy", y);
c.setAttributeNS(null, "r", 1);
c.setAttributeNS(null, "fill", color || "red");
document.getElementById("box").appendChild(c);
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment