/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Happiness Bar Class var HappinessBar = Container.expand(function () { var self = Container.call(this); // Attach background self.bg = self.attachAsset('happyBarBg', { anchorX: 0, anchorY: 0.5 }); // Attach fill self.fill = self.attachAsset('happyBarFill', { anchorX: 0, anchorY: 0.5 }); // Set value (0-100) self.setValue = function (val) { if (val < 0) val = 0; if (val > 100) val = 100; self.value = val; self.fill.width = 8 * val; }; // Set initial value self.setValue(100); return self; }); /**** * Game Data ****/ // Each scenario: { text: String, options: [ { text: String, happiness: Number, next: Number|null, ending: String|null } ] } // If next is null and ending is not null, it's an ending. // Option Button Class var OptionButton = Container.expand(function () { var self = Container.call(this); // Default state self.selected = false; self.disabled = false; // Attach background self.bg = self.attachAsset('optionBtn', { anchorX: 0.5, anchorY: 0.5 }); // Attach text self.label = new Text2('', { size: 70, fill: 0x222222, wordWrap: true, wordWrapWidth: 1100 }); self.label.anchor.set(0.5, 0.5); self.addChild(self.label); // Set label text self.setText = function (txt) { self.label.setText(txt); }; // Set selected state self.setSelected = function (selected) { self.selected = selected; if (self.selected) { self.bg.assetId = 'optionBtnSelected'; self.bg.setAsset('optionBtnSelected'); } else { self.bg.assetId = 'optionBtn'; self.bg.setAsset('optionBtn'); } }; // Set disabled state self.setDisabled = function (disabled) { self.disabled = disabled; if (self.disabled) { self.bg.assetId = 'optionBtnDisabled'; self.bg.setAsset('optionBtnDisabled'); } else { self.setSelected(self.selected); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xfafafa }); /**** * Game Code ****/ // Background music (loops) // Sound for scenario transition // Sound for incorrect choice // Sound for correct choice // If next is null and ending is not null, it's an ending. // Each scenario: { text: String, options: [ { text: String, happiness: Number, next: Number|null, ending: String|null } ] } /**** * Game Data ****/ // Happiness bar fill // Happiness bar background // Option button (disabled) // Option button (selected) // Option button // Character: The girl // Game state var scenarios = [{ text: "It's the first day of high school. The girl feels nervous and alone. What should she do?", options: [{ text: "Try to talk to a classmate and make a friend.", happiness: +10, next: 1 }, { text: "Stay quiet and hope someone approaches her.", happiness: -5, next: 2 }, { text: "Skip class and go home.", happiness: -20, next: null, ending: "She misses important introductions and feels even more isolated. Her happiness drops." }] }, { text: "She made a new friend! But now she has a lot of homework and her friend invites her out.", options: [{ text: "Go out with her friend and do homework later.", happiness: +5, next: 3 }, { text: "Politely decline and focus on homework.", happiness: +0, next: 4 }, { text: "Lie to her parents and sneak out.", happiness: -10, next: null, ending: "Her parents find out and she loses their trust. She feels guilty." }] }, { text: "She waits, but no one talks to her. She feels sad. What should she do next?", options: [{ text: "Try to join a club after school.", happiness: +10, next: 5 }, { text: "Go home and cry.", happiness: -10, next: null, ending: "She feels alone and her confidence drops." }] }, { text: "She had fun with her friend, but now it's late and homework isn't done.", options: [{ text: "Stay up late to finish homework.", happiness: -5, next: 6 }, { text: "Go to bed and hope for the best.", happiness: -10, next: null, ending: "She gets in trouble at school for not doing homework." }] }, { text: "She finishes her homework and feels accomplished, but her friend is upset.", options: [{ text: "Explain to her friend why homework was important.", happiness: +5, next: 7 }, { text: "Ignore her friend's feelings.", happiness: -10, next: null, ending: "Her friend feels hurt and distances herself." }] }, { text: "She joins a club and meets new people. She feels happier.", options: [{ text: "Continue attending the club.", happiness: +10, next: 7 }, { text: "Quit after one day.", happiness: -10, next: null, ending: "She misses out on new friendships." }] }, { text: "She is tired the next day and can't focus in class.", options: [{ text: "Ask the teacher for help.", happiness: +5, next: 7 }, { text: "Try to get through the day alone.", happiness: -5, next: null, ending: "She struggles and feels overwhelmed." }] }, { text: "Her parents notice she's stressed. They ask if she's okay.", options: [{ text: "Open up to her parents.", happiness: +10, next: null, ending: "Her parents support her and she feels loved. She is happy!" }, { text: "Keep her feelings to herself.", happiness: -10, next: null, ending: "She feels alone, but hopes things will get better." }] }]; var currentScenario = 0; var happiness = 100; var optionButtons = []; var scenarioText = null; var girlSprite = null; var happinessBar = null; var endingText = null; var canSelect = true; // Add girl sprite (centered horizontally, upper part of screen) girlSprite = LK.getAsset('girl', { anchorX: 0.5, anchorY: 0, x: 2048 / 2, y: 180 }); game.addChild(girlSprite); // Add scenario text (centered, below girl) scenarioText = new Text2('', { size: 80, fill: 0x333333, wordWrap: true, wordWrapWidth: 1800 }); scenarioText.anchor.set(0.5, 0); scenarioText.x = 2048 / 2; scenarioText.y = 180 + girlSprite.height + 60; game.addChild(scenarioText); // Add happiness bar (centered, above girl) happinessBar = new HappinessBar(); happinessBar.x = (2048 - 800) / 2; happinessBar.y = 120; game.addChild(happinessBar); // Add happiness label var happyLabel = new Text2('Happiness', { size: 48, fill: 0x666666 }); happyLabel.anchor.set(0.5, 1); happyLabel.x = 2048 / 2; happyLabel.y = happinessBar.y - 10; game.addChild(happyLabel); // Add option buttons (max 3 per scenario) for (var i = 0; i < 3; i++) { var btn = new OptionButton(); btn.x = 2048 / 2; btn.y = 1200 + i * 260; btn.visible = false; (function (idx) { btn.down = function (x, y, obj) { if (!canSelect || btn.disabled) return; selectOption(idx); }; })(i); game.addChild(btn); optionButtons.push(btn); } // Add ending text (hidden by default) endingText = new Text2('', { size: 90, fill: 0xD32F2F, wordWrap: true, wordWrapWidth: 1800 }); endingText.anchor.set(0.5, 0.5); endingText.x = 2048 / 2; endingText.y = 2732 / 2; endingText.visible = false; game.addChild(endingText); // Show scenario function showScenario(idx) { canSelect = true; endingText.visible = false; var sc = scenarios[idx]; scenarioText.setText(sc.text); // Show options for (var i = 0; i < optionButtons.length; i++) { if (sc.options[i]) { optionButtons[i].visible = true; optionButtons[i].setText(sc.options[i].text); optionButtons[i].setSelected(false); optionButtons[i].setDisabled(false); } else { optionButtons[i].visible = false; } } } // Handle option selection function selectOption(optIdx) { canSelect = false; var sc = scenarios[currentScenario]; var opt = sc.options[optIdx]; // Animate button selection for (var i = 0; i < optionButtons.length; i++) { optionButtons[i].setDisabled(true); optionButtons[i].setSelected(i === optIdx); } // Play sound for correct/incorrect choice if (opt.happiness >= 0) { LK.getSound('choice_correct').play(); } else { LK.getSound('choice_wrong').play(); } // Animate happiness bar var newHappiness = happiness + opt.happiness; if (newHappiness > 100) newHappiness = 100; if (newHappiness < 0) newHappiness = 0; tween(happinessBar.fill, { width: 8 * newHappiness }, { duration: 400, easing: tween.cubicOut }); happiness = newHappiness; // Animate girl (flash color if happiness drops) if (opt.happiness < 0) { tween(girlSprite, { tint: 0xd32f2f }, { duration: 200, onFinish: function onFinish() { tween(girlSprite, { tint: 0xf7b6d2 }, { duration: 400 }); } }); } else if (opt.happiness > 0) { tween(girlSprite, { tint: 0x81c784 }, { duration: 200, onFinish: function onFinish() { tween(girlSprite, { tint: 0xf7b6d2 }, { duration: 400 }); } }); } // After short delay, go to next scenario or ending LK.setTimeout(function () { // Play scenario transition sound if not ending if (!opt.ending) { LK.getSound('scenario_next').play(); } if (opt.ending) { showEnding(opt.ending); } else if (opt.next !== undefined && opt.next !== null) { currentScenario = opt.next; showScenario(currentScenario); } else { // No next, no ending: treat as ending showEnding("The story ends here."); } }, 700); } // Show ending function showEnding(txt) { for (var i = 0; i < optionButtons.length; i++) { optionButtons[i].visible = false; } scenarioText.setText(''); endingText.setText(txt + "\n\nFinal Happiness: " + happiness); endingText.visible = true; // Stop background music LK.stopMusic(); // If happiness is high, show win, else show game over LK.setTimeout(function () { if (happiness >= 60) { LK.showYouWin(); } else { LK.showGameOver(); } }, 1800); } // Start game function startGame() { currentScenario = 0; happiness = 100; happinessBar.setValue(happiness); girlSprite.tint = 0xf7b6d2; showScenario(currentScenario); // Play background music (looping) LK.playMusic('bgm_story'); } startGame(); // No dragging or move events needed for this game // Update happiness bar value every frame (in case of tween) game.update = function () { // Clamp fill width if (happinessBar.fill.width < 0) happinessBar.fill.width = 0; if (happinessBar.fill.width > 800) happinessBar.fill.width = 800; // Optionally, could animate other things here };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Happiness Bar Class
var HappinessBar = Container.expand(function () {
var self = Container.call(this);
// Attach background
self.bg = self.attachAsset('happyBarBg', {
anchorX: 0,
anchorY: 0.5
});
// Attach fill
self.fill = self.attachAsset('happyBarFill', {
anchorX: 0,
anchorY: 0.5
});
// Set value (0-100)
self.setValue = function (val) {
if (val < 0) val = 0;
if (val > 100) val = 100;
self.value = val;
self.fill.width = 8 * val;
};
// Set initial value
self.setValue(100);
return self;
});
/****
* Game Data
****/
// Each scenario: { text: String, options: [ { text: String, happiness: Number, next: Number|null, ending: String|null } ] }
// If next is null and ending is not null, it's an ending.
// Option Button Class
var OptionButton = Container.expand(function () {
var self = Container.call(this);
// Default state
self.selected = false;
self.disabled = false;
// Attach background
self.bg = self.attachAsset('optionBtn', {
anchorX: 0.5,
anchorY: 0.5
});
// Attach text
self.label = new Text2('', {
size: 70,
fill: 0x222222,
wordWrap: true,
wordWrapWidth: 1100
});
self.label.anchor.set(0.5, 0.5);
self.addChild(self.label);
// Set label text
self.setText = function (txt) {
self.label.setText(txt);
};
// Set selected state
self.setSelected = function (selected) {
self.selected = selected;
if (self.selected) {
self.bg.assetId = 'optionBtnSelected';
self.bg.setAsset('optionBtnSelected');
} else {
self.bg.assetId = 'optionBtn';
self.bg.setAsset('optionBtn');
}
};
// Set disabled state
self.setDisabled = function (disabled) {
self.disabled = disabled;
if (self.disabled) {
self.bg.assetId = 'optionBtnDisabled';
self.bg.setAsset('optionBtnDisabled');
} else {
self.setSelected(self.selected);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xfafafa
});
/****
* Game Code
****/
// Background music (loops)
// Sound for scenario transition
// Sound for incorrect choice
// Sound for correct choice
// If next is null and ending is not null, it's an ending.
// Each scenario: { text: String, options: [ { text: String, happiness: Number, next: Number|null, ending: String|null } ] }
/****
* Game Data
****/
// Happiness bar fill
// Happiness bar background
// Option button (disabled)
// Option button (selected)
// Option button
// Character: The girl
// Game state
var scenarios = [{
text: "It's the first day of high school. The girl feels nervous and alone. What should she do?",
options: [{
text: "Try to talk to a classmate and make a friend.",
happiness: +10,
next: 1
}, {
text: "Stay quiet and hope someone approaches her.",
happiness: -5,
next: 2
}, {
text: "Skip class and go home.",
happiness: -20,
next: null,
ending: "She misses important introductions and feels even more isolated. Her happiness drops."
}]
}, {
text: "She made a new friend! But now she has a lot of homework and her friend invites her out.",
options: [{
text: "Go out with her friend and do homework later.",
happiness: +5,
next: 3
}, {
text: "Politely decline and focus on homework.",
happiness: +0,
next: 4
}, {
text: "Lie to her parents and sneak out.",
happiness: -10,
next: null,
ending: "Her parents find out and she loses their trust. She feels guilty."
}]
}, {
text: "She waits, but no one talks to her. She feels sad. What should she do next?",
options: [{
text: "Try to join a club after school.",
happiness: +10,
next: 5
}, {
text: "Go home and cry.",
happiness: -10,
next: null,
ending: "She feels alone and her confidence drops."
}]
}, {
text: "She had fun with her friend, but now it's late and homework isn't done.",
options: [{
text: "Stay up late to finish homework.",
happiness: -5,
next: 6
}, {
text: "Go to bed and hope for the best.",
happiness: -10,
next: null,
ending: "She gets in trouble at school for not doing homework."
}]
}, {
text: "She finishes her homework and feels accomplished, but her friend is upset.",
options: [{
text: "Explain to her friend why homework was important.",
happiness: +5,
next: 7
}, {
text: "Ignore her friend's feelings.",
happiness: -10,
next: null,
ending: "Her friend feels hurt and distances herself."
}]
}, {
text: "She joins a club and meets new people. She feels happier.",
options: [{
text: "Continue attending the club.",
happiness: +10,
next: 7
}, {
text: "Quit after one day.",
happiness: -10,
next: null,
ending: "She misses out on new friendships."
}]
}, {
text: "She is tired the next day and can't focus in class.",
options: [{
text: "Ask the teacher for help.",
happiness: +5,
next: 7
}, {
text: "Try to get through the day alone.",
happiness: -5,
next: null,
ending: "She struggles and feels overwhelmed."
}]
}, {
text: "Her parents notice she's stressed. They ask if she's okay.",
options: [{
text: "Open up to her parents.",
happiness: +10,
next: null,
ending: "Her parents support her and she feels loved. She is happy!"
}, {
text: "Keep her feelings to herself.",
happiness: -10,
next: null,
ending: "She feels alone, but hopes things will get better."
}]
}];
var currentScenario = 0;
var happiness = 100;
var optionButtons = [];
var scenarioText = null;
var girlSprite = null;
var happinessBar = null;
var endingText = null;
var canSelect = true;
// Add girl sprite (centered horizontally, upper part of screen)
girlSprite = LK.getAsset('girl', {
anchorX: 0.5,
anchorY: 0,
x: 2048 / 2,
y: 180
});
game.addChild(girlSprite);
// Add scenario text (centered, below girl)
scenarioText = new Text2('', {
size: 80,
fill: 0x333333,
wordWrap: true,
wordWrapWidth: 1800
});
scenarioText.anchor.set(0.5, 0);
scenarioText.x = 2048 / 2;
scenarioText.y = 180 + girlSprite.height + 60;
game.addChild(scenarioText);
// Add happiness bar (centered, above girl)
happinessBar = new HappinessBar();
happinessBar.x = (2048 - 800) / 2;
happinessBar.y = 120;
game.addChild(happinessBar);
// Add happiness label
var happyLabel = new Text2('Happiness', {
size: 48,
fill: 0x666666
});
happyLabel.anchor.set(0.5, 1);
happyLabel.x = 2048 / 2;
happyLabel.y = happinessBar.y - 10;
game.addChild(happyLabel);
// Add option buttons (max 3 per scenario)
for (var i = 0; i < 3; i++) {
var btn = new OptionButton();
btn.x = 2048 / 2;
btn.y = 1200 + i * 260;
btn.visible = false;
(function (idx) {
btn.down = function (x, y, obj) {
if (!canSelect || btn.disabled) return;
selectOption(idx);
};
})(i);
game.addChild(btn);
optionButtons.push(btn);
}
// Add ending text (hidden by default)
endingText = new Text2('', {
size: 90,
fill: 0xD32F2F,
wordWrap: true,
wordWrapWidth: 1800
});
endingText.anchor.set(0.5, 0.5);
endingText.x = 2048 / 2;
endingText.y = 2732 / 2;
endingText.visible = false;
game.addChild(endingText);
// Show scenario
function showScenario(idx) {
canSelect = true;
endingText.visible = false;
var sc = scenarios[idx];
scenarioText.setText(sc.text);
// Show options
for (var i = 0; i < optionButtons.length; i++) {
if (sc.options[i]) {
optionButtons[i].visible = true;
optionButtons[i].setText(sc.options[i].text);
optionButtons[i].setSelected(false);
optionButtons[i].setDisabled(false);
} else {
optionButtons[i].visible = false;
}
}
}
// Handle option selection
function selectOption(optIdx) {
canSelect = false;
var sc = scenarios[currentScenario];
var opt = sc.options[optIdx];
// Animate button selection
for (var i = 0; i < optionButtons.length; i++) {
optionButtons[i].setDisabled(true);
optionButtons[i].setSelected(i === optIdx);
}
// Play sound for correct/incorrect choice
if (opt.happiness >= 0) {
LK.getSound('choice_correct').play();
} else {
LK.getSound('choice_wrong').play();
}
// Animate happiness bar
var newHappiness = happiness + opt.happiness;
if (newHappiness > 100) newHappiness = 100;
if (newHappiness < 0) newHappiness = 0;
tween(happinessBar.fill, {
width: 8 * newHappiness
}, {
duration: 400,
easing: tween.cubicOut
});
happiness = newHappiness;
// Animate girl (flash color if happiness drops)
if (opt.happiness < 0) {
tween(girlSprite, {
tint: 0xd32f2f
}, {
duration: 200,
onFinish: function onFinish() {
tween(girlSprite, {
tint: 0xf7b6d2
}, {
duration: 400
});
}
});
} else if (opt.happiness > 0) {
tween(girlSprite, {
tint: 0x81c784
}, {
duration: 200,
onFinish: function onFinish() {
tween(girlSprite, {
tint: 0xf7b6d2
}, {
duration: 400
});
}
});
}
// After short delay, go to next scenario or ending
LK.setTimeout(function () {
// Play scenario transition sound if not ending
if (!opt.ending) {
LK.getSound('scenario_next').play();
}
if (opt.ending) {
showEnding(opt.ending);
} else if (opt.next !== undefined && opt.next !== null) {
currentScenario = opt.next;
showScenario(currentScenario);
} else {
// No next, no ending: treat as ending
showEnding("The story ends here.");
}
}, 700);
}
// Show ending
function showEnding(txt) {
for (var i = 0; i < optionButtons.length; i++) {
optionButtons[i].visible = false;
}
scenarioText.setText('');
endingText.setText(txt + "\n\nFinal Happiness: " + happiness);
endingText.visible = true;
// Stop background music
LK.stopMusic();
// If happiness is high, show win, else show game over
LK.setTimeout(function () {
if (happiness >= 60) {
LK.showYouWin();
} else {
LK.showGameOver();
}
}, 1800);
}
// Start game
function startGame() {
currentScenario = 0;
happiness = 100;
happinessBar.setValue(happiness);
girlSprite.tint = 0xf7b6d2;
showScenario(currentScenario);
// Play background music (looping)
LK.playMusic('bgm_story');
}
startGame();
// No dragging or move events needed for this game
// Update happiness bar value every frame (in case of tween)
game.update = function () {
// Clamp fill width
if (happinessBar.fill.width < 0) happinessBar.fill.width = 0;
if (happinessBar.fill.width > 800) happinessBar.fill.width = 800;
// Optionally, could animate other things here
};