diff --git a/assets/emotes/boo.png b/assets/emotes/boo.png new file mode 100644 index 0000000..746814c Binary files /dev/null and b/assets/emotes/boo.png differ diff --git a/assets/emotes/grumpy.png b/assets/emotes/grumpy.png new file mode 100644 index 0000000..1e5f9e2 Binary files /dev/null and b/assets/emotes/grumpy.png differ diff --git a/assets/emotes/laugh.png b/assets/emotes/laugh.png new file mode 100644 index 0000000..d1bb5d1 Binary files /dev/null and b/assets/emotes/laugh.png differ diff --git a/assets/emotes/sad.png b/assets/emotes/sad.png new file mode 100644 index 0000000..f422d17 Binary files /dev/null and b/assets/emotes/sad.png differ diff --git a/assets/emotes/smile.png b/assets/emotes/smile.png new file mode 100644 index 0000000..c502aa8 Binary files /dev/null and b/assets/emotes/smile.png differ diff --git a/assets/emotes/surprised.png b/assets/emotes/surprised.png new file mode 100644 index 0000000..1d35361 Binary files /dev/null and b/assets/emotes/surprised.png differ diff --git a/assets/emotes/wave.png b/assets/emotes/wave.png new file mode 100644 index 0000000..f4ad273 Binary files /dev/null and b/assets/emotes/wave.png differ diff --git a/assets/emotes/yelling.png b/assets/emotes/yelling.png new file mode 100644 index 0000000..ca73d00 Binary files /dev/null and b/assets/emotes/yelling.png differ diff --git a/assets/speech-bubbles.aseprite b/assets/speech-bubbles.aseprite index 893956d..8de4516 100644 Binary files a/assets/speech-bubbles.aseprite and b/assets/speech-bubbles.aseprite differ diff --git a/ideas.txt b/ideas.txt index 832fb51..01b6073 100644 --- a/ideas.txt +++ b/ideas.txt @@ -66,4 +66,3 @@ A: grumpy B: grumpy - If it goes down the negative branch, set both fish moods to unhappy. - If it goes down the positive branch, set both fish moods to happy. - diff --git a/src/actions.js b/src/actions.js index e2d0d5a..a081625 100644 --- a/src/actions.js +++ b/src/actions.js @@ -39,6 +39,8 @@ export default class ActionManager { case 'flip': fish.flipOverride = action.value; break; + case 'mood': + fish.updateMood(action.value, true); } } diff --git a/src/chats.js b/src/chats.js new file mode 100644 index 0000000..7b7bb41 --- /dev/null +++ b/src/chats.js @@ -0,0 +1,138 @@ +let pleasantChat = { + description: "FISH1 and FISH2 are having a nice chat.", + start: ['wave', 'wave', 'smile'], + positive: ['smile', 'happy', 'heart', 'A-happy', 'B-happy'], + negative: ['angry', 'surprised', 'grumpy', 'A-unhappy'], + isPositive: function (fish1, fish2) { + return Math.random() < 0.8; + }, +}; +let prankChat = { + description: "FISH1 is playing a prank on FISH2!", + start: ['boo', 'shocked', 'laugh'], + positive: ['laugh', 'heart', 'heart', 'A-happy', 'B-happy'], + negative: ['angry', 'surprised', 'grumpy', 'B-unhappy'], + isPositive: function (fish1, fish2) { + if (!fish2.goodMood) { + return Math.random() < 0.3; + } + return Math.random() < 0.6; + }, +}; +let cheerUpChat = { + description: "FISH1 is trying to cheer FISH2 up.", + start: ['smile', 'grumpy', 'heart'], + positive: ['heart', 'happy', 'smile', 'B-happy'], + negative: ['angry', 'surprised', 'grumpy'], + isPositive: function (fish1, fish2) { + return Math.random() < 0.7; + }, +}; +let argumentChat = { + description: "FISH1 and FISH2 are arguing about something...", + start: ['yelling', 'angry', 'angry'], + positive: ['sad', 'heart', 'heart', 'A-happy', 'B-happy'], + negative: ['yelling', 'grumpy', 'grumpy', 'A-unhappy', 'B-unhappy'], + isPositive: function (fish1, fish2) { + if (!fish1.goodMood && !fish2.goodMood) { + return false; + } + if (fish1.goodMood && fish2.goodMood) { + return Math.random() < 0.5; + } + return Math.random() < 0.3; + } +}; + +export default function generateChatScripts(fish1, fish2) { + console.log(`${fish1.name} is feeling ${fish1.mood}`); + console.log(`${fish2.name} is feeling ${fish2.mood}`); + + // Choose which chat the fish will have + let chat = null; + let chance = Math.random(); + if (fish1.goodMood && fish2.goodMood) { + // Both fish are in a good mood + if (chance < 0.6) { + chat = pleasantChat; + } else if (chance < 0.9) { + chat = prankChat; + } else { + chat = argumentChat; + } + } else if (fish1.goodMood && !fish2.goodMood) { + // Only first fish is in a good mood + if (chance < 0.7) { + chat = cheerUpChat; + } else if (chance < 0.8) { + chat = pleasantChat; + } else if (chance < 0.9) { + chat = argumentChat; + } else { + chat = prankChat; + } + } else if (!fish1.goodMood && !fish2.goodMood) { + // Both fish are in a bad mood + if (chance < 0.8) { + chat = argumentChat; + } else if (chance < 0.9) { + chat = prankChat; + } else { + chat = pleasantChat; + } + } else { + // Only second fish is in a good mood + if (chance < 0.5) { + chat = argumentChat; + } else if (chance < 0.9) { + chat = pleasantChat; + } else { + chat = prankChat; + } + } + + // Determine whether the chat is positive or negative + let isPositive = chat.isPositive(fish1, fish2); + + // Concatenate the script cues + let cues = chat.start; + if (isPositive) { + cues = cues.concat(chat.positive); + } else { + cues = cues.concat(chat.negative); + } + + // Construct the two actual scripts + let scriptA = []; + let scriptB = []; + let flagA = true; + for(let cue of cues) { + let action = {}; + if (cue.includes("-")) { + action.type = "mood"; + action.value = cue.includes("-happy"); + action.duration = 0; + if (cue.includes("A-")) { + scriptA.push(action); + } else { + scriptB.push(action); + } + } else { + action.type = "emote"; + action.value = cue; + action.duration = 3000; + if (flagA) { + scriptA.push(action); + } else { + scriptB.push(action); + } + flagA = !flagA; + } + } + + return { + record: chat.description, + scriptA, + scriptB, + }; +} diff --git a/src/fish.js b/src/fish.js index 93edeed..35a93e3 100644 --- a/src/fish.js +++ b/src/fish.js @@ -21,7 +21,8 @@ export default class Fish { this.selected = false; // Personal information about this fish - this.name = randomFishName(); + this.name = randomFishName(); + this.updateMood(Math.random() > 0.5); } setRandomVelocity() { @@ -230,4 +231,19 @@ export default class Fish { this.action = false; this.flipOverride = null; } + + updateMood (goodMood, addRecord) { + let goodMoods = ["cheerful", "jovial", "happy", "great"]; + let badMoods = ["grumpy", "upset", "moody", "down"]; + this.goodMood = goodMood; + if (goodMood) { + this.mood = goodMoods[randomIntFromInterval(0, goodMoods.length-1)]; + } else { + this.mood = badMoods[randomIntFromInterval(0, badMoods.length-1)]; + } + + if (addRecord) { + uiManager.addRecord(`FISH1 is feeling ${this.mood}.`, this); + } + } } diff --git a/src/main.js b/src/main.js index ced9de2..7707e83 100644 --- a/src/main.js +++ b/src/main.js @@ -17,6 +17,13 @@ window.emoteImages = { happy: null, sleepy: null, angry: null, + grumpy: null, + wave: null, + smile: null, + surprised: null, + yelling: null, + boo: null, + sad: null, }; window.foodImages = { broccoli: null, diff --git a/src/routines.js b/src/routines.js index 0c506e9..db6bba4 100644 --- a/src/routines.js +++ b/src/routines.js @@ -1,12 +1,12 @@ import { states as fishStates } from './fish.js'; +import generateChatScripts from './chats.js'; export const SCRIPTS = { happy: [ { type: 'emote', value: 'happy', duration: 3000 }, // Set emote to happy, wait 3s { type: 'emote', value: null, duration: 1000 }, // Set emote to nothing, wait 3s - { type: 'state', value: fishStates.IDLING, duration: 1000 }, // Set state to idling - { type: 'state', value: fishStates.BOIDING, duration: 0 }, // Set state to boiding, go to next action { type: 'emote', value: 'heart', duration: 3000 }, // Set emote to heart, wait 3s + { type: 'mood', value: true, duration: 0}, // Set mood to happy ], moveToCorner: [ { type: 'state', value: fishStates.MOVING, duration: 4000, moveto: {x: 500, y: 500} }, @@ -119,6 +119,8 @@ export default class RoutineManager { indexB = randomIntFromInterval(0, filteredFish.length-1); } while (indexB == indexA); + console.log(generateChatScripts(filteredFish[indexA], filteredFish[indexB])); + // Choose two random conversation scripts let scriptA = JSON.parse(JSON.stringify(SCRIPTS.chat1[0])); let scriptB = JSON.parse(JSON.stringify(SCRIPTS.chat1[1])); @@ -149,7 +151,7 @@ export default class RoutineManager { ); // Add record - uiManager.addRecord(`FISH1 and FISH2 are having a nice chat!`, filteredFish[indexA], filteredFish[indexB]); + uiManager.addRecord("FISH1 and FISH2 are having a nice chat!", filteredFish[indexA], filteredFish[indexB]); }); } } diff --git a/src/ui.js b/src/ui.js index 461a630..d193548 100644 --- a/src/ui.js +++ b/src/ui.js @@ -40,11 +40,11 @@ export default class UIManager { fishImage.src = `assets/fish/fish${fish.type}.png`; // Create paragraphs for the name and personality - let nameParagraph = document.createElement("p"); - nameParagraph.innerHTML = `Name: ${fish.name}`; + let fishInfo = document.createElement("div"); + fishInfo.innerHTML = `Name: ${fish.name}
Mood: ${fish.mood}`; fishDiv.appendChild(fishImage); - fishDiv.appendChild(nameParagraph); + fishDiv.appendChild(fishInfo); // Add it to the selected fish div selectedFishDiv.appendChild(fishDiv);