Permalink
Browse files

New performers (Fixed, Glow), filter (Shift), functionality (automati…

…on) and various bugfixes and enhancements, as used in Conflagration performance
  • Loading branch information...
1 parent 5f9aafc commit 686cf54a75939dd742280e7887500c00c124595f @barryvan committed May 3, 2012
View
@@ -5,6 +5,7 @@ A library for creating performances of music, using HTML5 canvas and audio.
## Examples
[Index of examples](http://barryvan.github.com/trackPerformer/)
+- [Conflagration](https://developer.mozilla.org/en-US/demos/detail/trackperformer-conflagration)
- [We Three Kings](http://barryvan.github.com/trackPerformer/kings.html)
- [Carol of the Bells](http://barryvan.github.com/trackPerformer/bells.html)
- [Joy to the World](http://barryvan.github.com/trackPerformer/joy.html)
@@ -5,6 +5,7 @@ barryvan.tp.filter.Pick = new Class({
Extends: barryvan.tp.filter.Base,
Binds: [
+ 'updateOpts',
'frame',
'resize'
],
@@ -31,6 +32,10 @@ barryvan.tp.filter.Pick = new Class({
this.resize(this._canvas.width, this._canvas.height);
},
+ updateOpts: function(options) {
+ this.options = Object.merge(this.options, options);
+ },
+
frame: function() {
var cdata = this._context.getImageData(0, 0, this._width, this._height),
data = cdata.data,
@@ -0,0 +1,55 @@
+/* Swap horizontal lines of the canvas */
+barryvan.tp.filter.Shift = new Class({
+ Implements: [Options],
+
+ Extends: barryvan.tp.filter.Base,
+
+ Binds: [
+ 'updateOpts',
+ 'frame',
+ 'resize'
+ ],
+
+ options: {
+ x: 0,
+ y: 1,
+ randomiseSign: 0
+ },
+
+ _width: 0,
+ _height: 0,
+ _frame: 0,
+ _imageData: null,
+
+ _iteration: 0,
+
+ initialize: function(context, canvas, options) {
+ this.parent(context, canvas, options);
+
+ this.resize(this._canvas.width, this._canvas.height);
+ },
+
+ updateOpts: function(options) {
+ this.options = Object.merge(this.options, options);
+ },
+
+ frame: function() {
+ var x = this.options.x,
+ y = this.options.y,
+ randomiseSign = this.options.randomiseSign,
+ cdata;
+
+ if (this.options.randomiseSign) {
+ if (Math.random() < randomiseSign) x = -x;
+ if (Math.random() < randomiseSign) y = -y;
+ }
+
+ cdata = this._context.getImageData(0, 0, this._width, this._height);
+ this._context.putImageData(cdata, x, y);
+ },
+
+ resize: function(width, height) {
+ this._width = width;
+ this._height = height;
+ }
+});
@@ -0,0 +1,82 @@
+barryvan.tp.performer.Fixed = new Class({
+ Implements: [Options],
+
+ Extends: barryvan.tp.performer.Base,
+
+ Binds: [
+ 'updateOpts',
+ 'noteEvent',
+ 'frame',
+ 'tick',
+ '_drawNote'
+ ],
+
+ options: {
+ colour: '#729fcf',
+ x: 10,
+ y: 10,
+ width: 10,
+ height: 10,
+ sustain: false,
+ vitalisation: 0,
+ honourCuts: true
+ },
+
+ _vitality: 0,
+
+ initialize: function(context, canvas, options) {
+ this.parent(context, canvas, options);
+ },
+
+ updateOpts: function(options) {
+ this.options = Object.merge(this.options, options);
+ },
+
+ noteEvent: function(data) {
+ if ((data.note < 0) && this.options.honourCuts) {
+ this._currentNote = null;
+ this._vitality = this._vitality / 2;
+ // Note cut / note off
+ return;
+ }
+
+ if (!this.filterNote(data)) return;
+
+ this._currentNote = data.note;
+
+ this._vitality = this.options.vitalisation;
+
+ // If we're sustained or vitalised, drawing is handled in frame(), not noteEvent().
+ // if (this.options.sustain || this.options.vitalisation) return;
+
+ this._drawNote();
+ },
+
+ tick: function() {
+ // Decrement vitality in tick() rather than frame() to ensure it's fairly
+ // consistent regardless of FPS
+ if (this._vitality > 0) this._vitality -= 1;
+ },
+
+ frame: function() {
+ if (this._vitality || this.options.sustain) {
+ this._drawNote();
+ }
+ },
+
+ _drawNote: function() {
+ if (!this._currentNote) return;
+
+ if (this.options.vitalisation) {
+ var prev_alpha = this._context.globalAlpha;
+ this._context.globalAlpha = this._vitality / this.options.vitalisation;
+ }
+
+ this._context.fillStyle = this.options.colour;
+ this._context.fillRect(this.options.x, this.options.y, this.options.width, this.options.height);
+
+ if (this.options.vitalisation) {
+ this._context.globalAlpha = prev_alpha;
+ }
+ }
+});
@@ -0,0 +1,71 @@
+barryvan.tp.performer.Glow = new Class({
+ Implements: [Options],
+
+ Extends: barryvan.tp.performer.Base,
+
+ Binds: [
+ 'updateOpts',
+ 'frame',
+ 'noteEvent'
+ ],
+
+ options: {
+ size: 20,
+ decay: 2,
+ colour: '#204a87',
+ template: '0 0 {size}px {colour}',
+ velocity: {
+ size: true,
+ opacity: false
+ }
+ },
+
+ _currentSize: 0,
+ _currentOpacity: 0,
+ _colourPart: 0,
+
+ initialize: function(context, canvas, options) {
+ this.parent(context, canvas, options);
+
+ this._colourPart = 'rgba(' + (new Color(this.options.colour)).join(',') + ',';
+ },
+
+ updateOpts: function(options) {
+ this.options = Object.merge(this.options, options);
+ this._colourPart = 'rgba(' + (new Color(this.options.colour)).join(',') + ',';
+ },
+
+ frame: function() {
+ var shadow = 'none';
+ if (this._currentSize && this._currentOpacity) {
+ shadow = this.options.template;
+ shadow = shadow.replace(/\{size\}/g, this._currentSize);
+ shadow = shadow.replace(/\{colour\}/g, this._colourPart + this._currentOpacity + ')');
+ }
+
+ this._canvas.setStyle('box-shadow', shadow);
+
+ if (this._currentSize) this._currentSize -= this.options.decay;
+ },
+
+ noteEvent: function(data) {
+ if (data.note < 0) {
+ // Note cut / note off
+ return;
+ }
+
+ if (!this.filterNote(data)) return;
+
+ var multiplier = (data.volume === undefined ? 64 : data.volume) / 64;
+ if (this.options.velocity.size) {
+ this._currentSize = this.options.size * multiplier;
+ } else {
+ this._currentSize = this.options.size;
+ }
+ if (this.options.velocity.opacity) {
+ this._currentOpacity = multiplier;
+ } else {
+ this._currentOpacity = 1;
+ }
+ }
+});
Oops, something went wrong. Retry.

0 comments on commit 686cf54

Please sign in to comment.