xxxxxxxxxx
338
const SCREEN_WIDTH = 1200;
const SCREEN_HEIGHT = SCREEN_WIDTH / 2;
const TEXT_SIZE = SCREEN_WIDTH / 50;
const BOX_SIZE = SCREEN_HEIGHT / 2;
const USER_INPUT_MAX_LENGTH = 60;
// list of questions that can show up
const Questions = [
['Who do you miss the', 'most?'],
['What is a fear of yours?'],
['What brings you joy?'],
['What is something that', 'makes you sad?'],
['Who do you love?'],
['What inspires you?'],
['What\'s your favorite', 'song lyric?'],
['Share a lesson for', 'the next person.'],
['What\'s your favorite', 'memory?'],
]
/* a list of coordinates for drawing the boxes in this order
4 3
2 1
*/
let memoryCoords = [
[SCREEN_WIDTH * 0.25, SCREEN_HEIGHT * 0.5],
[0, SCREEN_HEIGHT * 0.5],
[SCREEN_WIDTH * 0.25, 0],
[0, 0],
]
let initialImages = []
let typeWriterSounds = []
function preload() {
initialImages[0] = loadImage('initial_memories/1.png');
initialImages[1] = loadImage('initial_memories/2.png');
initialImages[2] = loadImage('initial_memories/3.png');
initialImages[3] = loadImage('initial_memories/4.png');
typeWriterSounds[0] = loadSound('sounds/typewriter1.mp3');
typeWriterSounds[1] = loadSound('sounds/typewriter2.mp3');
typeWriterSounds[2] = loadSound('sounds/typewriter3.mp3');
typeWriterSounds[3] = loadSound('sounds/typewriter4.mp3');
typeWriterSounds[4] = loadSound('sounds/typewriter5.mp3');
typeWriterSounds[5] = loadSound('sounds/typewriter6.mp3');
}
let titleText;
function setup() {
createCanvas(SCREEN_WIDTH, SCREEN_HEIGHT);
video = createCapture(VIDEO);
video.size(BOX_SIZE * 1.01, BOX_SIZE * 1.01);
video.hide(); // hide it
pixelDensity(1);
textFont('Courier New');
textStyle(BOLD)
textSize(TEXT_SIZE)
generateNewQuestion();
textSize(TEXT_SIZE * 2.5)
titleText = new WobblyText('Memory Box', SCREEN_WIDTH * 0.75 - SCREEN_WIDTH / 5, SCREEN_HEIGHT * 0.15, 40)
push();
translate(width, 0);
scale(-1, 1);
image(video, 0, 0, BOX_SIZE, BOX_SIZE);
pop();
memoryList.push(new MemoryBox('', initialImages[0]))
memoryList.push(new MemoryBox('', initialImages[1]))
memoryList.push(new MemoryBox('', initialImages[2]))
memoryList.push(new MemoryBox('', initialImages[3]))
}
class WobblyText {
constructor(message, x, y, size = TEXT_SIZE) {
this.letters = []
this.size = size
this.message = message
this.x = x
this.y = y
let curString = '';
for (let i = 0; i < message.length; i++) {
let curLetter = message[i]
this.letters.push(new Letter(curLetter, this.x + textWidth(curString) * 1.2, this.y, this.size))
curString += curLetter
}
}
render() {
for (let letter of this.letters) {
letter.render()
}
}
}
class Letter {
constructor(letter, x, y, size = 16) {
this.letter = letter
this.size = size
this.originX = x
this.originY = y
this.offsetX = 0
this.offsetY = 0
this.maxOffset = 2 + (size / 12)
this.noiseX = random(10000)
this.noiseY = random(10000)
}
render() {
push()
textSize(this.size)
text(this.letter, this.originX + this.offsetX, this.originY + this.offsetY)
pop()
this.offsetX = (noise(this.noiseX) - 0.5) * 2 * this.maxOffset
this.offsetY = (noise(this.noiseY) - 0.5) * 2 * this.maxOffset
this.noiseX += 0.01;
this.noiseY += 0.01;
}
}
// the boxes on the left for each 'memory'
// contains the text and picture
class MemoryBox {
constructor(memoryText, picture, size) {
this.memoryText = memoryText;
this.picture = picture;
this.size = BOX_SIZE;
this.fadeTime = 0
this.startFade = false;
}
fadeOut() {
this.startFade = true;
}
render(x, y, imgSize = 150) {
push()
stroke(50)
noFill()
rect(x, y, this.size, this.size);
fill(50)
textSize(TEXT_SIZE * 0.75)
this.picture.resize(imgSize, imgSize);
image(this.picture, x, y, this.size, this.size)
drawingContext.filter = 'blur('+str(0.25 + (BOX_SIZE - imgSize) / 120)+'px)'
text(this.memoryText, x + this.size / 8, y + this.size * 0.15, this.size * 0.75)
drawingContext.filter = '';
if (this.startFade) {
this.fadeTime += 2.5
noStroke()
fill(255, 255, 255, this.fadeTime)
rect(x, y, this.size, this.size);
}
pop()
}
}
// randomly chooses a new question and puts it under the
// variable {questionText}
function generateNewQuestion() {
questionText = []
let question = random(Questions)
for (let i = 0; i < question.length; i++) {
let curLine = question[i]
questionText.push(new WobblyText(curLine, SCREEN_WIDTH * 0.75 - SCREEN_WIDTH / 5, SCREEN_HEIGHT * 0.25 + i * (TEXT_SIZE * 2), TEXT_SIZE))
}
}
let shouldCreateNewMemory = false;
let userInput = ''
let memoryList = []
let questionText = []
let blinkingTime = 0
let informationText = ''
// captures a picture from the webcam and returns an Image
function captureWebcamPixelArray() {
push();
translate(width, 0);
scale(-1, 1);
image(video, 0, 0, BOX_SIZE, BOX_SIZE);
pop();
photo = createImage(BOX_SIZE, BOX_SIZE);
photo.loadPixels()
loadPixels()
let photoIndex = 0
for (let y = 0; y < BOX_SIZE; y++) {
for (let x = SCREEN_WIDTH * 0.75; x < SCREEN_WIDTH; x++) {
let i = (width * y + x) * 4;
let rI = ((width * y) + (width - x - 1)) * 4;
// get r,g,b values from pixel array
let r = pixels[i + 0];
let g = pixels[i + 1];
let b = pixels[i + 2];
// get the average brightness of the pixel
let br = (r + b + g) / 3;
// if the pixel is brighter that 120,
if (br > 120) {
photo.pixels[photoIndex++] = 255
photo.pixels[photoIndex++] = 255
photo.pixels[photoIndex++] = 255
photo.pixels[photoIndex++] = 256
} else {
photo.pixels[photoIndex++] = 128
photo.pixels[photoIndex++] = 128
photo.pixels[photoIndex++] = 128
photo.pixels[photoIndex++] = 256
}
}
}
photo.updatePixels()
push()
noStroke()
fill(245)
rect(SCREEN_WIDTH * 0.75, 0, SCREEN_WIDTH * 0.25, SCREEN_HEIGHT * 0.5)
pop()
return photo;
}
function createNewMemory() {
memoryList.unshift(new MemoryBox(userInput, photo))
if (memoryList.length > 4) {
memoryList = memoryList.slice(0, 4);
}
userInput = ''
shouldCreateNewMemory = false
generateNewQuestion()
}
let photo;
function draw() {
background(245);
fill(0)
if (shouldCreateNewMemory) {
if (memoryList[3] && !memoryList[3].startFade) {
photo = captureWebcamPixelArray();
memoryList[3].fadeOut();
}
if (memoryList[3] && memoryList[3].fadeTime > 270) {
createNewMemory()
}
if (!memoryList[3]) {
photo = captureWebcamPixelArray();
createNewMemory()
}
}
for (let question of questionText) {
question.render()
}
titleText.render()
blinkingTime++
if (blinkingTime < 45) {
text('>', SCREEN_WIDTH * 0.75 - BOX_SIZE * 0.9, SCREEN_HEIGHT * 0.75, SCREEN_WIDTH / 2.5)
} else if (blinkingTime > 60) {
blinkingTime = 0;
}
textSize(TEXT_SIZE)
if (!userInput) {
fill(128)
text('type something...', SCREEN_WIDTH * 0.75 - SCREEN_WIDTH / 5, SCREEN_HEIGHT * 0.75, SCREEN_WIDTH / 2.5)
} else {
text(userInput, SCREEN_WIDTH * 0.75 - SCREEN_WIDTH / 5, SCREEN_HEIGHT * 0.75, SCREEN_WIDTH / 2.5)
}
fill(128)
text(informationText, SCREEN_WIDTH * 0.75 - SCREEN_WIDTH / 5, SCREEN_HEIGHT * 0.9, SCREEN_WIDTH / 2.5)
for (let i = 0; i < memoryList.length; i++) {
const curMemory = memoryList[i]
curMemory.render(memoryCoords[i][0], memoryCoords[i][1], BOX_SIZE - (i * BOX_SIZE / 4));
}
}
function playTypeSound() {
const typeSound = random(typeWriterSounds)
typeSound.play()
}
function keyPressed() {
if (keyCode === BACKSPACE) {
userInput = userInput.slice(0, -1)
playTypeSound();
informationText = ''
} else if (keyCode === ENTER) {
if (userInput.length > 0) {
playTypeSound();
shouldCreateNewMemory = true;
informationText = '';
}
}
}
function keyTyped() {
if (key.length === 1 && !shouldCreateNewMemory) {
if (userInput.length < USER_INPUT_MAX_LENGTH) {
playTypeSound();
userInput = userInput + key;
} else {
informationText = 'max characters reached...'
}
}
return false;
}