From 2f5427a41afa0b8001850fa1e312803c31c00688 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Mon, 3 Feb 2020 12:06:17 +0100 Subject: [PATCH] Try to comment out what we have so far --- voicegardens/static/voicegardens.js | 211 +++++++++++++++++----------- 1 file changed, 132 insertions(+), 79 deletions(-) diff --git a/voicegardens/static/voicegardens.js b/voicegardens/static/voicegardens.js index 64fdca6..c9b6140 100644 --- a/voicegardens/static/voicegardens.js +++ b/voicegardens/static/voicegardens.js @@ -4,31 +4,56 @@ // Voicegardens front-end Javascript // +// URL which exposes the archive saving API end-point var archiveUrl = window.location + "add-to-archive"; -var canvasHeight; -var canvasWidth; + +// The x,y coordinates which gives the center of the canvas var centerX; var centerY; + +// The canvas frame rate which controls how many times the draw function is +// called. So far as we have seen, this can affect performance. Try the value +// of 30 and also 60 to see the difference. Higher values may also give more +// fun animation effects. var frameRate = 30; + +// Sound recording API objects var microphone; +var recorder; +var recording; + +// Boolean which is only true when the user stops the recording of a sound. +// This then triggers the generation of a shape based on that recording. var newSoundJustRecorded = false; + +// All user clickable buttons +var archiveButton; var playButton; var recordButton; -var recorder; -var recording; -var recordingTimeout = 30000; // 30 seconds (in milliseconds) -var screenX; -var screenY; -var secondTick = false; -var shapes = []; var stopButton; -var timer = 0; -var toScreenX; -var toScreenY; +var viewArchiveButton; + +// Time-out used to stop a recording in case the user forgets to stop it +// themselves. It also gurantees to turn off the mic in case of some unknown +// error that we didn't take into consideration. This is 30 seconds in +// milliseconds. +var recordingTimeout = 30000; + +// The x,y coordinates which shows where the window position is. This is useful +// because we use the `translate` function to offset the window view in +// relation to the canvas (users can drag their view across the "environment") +// and we need to record where that x position leaves us. +var screenX = 0; +var screenY = 0; +var toScreenX = 0; +var toScreenY = 0; + +// All shapes generated +var shapes = []; function record() { /** - * Starting recording. + * Start recording a sound. **/ if (microphone.enabled) { setTimeout(recorder.record(recording), recordingTimeout); @@ -37,17 +62,19 @@ function record() { function stop() { /** - * Stop recording a new recording. + * Stop recording a new sound. **/ if (recorder.recording) { recorder.stop(); + + // signal to the draw loop that we should generate a new shape newSoundJustRecorded = true; } } function play() { /** - * Play the recording. + * Play the sound just recorded. **/ if (recording.isLoaded()) { recording.play(); @@ -56,7 +83,7 @@ function play() { function archive() { /** - * Send the recording to the back-end. + * Send the sound to the back-end for archving. **/ var soundBlob = recording.getBlob(); @@ -77,12 +104,15 @@ function archive() { } function showArchive() { + /** + * Set URL to view archive. Called by the `archiveButton`. + **/ window.location.href = "/archive"; } function setupRecording() { /** - * Setup logic for recording. + * Setup logic for sound recording. **/ microphone = new p5.AudioIn(); microphone.start(); @@ -104,13 +134,13 @@ function setupRecording() { playButton.position(10, 75); playButton.mousePressed(play); - playButton = createButton("archive"); - playButton.position(10, 110); - playButton.mousePressed(archive); + archiveButton = createButton("archive"); + archiveButton.position(10, 110); + archiveButton.mousePressed(archive); - playButton = createButton("view archive"); - playButton.position(10, 145); - playButton.mousePressed(showArchive); + viewArchiveButton = createButton("view archive"); + viewArchiveButton.position(10, 145); + viewArchiveButton.mousePressed(showArchive); } function getSoundInfo() { @@ -139,41 +169,71 @@ class GeneratedShape { /** * Initialise the new shape. **/ - this.synth = new p5.MonoSynth(); + // The opacity of the shape. This controls whether we can see the shape or + // not (transparency). It starts at zero as we want to fade the shapes in + // when they enter the environment this.opacity = 0; + + // the colour of the shape this.colour = this.chooseColour(); + // Acceleration x,y values which control at which speed the shape + // accelerates towards the intended x,y destination. this.accelX = 0.0; this.accelY = 0.0; + // The x, y destination values which the shape moves towards. This can be + // calculated against the `mouseX` and `mouseY` values, for example. Then + // the shape will follow the mouse. this.deltaX = 0.0; this.deltaY = 0.0; + // ??? this.springing = 0.0009; + + // ??? this.damping = 0.98; + + // Value that controls the tightness or looseness of the curves between the + // x,y values of the shape. AFAIK, this value can go between -5 and +5. + // With +5 we have very sharp curves and edges. this.organicConstant = random(-5, 5); + // The x,y values which determine where the shape is currently. These are + // required in order to calculate where the shape is currently so that we + // can then go about moving it to the new destination. this.startXs = []; this.startYs = []; + // The x,y values which track the new position of the shape (and therefore + // update the `startXs` and `startYs`) as the shape moves about the + // environment this.xs = []; this.ys = []; + // ??? this.angles = []; - this.frequency = []; + // ??? + this.frequencies = []; + + // Random x,y values (only randomly chosen once, then fixed) which are used + // in the calculation of the curve drawing between the x,y vectors of the + // shape this.randXs = []; this.randYs = []; + // Number of edges of the shape this.edges = random(3, 10); + // ??? this.radius = random(120, 140); - this.angle = radians(360 / this.edges); - this.destX = random(canvasWidth); - this.destY = random(canvasHeight); + // ??? + this.angle = radians(360 / this.edges); + // ??? this.centerX = random(windowWidth); this.centerY = random(windowHeight); @@ -182,7 +242,7 @@ class GeneratedShape { initialise() { /** - * Initialise the shape. + * Initialise the shape values. **/ for (let i = 0; i < this.edges; i++) { this.startXs[i] = 0; @@ -195,7 +255,7 @@ class GeneratedShape { } for (let i = 0; i < this.edges; i++) { - this.frequency[i] = random(5, 12); + this.frequencies[i] = random(5, 12); } } @@ -203,34 +263,40 @@ class GeneratedShape { /** * Detect if the shape collides with another shape. **/ - // TODO: implement once again - return false; + return false; // TODO: implement once again } sound() { /** * Play a sound after a collision is detected. **/ - // TODO: implement once again - return; + return; // TODO: implement once again } - fadein() { + docolour() { /** - * Fade-in the shape using alpha values. + * Draw colour and fade-in shape. **/ - if (this.opacity < 256) { - let currentAlpha = this.colour._getAlpha(); - this.colour.setAlpha(currentAlpha + random(0, 3)); - } else { - this.opacity = 256; + if (this.opacity != 256) { + if (this.opacity < 256) { + // shape should fade in, so increment alpha value + let currentAlpha = this.colour._getAlpha(); + this.colour.setAlpha(currentAlpha + random(0, 3)); + } else { + // shape has faded-in, show it as fully visible now + this.opacity = 256; + } } + fill(this.colour); } chooseColour() { /** * Choose a colour for the shape. **/ + // TODO: choose nicer colours + // TODO: Can we have gradient colours + // TODO: Can we have multiple colours let colourChoices = [ color("red"), color("blue"), @@ -238,19 +304,35 @@ class GeneratedShape { color("black"), color("white") ]; + let index = floor(random(0, colourChoices.length)); let chosenColour = colourChoices[index]; + + // set shape opacity to 0 initially to enable fade-in chosenColour.setAlpha(this.opacity); + return chosenColour; } + curve() { + /** + * Curve the shape. + **/ + curveTightness(this.organicConstant); + beginShape(); + for (let i = 0; i < this.edges; i++) { + curveVertex(this.xs[i], this.ys[i]); + } + endShape(CLOSE); + } + draw() { /** * Draw the shape vectors. **/ - if (this.opacity != 256) this.fadein(); - fill(this.colour); + this.docolour(); + // set the start x,y positions for the shape on each draw loop for (let i = 0; i < this.edges; i++) { this.startXs[i] = this.centerX + cos(this.angle * i) * this.radius + this.randXs[i]; @@ -258,12 +340,7 @@ class GeneratedShape { this.centerY + sin(this.angle * i) * this.radius + this.randYs[i]; } - curveTightness(this.organicConstant); - beginShape(); - for (let i = 0; i < this.edges; i++) { - curveVertex(this.xs[i], this.ys[i]); - } - endShape(CLOSE); + this.curve(); } move() { @@ -292,39 +369,31 @@ class GeneratedShape { this.startXs[i] + sin(radians(this.angles[i])) * (this.accelX * 2); this.ys[i] = this.startYs[i] + sin(radians(this.angles[i])) * (this.accelY * 2); - this.angles[i] += this.frequency[i]; + this.angles[i] += this.frequencies[i]; } } } function setup() { /** - * The p5.js initial setup function. + * The initial setup function called once on start. **/ - canvasWidth = windowWidth; - canvasHeight = windowHeight; - - createCanvas(canvasWidth, canvasHeight); + createCanvas(windowWidth, windowHeight); frameRate(frameRate); - setupRecording(); - - centerX = canvasWidth / 2; - centerY = canvasHeight / 2; - - screenX = toScreenX = 0; - screenY = toScreenY = 0; } function draw() { /** - * The p5.js draw loop. + * The draw loop which is called x times a second where x is the frameRate. **/ background("#69D2E7"); blendMode(BLEND); smooth(); noStroke(); + // offset the window view based on new values of x,y related to the screen. + // These values are generated once the user drags the screen with the mouse. screenX = lerp(screenX, toScreenX, 0.2); screenY = lerp(screenY, toScreenY, 0.2); translate(screenX, screenY); @@ -334,30 +403,14 @@ function draw() { newSoundJustRecorded = false; } - if (millis() >= 1000 + timer) { - secondTick = true; - timer = millis(); - } - for (let i = 0; i < shapes.length; i++) { let shape = shapes[i]; - shape.draw(); shape.move(); - - if (secondTick) { - setTimeout(function() { - shape.destX = random(canvasWidth); - shape.destY = random(canvasHeight); - }, random(100, 3000)); - } - if (shape.collide(shapes) === true) { shape.sound(); } } - - secondTick = false; } function mouseDragged() {