/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Apple class
var Apple = Container.expand(function () {
var self = Container.call(this);
var appleAsset = self.attachAsset('apple', {
anchorX: 0.5,
anchorY: 1
});
self.isSalty = false;
return self;
});
// Bird class
var Bird = Container.expand(function () {
var self = Container.call(this);
// Attach asset based on self.birdType
var birdAsset = null;
if (self.birdType === 1) {
birdAsset = self.attachAsset('bird1', {
anchorX: 0.5,
anchorY: 1
});
} else if (self.birdType === 2) {
birdAsset = self.attachAsset('bird2', {
anchorX: 0.5,
anchorY: 1
});
} else {
birdAsset = self.attachAsset('bird3', {
anchorX: 0.5,
anchorY: 1
});
}
// Speech bubble
self.bubble = self.addChild(LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 1,
y: -160,
x: 0,
scaleX: 1,
scaleY: 1
}));
self.bubble.visible = false;
self.bubbleText = new Text2('', {
size: 48,
fill: '#222222'
});
self.bubbleText.anchor.set(0.5, 1);
self.bubbleText.x = 0;
self.bubbleText.y = -30;
self.bubble.addChild(self.bubbleText);
// Show speech
self.say = function (text, duration) {
self.bubble.visible = true;
self.bubbleText.setText(text);
if (duration) {
LK.setTimeout(function () {
self.bubble.visible = false;
}, duration);
}
};
// Hide speech
self.hideSpeech = function () {
self.bubble.visible = false;
};
// Animate jump
self.jump = function (cb) {
tween(self, {
y: self.y - 120
}, {
duration: 180,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 120
}, {
duration: 220,
easing: tween.cubicIn,
onFinish: cb
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf7e9b0
});
/****
* Game Code
****/
// Speech bubble
// Desert ground
// Apple asset
// Bird assets: 3 birds, each a different color and shape
// Game state
var birds = [];
var apple = null;
var ground = null;
var currentTurn = 0; // 0,1,2 for birds
var phase = 0; // 0: intro, 1: arguing, 2: action, 3: reveal, 4: end
var choices = [["I saw it first!", "I'm the hungriest!", "I can sing for it!"], ["Let's share!", "No way, it's mine!", "Rock-paper-scissors?"], ["Fine, you take it.", "I'm not giving up!", "Let's race for it!"]];
var selectedChoices = [null, null, null];
var winner = null;
var saltyRevealDone = false;
// Add desert ground
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 1,
x: 0,
y: 2732
});
game.addChild(ground);
// Add birds
var birdPositions = [600, 1024, 1448];
for (var i = 0; i < 3; i++) {
var b = new Bird();
b.birdType = i + 1;
b.x = birdPositions[i];
b.y = 2732 - 300;
birds.push(b);
game.addChild(b);
}
// Add apple in the center, slightly above ground
apple = new Apple();
apple.x = 1024;
apple.y = 2732 - 300 - 40;
game.addChild(apple);
// Title text
var titleText = new Text2("The Last Apple", {
size: 120,
fill: '#c0392b'
});
titleText.anchor.set(0.5, 0);
titleText.x = 1024;
titleText.y = 80;
LK.gui.top.addChild(titleText);
// Instruction text
var instrText = new Text2("Help the birds decide who gets the apple!", {
size: 64,
fill: '#333333'
});
instrText.anchor.set(0.5, 0);
instrText.x = 1024;
instrText.y = 220;
LK.gui.top.addChild(instrText);
// Choice buttons
var choiceButtons = [];
function showChoices(birdIdx) {
// Remove old buttons
for (var i = 0; i < choiceButtons.length; i++) {
if (choiceButtons[i].parent) {
LK.gui.bottom.removeChild(choiceButtons[i]);
}
}
choiceButtons = [];
// Show 3 choices for this bird
for (var j = 0; j < 3; j++) {
var btn = new Text2(choices[birdIdx][j], {
size: 60,
fill: '#222222'
});
btn.anchor.set(0.5, 0.5);
btn.x = 512 + j * 512;
btn.y = 100;
btn.bg = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 0.7
});
btn.addChild(btn.bg);
btn.bg.zIndex = -1;
btn.zIndex = 1;
// Touch/click handler
(function (idx, choiceIdx) {
btn.down = function (x, y, obj) {
selectChoice(idx, choiceIdx);
};
})(birdIdx, j);
LK.gui.bottom.addChild(btn);
choiceButtons.push(btn);
}
}
// Select a choice for a bird
function selectChoice(birdIdx, choiceIdx) {
selectedChoices[birdIdx] = choiceIdx;
birds[birdIdx].say(choices[birdIdx][choiceIdx], 1200);
// Animate bird
birds[birdIdx].jump(function () {
// Next turn or next phase
if (birdIdx < 2) {
currentTurn++;
showChoices(currentTurn);
} else {
// All birds have chosen, move to action phase
phase = 2;
LK.setTimeout(startActionPhase, 900);
}
});
// Remove buttons
for (var i = 0; i < choiceButtons.length; i++) {
if (choiceButtons[i].parent) {
LK.gui.bottom.removeChild(choiceButtons[i]);
}
}
choiceButtons = [];
}
// Start the action phase: birds act out their choices
function startActionPhase() {
// Each bird acts in turn
var actIdx = 0;
function nextAct() {
if (actIdx >= 3) {
// All acted, pick winner
phase = 3;
LK.setTimeout(revealSaltyApple, 900);
return;
}
var b = birds[actIdx];
var c = selectedChoices[actIdx];
// Animate based on choice
if (c === 0) {
// First option: move toward apple
tween(b, {
x: apple.x
}, {
duration: 400,
easing: tween.cubicInOut,
onFinish: function onFinish() {
b.say("Mine!", 900);
LK.setTimeout(function () {
actIdx++;
nextAct();
}, 900);
}
});
} else if (c === 1) {
// Second option: jump
b.say("No way!", 900);
b.jump(function () {
LK.setTimeout(function () {
actIdx++;
nextAct();
}, 900);
});
} else {
// Third option: shake
b.say("Let's go!", 900);
tween(b, {
rotation: 0.2
}, {
duration: 120,
onFinish: function onFinish() {
tween(b, {
rotation: -0.2
}, {
duration: 120,
onFinish: function onFinish() {
tween(b, {
rotation: 0
}, {
duration: 80,
onFinish: function onFinish() {
LK.setTimeout(function () {
actIdx++;
nextAct();
}, 900);
}
});
}
});
}
});
}
}
nextAct();
}
// Reveal the apple is salty!
function revealSaltyApple() {
if (saltyRevealDone) return;
saltyRevealDone = true;
// Pick a winner: random among birds who chose option 0 (move toward apple), else random
var candidates = [];
for (var i = 0; i < 3; i++) {
if (selectedChoices[i] === 0) candidates.push(i);
}
if (candidates.length === 0) {
candidates = [0, 1, 2];
}
winner = candidates[Math.floor(Math.random() * candidates.length)];
// Animate winner to apple
var b = birds[winner];
tween(b, {
x: apple.x
}, {
duration: 500,
easing: tween.cubicInOut,
onFinish: function onFinish() {
b.say("I got it!", 1000);
// Animate apple "bite"
LK.setTimeout(function () {
apple.isSalty = true;
// Show salty face
b.say("Yuck! It's salty!", 1800);
// Animate apple color to blue
tween(apple.children[0], {
tint: 0x5dade2
}, {
duration: 600
});
// Show other birds laughing
for (var i = 0; i < 3; i++) {
if (i !== winner) {
birds[i].say("Haha!", 1200);
}
}
// End
LK.setTimeout(showEnd, 2000);
}, 1000);
}
});
}
// Show end screen
function showEnd() {
phase = 4;
// Remove all speech
for (var i = 0; i < 3; i++) birds[i].hideSpeech();
// Show final message
var endText = new Text2("The real prize was laughter!\nPlay again for a new story.", {
size: 80,
fill: '#2d3436'
});
endText.anchor.set(0.5, 0.5);
endText.x = 1024;
endText.y = 900;
LK.gui.center.addChild(endText);
// Show "You Win" after a moment
LK.setTimeout(function () {
LK.showYouWin();
}, 2200);
}
// Start game: intro phase
function startGame() {
phase = 1;
currentTurn = 0;
selectedChoices = [null, null, null];
winner = null;
saltyRevealDone = false;
// Remove any end text
if (LK.gui.center.children.length > 0) {
for (var i = LK.gui.center.children.length - 1; i >= 0; i--) {
LK.gui.center.removeChild(LK.gui.center.children[i]);
}
}
// Reset birds and apple
for (var i = 0; i < 3; i++) {
birds[i].x = birdPositions[i];
birds[i].y = 2732 - 300;
birds[i].rotation = 0;
birds[i].hideSpeech();
}
apple.x = 1024;
apple.y = 2732 - 300 - 40;
apple.children[0].tint = 0xc0392b;
// Show first choices
showChoices(0);
}
// Restart on game reset
game.on('reset', function () {
startGame();
});
// Start game on load
startGame();
// No update loop needed, all is event-driven. /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Apple class
var Apple = Container.expand(function () {
var self = Container.call(this);
var appleAsset = self.attachAsset('apple', {
anchorX: 0.5,
anchorY: 1
});
self.isSalty = false;
return self;
});
// Bird class
var Bird = Container.expand(function () {
var self = Container.call(this);
// Attach asset based on self.birdType
var birdAsset = null;
if (self.birdType === 1) {
birdAsset = self.attachAsset('bird1', {
anchorX: 0.5,
anchorY: 1
});
} else if (self.birdType === 2) {
birdAsset = self.attachAsset('bird2', {
anchorX: 0.5,
anchorY: 1
});
} else {
birdAsset = self.attachAsset('bird3', {
anchorX: 0.5,
anchorY: 1
});
}
// Speech bubble
self.bubble = self.addChild(LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 1,
y: -160,
x: 0,
scaleX: 1,
scaleY: 1
}));
self.bubble.visible = false;
self.bubbleText = new Text2('', {
size: 48,
fill: '#222222'
});
self.bubbleText.anchor.set(0.5, 1);
self.bubbleText.x = 0;
self.bubbleText.y = -30;
self.bubble.addChild(self.bubbleText);
// Show speech
self.say = function (text, duration) {
self.bubble.visible = true;
self.bubbleText.setText(text);
if (duration) {
LK.setTimeout(function () {
self.bubble.visible = false;
}, duration);
}
};
// Hide speech
self.hideSpeech = function () {
self.bubble.visible = false;
};
// Animate jump
self.jump = function (cb) {
tween(self, {
y: self.y - 120
}, {
duration: 180,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 120
}, {
duration: 220,
easing: tween.cubicIn,
onFinish: cb
});
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf7e9b0
});
/****
* Game Code
****/
// Speech bubble
// Desert ground
// Apple asset
// Bird assets: 3 birds, each a different color and shape
// Game state
var birds = [];
var apple = null;
var ground = null;
var currentTurn = 0; // 0,1,2 for birds
var phase = 0; // 0: intro, 1: arguing, 2: action, 3: reveal, 4: end
var choices = [["I saw it first!", "I'm the hungriest!", "I can sing for it!"], ["Let's share!", "No way, it's mine!", "Rock-paper-scissors?"], ["Fine, you take it.", "I'm not giving up!", "Let's race for it!"]];
var selectedChoices = [null, null, null];
var winner = null;
var saltyRevealDone = false;
// Add desert ground
ground = LK.getAsset('ground', {
anchorX: 0,
anchorY: 1,
x: 0,
y: 2732
});
game.addChild(ground);
// Add birds
var birdPositions = [600, 1024, 1448];
for (var i = 0; i < 3; i++) {
var b = new Bird();
b.birdType = i + 1;
b.x = birdPositions[i];
b.y = 2732 - 300;
birds.push(b);
game.addChild(b);
}
// Add apple in the center, slightly above ground
apple = new Apple();
apple.x = 1024;
apple.y = 2732 - 300 - 40;
game.addChild(apple);
// Title text
var titleText = new Text2("The Last Apple", {
size: 120,
fill: '#c0392b'
});
titleText.anchor.set(0.5, 0);
titleText.x = 1024;
titleText.y = 80;
LK.gui.top.addChild(titleText);
// Instruction text
var instrText = new Text2("Help the birds decide who gets the apple!", {
size: 64,
fill: '#333333'
});
instrText.anchor.set(0.5, 0);
instrText.x = 1024;
instrText.y = 220;
LK.gui.top.addChild(instrText);
// Choice buttons
var choiceButtons = [];
function showChoices(birdIdx) {
// Remove old buttons
for (var i = 0; i < choiceButtons.length; i++) {
if (choiceButtons[i].parent) {
LK.gui.bottom.removeChild(choiceButtons[i]);
}
}
choiceButtons = [];
// Show 3 choices for this bird
for (var j = 0; j < 3; j++) {
var btn = new Text2(choices[birdIdx][j], {
size: 60,
fill: '#222222'
});
btn.anchor.set(0.5, 0.5);
btn.x = 512 + j * 512;
btn.y = 100;
btn.bg = LK.getAsset('bubble', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 1.2,
scaleY: 0.7
});
btn.addChild(btn.bg);
btn.bg.zIndex = -1;
btn.zIndex = 1;
// Touch/click handler
(function (idx, choiceIdx) {
btn.down = function (x, y, obj) {
selectChoice(idx, choiceIdx);
};
})(birdIdx, j);
LK.gui.bottom.addChild(btn);
choiceButtons.push(btn);
}
}
// Select a choice for a bird
function selectChoice(birdIdx, choiceIdx) {
selectedChoices[birdIdx] = choiceIdx;
birds[birdIdx].say(choices[birdIdx][choiceIdx], 1200);
// Animate bird
birds[birdIdx].jump(function () {
// Next turn or next phase
if (birdIdx < 2) {
currentTurn++;
showChoices(currentTurn);
} else {
// All birds have chosen, move to action phase
phase = 2;
LK.setTimeout(startActionPhase, 900);
}
});
// Remove buttons
for (var i = 0; i < choiceButtons.length; i++) {
if (choiceButtons[i].parent) {
LK.gui.bottom.removeChild(choiceButtons[i]);
}
}
choiceButtons = [];
}
// Start the action phase: birds act out their choices
function startActionPhase() {
// Each bird acts in turn
var actIdx = 0;
function nextAct() {
if (actIdx >= 3) {
// All acted, pick winner
phase = 3;
LK.setTimeout(revealSaltyApple, 900);
return;
}
var b = birds[actIdx];
var c = selectedChoices[actIdx];
// Animate based on choice
if (c === 0) {
// First option: move toward apple
tween(b, {
x: apple.x
}, {
duration: 400,
easing: tween.cubicInOut,
onFinish: function onFinish() {
b.say("Mine!", 900);
LK.setTimeout(function () {
actIdx++;
nextAct();
}, 900);
}
});
} else if (c === 1) {
// Second option: jump
b.say("No way!", 900);
b.jump(function () {
LK.setTimeout(function () {
actIdx++;
nextAct();
}, 900);
});
} else {
// Third option: shake
b.say("Let's go!", 900);
tween(b, {
rotation: 0.2
}, {
duration: 120,
onFinish: function onFinish() {
tween(b, {
rotation: -0.2
}, {
duration: 120,
onFinish: function onFinish() {
tween(b, {
rotation: 0
}, {
duration: 80,
onFinish: function onFinish() {
LK.setTimeout(function () {
actIdx++;
nextAct();
}, 900);
}
});
}
});
}
});
}
}
nextAct();
}
// Reveal the apple is salty!
function revealSaltyApple() {
if (saltyRevealDone) return;
saltyRevealDone = true;
// Pick a winner: random among birds who chose option 0 (move toward apple), else random
var candidates = [];
for (var i = 0; i < 3; i++) {
if (selectedChoices[i] === 0) candidates.push(i);
}
if (candidates.length === 0) {
candidates = [0, 1, 2];
}
winner = candidates[Math.floor(Math.random() * candidates.length)];
// Animate winner to apple
var b = birds[winner];
tween(b, {
x: apple.x
}, {
duration: 500,
easing: tween.cubicInOut,
onFinish: function onFinish() {
b.say("I got it!", 1000);
// Animate apple "bite"
LK.setTimeout(function () {
apple.isSalty = true;
// Show salty face
b.say("Yuck! It's salty!", 1800);
// Animate apple color to blue
tween(apple.children[0], {
tint: 0x5dade2
}, {
duration: 600
});
// Show other birds laughing
for (var i = 0; i < 3; i++) {
if (i !== winner) {
birds[i].say("Haha!", 1200);
}
}
// End
LK.setTimeout(showEnd, 2000);
}, 1000);
}
});
}
// Show end screen
function showEnd() {
phase = 4;
// Remove all speech
for (var i = 0; i < 3; i++) birds[i].hideSpeech();
// Show final message
var endText = new Text2("The real prize was laughter!\nPlay again for a new story.", {
size: 80,
fill: '#2d3436'
});
endText.anchor.set(0.5, 0.5);
endText.x = 1024;
endText.y = 900;
LK.gui.center.addChild(endText);
// Show "You Win" after a moment
LK.setTimeout(function () {
LK.showYouWin();
}, 2200);
}
// Start game: intro phase
function startGame() {
phase = 1;
currentTurn = 0;
selectedChoices = [null, null, null];
winner = null;
saltyRevealDone = false;
// Remove any end text
if (LK.gui.center.children.length > 0) {
for (var i = LK.gui.center.children.length - 1; i >= 0; i--) {
LK.gui.center.removeChild(LK.gui.center.children[i]);
}
}
// Reset birds and apple
for (var i = 0; i < 3; i++) {
birds[i].x = birdPositions[i];
birds[i].y = 2732 - 300;
birds[i].rotation = 0;
birds[i].hideSpeech();
}
apple.x = 1024;
apple.y = 2732 - 300 - 40;
apple.children[0].tint = 0xc0392b;
// Show first choices
showChoices(0);
}
// Restart on game reset
game.on('reset', function () {
startGame();
});
// Start game on load
startGame();
// No update loop needed, all is event-driven.