Skip to content

Instantly share code, notes, and snippets.

@qgustavor
Last active August 29, 2015 14:15
Show Gist options
  • Save qgustavor/261a0902743f94027c08 to your computer and use it in GitHub Desktop.
Save qgustavor/261a0902743f94027c08 to your computer and use it in GitHub Desktop.
Faster "Stronger"
<!doctype html>
<!-- Use cdn.rawgit.com or htmlpreview.github.io to test -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<meta property="og:title" content="Harder, Better, Faster, Stronger"/>
<meta property="og:url" content="http://davealger.c.mom/stronger/"/>
<meta property="og:image" content="http://davealger.com/stronger/punk_small.jpg"/>
<meta property="og:site_name" content="davealger.com"/>
<meta property="og:description" content="a daft punk sound pad."/>
<script src="//cdnjs.cloudflare.com/ajax/libs/paper.js/0.9.21/paper-full.min.js"></script>
<script src="//cdn.rawgit.com/IonDen/ion.sound/71e5c138eda7ff386ceefa1cd0f902567c7b6c57/js/ion.sound.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/3.0.2/normalize.min.css">
<style>html,body{overflow:hidden;background:#111;}</style>
</head>
<body>
<!-- disabled facebook, I don't know how those social thing works also it was above touch input -->
<!-- pretty much everything is drawn dynamically using paper.js -->
<canvas id="strongerCanvas" resize></canvas>
<script type="text/paperscript" canvas="strongerCanvas">
// Set color variables
var lightCell = '#CCC';
var selectedCell = '#FF8';
var selectedMode = '#FF0';
var unselectedMode = '#880';
var playCell = '#8F8';
// Current playing mode
var mode = 0;
// Those variables change on resizing
var width, height;
// Width, height, margin and array of cells (or buttons)
var sW, sH;
var margin = 4;
var cells = [];
// Play/pause element
var isPlaying = false;
var playSegments = [[0, 0], [40, 20], [0, 40]];
var pauseSegments = [[0, 0], [40, 0], [40, 40], [0, 40]]; // Actualy is more a stop:
var playElement;
// Help elements
var helpEl;
// Default keymapping is QWERTY:
var keymapping = {
'q': [0, 0],
'w': [1, 0],
'e': [2, 0],
'r': [3, 0],
'a': [0, 1],
's': [1, 1],
'd': [2, 1],
'f': [3, 1],
'y': [0, 2],
'u': [1, 2],
'i': [2, 2],
'o': [3, 2],
'h': [0, 3],
'j': [1, 3],
'k': [2, 3],
'l': [3, 3],
// mode buttons
'z': [4, 0],
'x': [4, 1],
'c': [4, 2],
'space': [4, 3]
};
var customizingState = {
lastMode: null,
coords: null,
selectedCell: null,
textElements: []
};
initializePath();
function initializePath() {
var box;
width = view.size.width;
height = view.size.height;
sW = width / 5;
sH = height / 4;
// remove already existing cells
cells.forEach(function (e) {
e.remove();
});
cells = [];
// Create array of cells
var index = 0;
for(var boxY = 0; boxY < 4; boxY++) {
for(var boxX = 0; boxX < 5; boxX++) {
// Creates a rounded rectangle with margin:
box = new Path.Rectangle(
new Rectangle(
boxX * sW + margin, boxY * sH + margin,
sW - 2 * margin, sH - 2 * margin),
margin * (boxX === 4 ? 4 : 2));
box.fillColor = boxX === 4 ? (
// Button is a mode button
boxY === 0 ? selectedMode : boxY === 3 ? playCell : unselectedMode
) : lightCell;
cells.push(box);
}
}
if (playElement) {
playElement.remove();
}
playElement = new Path({
segments: isPlaying ? pauseSegments : playSegments,
fillColor: 'black',
closed: true
});
playElement.position = new Point(width - sW / 2, height - sH / 2);
}
function onMouseDown(event) {
var mX = event.point.x;
var mY = event.point.y;
var jR = Math.floor(mX / sW);
var jD = Math.floor(mY / sH);
var textElements = customizingState.textElements;
textElements.forEach(function (e) {
e.remove();
});
if (mode === 3) {
mode = customizingState.lastState;
customizingState.selectedCell.fillColor = lightCell;
customizingState.selectedCell = null;
}
if (mode === 2 && jD > 1) {
// Do something with the help
window.open('https://www.reddit.com/duplicates/2vq8t0');
} else if (event.event.ctrlKey) {
customizingState.lastState = mode;
customizingState.coords = [jR, jD];
customizingState.selectedCell = cells[jR + (jD * 5)];
mode = 3;
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 5; col++) {
for (var mapping in keymapping) {
if (keymapping[mapping][1] === row && keymapping[mapping][0] === col) {
textElements[row * 5 + col] = new PointText({
point: [margin * 8 + col * sW, row * sH + margin * 8],
content: mapping,
fillColor: 'black',
fontFamily: 'Courier New',
fontWeight: 'bold',
fontSize: 18
});
if (row === jD && col === jR) {
customizingState.oldMapping = mapping;
}
break;
}
}
}
}
} else {
processInput(jR, jD);
}
}
function onKeyDown(evt) {
if (evt.event.shitKey || evt.event.ctrlKey || evt.event.altKey) {return;}
if (mode === 3) {
// key customizing mode
keymapping[evt.key] = customizingState.coords;
delete keymapping[customizingState.oldMapping];
mode = customizingState.lastState;
customizingState.selectedCell = null;
var textElements = customizingState.textElements;
textElements.forEach(function (e) {
e.remove();
});
textElements = [];
}
var key = keymapping[evt.key];
if (key) {
processInput(key[0], key[1]);
}
}
function processInput(jR, jD) {
var cellsum = jR + (jD * 5);
var punNum = jR + (jD * 4) + mode * 16 + 1;
var box = cells[cellsum];
if (jR === 4) {
if (jD === 3) {
playBackBacking();
} else {
for (var row = 0; row < 3; row++) {
cells[row * 5 + 4].fillColor = (row === jD) ? selectedMode : unselectedMode;
}
if (jD === 2) {
var helpBackground = new Path.Rectangle(
new Rectangle(margin, 2 * sH + margin,
sW * 4 - 2 * margin, sH * 2 - 2 * margin),
2 * margin);
helpBackground.fillColor = lightCell;
helpEl = new Group([helpBackground].concat([
'You can use the keyboard, the mouse or touch to control',
'To change keyboard mappings hold ctrl then press a button',
'(I expect there is a ctrl in your keyboard)','',
'Future improvements:',
' - A better interface',
' - Animations, again',
' - Customizable samples',
' - Web MIDI input (maybe)','',
'Click here to visit reddit post'
].map(function (text, n) {
return new PointText({
point: [margin * 8, 2 * sH + margin * 8 + n * 20],
content: text,
fillColor: 'black',
fontFamily: 'Courier New',
fontWeight: 'bold',
fontSize: 18
});
})));
} else if (mode === 2) {
helpEl.remove();
}
}
mode = jD;
} else if (punks[punNum]) {
box.fillColor = selectedCell;
ion.sound.play(punks[punNum].name);
setTimeout(function () {
box.fillColor = lightCell;
}, 250);
}
}
// Reposition the path whenever the window is resized:
function onResize() {
initializePath();
}
function onFrame(evt) {
if (customizingState.selectedCell) {
customizingState.selectedCell.fillColor = Math.floor(evt.count / 30) % 2 ?
selectedMode: playCell;
}
}
function playBackBacking() {
if (isPlaying) {
isPlaying = false;
ion.sound.pause(punks[0].name);
playElement.segments = playSegments;
} else {
isPlaying = true;
ion.sound.play(punks[0].name);
playElement.segments = pauseSegments;
}
playElement.position = new Point(width - sW / 2, height - sH / 2);
}
setTimeout(playBackBacking, 1000);
var punks = ['beat',
'WorkIt1', 'MakeIt1', 'DoIt1', 'MakesUs1', 'Harder1', 'Better1', 'Faster1', 'Stronger1',
'MoreThan1', 'Hour1', 'Our1', 'Never1', 'Ever1', 'After1', 'WorkIs1', 'Over1',
'WorkIt2', 'MakeIt2', 'DoIt2', 'MakesUs2', 'Harder2', 'Better2', 'Faster2', 'Stronger2',
'MoreThan2', 'Hour2', 'Our2', 'Never2', 'Ever2', 'After2', 'WorkIs2', 'Over2',
'MoreThan3', 'Hour3', 'Our3', 'Never3', 'Ever3', 'After3', 'WorkIs3', 'Over3'
].map(function (punk) {
return {name: punk};
});
ion.sound({
sounds: punks,
volume: 0.5,
// Seen that it doesn't support HTTPS
path: "http://s.cdpn.io/190177/",
preload: true
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment