Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Livecoding in Javascript

Livecoding in Javascript

Jason Frame

May 09, 2013
Tweet

More Decks by Jason Frame

Other Decks in Programming

Transcript

  1. Microworlds Paper - “Twenty Reasons Why You Should Use Boxer

    (Instead of Logo)” Andrea A. diSessa Friday, 31 May 13
  2. Why Javascript? • Flexible language • Ecosystem - browser +

    node.js = node- webkit • Single threaded • Event loop Friday, 31 May 13
  3. Why Javascript? Describing Live programming using program transformations and a

    callstack explicit interpreter Olov Johansson Friday, 31 May 13
  4. Domain-Specific Livecoding • Generalised tools can be complex • May

    also make unacceptable performance/ timing trade-offs • Evolve tools with your application Friday, 31 May 13
  5. Implementation Strategies • Private State • Variable Injection • “Globals”

    Preservation • Internal eval() • Blueprints • Snapshot • Clocksources Friday, 31 May 13
  6. Private State function setup() { position = {x: 10, y:

    20}; velocity = {x: 1, y: 1}; } function loop() { position.x += velocity.x; position.y += velocity.y; } Friday, 31 May 13
  7. Private State (function() { “use strict”; var position; var velocity;

    function setup() { position = {x: 10, y: 20}; velocity = {x: 1, y: 1}; } function loop() { position.x += velocity.x; position.y += velocity.y; } })(); Friday, 31 May 13
  8. Private State (function() { “use strict”; var position; var velocity;

    function setup() { position = {x: 10, y: 20}; velocity = {x: 1, y: 1}; } function loop() { position.x += velocity.x; position.y += velocity.y; } return { setup: setup, loop: loop }; })(); Friday, 31 May 13
  9. Variable Injection // Generate method signature from defined // objects

    (function(car, trafficLights, background) { // Paste user code here function loop() { car.drawAt(0,0,50,50) } // ... // ... // ... }).apply(null, exposedObjects); Friday, 31 May 13
  10. “Globals” Preservation var carX = 0; var carY = 0;

    var speed = 5; function loop() { carY += speed; draw(); } Friday, 31 May 13
  11. “Globals” Preservation var carX = 0; var carY = 0;

    var speed = 5; function loop() { carY += speed; draw(); } Friday, 31 May 13
  12. “Globals” Preservation (function() { "use strict"; var carX = 0;

    var carY = 0; var speed = 5; function loop() { carY += speed; draw(); } return { loop: loop, getVars: function() { return {carX: carX, carY: carY, speed: speed}; }, setVars: function(vars) { carX = vars.carX; carY = vars.carY; speed = vars.speed; } }; })(); Friday, 31 May 13
  13. Internal eval() var car = {x: 20, y: 20} var

    lightState = “red-amber” function setup() { // ... } function loop() { // ... } Friday, 31 May 13
  14. Internal eval() (function() { "use strict"; var car = {x:

    20, y: 20} var lightState = “red-amber” function setup() { // ... } function loop() { // ... } })(); Friday, 31 May 13
  15. Internal eval() (function() { "use strict"; var car = {x:

    20, y: 20} var lightState = “red-amber” function setup() { // ... } function loop() { // ... } function evaluate(code) { return eval(code); } return { __eval__: evaluate } })(); Friday, 31 May 13
  16. Blueprints // Inside engine var blueprint = new SystemBlueprint(); blueprint.id

    = oldSystem.id; blueprint.enabled = oldSystem.enabled; blueprint.update = function() { /* default impl */ } USERCODE = ‘(function(system) { // augment blueprint system.title = “foo”; system.update = function() { ... } })’; // Compile code systemBuilder = eval(USERCODE); systemBuilder(blueprint); // inspect user’s refinements to blueprint and // setup accordingly Friday, 31 May 13
  17. Snapshots system.snapshot = function() { return { entities: Object.keys(this.entities), lastShotTime:

    this.lastShotTime } } system.restore = function(snapshot) { var self = this; this.entities = {}; snapshot.entities.forEach(function(eid) { self.entities[eid] = self.world.getEntityById(eid); } this.lastShotTime = snapshot.lastShotTime; } Friday, 31 May 13
  18. Snapshots function updateSystem(registry, systemId, newSystem) { var existingSystem = registry.getSystemById(systemId);

    var snapshot = existingSystem.snapshot(); try { newSystem.restore(snapshot); registry.setSystem(systemId, newSystem); } catch (e) { // Incompatible snapshot - restart app? } } Friday, 31 May 13
  19. Clocksources Date.now() function Clock() { this.time = 0; this.lastDelta =

    null; } Clock.prototype.tick = function(delta) { this.time += delta; this.lastDelta = delta; } function tick() { var wallclockDelta = Date.now() - lastTick; clock.tick(wallclockDelta); } Friday, 31 May 13