// extended event class ballEvent extends Event { int newball; string type; int owner; int id; float x; float y; float z; int target; int bounce; int explode; } // declare constants 8 => int SPEAKERCOUNT; 32 => int CLIENTCOUNT; 1000 => int PROJECTILECOUNT; 2 => int LISTENERCOUNT; "plasma" => string PLASMA; "bfg" => string BFG; "rocket" => string ROCKET; "chaingun" => string CHAINGUN; .1 => float ampPad; // for scaling float roomMinY; float roomMaxY; float roomMinX; float roomMaxX; float roomMinZ; float roomMaxZ; float scaledRoomX; float scaledRoomY; float scaledRoomZ; JCRev gReverbfromjohnchowningLeft => dac.left; JCRev gReverbfromjohnchowningRight => dac.right; .5 => gReverbfromjohnchowningLeft.gain; .075 => gReverbfromjohnchowningLeft.mix; .5 => gReverbfromjohnchowningRight.gain; .075 => gReverbfromjohnchowningRight.mix; //recording //gReverbfromjohnchowning => WvOut w => blackhole; //"chuck-session" => w.autoPrefix; //"special:auto" => w.wavFilename; // declare "global" vars int gClients; int gProjectiles; // fake enumerated type (better way?) ["plasma", "bfg", "rocket", "chaingun"] @=> string PTYPES[]; // array declarations float worldcoordinates[3]; //Client clients[CLIENTCOUNT]; //Projectile projectiles[PROJECTILECOUNT]; // OSC // create our OSC receiver OscRecv recv; 6662 => recv.port; recv.listen(); recv.event( "/projectile, s i i f f f i i i" ) @=> OscEvent oeProjectile; string type; int owner; int id; float X; float Y; float Z; int target; int bounce; int explode; int projectiles[PROJECTILECOUNT]; ballEvent @ bprojectiles[PROJECTILECOUNT]; int temp; 0=>int inc; // Client methods fun int addCLient(int id) { // mark client position in array active gClients++; return 0; } fun int removeClient(int id){ // mark client position in array inactive gClients--; return 0; } fun void scaleRoomsize(int i) { if (i==0) Math.fabs(roomMaxX-roomMinX) => scaledRoomX; else if (i==1) Math.fabs(roomMaxY-roomMinY) => scaledRoomY; else //i== 2 Math.fabs(roomMaxZ-roomMinZ) => scaledRoomZ; } // method to listen to broadcast OSC messages for a given ball id //--------------------------------------------------------------- fun void ball(ballEvent e) { // SinOsc s => ADSR bob => gReverbfromjohnchowning; SinOsc s => ADSR bob => Gain lGain; bob => Gain rGain; lGain => gReverbfromjohnchowningLeft; rGain => gReverbfromjohnchowningRight; 0 =>s.gain; bob.set(10::ms, 5::ms, .5, 200::ms); float noteduration; e.id => int id; while ( true ) { // wait on event e e => now; if(e.id != id) continue; // listen if (e.explode == 1) { // if explode message, kill sound // <<<"explode: ball_num = ", e.id>>>; // let decay 3::second => now; break; } if (e.bounce == 1) { //set L and R amplitudes based on Y //<<< "amp:", Math.fabs(e.y + roomMinY)/scaledRoomY>>>; Math.fabs(e.y + roomMinY)/scaledRoomY => float tpan; // go 0 to 1; tpan + ampPad=> lGain.gain; 1-tpan=>rGain.gain; // if bounce, play bounce sound // <<<"bounce: ball_num = ", e.id>>>; .5 =>s.gain; bob.keyOn(); // convert MIDI note to hz //Std.mtof( note ) => s.freq; e.x => s.freq; // advance time (e.y - roomMinY)/(100*(scaledRoomY)) => noteduration; // <<<"noteduration: ", noteduration >>>; // noteduration = // noteduration::ms => now; // 15::ms => now; (1000*noteduration+5)::ms => now; bob.keyOff(); } } // <<< "I now take my life: mr. ", id >>>; // bob =< gReverbfromjohnchowning; lGain =< gReverbfromjohnchowningLeft; rGain =< gReverbfromjohnchowningRight; } ballEvent e; while ( true ) { oeProjectile => now; while ( oeProjectile.nextMsg() != 0 ) { //<<< "type:", oeProjectile.getString()>>>; oeProjectile.getString() => type; oeProjectile.getInt() => owner; oeProjectile.getInt() => id; oeProjectile.getFloat() => X; oeProjectile.getFloat() => Y; oeProjectile.getFloat() => Z; oeProjectile.getInt() => target; oeProjectile.getInt() => bounce; oeProjectile.getInt() => explode; // set max and min X if(X > roomMaxX) { X => roomMaxX; scaleRoomsize(0); // <<< "room Max X: ", roomMaxX >>>; } else if(X < roomMinX) { X => roomMinX; scaleRoomsize(0); // <<< "room Min X: ", roomMinX >>>; } // set max and min Y if(Y > roomMaxY) { Y => roomMaxY; scaleRoomsize(1); // <<< "room Max Y: ", roomMaxY >>>; } else if(Y < roomMinY) { Y => roomMinY; scaleRoomsize(1); // <<< "room Min Y: ", roomMinY >>>; } // set max and min Z if(Z > roomMaxZ) { Z => roomMaxZ; scaleRoomsize(2); // <<< "room Max Z: ", roomMaxZ >>>; } else if(Z < roomMinZ) { Z => roomMinZ; scaleRoomsize(2); // <<< "room Min Z: ", roomMinZ >>>; } // ------------------------------------- // if(projectiles[id]==0) { if(bprojectiles[id]==null) { 1 => projectiles[id]; ballEvent @tempBall; new ballEvent @=> tempBall @=>bprojectiles[id]; type => tempBall.type; owner => tempBall.owner; id => tempBall.id; X =>tempBall.x; Y => tempBall.y; Z =>tempBall.z; target => tempBall.target; bounce => tempBall.bounce; explode => tempBall.explode; inc++; //<<<"added projectile: ", id, " - size: ", inc >>>; //<<<"value at: ", id, " = ", projectiles[id]>>>; 1 => tempBall.newball; spork ~ ball( tempBall ); me.yield(); tempBall.broadcast(); // send events to all balls } else { bprojectiles[id] @=> ballEvent @ temp2Ball; if(explode==1) { 0 => projectiles[id]; null @=> bprojectiles[id]; inc--; // <<<"removed projectile: ", id, " - size: ", inc >>>; // <<<"value at: ", id, " = ", projectiles[id]>>>; } type => temp2Ball.type; owner => temp2Ball.owner; id => temp2Ball.id; X =>temp2Ball.x; Y => temp2Ball.y; Z =>temp2Ball.z; target => temp2Ball.target; bounce => temp2Ball.bounce; explode => temp2Ball.explode; -1 => temp2Ball.newball; // not a new ball temp2Ball.broadcast(); // send events to all balls } } }