xxxxxxxxxx
545
// Emoji sound game
var mic
var vol = 0
let time;
let wait = 500;
let startGameColor = 0;
let startGameColorStroke = 255;
let lightBlue = [165, 231, 239];
let black = [0, 0, 0];
let tintStar = 127;
let displayLabelColor = 'white';
let endGameColor = lightBlue;
let endGameColorStroke = black;
let backgroundImage, nightBackgroundImage, starsImage, clickHandImage, animatedHandImage, skyBackgroundImage;
let fontRegular;
let classifier;
let score = 0;
let screen = -1;
let fallenEmojiCount = 0;
let currentEmojiIndex = 0;
let countDownTime = 3;
// Change this number to update how many emojis can hit to the ground before game over
const END_GAME_COUNT = 3;
// Change this number to update how fast the emoji falls
const EMOJI_SPEED = 1.1;
let emojiSpeed = EMOJI_SPEED;
// Label (start by showing listening)
let label = "Listening...";
let displayLabel = label;
let flipHand = false;
// Sound
let introSound, gameoverSound, dingSound, crashSound, countdownSound;
// Teachable Machine model URL:
let soundModelURL = 'https://teachablemachine.withgoogle.com/models/VfCw0WzmB/model.json';
// old model 4 classes:
//'https://teachablemachine.withgoogle.com/models/VfCw0WzmB/model.json';
let akngwelye, unyerre, aherte, yerrampe, arenge, lyerrelyerre, utnerrengatye, emojis;
const emojiNames = ['aherte', 'akngwelye', 'apmwe', 'arenge', 'lyerre-lyerre', 'unyerre', 'utnerrengatye', 'yerrampe']
let clouds = [], cloudsRange = [], cloudsPosX = [];
let learnEmojis;
function preload() {
// Load the background image
backgroundImage = loadImage('assets/background/background.png');
nightBackgroundImage = loadImage('assets/background/nightbackground.png');
starsImage = loadImage('assets/background/stars.png');
clickHandImage = loadImage('assets/background/blackclickhand.png');
animatedHandImage = loadImage('werte.gif');
skyBackgroundImage = loadImage('assets/background/skybackground.jpg');
// Load the font
fontRegular = loadFont('assets/font/joystix.monospace.ttf');
// Load the sound
introSound = loadSound('assets/sound/intro.mp3');
gameoverSound = loadSound('assets/sound/ending.mp3');
dingSound= loadSound('assets/sound/right.mp3');
crashSound= loadSound('assets/sound/wrong.mp3');
countdownSound = loadSound('assets/sound/countdown.mp3');
loadEmojiSounds();
// Load the model
classifier = ml5.soundClassifier(soundModelURL);
// Start classifying
// The sound model will continuously listen to the microphone
classifier.classify(gotResult);
}
function loadEmojiSounds() {
learnEmojis = emojiNames.map(e => loadEmoji(e));
// console.log('learnEmojis', learnEmojis)
}
function loadEmoji(name) {
const sound = loadSound(`assets/sound/emojis/${name}.mp3`);
const image = loadImage(`assets/emojis/${name}.png`);
return {
name,
sound,
image
}
}
function setup() {
// Create an Audio input
mic = new p5.AudioIn();
// start the Audio Input.
// By default, it does not .connect() (to the computer speakers)
mic.start();
// Set the volumn
outputVolume(0.2);
time = millis(); // store the current time
createCanvas(windowWidth, windowHeight);
animatedHandImage.play();
// Create clouds
createClouds();
cloudsRange = [[130, 230], [width - 400, width - 300], [width - 250, width - 150]];
cloudsPosX = [180, width - 350, width - 200]
// Create emojis
currentEmojiIndex = random([0,1,2,3,4,5,6,7]);
akngwelye = createEmoji('akngwelye', 100);
unyerre = createEmoji('unyerre', 200);
aherte = createEmoji('aherte', 300);
yerrampe = createEmoji('yerrampe', 400);
apmwe = createEmoji('apmwe', 500);
arenge = createEmoji('arenge', 600);
lyerrelyerre = createEmoji('lyerre-lyerre', 700);
utnerrengatye = createEmoji('utnerrengatye', 800);
emojis = [aherte, akngwelye, apmwe, arenge, lyerrelyerre, unyerre, utnerrengatye, yerrampe];
// Reset game score and music
if (screen === 0) {
reset();
}
textFont(fontRegular);
textAlign(CENTER, CENTER);
}
function createEmoji(name, xPos) {
const emoji = createSprite(xPos, 0);
emoji.addAnimation('normal', `assets/emojis/${name}.png`, `assets/emojis/${name}1.png`);
emoji.scale = 0.3;
emoji.velocity.y = 0;
emoji.position.y = 0;
emoji.visible = false;
return emoji;
}
function createClouds() {
const c1 = createCloud('left', 180, height / 2, 0.55);
const c2 = createCloud('mid', width - 350, height / 2 + 150, 0.5);
const c3 = createCloud('right', width - 200, height / 2 - 30, 0.5);
clouds = [c1, c2, c3];
}
function createCloud(name, xPos, yPos, scale) {
const cloud = createSprite(xPos, yPos);
cloud.addAnimation('normal', `assets/cloud/${name}-cloud.png`);
cloud.scale = scale;
cloud.velocity.y = 0;
cloud.velocity.x = 0.5;
cloud.position.x = xPos;
cloud.position.y = yPos;
cloud.visible = true;
return cloud;
}
function draw() {
if (screen === -2) {
learnPage();
}
if (screen === -1) {
goToGame();
} else if (screen === 0) {
startScreen();
} else if (screen === 0.5) {
countDownScreen();
} else if (screen === 1) {
gameOn();
} else if (screen === 2) {
endScreen();
}
}
const learnEmojiSize = 140;
function learnPage() {
background(skyBackgroundImage, 0, 0, width, height);
textSize(40);
push();
stroke(255);
strokeWeight(4);
text('AWAYE!', width / 2, 60);
pop();
learnEmojis.map((e, i) => {
const rowFactor = parseInt(i % 4) - 2;
const colFactor = i > 3 ? 1 : -1;
drawLearnEmoji(e, width / 2 + learnEmojiSize * rowFactor * 2, height / 2 + learnEmojiSize * colFactor * 2 / 3);
});
if ((millis() - time) >= wait) {
if (startGameColor === 0) {
startGameColor = 255;
startGameColorStroke = 0;
} else {
startGameColor = 0;
startGameColorStroke = 255;
}
time = millis(); //also update the stored time
}
fill(startGameColor);
stroke(startGameColorStroke);
strokeWeight(4);
textSize(28);
text('Kele arrkene-irraye / Click to play', width / 2, height - 90);
}
function drawLearnEmoji(emoji, posX, posY) {
image(emoji.image, posX + learnEmojiSize / 2, posY - learnEmojiSize / 2, learnEmojiSize, learnEmojiSize);
textSize(24);
text(emoji.name, posX + learnEmojiSize, posY + learnEmojiSize / 2);
}
function goToGame() {
image(backgroundImage, 0, 0, width, height);
fill(0);
stroke(255);
strokeWeight(4);
textSize(50);
text('Werte!', width / 2, height / 2 - 100);
// if ((millis() - time) >= wait) {
// flipHand = !flipHand;
// time = millis(); // also update the stored time
// }
// if (flipHand) {
// push();
// scale(-1, 1)
// image(clickHandImage, -width / 2 - 60/2 - 15 - 160, height / 2 - 127, 60, 60);
// pop();
// } else {
// image(clickHandImage, width / 2 + 160, height / 2 - 127, 60, 60);
// }
image(animatedHandImage, width / 2 + 160, height / 2 - 120, 70, 70);
textSize(20);
fill(0);
noStroke();
textAlign(LEFT, CENTER);
text('ARRERNTE-KENHE APMERE', 10, height - 30);
textAlign(CENTER, CENTER);
// Draw the clouds
animateClouds();
drawSprites();
fill(0);
stroke(255);
strokeWeight(4);
}
const COUNTDOWN_WORDS = ['Urrpetye', 'Atherre', 'Anyente'];
function countDownScreen() {
background(255);
image(backgroundImage, 0, 0, width, height);
fill(0);
stroke(255);
strokeWeight(4);
textFont(fontRegular);
textAlign(CENTER, CENTER);
textSize(20);
if (countDownTime !== 0) {
textSize(50);
const countdownString = COUNTDOWN_WORDS[3 - countDownTime];
text(`${countdownString} / ${countDownTime}`, width / 2, height / 2);
} else {
textSize(40);
text('Arrernte angkirtne-anaye / SAY IT', width / 2, height / 2);
}
}
function startScreen() {
image(backgroundImage, 0, 0, width, height);
// Draw the clouds
animateClouds();
drawSprites();
fill(0);
stroke(255);
strokeWeight(4);
textFont(fontRegular);
textAlign(CENTER, CENTER);
textSize(48);
text('Kwene-akerle atnarnpintyeme', width / 2, height / 2 - 200);
text('/ Downwards', width / 2, height / 2 - 140);
if ((millis() - time) >= wait) {
if (startGameColor === 0) {
startGameColor = 255;
startGameColorStroke = 0;
} else {
startGameColor = 0;
startGameColorStroke = 255;
}
time = millis(); //also update the stored time
}
fill(startGameColor);
stroke(startGameColorStroke);
strokeWeight(4);
textSize(28);
text('Kele arrkene-irraye / Click to play', width / 2, height / 2);
fill(startGameColorStroke);
stroke(startGameColor);
text('AKALTYE-IRREME / LEARN', width / 2, height / 2 + 100);
}
function hideClouds() {
clouds.forEach(c => {
c.velocity.x = 0;
c.visible = false;
})
}
function showClouds() {
clouds.forEach((c, i) => {
c.velocity.x = 0.5;
c.position.x = cloudsPosX[i];
c.visible = true;
});
}
function animateClouds() {
clouds.forEach((c, i) => {
if (c.position.x > cloudsRange[i][1] || c.position.x < cloudsRange[i][0]) {
c.velocity.x = -1 * c.velocity.x;
}
})
}
function gameOn() {
background(255);
image(backgroundImage, 0, 0, width, height);
//sprites' visibility can be turned on an off
//and invisible sprite is still updating normally
const currentEmoji = emojis[currentEmojiIndex];
displayLabel = emojiNames[currentEmojiIndex];
if (score >= 10) {
currentEmoji.velocity.y = EMOJI_SPEED + 1.3;
} else if (score >= 20) {
currentEmoji.velocity.y = EMOJI_SPEED + 2;
} else {
currentEmoji.velocity.y = EMOJI_SPEED;
}
if (label === emojiNames[currentEmojiIndex]) {
resetEmoji(currentEmoji);
currentEmojiIndex = random([0,1,2,3,4,5,6,7]);
} else {
currentEmoji.visible = true;
// If the emoji hits the ground
if (currentEmoji.position.y > height - 150) {
resetEmoji(currentEmoji);
fallenEmojiCount++;
currentEmojiIndex = random([0,1,2,3,4,5,6,7]);
// Play crash sound
crashSound.play();
introSound.stop();
gameoverSound.stop();
dingSound.stop();
}
if (fallenEmojiCount >= END_GAME_COUNT) {
screen = 2;
gameoverSound.play();
introSound.stop();
dingSound.stop();
crashSound.stop();
}
}
//draw the sprites
drawSprites();
// if (displayLabel !== 'Background Noise') {
textFont(fontRegular);
textSize(32);
textAlign(RIGHT, 50);
fill(displayLabelColor);
text(`"${displayLabel}"`, width - 20, 30);
// }
// Draw score and lives left
fill('white');
textFont(fontRegular);
textSize(20);
textAlign(LEFT, 50);
text(`Unte kwenhe mwerre anthurre mpwareke / Score: ${score}`, 20, 30);
text(`Arrkene urrpetye akwete / LIVES: ${END_GAME_COUNT - fallenEmojiCount}`, 20, 80);
}
function resetEmoji(currentEmoji) {
currentEmoji.visible = false;
currentEmoji.velocity.y = 0;
currentEmoji.position.y = 0;
}
function endScreen() {
background(100);
image(nightBackgroundImage, 0, 0, width, height);
textAlign(CENTER, CENTER);
textFont(fontRegular);
fill(165, 231, 239);
stroke(0);
strokeWeight(4);
textSize(48);
text('Arrkene uyerreke / Game over', width / 2, height / 2 - 200);
textSize(32);
text("Unte kwenhe mwerre anthurre mpwareke / SCORE = " + score, width / 2, height / 2 - 100);
if ((millis() - time) >= wait) {
if (endGameColor[0] === lightBlue[0]) {
endGameColor = black;
endGameColorStroke = lightBlue;
tintStar = 200;
} else {
endGameColor = lightBlue;
endGameColorStroke = black;
tintStar = 127;
}
time = millis(); //also update the stored time
}
tint(255, tintStar);
image(starsImage, 0, 0, width, height * 0.6);
fill(endGameColor);
stroke(endGameColorStroke);
text('Awethe arrkene-irraye / PLAY AGAIN ?', width / 2, height / 2);
textSize(24);
fill(0);
noStroke();
textAlign(LEFT, CENTER);
text('INDIGEMOJI.COM.AU', 10, height - 30);
}
function mousePressed() {
if (screen === -1) {
screen = 0;
reset();
} else if (screen === 0) {
if (introSound.isPlaying()) {
introSound.stop();
}
if (mouseY <= height / 2 + 50) {
startCountDown();
} else {
screen = -2;
}
} else if (screen === 2) {
screen = 0;
reset();
} else if (screen === -2) {
if (mouseY > height - 90 - 14 && mouseY < height - 90 + 14) {
startCountDown();
return;
}
if (mouseY < height / 2 - learnEmojiSize || mouseY > height / 2 + learnEmojiSize * 1.2 + 14) return;
if (mouseX < width / 2 - learnEmojiSize * 4 || mouseX > width / 2 + learnEmojiSize * 4) return;
let row = 0;
if (mouseX < width / 2 - learnEmojiSize * 2) {
row = 0;
} else if (mouseX < width / 2) {
row = 1;
} else if (mouseX < width / 2 + learnEmojiSize * 2) {
row = 2;
} else if (mouseX < width / 2 + learnEmojiSize * 4) {
row = 3;
}
const col = mouseY > height / 2 ? 1 : 0;
const index = col * 4 + row;
const selectedEmoji = learnEmojis[index];
if (selectedEmoji) {
selectedEmoji.sound.play();
}
}
}
function startCountDown() {
countDownTime = 3;
screen = 0.5;
if (!countdownSound.isPlaying()) {
countdownSound.play();
}
setTimeout(() => {
countDownTime = 2;
}, 1000)
setTimeout(() => {
countDownTime = 1;
}, 2000)
setTimeout(() => {
countDownTime = 0;
}, 3000)
setTimeout(() => {
countDownTime = 0;
screen = 1;
hideClouds();
}, 6000);
}
function reset() {
score = 0;
fallenEmojiCount = 0;
countDownTime = 3;
if (!introSound.isPlaying()) {
introSound.play();
gameoverSound.stop();
dingSound.stop();
crashSound.stop();
}
showClouds();
}
// The model recognizing a sound will trigger this event
function gotResult(error, results) {
if (error) {
console.error(error);
return;
}
if (screen !== 1) return;
// The results are in an array ordered by confidence.
// console.log(results[0]);
if (results[0].confidence > 0.5) {
label = results[0].label;
if (results[0].label !== 'Background Noise') {
// displayLabel = label;
// fill('green');
if (results[0].label === emojiNames[currentEmojiIndex]) {
score = score + 1;
// Play success sound
dingSound.play();
introSound.stop();
gameoverSound.stop();
crashSound.stop();
displayLabelColor = lightBlue;
} else {
displayLabelColor = 'white'
}
} else {
displayLabelColor = 'white'
}
}
}
function touchStarted() {
if (getAudioContext().state !== 'running') {
getAudioContext().resume();
}
}