Skip to content

Commit

Permalink
Adding CongaCelebration
Browse files Browse the repository at this point in the history
  • Loading branch information
catalanojuan committed Dec 8, 2021
1 parent 21288fe commit 99604ea
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 20 deletions.
4 changes: 2 additions & 2 deletions audio/input.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class AudioInput extends EventEmitter {
constructor(options) {
super();
// this._sampleRate = options._sampleRate || 48000;
const deviceIndex = options.deviceIndex || null;
const deviceIndex = options.deviceIndex ?? null;
const profile = options.profile || null;
this._args = [ '-u' ];
if (!profile) {
Expand All @@ -22,7 +22,7 @@ class AudioInput extends EventEmitter {
const profilePath = options.profilePath || 'audioprofile.pstats';
this._args.push('-m', 'cProfile', '-o', profilePath, mainScript);
}
if (deviceIndex) {
if(deviceIndex !== undefined ){
this._args.push('-d', deviceIndex.toString());
}
this._subprocess = null;
Expand Down
67 changes: 67 additions & 0 deletions server/setups/program-presets/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,73 @@
}
],
"multiply": true
"ShootingArcCelebration": {
"programs": [
{
"programName": "congaShooting2",
"shape": "fullArc",
"config": {
"fireThreshold": 0.31,
"soundMetricP1": "mic2_rms",
"soundMetricP2": "mic2_rms"
}
},
{
"programName": "congaScore",
"shape": "highestSide",
"config": {
"playerNumber": 1,
"globalBrightness": 0.47,
"reverse": true,
"colorHue": 0.7,
"colorSat": 0.7
}
},
{
"programName": "congaScore",
"shape": "lowestSide",
"config": {
"globalBrightness": 1,
"reverse": true,
"playerNumber": "0",
"colorHue": 0.71,
"colorSat": 0.84
}
},
{
"programName": "congaCelebration",
"shape": "head",
"config": {
"programs": [
{
"programName": "radial3d",
"config": {
"colorMap": "a_pink_r"
}
}
],
"animateOnlyOnCelebration": true
}
}
],
"fps": 60
},
"Rope w/ Celebration": {
"programs": [
{
"programName": "congaCelebration",
"shape": "man"
},
{
"programName": "congaRope",
"shape": "fullArc",
"config": {
"soundMetricP1": "peakDecay",
"soundMetricP2": "mic2_peakDecay"
}
}
],
"multiply": false
}
},
"sound-waves": {
Expand Down
1 change: 1 addition & 0 deletions server/src/LightController.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const programNames = [
"mix",
"congaShooting2",
"congaScore",
"congaCelebration",
"congaShooting",
"congaRope",
"PROGRAM_Main_fuego2019",
Expand Down
18 changes: 18 additions & 0 deletions server/src/light-programs/conga-utils/GlobalGame.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
const ColorUtils = require("./../utils/ColorUtils");

class Game {
constructor() {
this.score = [0,0];
this.player1Color = ColorUtils.HSVtoRGB(400, 1, 1);
this.player2Color = ColorUtils.HSVtoRGB(400+0.33, 1, 1);
}

addPoint(playerIndex, points = 1) {
Expand All @@ -14,6 +18,20 @@ class Game {
restart() {
this.score = [0,0];
}

winner(){
let winner = false;
if (this.score[0] == this.max()){
winner = 1;
}
else if(this.score[1] == this.max()){
winner = 2;
}
if(winner){
this.restart();
}
return winner;
}
}

module.exports = {
Expand Down
135 changes: 135 additions & 0 deletions server/src/light-programs/programs/congaCelebration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
const LightProgram = require("./../base-programs/LightProgram");
const ColorUtils = require("./../utils/ColorUtils");
const GlobalGame = require("./../conga-utils/GlobalGame");
const _ = require("lodash");
const programsByShape = require("./../base-programs/ProgramsByShape");

module.exports = class CongaCelebratiton extends LightProgram {
init() {
this.past = null;
this.celebrate = 0;
this.winner = false;
this.colors = new Array(this.numberOfLeds).fill(ColorUtils.HSVtoRGB(0, 0, this.config.brillo));
// Shallow copy of schedule
this.programs = _.map(this.config.programs, config => this.getProgramInstanceFromParam(config));
}

getProgramInstanceFromParam({programName, config, shape}) {
let p = null;
// For performance, only use programsByShape if there is a shape
if(shape) {
const programClass = this.lightController.programs[programName].generator;
const byShapeClass = programsByShape({[shape]: [programClass, config || {}]});
p = new byShapeClass(this.config, this.geometry, this.shapeMapping, this.lightController);
} else {
p = this.lightController.instanciateProgram(programName);
p.updateConfig({...p.config, ...config})
}

p.init();
return p;
}

getCelebrationBaseColors() {



}

drawFrame(draw, audio) {
this.colors = new Array(this.numberOfLeds).fill(ColorUtils.HSVtoRGB(0, 0, this.config.brillo/100));
let winner = GlobalGame.game.winner();
let combinedColors = this.colors;
if (winner && (this.celebrate == 0 || winner != this.winner)){
this.winner = winner;
this.celebrate = this.config.celebrationDurationInFrames;
}
if (this.celebrate > 0){
let winnerColor = this.winner == 1 ? GlobalGame.game.player1Color : GlobalGame.game.player2Color;
this.colors = new Array(this.numberOfLeds).fill(winnerColor);
this.celebrate--;
}
if(!this.config.animateOnlyOnCelebration || this.celebrate > 0){
combinedColors = this.colors;

this.extraTime = (this.extraTime || 0) + Math.random() * 10;

for (const prog of this.programs) {
// Done by ProgramScheduler, has to be replicated here
prog.timeInMs = this.timeInMs;
let globalBrightness = prog.config.globalBrightness || 0;
prog.drawFrame((colors) => {
for (let i = 0; i < this.numberOfLeds; i++) {
let [r, g, b, a] = combinedColors[i]
const [r2, g2, b2, a2] = colors[i];
if (this.config.multiply) {
// globalBrightness of 0 means "the layer does not darken the other layer"
r = r * ((r2+(255-r2)*(1-globalBrightness)) || 0) / 255;
g = g * ((g2+(255-g2)*(1-globalBrightness)) || 0) / 255;
b = b * ((b2+(255-b2)*(1-globalBrightness)) || 0) / 255;
a = a + (a2 || 0)
} else {
r += (r2 || 0) * globalBrightness;
g += (g2 || 0) * globalBrightness;
b += (b2 || 0) * globalBrightness;
a += a2 || 0;
}
combinedColors[i] = [r, g, b, a];
}
}, audio)
}
}
draw(combinedColors);
}

updateConfig(newConfig) {
// TODO: backwards compatibility with previous version of mix
if(newConfig.a && newConfig.b) {
let {a, b, ... other} = newConfig;
newConfig = {... other, programs: [a, b]}
}

// Override LightProgram version to decide when a program init needs to be called
if (this.programs) {
let updated = newConfig.programs;
let oldConfigs = this.config.programs;

this.programs = _.map(updated, (newProgDef, i) => {
let oldProgDef = oldConfigs[i];

let subprogram = null;

// Detect if the selected program type is the same or it changed
if (oldProgDef && oldProgDef.programName === newProgDef.programName && oldProgDef.shape === newProgDef.shape) {
subprogram = this.programs[i]
subprogram.updateConfig({ ... subprogram.config, ... newProgDef.config })
} else {
subprogram = this.getProgramInstanceFromParam(newProgDef)
}

// Detect if a different preset was selected and apply the default+preset program config
if(oldProgDef && oldProgDef.presetName !== newProgDef.presetName && newProgDef.presetName) {
const presets = this.lightController.getProgramPresets(newProgDef.programName);
const defaults = this.lightController.getProgramDefaultParams(newProgDef.programName);
newProgDef.config = presets[newProgDef.presetName];
subprogram.updateConfig({ ... defaults, ... presets[newProgDef.presetName] })
}

return subprogram
});
}

super.updateConfig(newConfig)
}

// Override and extend config Schema
static configSchema() {
let res = super.configSchema();
res.brillo = { type: Number, min: 0, max: 1, step: 0.01, default: 0.5 };
res.celebrationDurationInFrames = { type: Number, min: 0, max: 200, step: 5, default: 500 };
res.animateOnlyOnCelebration = {type: Boolean, default: false};
res.programs = {type: 'programs', default: [{programName: 'circles'}]};
res.multiply = {type: Boolean, default: false};
return res;
}
};
16 changes: 8 additions & 8 deletions server/src/light-programs/programs/congaRope.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const LightProgram = require("./../base-programs/LightProgram");
const ColorUtils = require("./../utils/ColorUtils");
const _ = require("lodash");
const GlobalGame = require("./../conga-utils/GlobalGame");

module.exports = class CongaShooting extends LightProgram {

Expand All @@ -11,8 +12,8 @@ module.exports = class CongaShooting extends LightProgram {
this.rope = {pos: this.center - this.segmentSize, length: 2 * this.segmentSize};
this.explosionLevel = 0;
this.time = 0;
this.audioWindow1 = new Array(1000).fill(0);
this.audioWindow2 = new Array(1000).fill(0);
this.audioWindow1 = new Array(600).fill(0);
this.audioWindow2 = new Array(600).fill(0);
this.maxVolume = 0;
}

Expand All @@ -21,17 +22,16 @@ module.exports = class CongaShooting extends LightProgram {
let volP2 = (audio[this.config.soundMetricP2] || 0) * this.config.multiplier;

this.audioWindow1.unshift();
this.audioWindow1.push(volP1 > this.config.fireThreshold ? 1 : 0);
this.audioWindow1.push(volP1 > this.config.fireThreshold ? volP1 : 0);

this.audioWindow2.unshift();
this.audioWindow2.push(volP2 > this.config.fireThreshold ? 1 : 0);
this.audioWindow2.push(volP2 > this.config.fireThreshold ? volP2 : 0);
}

detectBursts(audio){
this.updateAudioWindow(audio);
let burstSizeP1 = _.sum(this.audioWindow1);
let burstSizeP2 = _.sum(this.audioWindow2);
console.log(burstSizeP1, burstSizeP2);

if(burstSizeP1 < this.config.burstThreshold){
burstSizeP1 = 0;
Expand Down Expand Up @@ -82,7 +82,7 @@ module.exports = class CongaShooting extends LightProgram {
}
gameOver(winner){
this.rope = {pos: this.center - this.segmentSize, length: 2 * this.segmentSize};
this.paintAll();
GlobalGame.game.score[winner] = GlobalGame.game.max();
}

drawFrame(draw, audio) {
Expand All @@ -98,10 +98,10 @@ module.exports = class CongaShooting extends LightProgram {
}

if (this.rope.pos == 0){
this.gameOver('P1');
this.gameOver(0);
}
if(this.rope.pos + this.rope.length == this.numberOfLeds){
this.gameOver('P2');
this.gameOver(1);
}
let baseColor = ColorUtils.HSVtoRGB(0, 0, this.explosionLevel/20);
for (let i = 0; i < this.numberOfLeds; i++) {
Expand Down
12 changes: 2 additions & 10 deletions server/src/light-programs/programs/congaShooting2.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ module.exports = class CongaShooting extends LightProgram {
if(b.pos < 0 || b.pos > this.numberOfLeds) {
this.bulletsA = _.without(this.bulletsA, b);
GlobalGame.game.addPoint(0);

if(GlobalGame.game.score[0] === 10) {
GlobalGame.game.restart()
}
}
}

Expand All @@ -54,10 +50,6 @@ module.exports = class CongaShooting extends LightProgram {
if(b.pos < 0 || b.pos > this.numberOfLeds) {
this.bulletsB = _.without(this.bulletsB, b);
GlobalGame.game.addPoint(1);

if(GlobalGame.game.score[1] === 10) {
GlobalGame.game.restart()
}
}
}

Expand Down Expand Up @@ -97,12 +89,12 @@ module.exports = class CongaShooting extends LightProgram {
this.colors[i] = baseColor;
for(const b of this.bulletsA){
if (Math.abs(b.pos - i) < this.config.speed){
this.colors[i] = ColorUtils.HSVtoRGB(b.size/400, 1, 1);
this.colors[i] = GlobalGame.game.player1Color;
}
}
for(const b of this.bulletsB){
if (Math.abs(b.pos - i) < this.config.speed){
this.colors[i] = ColorUtils.HSVtoRGB(b.size/400+0.33, 1, 1);
this.colors[i] = GlobalGame.game.player2Color;
}
}
}
Expand Down

0 comments on commit 99604ea

Please sign in to comment.