JavaScript preprocessors can help make authoring JavaScript easier and more convenient. For instance, CoffeeScript can help prevent easy-to-make mistakes and offer a cleaner syntax and Babel can bring ECMAScript 6 features to browsers that only support ECMAScript 5.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
HTML Settings
Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
<canvas id = "canvas">
body { margin: 0; overflow: hidden; background: #111; color: #ccc; }
#canvas {
position: fixed;
top:50%;
bottom: 0;
left: 50%;
right: 0;
width: 100vmin;
height: 100vmin;
transform:translate(-50%, -25%);
image-rendering: optimizeSpeed;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: -o-crisp-edges;
image-rendering: pixelated;
-ms-interpolation-mode: nearest-neighbor;
cursor: none;
margin: auto;
}
//ctx.canvas.style = 'position:fixed; top: 50%; left:50%;width:!00vmin;height:100vmin;transform:translate(-50%, -50%)';
var GAME = (function(){
var states = {};
assets = {
//font:{
// string: "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_!@.'\"?/<()",
// bin: [
// ["111111111011111111001111111111111111000111111111111000110000100011000101110111100111011110011111111110001100011000110001100011111100100011101111010010111110111111111011100111001110000000010011111010100000000110110110111000001000100001001000"],
// ["100011000110000100101000010000100001000100100000101001010000110111100110001100011000110001100000010010001100011000101010010100001001100100010000110010100001000000001100011000110001000000010010001111110000000010010011000100010001000010000100"],
// ["111111111010000100011110011100101111111100100000101110010000101011010110001100101000111110011100010010001100011010100100001000010000100000100011011111111101111000010011100111110001000000010010111010100000000100100100011000100010000010000100"],
// ["100011000110000100011000010000100011000100100100101001010000100011001110001111001001010001000010010010001010101010101010001000100000100001000000100010000011000100100100010000110001000000000010101111110000000000000000000001000001000010000100"],
// ["100011111001111111101111110000111111000111111111101000111111100011000101110100000111110001111100010001110001000111010001001001111101110111111111000010111100111000100011100111001110111110010010111010100010000000000000010010000000100001001000"]
// ],
// },
song: {
songData: [
{ // Instrument 0
i: [
1, // OSC1_WAVEFORM
192, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
1, // OSC2_WAVEFORM
191, // OSC2_VOL
116, // OSC2_SEMI
9, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
6, // ENV_ATTACK
22, // ENV_SUSTAIN
34, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
69, // LFO_AMT
3, // LFO_FREQ
1, // LFO_FX_FREQ
1, // FX_FILTER
23, // FX_FREQ
167, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
77, // FX_PAN_AMT
6, // FX_PAN_FREQ
25, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [1],
// Columns
c: [
{n: [159],
f: []}
]
},
{ // Instrument 1
i: [
2, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
6, // ENV_SUSTAIN
58, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
195, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
121, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [],
// Columns
c: [
]
},
{ // Instrument 2
i: [
2, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
6, // ENV_SUSTAIN
58, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
195, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
121, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [],
// Columns
c: [
]
},
{ // Instrument 3
i: [
2, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
6, // ENV_SUSTAIN
58, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
195, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
121, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [],
// Columns
c: [
]
},
{ // Instrument 4
i: [
2, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
6, // ENV_SUSTAIN
58, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
195, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
121, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [],
// Columns
c: [
]
},
{ // Instrument 5
i: [
2, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
6, // ENV_SUSTAIN
58, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
195, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
121, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [],
// Columns
c: [
]
},
{ // Instrument 6
i: [
2, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
6, // ENV_SUSTAIN
58, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
195, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
121, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [],
// Columns
c: [
]
},
{ // Instrument 7
i: [
2, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
6, // ENV_SUSTAIN
58, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
195, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
121, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [],
// Columns
c: [
]
}
],
rowLen: 5513, // In sample lengths
patternLen: 1, // Rows per pattern
endPattern: 2 // End pattern
},
songdemo: {
songData: [
{ // Instrument 0
i: [
2, // OSC1_WAVEFORM
159, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
4, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
0, // ENV_ATTACK
21, // ENV_SUSTAIN
33, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
2, // LFO_WAVEFORM
232, // LFO_AMT
3, // LFO_FREQ
1, // LFO_FX_FREQ
3, // FX_FILTER
50, // FX_FREQ
210, // FX_RESONANCE
149, // FX_DIST
244, // FX_DRIVE
156, // FX_PAN_AMT
6, // FX_PAN_FREQ
123, // FX_DELAY_AMT
6 // FX_DELAY_TIME
],
// Patterns
p: [1,1,1,1,4,4,2,3,1,1,2,3,4,4,2,3,1,1,2,3,4,4,4,4,4,4,5,4,5,1,5,4,4,2,3,6],
// Columns
c: [
{n: [120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132],
f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,33]},
{n: [118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130],
f: []},
{n: [113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125],
f: []},
{n: [120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132,120,120,132,120,132,120,130,132],
f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,43]},
{n: [118,118,130,118,130,118,128,130,118,118,130,118,130,118,128,130,113,113,125,113,125,113,123,125,113,113,125,113,125,113,123,125],
f: []},
{n: [120,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,127],
f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,115]}
]
},
{ // Instrument 1
i: [
0, // OSC1_WAVEFORM
128, // OSC1_VOL
106, // OSC1_SEMI
1, // OSC1_XENV
0, // OSC2_WAVEFORM
127, // OSC2_VOL
106, // OSC2_SEMI
12, // OSC2_DETUNE
1, // OSC2_XENV
16, // NOISE_VOL
0, // ENV_ATTACK
0, // ENV_SUSTAIN
191, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
0, // LFO_AMT
0, // LFO_FREQ
0, // LFO_FX_FREQ
2, // FX_FILTER
24, // FX_FREQ
169, // FX_RESONANCE
5, // FX_DIST
71, // FX_DRIVE
83, // FX_PAN_AMT
5, // FX_PAN_FREQ
0, // FX_DELAY_AMT
0 // FX_DELAY_TIME
],
// Patterns
p: [,,,,1,1,1,1,1,1,1,1,1,1,1,1,,,,,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2],
// Columns
c: [
{n: [135,,,135,,,135,,135,,,135,,,135,,135,,,135,,,135,,135,,,135,,,135],
f: [13,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,138,56]},
{n: [135],
f: [13,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,164,,,,,,,,,,,191]}
]
},
{ // Instrument 2
i: [
0, // OSC1_WAVEFORM
107, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
0, // OSC2_WAVEFORM
7, // OSC2_VOL
128, // OSC2_SEMI
0, // OSC2_DETUNE
1, // OSC2_XENV
0, // NOISE_VOL
109, // ENV_ATTACK
27, // ENV_SUSTAIN
208, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
3, // LFO_WAVEFORM
236, // LFO_AMT
9, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
135, // FX_FREQ
0, // FX_RESONANCE
0, // FX_DIST
11, // FX_DRIVE
147, // FX_PAN_AMT
6, // FX_PAN_FREQ
152, // FX_DELAY_AMT
3 // FX_DELAY_TIME
],
// Patterns
p: [,,2,,,2,,,,,3,,,2,,,1,2,3,4,,,2,,,2,,1,5,1,5],
// Columns
c: [
{n: [156,,168],
f: []},
{n: [156,,163],
f: []},
{n: [154,,166],
f: []},
{n: [149,,161],
f: []},
{n: [154,,166,,,,,,,,,,,,,,149,,161],
f: []}
]
},
{ // Instrument 3
i: [
0, // OSC1_WAVEFORM
0, // OSC1_VOL
140, // OSC1_SEMI
0, // OSC1_XENV
0, // OSC2_WAVEFORM
0, // OSC2_VOL
140, // OSC2_SEMI
0, // OSC2_DETUNE
0, // OSC2_XENV
255, // NOISE_VOL
242, // ENV_ATTACK
0, // ENV_SUSTAIN
0, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
2, // LFO_WAVEFORM
255, // LFO_AMT
3, // LFO_FREQ
1, // LFO_FX_FREQ
2, // FX_FILTER
77, // FX_FREQ
231, // FX_RESONANCE
0, // FX_DIST
32, // FX_DRIVE
243, // FX_PAN_AMT
3, // FX_PAN_FREQ
157, // FX_DELAY_AMT
2 // FX_DELAY_TIME
],
// Patterns
p: [,,,1,,,,1,,,,1,,,,1,,,,1,,,,1,,,1,,,,1,,,,1],
// Columns
c: [
{n: [147],
f: []}
]
},
{ // Instrument 4
i: [
3, // OSC1_WAVEFORM
0, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
0, // OSC2_WAVEFORM
0, // OSC2_VOL
128, // OSC2_SEMI
3, // OSC2_DETUNE
0, // OSC2_XENV
255, // NOISE_VOL
0, // ENV_ATTACK
0, // ENV_SUSTAIN
142, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
0, // LFO_AMT
0, // LFO_FREQ
0, // LFO_FX_FREQ
2, // FX_FILTER
21, // FX_FREQ
226, // FX_RESONANCE
104, // FX_DIST
255, // FX_DRIVE
105, // FX_PAN_AMT
4, // FX_PAN_FREQ
105, // FX_DELAY_AMT
4 // FX_DELAY_TIME
],
// Patterns
p: [,,,,2,,,,,,,,3,1,1,1,,,,,,,,,1,1,1,1,1,1,1,1,1,1,1,2],
// Columns
c: [
{n: [,,,,147,,,,,,,,147,,,,,,,,147,,,,,,,,147],
f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,65]},
{n: [147],
f: [13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,142]},
{n: [147,,,,,,,,,,,,147,,,,,,,,147,,,,,,,,147],
f: [13,13,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,142,65]}
]
},
{ // Instrument 5
i: [
0, // OSC1_WAVEFORM
192, // OSC1_VOL
104, // OSC1_SEMI
0, // OSC1_XENV
0, // OSC2_WAVEFORM
192, // OSC2_VOL
116, // OSC2_SEMI
4, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
5, // ENV_ATTACK
17, // ENV_SUSTAIN
56, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
69, // LFO_AMT
5, // LFO_FREQ
1, // LFO_FX_FREQ
3, // FX_FILTER
82, // FX_FREQ
181, // FX_RESONANCE
13, // FX_DIST
187, // FX_DRIVE
148, // FX_PAN_AMT
5, // FX_PAN_FREQ
128, // FX_DELAY_AMT
8 // FX_DELAY_TIME
],
// Patterns
p: [,,,,,,,,1,1,2,3,1,1,2,3,1,1,2,3,,,1,1,,,,1,4,1,4],
// Columns
c: [
{n: [144,,,144,,144,142,156,,,,,,,,,144,,,144,,144,142,156],
f: []},
{n: [142,,,142,,142,140,154,,,,,,,,,142,,,142,,142,140,154],
f: []},
{n: [149,,,149,,149,147,161,,,,,,,,,149,,,149,,149,147,161],
f: []},
{n: [142,,,142,,142,140,154,,,,,,,,,149,,,149,,149,147,161],
f: []}
]
},
{ // Instrument 6
i: [
0, // OSC1_WAVEFORM
131, // OSC1_VOL
116, // OSC1_SEMI
0, // OSC1_XENV
0, // OSC2_WAVEFORM
117, // OSC2_VOL
140, // OSC2_SEMI
2, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
120, // ENV_ATTACK
6, // ENV_SUSTAIN
47, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
39, // LFO_AMT
8, // LFO_FREQ
0, // LFO_FX_FREQ
2, // FX_FILTER
255, // FX_FREQ
0, // FX_RESONANCE
18, // FX_DIST
35, // FX_DRIVE
75, // FX_PAN_AMT
5, // FX_PAN_FREQ
108, // FX_DELAY_AMT
2 // FX_DELAY_TIME
],
// Patterns
p: [,,,,,,,,,,,,,,,,,,,,,,,,1,2,1,2,3,2,3,2],
// Columns
c: [
{n: [151,149,147,144,,,,,,,144,,147,151,,149,,,,,,,,,149,151,154,149,151,154,151,154],
f: [11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19]},
{n: [156],
f: [11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,120]},
{n: [151,149,151,154,,,,,,,156,,154,151,,149,,,,,,,,,149,151,154,149,151,154,151,154],
f: [11,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,19]}
]
},
{ // Instrument 7
i: [
3, // OSC1_WAVEFORM
100, // OSC1_VOL
128, // OSC1_SEMI
0, // OSC1_XENV
3, // OSC2_WAVEFORM
201, // OSC2_VOL
128, // OSC2_SEMI
3, // OSC2_DETUNE
0, // OSC2_XENV
0, // NOISE_VOL
135, // ENV_ATTACK
0, // ENV_SUSTAIN
100, // ENV_RELEASE
0, // ARP_CHORD
0, // ARP_SPEED
0, // LFO_WAVEFORM
81, // LFO_AMT
6, // LFO_FREQ
1, // LFO_FX_FREQ
3, // FX_FILTER
111, // FX_FREQ
165, // FX_RESONANCE
5, // FX_DIST
19, // FX_DRIVE
147, // FX_PAN_AMT
5, // FX_PAN_FREQ
162, // FX_DELAY_AMT
3 // FX_DELAY_TIME
],
// Patterns
p: [,,,,,,,,,,,,,,,,,,,,1,2,1,2,1,2,3,2,3,2,3,2],
// Columns
c: [
{n: [159,156,,,,,,,,,,,,,,,161,156],
f: []},
{n: [163,156,,,,,,,,,,,,,,,163,156],
f: []},
{n: [159,154,,,,,,,,,,,,,,,161,156],
f: []}
]
}
],
rowLen: 7350, // In sample lengths
patternLen: 32, // Rows per pattern
endPattern: 37 // End pattern
},
letters: {
'-' : [
[,,,,0],
[,,,,0],
[1,1,1,1,1],
[,,,,0],
[,,,,0]
],
'.' : [
[,,,,0],
[,,,,0],
[,,,,0],
[,,,,0],
[,,1,,0]
],
'1': [
[,1,1,,0],
[,,1,,0],
[,,1,,0],
[,,1,,0],
[1,1,1,1,1]
],
'2': [
[1, 1, 1, 1, 0],
[, , , , 1],
[, 1, 1, 1, 0],
[1, , , , 0],
[1, 1, 1, 1, 1]
],
'3': [
[1, 1, 1, 1, 0],
[, , , , 1],
[, 1, 1, 1, 1],
[, , , , 1],
[1, 1, 1, 1, 0]
],
'4': [
[1, , , 1, 0],
[1, , , 1, 0],
[1, 1, 1, 1, 1],
[, , , 1, 0],
[, , , 1, 0]
],
'5': [
[1, 1, 1, 1, 1],
[1, , , , 0],
[1, 1, 1, 1, 0],
[, , , , 1],
[1, 1, 1, 1, 0]
],
'6': [
[, 1, 1, 1, 0],
[1, , , , 0],
[1, 1, 1, 1, 0],
[1, , , , 1],
[, 1, 1, 1, 0]
],
'7': [
[1, 1, 1, 1, 1],
[, , , , 1],
[, , , 1, 0],
[, , 1, , 0],
[, , 1, , 0]
],
'8': [
[, 1, 1, 1, 0],
[1, , , , 1],
[, 1, 1, 1, 0],
[1, , , , 1],
[, 1, 1, 1, 0]
],
'9': [
[, 1, 1, 1, 0],
[1, , , , 1],
[, 1, 1, 1, 1],
[, , , , 1],
[, 1, 1, 1, 0]
],
'0': [
[, 1, 1, 1, 0],
[1, , , , 1],
[1, , , , 1],
[1, , , , 1],
[, 1, 1, 1, 0]
],
'A': [
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, , , , 1]
],
'B': [
[1, 1, 1, 1, 0],
[1, , , 1, 0],
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, 1, 1, 1, 1]
],
'C': [
[1, 1, 1, 1, 1],
[1, , , , 0],
[1, , , , 0],
[1, , , , 0],
[1, 1, 1, 1, 1]
],
'D': [
[1, 1, 1, , 0],
[1, , , 1, 0],
[1, , , , 1],
[1, , , , 1],
[1, 1, 1, 1, 1]
],
'E': [
[1, 1, 1, 1, 1],
[1, , , , 0],
[1, 1, 1, , 0],
[1, , , , 0],
[1, 1, 1, 1, 1]
],
'F': [
[1, 1, 1, 1, 1],
[1, , , , 0],
[1, 1, 1, , 0],
[1, , , , 0],
[1, , , , 0]
],
'G': [
[1, 1, 1, 1, 1],
[1, , , , 0],
[1, , 1, 1, 1],
[1, , , , 1],
[1, 1, 1, 1, 1]
],
'H': [
[1, , , , 1],
[1, , , , 1],
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, , , , 1]
],
'I': [
[1, 1, 1, 1, 1],
[, , 1, , 0],
[, , 1, , 0],
[, , 1, , 0],
[1, 1, 1, 1, 1]
],
'J': [
[, , , , 1],
[, , , , 1],
[, , , , 1],
[1, , , , 1],
[1, 1, 1, 1, 1]
],
'K': [
[1, , , 1, 0],
[1, , 1, , 0],
[1, 1, 1, , 0],
[1, , , 1, 0],
[1, , , , 1]
],
'L': [
[1, , , , 0],
[1, , , , 0],
[1, , , , 0],
[1, , , , 0],
[1, 1, 1, 1, 1]
],
'M': [
[1, , , , 1],
[1, 1, , 1, 1],
[1, , 1, , 1],
[1, , , , 1],
[1, , , , 1]
],
'N': [
[1, , , , 1],
[1, 1, , , 1],
[1, , 1, , 1],
[1, , , 1, 1],
[1, , , , 1]
],
'O': [
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, , , , 1],
[1, , , , 1],
[1, 1, 1, 1, 1]
],
'P': [
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, 1, 1, 1, 1],
[1, , , , 0],
[1, , , , 0]
],
'Q': [
[1, 1, 1, 1, 0],
[1, , , 1, 0],
[1, , , 1, 0],
[1, , , 1, 0],
[1, 1, 1, 1, 1]
],
'R': [
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, 1, 1, 1, 1],
[1, , , 1, 0],
[1, , , , 1]
],
'S': [
[1, 1, 1, 1, 1],
[1, , , , 0],
[1, 1, 1, 1, 1],
[, , , , 1],
[1, 1, 1, 1, 1]
],
'T': [
[1, 1, 1, 1, 1],
[, , 1, , 0],
[, , 1, , 0],
[, , 1, , 0],
[, , 1, , 0]
],
'U': [
[1, , , , 1],
[1, , , , 1],
[1, , , , 1],
[1, , , , 1],
[1, 1, 1, 1, 1]
],
'V': [
[1, , , , 1],
[1, , , , 1],
[1, , , , 1],
[, 1, , 1, 0],
[, , 1, , 0]
],
'W': [
[1, , , , 1],
[1, , , , 1],
[1, , 1, , 1],
[1, 1, , 1, 1],
[1, , , , 1]
],
'X': [
[1, , , , 1],
[, 1, , 1, 0],
[, , 1, , 0],
[, 1, , 1, 0],
[1, , , , 1]
],
'Y': [
[1, , , , 1],
[1, , , , 1],
[1, 1, 1, 1, 1],
[, , 1, , 0],
[, , 1, , 0]
],
'Z': [
[1, 1, 1, 1, 1],
[, , , 1, 0],
[, , 1, , 0],
[, 1, , , 0],
[1, 1, 1, 1, 1]
],
' ': [
[, , , , 0],
[, , , , 0],
[, , , , 0],
[, , , , 0],
[, , , , 0]
],
',': [
[, , , , 0],
[, , , , 0],
[, , , , 0],
[, , 1, , 0],
[, , 1, , 0]
],
'+': [
[, , , , 0],
[, , 1, , 0],
[, 1, 1, 1, 0],
[, , 1, , 0],
[, , , , 0]
],
'/': [
[, , , , 1],
[, , , 1, 0],
[, , 1, , 0],
[, 1, , , 0],
[1, , , , 0]
],
':': [
[, , , , 0],
[, , 1, , 0],
[, , , , 0],
[, , 1, , 0],
[, , , , 0]
],
'@': [
[1, 1, 1, 1, 1],
[, , , , 1],
[1, 1, 1, , 1],
[1, , 1, , 1],
[1, 1, 1, 1, 1]
],
/*'x': [ //solid first checkers
[1, , 1, , 1],
[, 1, , 1, 0],
[1, , 1, , 1],
[, 1, , 1, 0],
[1, , 1, , 1]
],
'z': [
//empty first checkers
[, 1, , 1, 0],
[1, , 1, , 1],
[, 1, , 1, 0],
[1, , 1, , 1],
[, 1, , 1, 0]
],
'o': [
//box with dot
[1, 1, 1, 1, 1],
[1, , , , 1],
[1, , 1, , 1],
[1, , , , 1],
[1, 1, 1, 1, 1]
],
'e': [
//down-right slope
[1,,,,0],
[1,1,,,0],
[1,1,1,,0],
[1,1,1,1,0],
[1,1,1,1,1],
],
'w': [
//down-left slope
[,,,,1],
[,,,1,1],
[,,1,1,1],
[,1,1,1,1],
[1,1,1,1,1],
],
's': [
//up-left slope
[1, 1, 1, 1, 1],
[, 1, 1, 1, 1],
[, , 1, 1, 1],
[, , , 1, 1],
[, , , , 1]
],
'd': [
//up-right slope
[1,1,1,1,1],
[1,1,1,1,0],
[1,1,1,,0],
[1,1,,,0],
[1,,,,0]
],
't': [
//player 1
[0,0,0,1,1],
[0,0,1,1,1],
[0,0,1,1,1],
[0,0,1,1,1],
[0,0,1,1,1],
],
'y': [
//player 1
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]
],
'u': [
//player 1
[1,1,0,0,0],
[1,1,1,0,0],
[0,0,1,0,0],
[0,1,1,0,0],
[1,1,1,0,0]
],
'g': [
//player 1
[0,0,1,1,1],
[0,0,0,1,1],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,1]
],
'h': [
//player 1
[1,1,1,1,1],
[1,1,1,1,1],
[0,1,1,1,0],
[1,1,1,1,1],
[1,1,1,1,1]
],
'j': [
//player 1
[1,1,1,0,0],
[1,1,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
[1,1,1,1,1]
],
'b': [
//player 1
[0,0,0,1,1],
[0,0,0,1,1],
[0,0,0,0,1],
[0,0,0,0,1],
[0,0,0,0,1]
],
'n': [
//player 1
[1,1,1,1,1],
[1,1,1,1,1],
[0,0,0,0,0],
[0,0,0,0,0],
[0,0,0,0,0],
],
'a': [
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
], */
}
};
//--this gets wrapped in a closure, so no namespace object, compresses better.
var
C = document.getElementById('canvas');
ctx = C.getContext('2d'),
renderTarget = 0x00000,
renderSource = 0x10000,
//Richard Fhager's DB32 Palette http://http://pixeljoint.com/forum/forum_posts.asp?TID=16247
//ofcourse you can change this to whatever you like, up to 256 colors.
//one GOTCHA: colors are stored 0xAABBGGRR, so you'll have to flop the values from your typical hex colors.
colors = [0xff000000, 0xff342022, 0xff3c2845, 0xff313966, 0xff3b568f, 0xff2671df, 0xff66a0d9, 0xff9ac3ee, 0xff36f2fb,
0xff50e599, 0xff30be6a, 0xff6e9437, 0xff2f694b, 0xff244b52, 0xff393c32, 0xff743f3f, 0xff826030, 0xffe16e5b,
0xffff9b63, 0xffe4cd5f, 0xfffcdbcb, 0xffffffff, 0xffb7ad9b, 0xff877e84, 0xff6a6a69, 0xff525659, 0xff8a4276,
0xff3232ac, 0xff6357d9, 0xffba7bd7, 0xff4a978f, 0xff306f8a],
//default palette index
palDefault = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],
//active palette index. maps to indices in colors[]. can alter this whenever for palette effects.
pal = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31];
ctx.imageSmoothingEnabled = false;
ctx.mozImageSmoothingEnabled = false;
C.width = C.height = 256;
var imageData = ctx.getImageData(0, 0, 256, 256),
buf = new ArrayBuffer(imageData.data.length),
buf8 = new Uint8Array(buf),
data = new Uint32Array(buf),
ram = new Uint8ClampedArray(0x80000);
//--------------graphics functions----------------
function clear(color){
ram.fill(color, renderTarget, renderTarget + 0x10000);
}
function pset(x, y, color) { //from colors array, 0-31
x = x|0; y = y|0;
if (x > -1 && x < 256 && y > -1 && y < 256) {
ram[renderTarget + (y * 256 + x)] = color;
}
}
function line(x1, y1, x2, y2, color) {
x1 = x1|0;
x2 = x2|0;
y1 = y1|0;
y2 = y2|0;
var dy = (y2 - y1);
var dx = (x2 - x1);
var stepx, stepy;
if (dy < 0) {
dy = -dy;
stepy = -1;
} else {
stepy = 1;
}
if (dx < 0) {
dx = -dx;
stepx = -1;
} else {
stepx = 1;
}
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
pset(x1, y1, color);
if (dx > dy) {
var fraction = dy - (dx >> 1); // same as 2*dy - dx
while (x1 != x2) {
if (fraction >= 0) {
y1 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
x1 += stepx;
fraction += dy; // same as fraction -= 2*dy
pset(x1, y1, color);
}
;
} else {
fraction = dx - (dy >> 1);
while (y1 != y2) {
if (fraction >= 0) {
x1 += stepx;
fraction -= dy;
}
y1 += stepy;
fraction += dx;
pset(x1, y1, color);
}
}
}
function circle(xm, ym, r, color) {
var x = -r, y = 0, err = 2 - 2 * r;
/* II. Quadrant */
do {
pset(xm - x, ym + y, color);
/* I. Quadrant */
pset(xm - y, ym - x, color);
/* II. Quadrant */
pset(xm + x, ym - y, color);
/* III. Quadrant */
pset(xm + y, ym + x, color);
/* IV. Quadrant */
r = err;
if (r <= y) err += ++y * 2 + 1;
/* e_xy+e_y < 0 */
if (r > x || err > y) err += ++x * 2 + 1;
/* e_xy+e_x > 0 or no 2nd y-step */
} while (x < 0);
}
function fillCircle(xm, ym, r, color) {
if(r < 0) return;
xm = xm|0; ym = ym|0, r = r|0; color = color|0;
var x = -r, y = 0, err = 2 - 2 * r;
/* II. Quadrant */
do {
line(xm-x, ym-y, xm+x, ym-y, color);
line(xm-x, ym+y, xm+x, ym+y, color);
r = err;
if (r <= y) err += ++y * 2 + 1;
if (r > x || err > y) err += ++x * 2 + 1;
} while (x < 0);
}
function rect(x, y, w, h, color) {
x1 = x|0;
y1 = y|0;
x2 = (x+w)|0;
y2 = (y+h)|0;
line(x1,y1, x2, y1, color);
line(x2, y1, x2, y2, color);
line(x1, y2, x2, y2, color);
line(x1, y1, x1, y2, color);
}
function fr(x, y, w, h, color) { //draw a filled rectangle
x1 = x|0;
y1 = y|0;
x2 = (x+w)|0;
y2 = (y+h)|0;
var i = Math.abs(y2 - y1);
line(x1, y1, x2, y1, color);
if(i > 0){
while (--i) {
line(x1, y1+i, x2, y1+i, color);
}
}
line(x1,y2, x2, y2, color);
}
function triangle(x1, y1, x2, y2, x3, y3, color) {
line(x1,y1, x2,y2, color);
line(x2,y2, x3,y3, color);
line(x3,y3, x1,y1, color);
}
function fillTriangle( x1, y1, x2, y2, x3, y3, color ) {
var canvasWidth = 256;
// http://devmaster.net/forums/topic/1145-advanced-rasterization/
// 28.4 fixed-point coordinates
var x1 = Math.round( 16 * x1 );
var x2 = Math.round( 16 * x2 );
var x3 = Math.round( 16 * x3 );
var y1 = Math.round( 16 * y1 );
var y2 = Math.round( 16 * y2 );
var y3 = Math.round( 16 * y3 );
// Deltas
var dx12 = x1 - x2, dy12 = y2 - y1;
var dx23 = x2 - x3, dy23 = y3 - y2;
var dx31 = x3 - x1, dy31 = y1 - y3;
// Bounding rectangle
var minx = Math.max( ( Math.min( x1, x2, x3 ) + 0xf ) >> 4, 0 );
var maxx = Math.min( ( Math.max( x1, x2, x3 ) + 0xf ) >> 4, 256 );
var miny = Math.max( ( Math.min( y1, y2, y3 ) + 0xf ) >> 4, 0 );
var maxy = Math.min( ( Math.max( y1, y2, y3 ) + 0xf ) >> 4, 256 );
// Block size, standard 8x8 (must be power of two)
var q = 8;
// Start in corner of 8x8 block
minx &= ~(q - 1);
miny &= ~(q - 1);
// Constant part of half-edge functions
var c1 = -dy12 * x1 - dx12 * y1;
var c2 = -dy23 * x2 - dx23 * y2;
var c3 = -dy31 * x3 - dx31 * y3;
// Correct for fill convention
if ( dy12 > 0 || ( dy12 == 0 && dx12 > 0 ) ) c1 ++;
if ( dy23 > 0 || ( dy23 == 0 && dx23 > 0 ) ) c2 ++;
if ( dy31 > 0 || ( dy31 == 0 && dx31 > 0 ) ) c3 ++;
// Note this doesn't kill subpixel precision, but only because we test for >=0 (not >0).
// It's a bit subtle. :)
c1 = (c1 - 1) >> 4;
c2 = (c2 - 1) >> 4;
c3 = (c3 - 1) >> 4;
// Set up min/max corners
var qm1 = q - 1; // for convenience
var nmin1 = 0, nmax1 = 0;
var nmin2 = 0, nmax2 = 0;
var nmin3 = 0, nmax3 = 0;
if (dx12 >= 0) nmax1 -= qm1*dx12; else nmin1 -= qm1*dx12;
if (dy12 >= 0) nmax1 -= qm1*dy12; else nmin1 -= qm1*dy12;
if (dx23 >= 0) nmax2 -= qm1*dx23; else nmin2 -= qm1*dx23;
if (dy23 >= 0) nmax2 -= qm1*dy23; else nmin2 -= qm1*dy23;
if (dx31 >= 0) nmax3 -= qm1*dx31; else nmin3 -= qm1*dx31;
if (dy31 >= 0) nmax3 -= qm1*dy31; else nmin3 -= qm1*dy31;
// Loop through blocks
var linestep = (canvasWidth-q);
for ( var y0 = miny; y0 < maxy; y0 += q ) {
for ( var x0 = minx; x0 < maxx; x0 += q ) {
// Edge functions at top-left corner
var cy1 = c1 + dx12 * y0 + dy12 * x0;
var cy2 = c2 + dx23 * y0 + dy23 * x0;
var cy3 = c3 + dx31 * y0 + dy31 * x0;
// Skip block when at least one edge completely out
if (cy1 < nmax1 || cy2 < nmax2 || cy3 < nmax3) continue;
// Offset at top-left corner
var offset = (x0 + y0 * canvasWidth);
// Accept whole block when fully covered
if (cy1 >= nmin1 && cy2 >= nmin2 && cy3 >= nmin3) {
for ( var iy = 0; iy < q; iy ++ ) {
for ( var ix = 0; ix < q; ix ++, offset ++ ) {
ram[renderTarget + offset] = color;
}
offset += linestep;
}
} else { // Partially covered block
for ( var iy = 0; iy < q; iy ++ ) {
var cx1 = cy1;
var cx2 = cy2;
var cx3 = cy3;
for ( var ix = 0; ix < q; ix ++ ) {
if ( (cx1 | cx2 | cx3) >= 0 ) {
ram[renderTarget + offset] = color;
}
cx1 += dy12;
cx2 += dy23;
cx3 += dy31;
offset ++;
}
cy1 += dx12;
cy2 += dx23;
cy3 += dx31;
offset += linestep;
}
}
}
}
}
function spr(sx = 0, sy = 0, sw = 16, sh = 16, x=0, y=0, flipx = false, flipy = false){
for(var i = 0; i < sh; i++){
for(var j = 0; j < sw; j++){
if(y+i < 255 && x+j < 255 && y+i > -1 && x+j > -1){
if(flipx & flipy){
if(ram[(renderSource + ( ( sy + (sh-i) )*256+sx+(sw-j)))] > 0) {
ram[ (renderTarget + ((y+i)*256+x+j)) ] = pal[ ram[(renderSource + ((sy+(sh-i))*256+sx+(sw-j)))] ];
}
}
else if(flipy && !flipx){
if(ram[(renderSource + ( ( sy + (sh-i) )*256+sx+j))] > 0) {
ram[ (renderTarget + ((y+i)*256+x+j)) ] = ram[(renderSource + ((sy+(sh-i))*256+sx+j))];
}
}
else if(flipx && !flipy){
if(ram[(renderSource + ((sy+i)*256+sx+(sw-j)))] > 0) {
ram[ (renderTarget + ((y+i)*256+x+j)) ] = ram[(renderSource + ((sy+i)*256+sx+(sw-j)))];
}
}
else if(!flipx && !flipy){
if(ram[(renderSource + ((sy+i)*256+sx+j))] > 0) {
ram[ (renderTarget + ((y+i)*256+x+j)) ] = pal[ ram[(renderSource + ((sy+i)*256+sx+j))] ];
}
}
}
}
}
}
function sspr(sx = 0, sy = 0, sw = 16, sh = 16, x=0, y=0, dw=16, dh=16, flipx = false, flipy = false){
var xratio = sw / dw;
var yratio = sh / dh;
for(var i = 0; i < dh; i++){
for(var j = 0; j < dw; j++){
px = (j*xratio)|0;
py = (i*yratio)|0;
if(y+i < 255 && x+j < 255 && y+i > -1 && x+j > -1) {
if (ram[(renderSource + ((sy + py) * 256 + sx + px))] > 0) {
ram[(renderTarget + ((y + i) * 256 + x + j))] = ram[(renderSource + ((sy + py) * 256 + sx + px))]
}
}
}
}
}
function rspr( sx, sy, sw, sh, destCenterX, destCenterY, scale, angle ){
angle = angle * 0.0174533 //convert to radians in place
var sourceCenterX = sx + sw / 2;
var sourceCenterY = sy + sh / 2;
var destWidth = sw * scale;
var destHeight = sh * scale;
var halfWidth = (destWidth / 2 * 1.41421356237)|0 + 5; //area will always be square, hypotenuse trick
var halfHeight = (destHeight / 2 * 1.41421356237)|0 + 5;
var startX = -halfWidth;
var endX = halfWidth;
var startY = -halfHeight;
var endY = halfHeight;
var scaleFactor = 1.0 / scale;
var cos = Math.cos(-angle) * scaleFactor;
var sin = Math.sin(-angle) * scaleFactor;
for(let y = startY; y < endY; y++){
for(let x = startX; x < endX; x++){
let u = sourceCenterX + Math.round(cos * x + sin * y);
let v = sourceCenterY + Math.round(-sin * x + cos * y);
let drawX = (x + destCenterX)|0;
let drawY = (y + destCenterY)|0;
if(u >= 0 && v >= 0 && u < sw && v < sh){
if( ram[ (renderSource + (v * 256 + u)) ] > 0) {
ram[(renderTarget + (drawY * 256 + drawX)) ] = ram[(renderSource + ( v * 256 + u )) ]
}
}
} //end x loop
} //end outer y loop
}
function checker(w, h, nRow, nCol, color) {
//var w = 256;
//var h = 256;
var x = 0;
var y = 0;
nRow = nRow || 8; // default number of rows
nCol = nCol || 8; // default number of columns
w /= nCol; // width of a block
h /= nRow; // height of a block
for (var i = 0; i < nRow; ++i) {
for (var j = 0, col = nCol / 2; j < col; ++j) {
x = 2 * j * w + (i % 2 ? 0 : w);
y = i * h;
fr(x, y, w-1, h-1, color);
}
}
}
// util: {
//
// toPolarScreen(p){
// let degrees = (360/256) * p.x * 0.0174533;
// let radius = p.y / 2;
// return util.polarToPoint(degrees, radius);
// },
//
// norm(value, min, max){
// return (value - min) / (max - min);
// },
//
// dist(x0, y0, x1, y1) {
// if(arguments.length === 2) {
// return this.dist(x0.x, x0.y, y0.x, y0.y);
// }
// var dx = x1 - x0,
// dy = y1 - y0;
// return Math.sqrt(dx * dx + dy * dy);
// },
//
//
// polarToPoint(angle, radius) {
// return {
// x: Math.cos(angle) * radius,
// y: Math.sin(angle) * radius
// };
// },
//
// pointToPolar(p) {
// return {
// angle: Math.atan2(p.y, p.x),
// radius: this.magnitude(p)
// };
// },
//
// magnitude(p) {
// return this.dist(0, 0, p.x, p.y);
// },
//
// scale(p) {
//
// }
//
//
// },
function render() {
var i = 0x10000; // display is first 0x10000 bytes of ram
while (i--) {
/*
data is 32bit view of final screen buffer
for each pixel on screen, we look up it's color and assign it
*/
data[i] = colors[pal[ram[i]]];
}
imageData.data.set(buf8);
ctx.putImageData(imageData, 0, 0);
}
playSound = function(buffer, playbackRate, pan, loop) {
var source = audioCtx.createBufferSource();
var gainNode = audioCtx.createGain();
var panNode = audioCtx.createStereoPanner();
source.buffer = buffer;
source.connect(panNode);
panNode.connect(gainNode);
gainNode.connect(audioCtx.destination);
//gainNode.connect(audioCtx.destination);
source.playbackRate.value = playbackRate;
source.loop = loop;
gainNode.gain.value = 1;
panNode.pan.value = pan;
source.start();
return {volume: gainNode, sound: source};
}
function download(t,e,n){function i(t){var e=t.split(/[:;,]/),n=e[1],i="base64"==e[2]?atob:decodeURIComponent,r=i(e.pop()),o=r.length,a=0,s=new Uint8Array(o);for(a;a<o;++a)s[a]=r.charCodeAt(a);return new m([s],{type:n})}function r(t,e){if("download"in l)return l.href=t,l.setAttribute("download",w),l.innerHTML="downloading...",l.style.display="none",f.body.appendChild(l),setTimeout(function(){l.click(),f.body.removeChild(l),e===!0&&setTimeout(function(){h.URL.revokeObjectURL(l.href)},250)},66),!0;var n=f.createElement("iframe");f.body.appendChild(n),e||(t="data:"+t.replace(/^data:([\w\/\-\+]+)/,d)),n.src=t,setTimeout(function(){f.body.removeChild(n)},333)}var o,a,s,h=window,d="application/octet-stream",u=n||d,c=t,f=document,l=f.createElement("a"),p=function(t){return String(t)},m=h.Blob||h.MozBlob||h.WebKitBlob||p,g=h.MSBlobBuilder||h.WebKitBlobBuilder||h.BlobBuilder,w=e||"download";if("true"===String(this)&&(c=[c,u],u=c[0],c=c[1]),String(c).match(/^data\:[\w+\-]+\/[\w+\-]+[,;]/))return navigator.msSaveBlob?navigator.msSaveBlob(i(c),w):r(c);try{o=c instanceof m?c:new m([c],{type:u})}catch(t){g&&(a=new g,a.append([c]),o=a.getBlob(u))}if(navigator.msSaveBlob)return navigator.msSaveBlob(o,w);if(h.URL)r(h.URL.createObjectURL(o),!0);else{if("string"==typeof o||o.constructor===p)try{return r("data:"+u+";base64,"+h.btoa(o))}catch(t){return r("data:"+u+","+encodeURIComponent(o))}s=new FileReader,s.onload=function(t){r(this.result)},s.readAsDataURL(o)}return!0}window.Whammy=function(){function t(t,n){for(var i=e(t),r=3e4,o=[{id:440786851,data:[{data:1,id:17030},{data:1,id:17143},{data:4,id:17138},{data:8,id:17139},{data:"webm",id:17026},{data:2,id:17031},{data:2,id:17029}]},{id:408125543,data:[{id:357149030,data:[{data:1e6,id:2807729},{data:"whammy",id:19840},{data:"whammy",id:22337},{data:c(i.duration),id:17545}]},{id:374648427,data:[{id:174,data:[{data:1,id:215},{data:1,id:29637},{data:0,id:156},{data:"und",id:2274716},{data:"V_VP8",id:134},{data:"VP8",id:2459272},{data:1,id:131},{id:224,data:[{data:i.width,id:176},{data:i.height,id:186}]}]}]},{id:475249515,data:[]}]}],s=o[1],d=s.data[2],u=0,f=0;u<t.length;){var l={id:187,data:[{data:Math.round(f),id:179},{id:183,data:[{data:1,id:247},{data:0,size:8,id:241}]}]};d.data.push(l);var p=[],m=0;do p.push(t[u]),m+=t[u].duration,u++;while(u<t.length&&m<r);var g=0,w={id:524531317,data:[{data:Math.round(f),id:231}].concat(p.map(function(t){var e=h({discardable:0,frame:t.data.slice(4),invisible:0,keyframe:1,lacing:0,trackNum:1,timecode:Math.round(g)});return g+=t.duration,{data:e,id:163}}))};s.data.push(w),f+=m}for(var v=0,y=0;y<s.data.length;y++){y>=3&&(d.data[y-3].data[1].data[1].data=v);var b=a([s.data[y]],n);v+=b.size||b.byteLength||b.length,2!=y&&(s.data[y]=b)}return a(o,n)}function e(t){for(var e=t[0].width,n=t[0].height,i=t[0].duration,r=1;r<t.length;r++){if(t[r].width!=e)throw"Frame "+(r+1)+" has a different width";if(t[r].height!=n)throw"Frame "+(r+1)+" has a different height";if(t[r].duration<0||t[r].duration>32767)throw"Frame "+(r+1)+" has a weird duration (must be between 0 and 32767)";i+=t[r].duration}return{duration:i,width:e,height:n}}function n(t){for(var e=[];t>0;)e.push(255&t),t>>=8;return new Uint8Array(e.reverse())}function i(t,e){for(var n=new Uint8Array(e),i=e-1;i>=0;i--)n[i]=255&t,t>>=8;return n}function r(t){for(var e=new Uint8Array(t.length),n=0;n<t.length;n++)e[n]=t.charCodeAt(n);return e}function o(t){var e=[],n=t.length%8?new Array(9-t.length%8).join("0"):"";t=n+t;for(var i=0;i<t.length;i+=8)e.push(parseInt(t.substr(i,8),2));return new Uint8Array(e)}function a(t,e){for(var h=[],d=0;d<t.length;d++)if("id"in t[d]){var u=t[d].data;if("object"==typeof u&&(u=a(u,e)),"number"==typeof u&&(u="size"in t[d]?i(u,t[d].size):o(u.toString(2))),"string"==typeof u&&(u=r(u)),u.length);for(var c=u.size||u.byteLength||u.length,f=0,l=56;l>0;l-=7)if(c>Math.pow(2,l)-2){f=l/7;break}var p=c.toString(2),m=new Array(8*(f+1)+1).join("0"),g=new Array(f+1).join("0")+1,w=m.substr(0,m.length-p.length-g.length)+p,v=g+w;h.push(n(t[d].id)),h.push(o(v)),h.push(u)}else h.push(t[d]);if(e){var y=s(h);return new Uint8Array(y)}return new Blob(h,{type:"video/webm"})}function s(t,e){null==e&&(e=[]);for(var n=0;n<t.length;n++)"object"==typeof t[n]?s(t[n],e):e.push(t[n]);return e}function h(t){var e=0;if(t.keyframe&&(e|=128),t.invisible&&(e|=8),t.lacing&&(e|=t.lacing<<1),t.discardable&&(e|=1),t.trackNum>127)throw"TrackNumber > 127 not supported";var n=[128|t.trackNum,t.timecode>>8,255&t.timecode,e].map(function(t){return String.fromCharCode(t)}).join("")+t.frame;return n}function d(t){for(var e=t.RIFF[0].WEBP[0],n=e.indexOf("*"),i=0,r=[];i<4;i++)r[i]=e.charCodeAt(n+3+i);var o,a,s,h,d;return d=r[1]<<8|r[0],o=16383&d,a=d>>14,d=r[3]<<8|r[2],s=16383&d,h=d>>14,{width:o,height:s,data:e,riff:t}}function u(t){for(var e=0,n={};e<t.length;){var i=t.substr(e,4);if(n[i]=n[i]||[],"RIFF"==i||"LIST"==i){var r=parseInt(t.substr(e+4,4).split("").map(function(t){var e=t.charCodeAt(0).toString(2);return new Array(8-e.length+1).join("0")+e}).join(""),2),o=t.substr(e+4+4,r);e+=8+r,n[i].push(u(o))}else"WEBP"==i?(n[i].push(t.substr(e+8)),e=t.length):(n[i].push(t.substr(e+4)),e=t.length)}return n}function c(t){return[].slice.call(new Uint8Array(new Float64Array([t]).buffer),0).map(function(t){return String.fromCharCode(t)}).reverse().join("")}function f(t,e){this.frames=[],this.duration=1e3/t,this.quality=e||.8}return f.prototype.add=function(t,e){if("undefined"!=typeof e&&this.duration)throw"you can't pass a duration if the fps is set";if("undefined"==typeof e&&!this.duration)throw"if you don't have the fps set, you need to have durations here.";if(t.canvas&&(t=t.canvas),t.toDataURL)t=t.getContext("2d").getImageData(0,0,t.width,t.height);else if("string"!=typeof t)throw"frame must be a a HTMLCanvasElement, a CanvasRenderingContext2D or a DataURI formatted string";if("string"==typeof t&&!/^data:image\/webp;base64,/gi.test(t))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";this.frames.push({image:t,duration:e||this.duration})},f.prototype.encodeFrames=function(t){if(this.frames[0].image instanceof ImageData){var e=this.frames,n=document.createElement("canvas"),i=n.getContext("2d");n.width=this.frames[0].image.width,n.height=this.frames[0].image.height;var r=function(o){var a=e[o];i.putImageData(a.image,0,0),a.image=n.toDataURL("image/webp",this.quality),o<e.length-1?setTimeout(function(){r(o+1)},1):t()}.bind(this);r(0)}else t()},f.prototype.compile=function(e,n){this.encodeFrames(function(){var i=new t(this.frames.map(function(t){var e=d(u(atob(t.image.slice(23))));return e.duration=t.duration,e}),e);n(i)}.bind(this))},{Video:f,fromImageArray:function(e,n,i){return t(e.map(function(t){var e=d(u(atob(t.slice(23))));return e.duration=1e3/n,e}),i)},toWebM:t}}(),function(){"use strict";function t(t){var e,n=new Uint8Array(t);for(e=0;e<t;e+=1)n[e]=0;return n}function e(e,n,i,r){var o=n+i,a=t((parseInt(o/r)+1)*r);return a.set(e),a}function n(t,e,n){return t=t.toString(n||8),"000000000000".substr(t.length+12-e)+t}function i(e,n,i){var r,o;for(n=n||t(e.length),i=i||0,r=0,o=e.length;r<o;r+=1)n[i]=e.charCodeAt(r),i+=1;return n}function r(t){function e(t){return o[t>>18&63]+o[t>>12&63]+o[t>>6&63]+o[63&t]}var n,i,r,a=t.length%3,s="";for(n=0,r=t.length-a;n<r;n+=3)i=(t[n]<<16)+(t[n+1]<<8)+t[n+2],s+=e(i);switch(s.length%4){case 1:s+="=";break;case 2:s+="=="}return s}var o=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"];window.utils={},window.utils.clean=t,window.utils.pad=n,window.utils.extend=e,window.utils.stringToUint8=i,window.utils.uint8ToBase64=r}(),function(){"use strict";function t(t,i){var r=n.clean(512),o=0;return e.forEach(function(e){var n,i,a=t[e.field]||"";for(n=0,i=a.length;n<i;n+=1)r[o]=a.charCodeAt(n),o+=1;o+=e.length-n}),"function"==typeof i?i(r,o):r}var e,n=window.utils;e=[{field:"fileName",length:100},{field:"fileMode",length:8},{field:"uid",length:8},{field:"gid",length:8},{field:"fileSize",length:12},{field:"mtime",length:12},{field:"checksum",length:8},{field:"type",length:1},{field:"linkName",length:100},{field:"ustar",length:8},{field:"owner",length:32},{field:"group",length:32},{field:"majorNumber",length:8},{field:"minorNumber",length:8},{field:"filenamePrefix",length:155},{field:"padding",length:12}],window.header={},window.header.structure=e,window.header.format=t}(),function(){"use strict";function t(t){this.written=0,e=(t||20)*r,this.out=i.clean(e),this.blocks=[],this.length=0}var e,n=window.header,i=window.utils,r=512;t.prototype.append=function(t,e,o,a){var s,h,d,u,c,f,l;if("string"==typeof e)e=i.stringToUint8(e);else if(e.constructor!==Uint8Array.prototype.constructor)throw"Invalid input type. You gave me: "+e.constructor.toString().match(/function\s*([$A-Za-z_][0-9A-Za-z_]*)\s*\(/)[1];"function"==typeof o&&(a=o,o={}),o=o||{},d=o.mode||4095&parseInt("777",8),u=o.mtime||Math.floor(+new Date/1e3),c=o.uid||0,f=o.gid||0,s={fileName:t,fileMode:i.pad(d,7),uid:i.pad(c,7),gid:i.pad(f,7),fileSize:i.pad(e.length,11),mtime:i.pad(u,11),checksum:" ",type:"0",ustar:"ustar ",owner:o.owner||"",group:o.group||""},h=0,Object.keys(s).forEach(function(t){var e,n,i=s[t];for(e=0,n=i.length;e<n;e+=1)h+=i.charCodeAt(e)}),s.checksum=i.pad(h,6)+"\0 ",l=n.format(s);var p=Math.ceil(l.length/r)*r,m=Math.ceil(e.length/r)*r;this.blocks.push({header:l,input:e,headerLength:p,inputLength:m})},t.prototype.save=function(){var t=[],e=[],n=0,i=Math.pow(2,20),o=[];return this.blocks.forEach(function(t){n+t.headerLength+t.inputLength>i&&(e.push({blocks:o,length:n}),o=[],n=0),o.push(t),n+=t.headerLength+t.inputLength}),e.push({blocks:o,length:n}),e.forEach(function(e){var n=new Uint8Array(e.length),i=0;e.blocks.forEach(function(t){n.set(t.header,i),i+=t.headerLength,n.set(t.input,i),i+=t.inputLength}),t.push(n)}),t.push(new Uint8Array(2*r)),new Blob(t,{type:"octet/stream"})},t.prototype.clear=function(){this.written=0,this.out=i.clean(e)},window.Tar=t}(),function(t){function e(t,n){if({}.hasOwnProperty.call(e.cache,t))return e.cache[t];var i=e.resolve(t);if(!i)throw new Error("Failed to resolve module "+t);var r={id:t,require:e,filename:t,exports:{},loaded:!1,parent:n,children:[]};n&&n.children.push(r);var o=t.slice(0,t.lastIndexOf("/")+1);return e.cache[t]=r.exports,i.call(r.exports,r,r.exports,o,t),r.loaded=!0,e.cache[t]=r.exports}e.modules={},e.cache={},e.resolve=function(t){return{}.hasOwnProperty.call(e.modules,t)?e.modules[t]:void 0},e.define=function(t,n){e.modules[t]=n};var n=function(e){return e="/",{title:"browser",version:"v0.10.26",browser:!0,env:{},argv:[],nextTick:t.setImmediate||function(t){setTimeout(t,0)},cwd:function(){return e},chdir:function(t){e=t}}}();e.define("/gif.coffee",function(t,n,i,r){function o(t,e){return{}.hasOwnProperty.call(t,e)}function a(t,e){for(var n=0,i=e.length;n<i;++n)if(n in e&&e[n]===t)return!0;return!1}function s(t,e){function n(){this.constructor=t}for(var i in e)o(e,i)&&(t[i]=e[i]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t}var h,d,u,c,f;u=e("events",t).EventEmitter,h=e("/browser.coffee",t),f=function(t){function e(t){var e,n;this.running=!1,this.options={},this.frames=[],this.freeWorkers=[],this.activeWorkers=[],this.setOptions(t);for(e in d)n=d[e],null!=this.options[e]?this.options[e]:this.options[e]=n}return s(e,t),d={workerScript:"gif.worker.js",workers:2,repeat:0,background:"#fff",quality:10,width:null,height:null,transparent:null},c={delay:500,copy:!1},e.prototype.setOption=function(t,e){return this.options[t]=e,null==this._canvas||"width"!==t&&"height"!==t?void 0:this._canvas[t]=e},e.prototype.setOptions=function(t){var e,n;return function(i){for(e in t)o(t,e)&&(n=t[e],i.push(this.setOption(e,n)));return i}.call(this,[])},e.prototype.addFrame=function(t,e){var n,i;null==e&&(e={}),n={},n.transparent=this.options.transparent;for(i in c)n[i]=e[i]||c[i];if(null!=this.options.width||this.setOption("width",t.width),null!=this.options.height||this.setOption("height",t.height),"undefined"!=typeof ImageData&&null!=ImageData&&t instanceof ImageData)n.data=t.data;else if("undefined"!=typeof CanvasRenderingContext2D&&null!=CanvasRenderingContext2D&&t instanceof CanvasRenderingContext2D||"undefined"!=typeof WebGLRenderingContext&&null!=WebGLRenderingContext&&t instanceof WebGLRenderingContext)e.copy?n.data=this.getContextData(t):n.context=t;else{if(null==t.childNodes)throw new Error("Invalid image");e.copy?n.data=this.getImageData(t):n.image=t}return this.frames.push(n)},e.prototype.render=function(){var t,e;if(this.running)throw new Error("Already running");if(null==this.options.width||null==this.options.height)throw new Error("Width and height must be set prior to rendering");this.running=!0,this.nextFrame=0,this.finishedFrames=0,this.imageParts=function(e){for(var n=function(){var t;t=[];for(var e=0;0<=this.frames.length?e<this.frames.length:e>this.frames.length;0<=this.frames.length?++e:--e)t.push(e);return t}.apply(this,arguments),i=0,r=n.length;i<r;++i)t=n[i],e.push(null);return e}.call(this,[]),e=this.spawnWorkers();for(var n=function(){var t;t=[];for(var n=0;0<=e?n<e:n>e;0<=e?++n:--n)t.push(n);return t}.apply(this,arguments),i=0,r=n.length;i<r;++i)t=n[i],this.renderNextFrame();return this.emit("start"),this.emit("progress",0)},e.prototype.abort=function(){for(var t;;){if(t=this.activeWorkers.shift(),!(null!=t))break;console.log("killing active worker"),t.terminate()}return this.running=!1,this.emit("abort")},e.prototype.spawnWorkers=function(){var t;return t=Math.min(this.options.workers,this.frames.length),function(){var e;e=[];for(var n=this.freeWorkers.length;this.freeWorkers.length<=t?n<t:n>t;this.freeWorkers.length<=t?++n:--n)e.push(n);return e}.apply(this,arguments).forEach(function(t){return function(e){var n;return console.log("spawning worker "+e),n=new Worker(t.options.workerScript),n.onmessage=function(t){return function(e){return t.activeWorkers.splice(t.activeWorkers.indexOf(n),1),t.freeWorkers.push(n),t.frameFinished(e.data)}}(t),t.freeWorkers.push(n)}}(this)),t},e.prototype.frameFinished=function(t){return console.log("frame "+t.index+" finished - "+this.activeWorkers.length+" active"),this.finishedFrames++,this.emit("progress",this.finishedFrames/this.frames.length),this.imageParts[t.index]=t,a(null,this.imageParts)?this.renderNextFrame():this.finishRendering()},e.prototype.finishRendering=function(){var t,e,n,i,r,o,a;r=0;for(var s=0,h=this.imageParts.length;s<h;++s)e=this.imageParts[s],r+=(e.data.length-1)*e.pageSize+e.cursor;r+=e.pageSize-e.cursor,console.log("rendering finished - filesize "+Math.round(r/1e3)+"kb"),t=new Uint8Array(r),o=0;for(var d=0,u=this.imageParts.length;d<u;++d){e=this.imageParts[d];for(var c=0,f=e.data.length;c<f;++c)a=e.data[c],n=c,t.set(a,o),o+=n===e.data.length-1?e.cursor:e.pageSize}return i=new Blob([t],{type:"image/gif"}),this.emit("finished",i,t)},e.prototype.renderNextFrame=function(){var t,e,n;if(0===this.freeWorkers.length)throw new Error("No free workers");return this.nextFrame>=this.frames.length?void 0:(t=this.frames[this.nextFrame++],n=this.freeWorkers.shift(),e=this.getTask(t),console.log("starting frame "+(e.index+1)+" of "+this.frames.length),this.activeWorkers.push(n),n.postMessage(e))},e.prototype.getContextData=function(t){return t.getImageData(0,0,this.options.width,this.options.height).data},e.prototype.getImageData=function(t){var e;return null!=this._canvas||(this._canvas=document.createElement("canvas"),this._canvas.width=this.options.width,this._canvas.height=this.options.height),e=this._canvas.getContext("2d"),e.setFill=this.options.background,e.fr(0,0,this.options.width,this.options.height),e.drawImage(t,0,0),this.getContextData(e)},e.prototype.getTask=function(t){var e,n;if(e=this.frames.indexOf(t),n={index:e,last:e===this.frames.length-1,delay:t.delay,transparent:t.transparent,width:this.options.width,height:this.options.height,quality:this.options.quality,repeat:this.options.repeat,canTransfer:"chrome"===h.name},null!=t.data)n.data=t.data;else if(null!=t.context)n.data=this.getContextData(t.context);else{if(null==t.image)throw new Error("Invalid frame");n.data=this.getImageData(t.image)}return n},e}(u),t.exports=f}),e.define("/browser.coffee",function(t,e,n,i){var r,o,a,s,h;s=navigator.userAgent.toLowerCase(),a=navigator.platform.toLowerCase(),h=s.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,"unknown",0],o="ie"===h[1]&&document.documentMode,r={name:"version"===h[1]?h[3]:h[1],version:o||parseFloat("opera"===h[1]&&h[4]?h[4]:h[2]),platform:{name:s.match(/ip(?:ad|od|hone)/)?"ios":(s.match(/(?:webos|android)/)||a.match(/mac|win|linux/)||["other"])[0]}},r[r.name]=!0,r[r.name+parseInt(r.version,10)]=!0,r.platform[r.platform.name]=!0,t.exports=r}),e.define("events",function(t,e,i,r){n.EventEmitter||(n.EventEmitter=function(){});var o=e.EventEmitter=n.EventEmitter,a="function"==typeof Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},s=10;o.prototype.setMaxListeners=function(t){this._events||(this._events={}),this._events.maxListeners=t},o.prototype.emit=function(t){if("error"===t&&(!this._events||!this._events.error||a(this._events.error)&&!this._events.error.length))throw arguments[1]instanceof Error?arguments[1]:new Error("Uncaught, unspecified 'error' event.");if(!this._events)return!1;var e=this._events[t];if(!e)return!1;if("function"!=typeof e){if(a(e)){for(var n=Array.prototype.slice.call(arguments,1),i=e.slice(),r=0,o=i.length;r<o;r++)i[r].apply(this,n);return!0}return!1}switch(arguments.length){case 1:e.call(this);break;case 2:e.call(this,arguments[1]);break;case 3:e.call(this,arguments[1],arguments[2]);break;default:var n=Array.prototype.slice.call(arguments,1);e.apply(this,n)}return!0},o.prototype.addListener=function(t,e){if("function"!=typeof e)throw new Error("addListener only takes instances of Function");if(this._events||(this._events={}),this.emit("newListener",t,e),this._events[t])if(a(this._events[t])){if(!this._events[t].warned){var n;n=void 0!==this._events.maxListeners?this._events.maxListeners:s,n&&n>0&&this._events[t].length>n&&(this._events[t].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[t].length),console.trace())}this._events[t].push(e)}else this._events[t]=[this._events[t],e];else this._events[t]=e;return this},o.prototype.on=o.prototype.addListener,o.prototype.once=function(t,e){var n=this;return n.on(t,function i(){n.removeListener(t,i),e.apply(this,arguments)}),this},o.prototype.removeListener=function(t,e){if("function"!=typeof e)throw new Error("removeListener only takes instances of Function");if(!this._events||!this._events[t])return this;var n=this._events[t];if(a(n)){var i=n.indexOf(e);if(i<0)return this;n.splice(i,1),0==n.length&&delete this._events[t]}else this._events[t]===e&&delete this._events[t];return this},o.prototype.removeAllListeners=function(t){return t&&this._events&&this._events[t]&&(this._events[t]=null),this},o.prototype.listeners=function(t){return this._events||(this._events={}),this._events[t]||(this._events[t]=[]),a(this._events[t])||(this._events[t]=[this._events[t]]),this._events[t]}}),t.GIF=e("/gif.coffee")}.call(this,this),function(){"use strict";function t(t){return t&&t.Object===Object?t:null}function e(t){return String("0000000"+t).slice(-7)}function n(){function t(){return Math.floor(65536*(1+Math.random())).toString(16).substring(1)}return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}function i(t){var e={};this.settings=t,this.on=function(t,n){e[t]=n},this.emit=function(t){var n=e[t];n&&n.apply(null,Array.prototype.slice.call(arguments,1))},this.filename=t.name||n(),this.extension="",this.mimeType=""}function r(t){i.call(this,t),this.extension=".tar",this.mimeType="application/x-tar",this.fileExtension="",this.tape=null,this.count=0}function o(t){r.call(this,t),this.type="image/png",this.fileExtension=".png"}function a(t){r.call(this,t),this.type="image/jpeg",this.fileExtension=".jpg",this.quality=t.quality/100||.8}function s(t){var e=document.createElement("canvas");"image/webp"!==e.toDataURL("image/webp").substr(5,10)&&console.log("WebP not supported - try another export format"),i.call(this,t),t.quality=t.quality/100||.8,this.extension=".webm",this.mimeType="video/webm",this.baseFilename=this.filename,this.frames=[],this.part=1}function h(t){i.call(this,t),t.quality=t.quality/100||.8,this.encoder=new FFMpegServer.Video(t),this.encoder.on("process",function(){this.emit("process")}.bind(this)),this.encoder.on("finished",function(t,e){var n=this.callback;n&&(this.callback=void 0,n(t,e))}.bind(this)),this.encoder.on("progress",function(t){this.settings.onProgress&&this.settings.onProgress(t)}.bind(this)),this.encoder.on("error",function(t){alert(JSON.stringify(t,null,2))}.bind(this))}function d(t){i.call(this,t),this.framerate=this.settings.framerate,this.type="video/webm",this.extension=".webm",this.stream=null,this.mediaRecorder=null,this.chunks=[]}function u(t){i.call(this,t),t.quality=31-(30*t.quality/100||10),t.workers=t.workers||4,this.extension=".gif",this.mimeType="image/gif",this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),this.sizeSet=!1,this.encoder=new GIF({workers:t.workers,quality:t.quality,workerScript:t.workersPath+"gif.worker.js"}),this.encoder.on("progress",function(t){this.settings.onProgress&&this.settings.onProgress(t)}.bind(this)),this.encoder.on("finished",function(t){var e=this.callback;e&&(this.callback=void 0,e(t))}.bind(this))}function c(t){function e(){function t(){return this._hooked||(this._hooked=!0,this._hookedTime=this.currentTime||0,this.pause(),et.push(this)),this._hookedTime+S.startTime}b("Capturer start"),A=window.Date.now(),L=A+S.startTime,D=window.performance.now(),E=D+S.startTime,window.Date.prototype.getTime=function(){return L},window.Date.now=function(){return L},window.setTimeout=function(t,e){var n={callback:t,time:e,triggerTime:L+e};return B.push(n),b("Timeout set to "+n.time),n},window.clearTimeout=function(t){for(var e=0;e<B.length;e++)B[e]!=t||(B.splice(e,1),b("Timeout cleared"))},window.setInterval=function(t,e){var n={callback:t,time:e,triggerTime:L+e};return j.push(n),b("Interval set to "+n.time),n},window.clearInterval=function(t){return b("clear Interval"),null},window.requestAnimationFrame=function(t){U.push(t)},window.performance.now=function(){return E};try{Object.defineProperty(HTMLVideoElement.prototype,"currentTime",{get:t}),Object.defineProperty(HTMLAudioElement.prototype,"currentTime",{get:t})}catch(t){b(t)}}function n(){e(),I.start(),M=!0}function i(){M=!1,I.stop(),f()}function r(t,e){Z(t,0,e)}function c(){r(v)}function f(){b("Capturer stop"),window.setTimeout=Z,window.setInterval=J,window.clearTimeout=Y,window.requestAnimationFrame=$,window.Date.prototype.getTime=tt,window.Date.now=Q,window.performance.now=X}function l(){var t=R/S.framerate;(S.frameLimit&&R>=S.frameLimit||S.timeLimit&&t>=S.timeLimit)&&(i(),y());var e=new Date(null);e.setSeconds(t),S.motionBlurFrames>2?P.textContent="CCapture "+S.format+" | "+R+" frames ("+O+" inter) | "+e.toISOString().substr(11,8):P.textContent="CCapture "+S.format+" | "+R+" frames | "+e.toISOString().substr(11,8)}function p(t){N.width===t.width&&N.height===t.height||(N.width=t.width,N.height=t.height,q=new Uint16Array(N.height*N.width*4),V.fillStyle="#0",V.fr(0,0,N.width,N.height))}function m(t){V.drawImage(t,0,0),z=V.getImageData(0,0,N.width,N.height);for(var e=0;e<q.length;e+=4)q[e]+=z.data[e],q[e+1]+=z.data[e+1],q[e+2]+=z.data[e+2];O++}function g(){for(var t=z.data,e=0;e<q.length;e+=4)t[e]=2*q[e]/S.motionBlurFrames,t[e+1]=2*q[e+1]/S.motionBlurFrames,t[e+2]=2*q[e+2]/S.motionBlurFrames;V.putImageData(z,0,0),I.add(N),R++,O=0,b("Full MB Frame! "+R+" "+L);for(var e=0;e<q.length;e+=4)q[e]=0,q[e+1]=0,q[e+2]=0;gc()}function w(t){M&&(S.motionBlurFrames>2?(p(t),m(t),O>=.5*S.motionBlurFrames?g():c()):(I.add(t),R++,b("Full Frame! "+R)))}function v(){var t=1e3/S.framerate,e=(R+O/S.motionBlurFrames)*t;L=A+e,E=D+e,et.forEach(function(t){t._hookedTime=e/1e3}),l(),b("Frame: "+R+" "+O);for(var n=0;n<B.length;n++)L>=B[n].triggerTime&&(r(B[n].callback),B.splice(n,1));for(var n=0;n<j.length;n++)L>=j[n].triggerTime&&(r(j[n].callback),j[n].triggerTime+=j[n].time);U.forEach(function(t){r(t,L-k)}),U=[]}function y(t){t||(t=function(t){return download(t,I.filename+I.extension,I.mimeType),!1}),I.save(t)}function b(t){_&&console.log(t)}function x(t,e){W[t]=e}function T(t){var e=W[t];e&&e.apply(null,Array.prototype.slice.call(arguments,1))}function C(t){T("progress",t)}var _,F,L,A,E,D,c,I,S=t||{},B=(new Date,[]),j=[],R=0,O=0,U=[],M=!1,W={};S.framerate=S.framerate||60,S.motionBlurFrames=2*(S.motionBlurFrames||1),_=S.verbose||!1,F=S.display||!1,S.step=1e3/S.framerate,S.timeLimit=S.timeLimit||0,S.frameLimit=S.frameLimit||0,S.startTime=S.startTime||0;var P=document.createElement("div");P.style.position="absolute",P.style.left=P.style.top=0,P.style.backgroundColor="black",P.style.fontFamily="monospace",P.style.fontSize="11px",P.style.padding="5px",P.style.color="red",P.style.zIndex=1e5,S.display&&document.body.appendChild(P);var q,z,N=document.createElement("canvas"),V=N.getContext("2d");b("Step is set to "+S.step+"ms");var H={gif:u,webm:s,ffmpegserver:h,png:o,jpg:a,"webm-mediarecorder":d},G=H[S.format];if(!G)throw"Error: Incorrect or missing format: Valid formats are "+Object.keys(H).join(", ");if(I=new G(S),I.step=c,I.on("process",v),I.on("progress",C),"performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var K=Date.now();performance.timing&&performance.timing.navigationStart&&(K=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-K}}var Z=window.setTimeout,J=window.setInterval,Y=window.clearTimeout,$=window.requestAnimationFrame,Q=window.Date.now,X=window.performance.now,tt=window.Date.prototype.getTime,et=[];return{start:n,capture:w,stop:i,save:y,on:x}}var f={function:!0,object:!0},l=(parseFloat,parseInt,f[typeof exports]&&exports&&!exports.nodeType?exports:void 0),p=f[typeof module]&&module&&!module.nodeType?module:void 0,m=p&&p.exports===l?l:void 0,g=t(l&&p&&"object"==typeof global&&global),w=t(f[typeof self]&&self),v=t(f[typeof window]&&window),y=t(f[typeof this]&&this),b=g||v!==(y&&y.window)&&v||w||y||Function("return this")();"gc"in window||(window.gc=function(){}),HTMLCanvasElement.prototype.toBlob||Object.defineProperty(HTMLCanvasElement.prototype,"toBlob",{value:function(t,e,n){for(var i=atob(this.toDataURL(e,n).split(",")[1]),r=i.length,o=new Uint8Array(r),a=0;a<r;a++)o[a]=i.charCodeAt(a);t(new Blob([o],{type:e||"image/png"}))}}),function(){if("performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var t=Date.now();performance.timing&&performance.timing.navigationStart&&(t=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-t}}}();var k=window.Date.now();i.prototype.start=function(){},i.prototype.stop=function(){},i.prototype.add=function(){},i.prototype.save=function(){},i.prototype.dispose=function(){},i.prototype.safeToProceed=function(){return!0},i.prototype.step=function(){console.log("Step not set!")},r.prototype=Object.create(i.prototype),r.prototype.start=function(){this.dispose()},r.prototype.add=function(t){var n=new FileReader;n.onload=function(){this.tape.append(e(this.count)+this.fileExtension,new Uint8Array(n.result)),this.count++,this.step()}.bind(this),n.readAsArrayBuffer(t)},r.prototype.save=function(t){t(this.tape.save())},r.prototype.dispose=function(){this.tape=new Tar,this.count=0},o.prototype=Object.create(r.prototype),o.prototype.add=function(t){t.toBlob(function(t){r.prototype.add.call(this,t)}.bind(this),this.type)},a.prototype=Object.create(r.prototype),a.prototype.add=function(t){t.toBlob(function(t){r.prototype.add.call(this,t)}.bind(this),this.type,this.quality)},s.prototype=Object.create(i.prototype),s.prototype.start=function(t){this.dispose()},s.prototype.add=function(t){this.frames.push(t.toDataURL("image/webp",this.quality)),this.settings.autoSaveTime>0&&this.frames.length/this.settings.framerate>=this.settings.autoSaveTime?this.save(function(t){this.filename=this.baseFilename+"-part-"+e(this.part),download(t,this.filename+this.extension,this.mimeType),this.dispose(),this.part++,this.filename=this.baseFilename+"-part-"+e(this.part),this.step()}.bind(this)):this.step()},s.prototype.save=function(t){if(this.frames.length){var e=Whammy.fromImageArray(this.frames,this.settings.framerate),n=new Blob([e],{type:"octet/stream"});t(n)}},s.prototype.dispose=function(t){this.frames=[]},h.prototype=Object.create(i.prototype),h.prototype.start=function(){this.encoder.start(this.settings)},h.prototype.add=function(t){this.encoder.add(t)},h.prototype.save=function(t){this.callback=t,this.encoder.end()},h.prototype.safeToProceed=function(){return this.encoder.safeToProceed()},d.prototype=Object.create(i.prototype),d.prototype.add=function(t){this.stream||(this.stream=t.captureStream(this.framerate),this.mediaRecorder=new MediaRecorder(this.stream),this.mediaRecorder.start(),this.mediaRecorder.ondataavailable=function(t){this.chunks.push(t.data)}.bind(this)),this.step()},d.prototype.save=function(t){this.mediaRecorder.onstop=function(e){var n=new Blob(this.chunks,{type:"video/webm"});this.chunks=[],t(n)}.bind(this),this.mediaRecorder.stop()},u.prototype=Object.create(i.prototype),u.prototype.add=function(t){this.sizeSet||(this.encoder.setOption("width",t.width),this.encoder.setOption("height",t.height),this.sizeSet=!0),this.canvas.width=t.width,this.canvas.height=t.height,this.ctx.drawImage(t,0,0),this.encoder.addFrame(this.ctx,{copy:!0,delay:this.settings.step}),this.step()},u.prototype.save=function(t){this.callback=t,this.encoder.render()},(v||w||{}).CCapture=c,"function"==typeof define&&"object"==typeof define.amd&&define.amd?define(function(){return c}):l&&p?(m&&((p.exports=c).CCapture=c),l.CCapture=c):b.CCapture=c}();
function Particle() {
this.inUse = false;
this.init = function(){
this.x = -500;
this.y = -500;
this.dead = true;
this.xvel = 0;
this.yvel = 1;
this.life = 1;
}
Particle.prototype.spawn = function(opt) {
this.x = opt.x;
this.y = opt.y;
this.xvel = opt.xvel;
this.yvel = opt.yvel;
this.inUse = true;
this.life = opt.life || 1;
this.remaining = opt.life || 1;
this.radius = opt.radius || 1;
this.color = opt.color || 21;
this.dead = false;
}
Particle.prototype.use = function(dt){
if(this.dead) {
return true;
}
else {
this.remaining -= dt;
this.x += dt * this.xvel;
this.y += dt * this.yvel;
this.draw();
//console.log('bullet used/updated');
if(this.remaining <= 0) {
this.dead = true;
return true;
}
if(this.y < 0){
this.dead = true;
}
}
return false;
}
Particle.prototype.clear = function(){
this.x = -500;
this.y = -500;
this.dead = true;
this.xvel = 0;
this.yvel = 0;
this.life = 1;
this.inUse = false;
}
Particle.prototype.draw = function(){
circle(this.x, this.y, 0|Math.random()*4, 21);
}
}
/**
* Created by ryan on 9/4/16.
*/
/**
* The Object Pool. Unused objects are grabbed from the back of
* the array and pushed to the front of the array. When using an
* object, if the object is ready to be removed, it splices the
* array and pushes the object to the back to be reused.
*/
function Pool(poolSize, objClass) {
var size = poolSize; // Max objects allowed in the pool
var pool = [];
/*
* Populates the pool array with objects
*/
this.init = function() {
for (var i = 0; i < size; i++) {
// Initialize the objects
var obj = new objClass();
obj.init();
pool[i] = obj;
}
};
/*
* Grabs the last item in the list and initializes it and
* pushes it to the front of the array.
*/
this.get = function(opt) {
// If the last item in the array is in use, the pool is full
if(!pool[size - 1].inUse) {
pool[size - 1].spawn(opt);
pool.unshift(pool.pop());
return pool[size -1];
}
};
this.getPool = function() {
return pool;
}
/*
* Uses any alive objects in the pool. If the call returns true,
* the object is ready to be cleared and reused.
*/
this.use = function() {
for (var i = 0; i < size; i++) {
//.log('pool use iteration');
// Only use objects that are currently in use
if (pool[i].inUse) {
if (pool[i].use(dt)) {
pool[i].clear();
pool.push((pool.splice(i,1))[0]);
}
} else {
// The first occurrence of an unused item we can
// break looping over the objects.
break;
}
}
};
};
/* -*- mode: javascript; tab-width: 4; indent-tabs-mode: nil; -*-
*
* Copyright (c) 2011-2013 Marcus Geelnard
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*
*/
"use strict";
var CPlayer = function() {
//--------------------------------------------------------------------------
// Private methods
//--------------------------------------------------------------------------
// Oscillators
var osc_sin = function (value) {
return Math.sin(value * 6.283184);
};
var osc_saw = function (value) {
return 2 * (value % 1) - 1;
};
var osc_square = function (value) {
return (value % 1) < 0.5 ? 1 : -1;
};
var osc_tri = function (value) {
var v2 = (value % 1) * 4;
if(v2 < 2) return v2 - 1;
return 3 - v2;
};
var getnotefreq = function (n) {
// 174.61.. / 44100 = 0.003959503758 (F3)
return 0.003959503758 * Math.pow(2, (n - 128) / 12);
};
var createNote = function (instr, n, rowLen) {
var osc1 = mOscillators[instr.i[0]],
o1vol = instr.i[1],
o1xenv = instr.i[3],
osc2 = mOscillators[instr.i[4]],
o2vol = instr.i[5],
o2xenv = instr.i[8],
noiseVol = instr.i[9],
attack = instr.i[10] * instr.i[10] * 4,
sustain = instr.i[11] * instr.i[11] * 4,
release = instr.i[12] * instr.i[12] * 4,
releaseInv = 1 / release,
arp = instr.i[13],
arpInterval = rowLen * Math.pow(2, 2 - instr.i[14]);
var noteBuf = new Int32Array(attack + sustain + release);
// Re-trig oscillators
var c1 = 0, c2 = 0;
// Local variables.
var j, j2, e, t, rsample, o1t, o2t;
// Generate one note (attack + sustain + release)
for (j = 0, j2 = 0; j < attack + sustain + release; j++, j2++) {
if (j2 >= 0) {
// Switch arpeggio note.
arp = (arp >> 8) | ((arp & 255) << 4);
j2 -= arpInterval;
// Calculate note frequencies for the oscillators
o1t = getnotefreq(n + (arp & 15) + instr.i[2] - 128);
o2t = getnotefreq(n + (arp & 15) + instr.i[6] - 128) * (1 + 0.0008 * instr.i[7]);
}
// Envelope
e = 1;
if (j < attack) {
e = j / attack;
} else if (j >= attack + sustain) {
e -= (j - attack - sustain) * releaseInv;
}
// Oscillator 1
t = o1t;
if (o1xenv) {
t *= e * e;
}
c1 += t;
rsample = osc1(c1) * o1vol;
// Oscillator 2
t = o2t;
if (o2xenv) {
t *= e * e;
}
c2 += t;
rsample += osc2(c2) * o2vol;
// Noise oscillator
if (noiseVol) {
rsample += (2 * Math.random() - 1) * noiseVol;
}
// Add to (mono) channel buffer
noteBuf[j] = (80 * rsample * e) | 0;
}
return noteBuf;
};
//--------------------------------------------------------------------------
// Private members
//--------------------------------------------------------------------------
// Array of oscillator functions
var mOscillators = [
osc_sin,
osc_square,
osc_saw,
osc_tri
];
// Private variables set up by init()
var mSong, mLastRow, mCurrentCol, mNumWords, mMixBuf;
//--------------------------------------------------------------------------
// Initialization
//--------------------------------------------------------------------------
this.init = function (song) {
// Define the song
mSong = song;
// Init iteration state variables
mLastRow = song.endPattern - 2;
mCurrentCol = 0;
// Prepare song info
mNumWords = song.rowLen * song.patternLen * (mLastRow + 1) * 2;
// Create work buffer (initially cleared)
mMixBuf = new Int32Array(mNumWords);
};
//--------------------------------------------------------------------------
// Public methods
//--------------------------------------------------------------------------
// Generate audio data for a single track
this.generate = function () {
// Local variables
var i, j, b, p, row, col, n, cp,
k, t, lfor, e, x, rsample, rowStartSample, f, da;
// Put performance critical items in local variables
var chnBuf = new Int32Array(mNumWords),
instr = mSong.songData[mCurrentCol],
rowLen = mSong.rowLen,
patternLen = mSong.patternLen;
// Clear effect state
var low = 0, band = 0, high;
var lsample, filterActive = false;
// Clear note cache.
var noteCache = [];
// Patterns
for (p = 0; p <= mLastRow; ++p) {
cp = instr.p[p];
// Pattern rows
for (row = 0; row < patternLen; ++row) {
// Execute effect command.
var cmdNo = cp ? instr.c[cp - 1].f[row] : 0;
if (cmdNo) {
instr.i[cmdNo - 1] = instr.c[cp - 1].f[row + patternLen] || 0;
// Clear the note cache since the instrument has changed.
if (cmdNo < 15) {
noteCache = [];
}
}
// Put performance critical instrument properties in local variables
var oscLFO = mOscillators[instr.i[15]],
lfoAmt = instr.i[16] / 512,
lfoFreq = Math.pow(2, instr.i[17] - 9) / rowLen,
fxLFO = instr.i[18],
fxFilter = instr.i[19],
fxFreq = instr.i[20] * 43.23529 * 3.141592 / 44100,
q = 1 - instr.i[21] / 255,
dist = instr.i[22] * 1e-5,
drive = instr.i[23] / 32,
panAmt = instr.i[24] / 512,
panFreq = 6.283184 * Math.pow(2, instr.i[25] - 9) / rowLen,
dlyAmt = instr.i[26] / 255,
dly = instr.i[27] * rowLen;
// Calculate start sample number for this row in the pattern
rowStartSample = (p * patternLen + row) * rowLen;
// Generate notes for this pattern row
for (col = 0; col < 4; ++col) {
n = cp ? instr.c[cp - 1].n[row + col * patternLen] : 0;
if (n) {
if (!noteCache[n]) {
noteCache[n] = createNote(instr, n, rowLen);
}
// Copy note from the note cache
var noteBuf = noteCache[n];
for (j = 0, i = rowStartSample * 2; j < noteBuf.length; j++, i += 2) {
chnBuf[i] += noteBuf[j];
}
}
}
// Perform effects for this pattern row
for (j = 0; j < rowLen; j++) {
// Dry mono-sample
k = (rowStartSample + j) * 2;
rsample = chnBuf[k];
// We only do effects if we have some sound input
if (rsample || filterActive) {
// State variable filter
f = fxFreq;
if (fxLFO) {
f *= oscLFO(lfoFreq * k) * lfoAmt + 0.5;
}
f = 1.5 * Math.sin(f);
low += f * band;
high = q * (rsample - band) - low;
band += f * high;
rsample = fxFilter == 3 ? band : fxFilter == 1 ? high : low;
// Distortion
if (dist) {
rsample *= dist;
rsample = rsample < 1 ? rsample > -1 ? osc_sin(rsample*.25) : -1 : 1;
rsample /= dist;
}
// Drive
rsample *= drive;
// Is the filter active (i.e. still audiable)?
filterActive = rsample * rsample > 1e-5;
// Panning
t = Math.sin(panFreq * k) * panAmt + 0.5;
lsample = rsample * (1 - t);
rsample *= t;
} else {
lsample = 0;
}
// Delay is always done, since it does not need sound input
if (k >= dly) {
// Left channel = left + right[-p] * t
lsample += chnBuf[k-dly+1] * dlyAmt;
// Right channel = right + left[-p] * t
rsample += chnBuf[k-dly] * dlyAmt;
}
// Store in stereo channel buffer (needed for the delay effect)
chnBuf[k] = lsample | 0;
chnBuf[k+1] = rsample | 0;
// ...and add to stereo mix buffer
mMixBuf[k] += lsample | 0;
mMixBuf[k+1] += rsample | 0;
}
}
}
// Next iteration. Return progress (1.0 == done!).
mCurrentCol++;
return mCurrentCol / 8;
};
// Create a WAVE formatted Uint8Array from the generated audio data
this.createWave = function() {
// Create WAVE header
var l1 = mNumWords * 2 - 8;
var l2 = l1 - 36;
var headerLen = 44;
var wave = new Uint8Array(headerLen + mNumWords * 2);
wave.set(
[82,73,70,70,
l1 & 255,(l1 >> 8) & 255,(l1 >> 16) & 255,(l1 >> 24) & 255,
87,65,86,69,102,109,116,32,16,0,0,0,1,0,2,0,
68,172,0,0,16,177,2,0,4,0,16,0,100,97,116,97,
l2 & 255,(l2 >> 8) & 255,(l2 >> 16) & 255,(l2 >> 24) & 255]
);
// Append actual wave data
for (var i = 0, idx = headerLen; i < mNumWords; ++i) {
// Note: We clamp here
var y = mMixBuf[i];
y = y < -32767 ? -32767 : (y > 32767 ? 32767 : y);
wave[idx++] = y & 255;
wave[idx++] = (y >> 8) & 255;
}
// Return the WAVE formatted typed array
return wave;
};
// Get n samples of wave data at time t [s]. Wave data in range [-2,2].
this.getData = function(t, n) {
var i = 2 * Math.floor(t * 44100);
var d = new Array(n);
for (var j = 0; j < 2*n; j += 1) {
var k = i + j;
d[j] = t > 0 && k < mMixBuf.length ? mMixBuf[k] / 32768 : 0;
}
return d;
};
};
Key = {
_pressed: {},
_released: {},
LEFT: 37,
UP: 38,
RIGHT: 39,
DOWN: 40,
SPACE: 32,
a: 65,
w: 87,
s: 83,
d: 68,
z: 90,
x: 88,
f: 70,
p: 80,
r: 82,
isDown(keyCode) {
return this._pressed[keyCode];
},
justReleased(keyCode) {
return this._released[keyCode];
},
onKeydown(event) {
this._pressed[event.keyCode] = true;
},
onKeyup(event) {
this._released[event.keyCode] = true;
delete this._pressed[event.keyCode];
},
update() {
this._released = {};
}
};
Txt = {
textLine(opt) {
var textLength = opt.text.length,
size = 5;
for (var i = 0; i < textLength; i++) {
var letter = assets.letters[( opt.text.charAt(i) )] || assets.letters['unknown'];
for (var y = 0; y < size; y++) {
//var g = (Math.random() > opt.glitchChance) * opt.glitchFactor;
for (var x = 0; x < size; x++) {
if (letter[y][x] === 1) {
//var gx = (Math.random() < gl.xch || 0) * (Math.random()-.5) * gl.xamt || 0;
//var gy = (Math.random() < gl.ych || 0) * (Math.random()-.5) * gl.yamt || 0;
if(opt.scale === 1){
pset(
opt.x + ( x * opt.scale ) + ( ( size * opt.scale ) + opt.hspacing ) * i,
opt.y + (y * opt.scale),
opt.color
);
}
else {
fr(
opt.x + ( x * opt.scale ) + ( ( size * opt.scale ) + opt.hspacing ) * i,
opt.y + (y * opt.scale),
opt.scale,
opt.scale,
opt.color);
}
//console.log(opt.color);
}
}
}
}
},
text(opt) {
var size = 5,
letterSize = size * opt.scale,
lines = opt.text.split('\n'),
linesCopy = lines.slice(0),
lineCount = lines.length,
longestLine = linesCopy.sort(function (a, b) {
return b.length - a.length;
})[0],
textWidth = ( longestLine.length * letterSize ) + ( ( longestLine.length - 1 ) * opt.hspacing ),
textHeight = ( lineCount * letterSize ) + ( ( lineCount - 1 ) * opt.vspacing );
if(!opt.halign)opt.halign = 'left';
if(!opt.valign)opt.valign = 'bottom';
var sx = opt.x,
sy = opt.y,
ex = opt.x + textWidth,
ey = opt.y + textHeight;
if (opt.halign == 'center') {
sx = opt.x - textWidth / 2;
ex = opt.x + textWidth / 2;
} else if (opt.halign == 'right') {
sx = opt.x - textWidth;
ex = opt.x;
}
if (opt.valign == 'center') {
sy = opt.y - textHeight / 2;
ey = opt.y + textHeight / 2;
} else if (opt.valign == 'bottom') {
sy = opt.y - textHeight;
ey = opt.y;
}
var cx = sx + textWidth / 2,
cy = sy + textHeight / 2;
if (opt.render) {
for (var i = 0; i < lineCount; i++) {
var line = lines[i],
lineWidth = ( line.length * letterSize ) + ( ( line.length - 1 ) * opt.hspacing ),
x = opt.x,
y = opt.y + ( letterSize + opt.vspacing ) * i;
if (opt.halign == 'center') {
x = opt.x - lineWidth / 2;
} else if (opt.halign == 'right') {
x = opt.x - lineWidth;
}
if (opt.valign == 'center') {
y = y - textHeight / 2;
} else if (opt.valign == 'bottom') {
y = y - textHeight;
}
if (opt.snap) {
x = Math.floor(x);
y = Math.floor(y);
}
this.textLine({
ctx: opt.ctx,
x: x,
y: y,
text: line,
hspacing: opt.hspacing || 0,
scale: opt.scale || 1,
color: opt.color
});
}
}
return {
sx: sx,
sy: sy,
cx: cx,
cy: cy,
ex: ex,
ey: ey,
width: textWidth,
height: textHeight
}
}
};
states.gameover = {
step: function(dt) {
if(Key.isDown(Key.r)){
state = 'menu';
}
},
render: function(dt) {
fr(0,0,256,256, 0);
fr(0,0,64,64,2);
Txt.text({
x: 128,
y: 40 + Math.sin(t*2.5)*15,
text: 'GAME\nOVER',
hspacing: 8 + Math.cos(t*2.9)*4,
vspacing: 15 + Math.sin(t*3.5)*5,
halign: 'center',
valign: 'top',
scale: 10,
snap: 1,
render: 1,
color: 21,
});
},
};
states.menu = {
step: function(dt) {
//game update
if(Key.isDown(Key.p)){
state = 'game';
}
},
render: function(dt) {
fr(0,0,256,256, 0);
fr(0,0,64,64,2);
Txt.text({
x: 128,
y: 40 + Math.sin(t*2.5)*15,
text: 'MENU',
hspacing: 8 + Math.cos(t*2.9)*4,
vspacing: 15 + Math.sin(t*3.5)*5,
halign: 'center',
valign: 'top',
scale: 10,
snap: 1,
render: 1,
color: 21,
});
//draw stuff here.
},
};
states.game = {
step(dt) {
player.update(dt);
//----hacky sound test
if(Key.justReleased(Key.z)){
songTrigger = true
}
if(songTrigger){
// playSound(sounds.song, 1, 1, 0);
songTrigger = false;
incrementState();
}
//---end hacky sound test
bulletPool.use();
Key.update();
},
render(dt) {
renderTarget = 0x00000;
switch(demostate){
case 1:
clear(0);
let r = 40;
for(x=0; x < 256; x+=r){
for( y=0; y < 256; y+=r){
let A = x-128+Math.sin(t)*r;
let B = y-128+Math.cos(t)*r;
let s = Math.sqrt(A*A+B*B);
circle(x,y, s-8, 21);
}
}
renderInstructions();
break;
case 2:
clear(0);
for(let a = 0; a < 2 * Math.PI; a+= 0.7){
for(let r = 20; r < 200; r += 9){
let v = a + .4 * Math.sin(a*8-r/20+t);
fillCircle((128+r*Math.cos(v)), 128+r*Math.sin(v), (10-r/12)|0, 10+(r/9%32)|0 );
}
}
renderInstructions();
break;
case 0:
//clear(0);
for(let u = 0; u < 1; u+=.001){
let x = Math.floor(128+128*Math.cos(3*u+t));
let y = Math.floor(128+128*Math.sin(5*u+t));
y = x^y;
pset(x,y,u*32);
}
renderInstructions();
break;
case 3:
clear(1);
renderColorNumbers();
renderDrawingAPI();
renderInstructions();
break;
case 4:
clear(1);
let s = 128;
let i = t/3;
for(let y = -s; y < s; y += 3 ){
for(let x = -s; x < s; x += 2 ){
pset(s+x+64*Math.cos( (y/s+i)*5 )+y, s+y+64*Math.sin( (x/s+i)*5 )+x, x/8%32)
}
}
renderInstructions();
break;
case 5:
clear(0);
for(let r = 0; r < 190; r+= 6){
for(let a = 0; a < 2*Math.PI; a += 1/r*8){
let x = r*Math.cos(a+t);
let y = r*Math.sin(a+t);
circle(x+128, y+128, 3+3*Math.cos(t*r/8+a*3), r/8%32)
}
}
renderInstructions();
break;
default:
clear(0);
renderInstructions();
break;
}
},
};
function incrementState(){
demostate += 1;
if(demostate > 6){
demostate = 0;
}
}
function renderColorNumbers(){
for(var i = 0; i < 32; i++){
Txt.text({
x: i < 16 ? ( 3+16*i ) : ( 3 + 16* (i-16) ) ,
y: i < 16 ? 8 : 8 + 16,
text: i.toString(),
scale: 1,
snap: 1,
hspacing: 1,
vspacing: 2,
halign: 'left',
valign: 'bottom',
render: 1,
color: i,
})
}
}
function renderDrawingAPI(){
pset(16*2, 16*5, 21);
line(16*4, 16*5, 16*5, 16*7, 21);
rect(16*6, 16*5, 16, 32, 21);
circle(16*8, 16*6, 16, 21);
}
function renderInstructions(){
fr(5,243,256,6,0);
Txt.text({
x: 5,
y: 249,
text: "THINGY "+ demostate + ": PRESS Z TO SEE NEXT THINGY",
scale: 1,
snap: 1,
hspacing: 1,
vspacing: 2,
halign: 'left',
valign: 'bottom',
render: 1,
color: 21,
})
}
player = {
// x: 0,
// y: 0,
// radius: 12,
// xvel: 0,
// yvel: 0,
// speed: 6,
// drag: .97,
bullet: {
x: 0, y:0, xvel: 0, yvel: 0
},
init (){
this.x = 64;
this.y = 230;
this.radius = 12;
this.xvel = 0;
this.yvel = 0;
this.xspeed = 400;
this.yspeed = 400;
this.drag = .6;
},
update (dt) {
this.bullet.x = player.x;
this.bullet.y = player.y;
this.xvel *= player.drag;
this.yvel *= player.drag;
let xIntegrate = dt * player.xvel;
let yIntegrate = dt * player.yvel;
player.x += xIntegrate;
player.y += yIntegrate;
//player movement
if (Key.isDown(Key.d) || Key.isDown(Key.RIGHT)) {
player.xvel = player.xspeed;
}
if (Key.isDown(Key.a) || Key.isDown(Key.LEFT)){
player.xvel = - player.xspeed;
}
if(Key.isDown(Key.w) || Key.isDown(Key.UP)){
player.yvel = -player.yspeed;
}
if(Key.isDown(Key.s) || Key.isDown(Key.DOWN)) {
player.yvel = player.yspeed;
}
if(Key.isDown(Key.SPACE || Key.isDown(Key.z))){
//player.bullet.xvel = E.player.xvel;
player.bullet.yvel = -350;
bulletPool.get(player.bullet);
}
//world wrap for player
if(player.x > 256){
player.x = 0;
}
if(player.x < 0){
player.x = 256;
}
if(player.y > 256){
player.y = 0;
}
if(player.y < 0){
state = 'gameover';
player.y = 256;
}
//end world wrap for player
},
draw (dt) {
// let degrees = (360/256) * E.player.x * 0.0174533;
// let radius = (E.player.y / 2);
// let playerDrawPoint = E.util.toPolarScreen({x:E.player.x, y:E.player.y});
//
// let distFromCenter = E.util.dist(playerDrawPoint.x+128, playerDrawPoint.y+128, 128,128);
//
// let playerSizeFactor = E.util.norm(distFromCenter, 0, 128);
//E.renderTarget = E.screen;
//E.gfx.fillCircle(playerDrawPoint.x+128, playerDrawPoint.y+128, E.player.radius * playerSizeFactor, 21);
fillCircle(this.x, this.y, this.radius, 21);
},
}
init = function(){
last = 0;
dt = 0;
now = 0;
t = 0;
moveX = 0;
speedFactor = .6;
songTrigger = false;
state = 'game';
demostate = 0,
bulletPool = new Pool(100, Particle);
sounds = {};
//stats = new Stats();
//document.body.appendChild( stats.dom );
starColors=[15,16,17,18,19,20,21];
bulletPool.init();
player.init();
soundInit();
eventInit();
//init vid capture
//capturer = new CCapture( {format: 'gif', workersPath: ''});
//capturer.start();
//start the game loop
loop();
},
stopCapture = (e) => {
//capturer.stop();
//capturer.save();
}
loop = () => {
// stats.begin();
//game timer
let now = new Date().getTime();
dt = Math.min(1, (now - last) / 1000);
t += dt;
//draw current state to buffer
states[state].render();
//update
states[state].step(dt);
last = now;
//draw buffer to screen
render();
//GIF capture
//capturer.capture(C);
//stats.end();
requestAnimationFrame(loop);
}
soundInit = () => {
sounds = {};
// if(audioCtx){audioCtx.close()};
// window.AudioContext = window.AudioContext || window.webkitAudioContext;
// if(!audioCtx) audioCtx = new AudioContext;
//
// var musicplayer = new CPlayer();
// musicplayer.init(assets.songdemo);
// var done = false;
// songWave = setInterval(function () {
// if (done) {
// return musicplayer.createWave();
// }
// done = musicplayer.generate() >= 1;
// });
//
// let soundGen = new sonantx.MusicGenerator(assets.song);
// soundGen.createAudioBuffer(function(buffer) {
// sounds.song = buffer;
// });
}
eventInit = () => {
//initialize keypress event listeners
window.addEventListener('keyup', function (event) {
Key.onKeyup(event);
}, false);
window.addEventListener('mousedown', function (event){
stopCapture(event);
}, false);
window.addEventListener('keydown', function (event) {
Key.onKeydown(event);
}, false);
window.addEventListener('blur', function (event) {
paused = true;
}, false);
window.addEventListener('focus', function (event) {
paused = false;
}, false);
}
window.onload = init();
}
()
)
Also see: Tab Triggers