/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { richardMood: "sleeping", lastFed: 0 }); /**** * Classes ****/ // Fish (food) var Fish = Container.expand(function () { var self = Container.call(this); self.fishNode = self.attachAsset('fish', { anchorX: 0.5, anchorY: 0.5 }); self.plateNode = self.attachAsset('plate', { anchorX: 0.5, anchorY: 0.5, y: 60 }); self.x = 0; self.y = 0; self.isDragging = false; // Drag logic self.down = function (x, y, obj) { self.isDragging = true; dragNode = self; self.offsetX = self.x - x; self.offsetY = self.y - y; }; self.up = function (x, y, obj) { self.isDragging = false; dragNode = null; }; return self; }); // Richard the Falcon var Richard = Container.expand(function () { var self = Container.call(this); // State: 'sleeping', 'awake', 'eating', 'happy', 'grumpy' self.state = storage.richardMood || 'sleeping'; self.lastFed = storage.lastFed || 0; self.lastStateChange = LK.ticks; self.isInteracting = false; // Asset nodes self.richardNode = null; self.zzzNode = null; // Dialogue self.dialogue = new Text2('', { size: 80, fill: "#fff", font: "Tahoma" }); self.dialogue.anchor.set(0.5, 0); self.dialogue.x = 0; self.dialogue.y = 270; self.addChild(self.dialogue); // Helper: Set Richard's visual state self.setState = function (state) { if (self.richardNode) { self.removeChild(self.richardNode); self.richardNode.destroy(); self.richardNode = null; } if (self.zzzNode) { self.removeChild(self.zzzNode); self.zzzNode.destroy(); self.zzzNode = null; } self.state = state; storage.richardMood = state; if (state === 'sleeping') { self.richardNode = self.attachAsset('richard_sleep', { anchorX: 0.5, anchorY: 0.5 }); self.zzzNode = self.attachAsset('zzz', { anchorX: 0.5, anchorY: 0.5, x: 120, y: -180, scaleX: 1.2, scaleY: 1.2 }); self.dialogue.setText("Zzz... (Tap to wake Richard)"); } else if (state === 'awake') { self.richardNode = self.attachAsset('richard_awake', { anchorX: 0.5, anchorY: 0.5 }); self.dialogue.setText("What? I'm up. Where's my breakfast?"); } else if (state === 'eating') { self.richardNode = self.attachAsset('richard_eat', { anchorX: 0.5, anchorY: 0.5 }); self.dialogue.setText("Mmm... Fish. Not bad."); } else if (state === 'happy') { self.richardNode = self.attachAsset('richard_happy', { anchorX: 0.5, anchorY: 0.5 }); self.dialogue.setText("Fine, I'm happy. For now."); } else if (state === 'grumpy') { self.richardNode = self.attachAsset('richard_grumpy', { anchorX: 0.5, anchorY: 0.5 }); self.dialogue.setText("Hmph! You call this care?"); } }; // Helper: Animate Richard (e.g. bounce) self.bounce = function () { tween(self, { y: self.y - 60 }, { duration: 120, easing: tween.cubicOut, onFinish: function onFinish() { tween(self, { y: self.y + 60 }, { duration: 180, easing: tween.bounceIn }); } }); }; // Interactions self.down = function (x, y, obj) { if (self.isInteracting) return; if (self.state === 'sleeping') { self.isInteracting = true; LK.getSound('wake').play(); self.setState('awake'); self.bounce(); LK.setTimeout(function () { self.isInteracting = false; }, 400); } else if (self.state === 'awake') { // Poke Richard self.isInteracting = true; LK.getSound('poke').play(); self.setState('grumpy'); self.bounce(); LK.setTimeout(function () { self.setState('awake'); self.isInteracting = false; }, 1200); } else if (self.state === 'happy') { // Pet Richard self.isInteracting = true; LK.getSound('happy').play(); self.dialogue.setText("Heh. Don't get used to this."); self.bounce(); LK.setTimeout(function () { self.setState('awake'); self.isInteracting = false; }, 1200); } else if (self.state === 'grumpy') { // Poke again self.isInteracting = true; LK.getSound('grumpy').play(); self.dialogue.setText("Stop poking me!"); self.bounce(); LK.setTimeout(function () { self.setState('awake'); self.isInteracting = false; }, 1200); } }; // Called when fed self.feed = function () { if (self.isInteracting) return; if (self.state === 'awake' || self.state === 'grumpy') { self.isInteracting = true; LK.getSound('eat').play(); self.setState('eating'); self.lastFed = LK.ticks; storage.lastFed = self.lastFed; LK.setTimeout(function () { self.setState('happy'); self.isInteracting = false; }, 1200); } }; // Update: handle mood decay self.update = function () { // If awake for a while and not fed, get grumpy if (self.state === 'awake' && LK.ticks - self.lastFed > 600 && !self.isInteracting) { self.setState('grumpy'); } // If happy for a while, return to awake if (self.state === 'happy' && LK.ticks - self.lastFed > 300 && !self.isInteracting) { self.setState('awake'); } // If grumpy for a while, fall asleep if (self.state === 'grumpy' && LK.ticks - self.lastFed > 1200 && !self.isInteracting) { self.setState('sleeping'); } }; // Initialize self.setState(self.state); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb // Light blue sky }); /**** * Game Code ****/ // Sound effects (placeholders) // Richard the Falcon (main character) // Center positions var centerX = 2048 / 2; var centerY = 2732 / 2 + 100; // Add Richard var richard = new Richard(); richard.x = centerX; richard.y = centerY - 200; game.addChild(richard); // Add Fish (food) var fish = new Fish(); fish.x = centerX; fish.y = centerY + 400; game.addChild(fish); // Score text: "Richard's Mood" var moodTxt = new Text2("Mood: Sleeping", { size: 90, fill: "#fff" }); moodTxt.anchor.set(0.5, 0); LK.gui.top.addChild(moodTxt); // Helper: Update mood text function updateMoodText() { var mood = richard.state; var moodStr = "Mood: "; if (mood === 'sleeping') moodStr += "Sleeping";else if (mood === 'awake') moodStr += "Hungry";else if (mood === 'eating') moodStr += "Eating";else if (mood === 'happy') moodStr += "Happy";else if (mood === 'grumpy') moodStr += "Grumpy"; moodTxt.setText(moodStr); } // Drag logic var dragNode = null; function handleMove(x, y, obj) { if (dragNode && dragNode.isDragging) { dragNode.x = x + (dragNode.offsetX || 0); dragNode.y = y + (dragNode.offsetY || 0); } } game.move = handleMove; // Down event: check if fish or Richard is pressed game.down = function (x, y, obj) { // Convert to local coordinates for fish and Richard var fishLocal = fish.toLocal(game.toGlobal({ x: x, y: y })); var richardLocal = richard.toLocal(game.toGlobal({ x: x, y: y })); // Check if fish is pressed if (fish.fishNode && fishLocal.x > -fish.fishNode.width / 2 && fishLocal.x < fish.fishNode.width / 2 && fishLocal.y > -fish.fishNode.height / 2 && fishLocal.y < fish.fishNode.height / 2) { fish.down(x, y, obj); return; } // Check if Richard is pressed if (richard.richardNode && richardLocal.x > -richard.richardNode.width / 2 && richardLocal.x < richard.richardNode.width / 2 && richardLocal.y > -richard.richardNode.height / 2 && richardLocal.y < richard.richardNode.height / 2) { richard.down(x, y, obj); return; } }; // Up event: release drag game.up = function (x, y, obj) { if (dragNode && dragNode.isDragging) { // Check if fish is dropped on Richard var fishCenter = { x: fish.x, y: fish.y }; var richardBounds = { x: richard.x - 250, y: richard.y - 250, width: 500, height: 500 }; if (fishCenter.x > richardBounds.x && fishCenter.x < richardBounds.x + richardBounds.width && fishCenter.y > richardBounds.y && fishCenter.y < richardBounds.y + richardBounds.height) { // Feed Richard richard.feed(); // Animate fish "disappear" and reset tween(fish, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { fish.x = centerX; fish.y = centerY + 400; fish.alpha = 1; } }); } else { // Snap back to plate tween(fish, { x: centerX, y: centerY + 400 }, { duration: 200 }); } fish.up(x, y, obj); } dragNode = null; }; // Main update loop game.update = function () { richard.update(); updateMoodText(); // If fish is not being dragged and not at plate, snap back if (!fish.isDragging && (Math.abs(fish.x - centerX) > 10 || Math.abs(fish.y - (centerY + 400)) > 10)) { tween(fish, { x: centerX, y: centerY + 400 }, { duration: 200 }); } }; // Initial mood text updateMoodText();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
richardMood: "sleeping",
lastFed: 0
});
/****
* Classes
****/
// Fish (food)
var Fish = Container.expand(function () {
var self = Container.call(this);
self.fishNode = self.attachAsset('fish', {
anchorX: 0.5,
anchorY: 0.5
});
self.plateNode = self.attachAsset('plate', {
anchorX: 0.5,
anchorY: 0.5,
y: 60
});
self.x = 0;
self.y = 0;
self.isDragging = false;
// Drag logic
self.down = function (x, y, obj) {
self.isDragging = true;
dragNode = self;
self.offsetX = self.x - x;
self.offsetY = self.y - y;
};
self.up = function (x, y, obj) {
self.isDragging = false;
dragNode = null;
};
return self;
});
// Richard the Falcon
var Richard = Container.expand(function () {
var self = Container.call(this);
// State: 'sleeping', 'awake', 'eating', 'happy', 'grumpy'
self.state = storage.richardMood || 'sleeping';
self.lastFed = storage.lastFed || 0;
self.lastStateChange = LK.ticks;
self.isInteracting = false;
// Asset nodes
self.richardNode = null;
self.zzzNode = null;
// Dialogue
self.dialogue = new Text2('', {
size: 80,
fill: "#fff",
font: "Tahoma"
});
self.dialogue.anchor.set(0.5, 0);
self.dialogue.x = 0;
self.dialogue.y = 270;
self.addChild(self.dialogue);
// Helper: Set Richard's visual state
self.setState = function (state) {
if (self.richardNode) {
self.removeChild(self.richardNode);
self.richardNode.destroy();
self.richardNode = null;
}
if (self.zzzNode) {
self.removeChild(self.zzzNode);
self.zzzNode.destroy();
self.zzzNode = null;
}
self.state = state;
storage.richardMood = state;
if (state === 'sleeping') {
self.richardNode = self.attachAsset('richard_sleep', {
anchorX: 0.5,
anchorY: 0.5
});
self.zzzNode = self.attachAsset('zzz', {
anchorX: 0.5,
anchorY: 0.5,
x: 120,
y: -180,
scaleX: 1.2,
scaleY: 1.2
});
self.dialogue.setText("Zzz... (Tap to wake Richard)");
} else if (state === 'awake') {
self.richardNode = self.attachAsset('richard_awake', {
anchorX: 0.5,
anchorY: 0.5
});
self.dialogue.setText("What? I'm up. Where's my breakfast?");
} else if (state === 'eating') {
self.richardNode = self.attachAsset('richard_eat', {
anchorX: 0.5,
anchorY: 0.5
});
self.dialogue.setText("Mmm... Fish. Not bad.");
} else if (state === 'happy') {
self.richardNode = self.attachAsset('richard_happy', {
anchorX: 0.5,
anchorY: 0.5
});
self.dialogue.setText("Fine, I'm happy. For now.");
} else if (state === 'grumpy') {
self.richardNode = self.attachAsset('richard_grumpy', {
anchorX: 0.5,
anchorY: 0.5
});
self.dialogue.setText("Hmph! You call this care?");
}
};
// Helper: Animate Richard (e.g. bounce)
self.bounce = function () {
tween(self, {
y: self.y - 60
}, {
duration: 120,
easing: tween.cubicOut,
onFinish: function onFinish() {
tween(self, {
y: self.y + 60
}, {
duration: 180,
easing: tween.bounceIn
});
}
});
};
// Interactions
self.down = function (x, y, obj) {
if (self.isInteracting) return;
if (self.state === 'sleeping') {
self.isInteracting = true;
LK.getSound('wake').play();
self.setState('awake');
self.bounce();
LK.setTimeout(function () {
self.isInteracting = false;
}, 400);
} else if (self.state === 'awake') {
// Poke Richard
self.isInteracting = true;
LK.getSound('poke').play();
self.setState('grumpy');
self.bounce();
LK.setTimeout(function () {
self.setState('awake');
self.isInteracting = false;
}, 1200);
} else if (self.state === 'happy') {
// Pet Richard
self.isInteracting = true;
LK.getSound('happy').play();
self.dialogue.setText("Heh. Don't get used to this.");
self.bounce();
LK.setTimeout(function () {
self.setState('awake');
self.isInteracting = false;
}, 1200);
} else if (self.state === 'grumpy') {
// Poke again
self.isInteracting = true;
LK.getSound('grumpy').play();
self.dialogue.setText("Stop poking me!");
self.bounce();
LK.setTimeout(function () {
self.setState('awake');
self.isInteracting = false;
}, 1200);
}
};
// Called when fed
self.feed = function () {
if (self.isInteracting) return;
if (self.state === 'awake' || self.state === 'grumpy') {
self.isInteracting = true;
LK.getSound('eat').play();
self.setState('eating');
self.lastFed = LK.ticks;
storage.lastFed = self.lastFed;
LK.setTimeout(function () {
self.setState('happy');
self.isInteracting = false;
}, 1200);
}
};
// Update: handle mood decay
self.update = function () {
// If awake for a while and not fed, get grumpy
if (self.state === 'awake' && LK.ticks - self.lastFed > 600 && !self.isInteracting) {
self.setState('grumpy');
}
// If happy for a while, return to awake
if (self.state === 'happy' && LK.ticks - self.lastFed > 300 && !self.isInteracting) {
self.setState('awake');
}
// If grumpy for a while, fall asleep
if (self.state === 'grumpy' && LK.ticks - self.lastFed > 1200 && !self.isInteracting) {
self.setState('sleeping');
}
};
// Initialize
self.setState(self.state);
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Light blue sky
});
/****
* Game Code
****/
// Sound effects (placeholders)
// Richard the Falcon (main character)
// Center positions
var centerX = 2048 / 2;
var centerY = 2732 / 2 + 100;
// Add Richard
var richard = new Richard();
richard.x = centerX;
richard.y = centerY - 200;
game.addChild(richard);
// Add Fish (food)
var fish = new Fish();
fish.x = centerX;
fish.y = centerY + 400;
game.addChild(fish);
// Score text: "Richard's Mood"
var moodTxt = new Text2("Mood: Sleeping", {
size: 90,
fill: "#fff"
});
moodTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(moodTxt);
// Helper: Update mood text
function updateMoodText() {
var mood = richard.state;
var moodStr = "Mood: ";
if (mood === 'sleeping') moodStr += "Sleeping";else if (mood === 'awake') moodStr += "Hungry";else if (mood === 'eating') moodStr += "Eating";else if (mood === 'happy') moodStr += "Happy";else if (mood === 'grumpy') moodStr += "Grumpy";
moodTxt.setText(moodStr);
}
// Drag logic
var dragNode = null;
function handleMove(x, y, obj) {
if (dragNode && dragNode.isDragging) {
dragNode.x = x + (dragNode.offsetX || 0);
dragNode.y = y + (dragNode.offsetY || 0);
}
}
game.move = handleMove;
// Down event: check if fish or Richard is pressed
game.down = function (x, y, obj) {
// Convert to local coordinates for fish and Richard
var fishLocal = fish.toLocal(game.toGlobal({
x: x,
y: y
}));
var richardLocal = richard.toLocal(game.toGlobal({
x: x,
y: y
}));
// Check if fish is pressed
if (fish.fishNode && fishLocal.x > -fish.fishNode.width / 2 && fishLocal.x < fish.fishNode.width / 2 && fishLocal.y > -fish.fishNode.height / 2 && fishLocal.y < fish.fishNode.height / 2) {
fish.down(x, y, obj);
return;
}
// Check if Richard is pressed
if (richard.richardNode && richardLocal.x > -richard.richardNode.width / 2 && richardLocal.x < richard.richardNode.width / 2 && richardLocal.y > -richard.richardNode.height / 2 && richardLocal.y < richard.richardNode.height / 2) {
richard.down(x, y, obj);
return;
}
};
// Up event: release drag
game.up = function (x, y, obj) {
if (dragNode && dragNode.isDragging) {
// Check if fish is dropped on Richard
var fishCenter = {
x: fish.x,
y: fish.y
};
var richardBounds = {
x: richard.x - 250,
y: richard.y - 250,
width: 500,
height: 500
};
if (fishCenter.x > richardBounds.x && fishCenter.x < richardBounds.x + richardBounds.width && fishCenter.y > richardBounds.y && fishCenter.y < richardBounds.y + richardBounds.height) {
// Feed Richard
richard.feed();
// Animate fish "disappear" and reset
tween(fish, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
fish.x = centerX;
fish.y = centerY + 400;
fish.alpha = 1;
}
});
} else {
// Snap back to plate
tween(fish, {
x: centerX,
y: centerY + 400
}, {
duration: 200
});
}
fish.up(x, y, obj);
}
dragNode = null;
};
// Main update loop
game.update = function () {
richard.update();
updateMoodText();
// If fish is not being dragged and not at plate, snap back
if (!fish.isDragging && (Math.abs(fish.x - centerX) > 10 || Math.abs(fish.y - (centerY + 400)) > 10)) {
tween(fish, {
x: centerX,
y: centerY + 400
}, {
duration: 200
});
}
};
// Initial mood text
updateMoodText();