User prompt
Please fix the bug: 'undefined is not an object (evaluating 'self.mouth.scale')' in or related to this line: 'self.mouth.scale.set(1, 0.5);' Line Number: 407
User prompt
Please fix the bug: 'undefined is not an object (evaluating 'self.leftEye.scale')' in or related to this line: 'self.leftEye.scale.set(1, 1);' Line Number: 390
User prompt
Just remove the mouth and eyes
User prompt
Make the mouth mouth of the animal I added, and put the eyes where they’re supposed to be and make them look like the animal, please
User prompt
Make the codes work
Code edit (1 edits merged)
Please save this source code
User prompt
Virtual Companion: Mortality
User prompt
Please continue polishing my design document.
Initial prompt
Can you make a game where you have a pet and when you leave the game, it dies forever when you rejoin it’s still dead. You can play with it. Have some codes go to some places and one code is season code revenge. The last code is the sun
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { created: "undefined", lastVisit: "undefined", hunger: 100, happiness: 100, cleanliness: 100, health: 100, alive: true, discoveredCodes: [] }); /**** * Classes ****/ var Button = Container.expand(function (text, color) { var self = Container.call(this); var bg = self.attachAsset('button', { anchorX: 0.5, anchorY: 0.5 }); if (color) { bg.tint = color; } var label = new Text2(text, { size: 60, fill: 0xFFFFFF }); label.anchor.set(0.5, 0.5); self.addChild(label); self.down = function () { tween(bg.scale, { x: 0.95, y: 0.95 }, { duration: 100, easing: tween.easeOut }); }; self.up = function () { tween(bg.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); }; return self; }); var CodeInput = Container.expand(function () { var self = Container.call(this); var bg = self.attachAsset('codeInput', { anchorX: 0.5, anchorY: 0.5 }); self.currentCode = ""; var codeText = new Text2("CODE: ", { size: 60, fill: 0x333333 }); codeText.anchor.set(0.5, 0.5); self.addChild(codeText); self.updateText = function () { codeText.setText("CODE: " + self.currentCode); }; self.addCharacter = function (_char) { if (self.currentCode.length < 10) { self.currentCode += _char; self.updateText(); } }; self.backspace = function () { if (self.currentCode.length > 0) { self.currentCode = self.currentCode.slice(0, -1); self.updateText(); } }; self.clear = function () { self.currentCode = ""; self.updateText(); }; self.checkCode = function () { var lowerCode = self.currentCode.toLowerCase(); // Check if code has already been discovered if (storage.discoveredCodes.indexOf(lowerCode) !== -1) { return false; } // Validate code against known codes var isValid = false; if (lowerCode === "revenge") { showMessage("The dead shall rise..."); isValid = true; } else if (lowerCode === "sun" && storage.discoveredCodes.indexOf("revenge") !== -1) { showMessage("The power of life is yours!"); isValid = true; if (!pet.alive) { pet.resurrect(); } } else if (lowerCode === "eternity") { showMessage("Time stands still..."); isValid = true; } else if (lowerCode === "genesis") { showMessage("A new beginning..."); isValid = true; } else if (lowerCode === "void") { showMessage("Emptiness consumes..."); isValid = true; } if (isValid) { // Save the discovered code storage.discoveredCodes.push(lowerCode); LK.getSound('secretFound').play(); return true; } return false; }; return self; }); var Keyboard = Container.expand(function (codeInput) { var self = Container.call(this); var keys = ["QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM⌫"]; var keySize = 80; var spacing = 10; var currentY = 0; keys.forEach(function (row, rowIndex) { var rowWidth = row.length * (keySize + spacing) - spacing; var startX = -rowWidth / 2; for (var i = 0; i < row.length; i++) { var key = row[i]; var keyButton = new Container(); var keyBg = LK.getAsset('button', { anchorX: 0.5, anchorY: 0.5, width: keySize, height: keySize, tint: 0x555555 }); keyButton.addChild(keyBg); var keyText = new Text2(key, { size: 40, fill: 0xFFFFFF }); keyText.anchor.set(0.5, 0.5); keyButton.addChild(keyText); keyButton.x = startX + i * (keySize + spacing) + keySize / 2; keyButton.y = currentY; keyButton.key = key; keyButton.interactive = true; keyButton.buttonMode = true; keyButton.down = function () { if (this.key === "⌫") { codeInput.backspace(); } else { codeInput.addCharacter(this.key); } LK.getSound('codeEntered').play(); tween(this.scale, { x: 0.9, y: 0.9 }, { duration: 100, easing: tween.easeOut }); }; keyButton.up = function () { tween(this.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); }; self.addChild(keyButton); } currentY += keySize + spacing; }); // Add submit button var submitButton = new Button("SUBMIT", 0x4CAF50); submitButton.y = currentY + 20; submitButton.down = function () { tween(this.scale, { x: 0.95, y: 0.95 }, { duration: 100, easing: tween.easeOut }); }; submitButton.up = function () { tween(this.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); if (codeInput.checkCode()) { codeInput.clear(); } }; self.addChild(submitButton); // Add clear button var clearButton = new Button("CLEAR", 0xF44336); clearButton.x = -180; clearButton.y = currentY + 20; clearButton.down = function () { tween(this.scale, { x: 0.95, y: 0.95 }, { duration: 100, easing: tween.easeOut }); }; clearButton.up = function () { tween(this.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); codeInput.clear(); }; self.addChild(clearButton); return self; }); var Pet = Container.expand(function () { var self = Container.call(this); // Variables to track pet state self.hunger = storage.hunger; self.happiness = storage.happiness; self.cleanliness = storage.cleanliness; self.health = storage.health; self.alive = storage.alive; self.moods = ["normal", "happy", "sad", "sick", "dead"]; self.currentMood = "normal"; self.blinkTimer = 0; self.mouthMoveTimer = 0; self.mouthOpen = false; // Create pet body var body = self.attachAsset('petBody', { anchorX: 0.5, anchorY: 0.5 }); // Define leftEye and rightEye as assets for the pet self.leftEye = self.attachAsset('petEye', { anchorX: 0.5, anchorY: 0.5, x: -100, // Adjust position as needed y: -100 // Adjust position as needed }); self.rightEye = self.attachAsset('petEye', { anchorX: 0.5, anchorY: 0.5, x: 100, // Adjust position as needed y: -100 // Adjust position as needed }); // Define mouth as an asset for the pet self.mouth = self.attachAsset('petMouth', { anchorX: 0.5, anchorY: 0.5, y: 100 // Adjust position as needed }); // Create pet face self.body = body; // Interactions self.feed = function () { if (!self.alive) { return; } self.hunger = Math.min(100, self.hunger + 30); self.health = Math.min(100, self.health + 5); // Animate eating self.mouthOpen = true; self.updateMouthState(); LK.setTimeout(function () { self.mouthOpen = false; self.updateMouthState(); }, 500); LK.getSound('eat').play(); self.updateStats(); }; self.play = function () { if (!self.alive) { return; } self.happiness = Math.min(100, self.happiness + 30); self.hunger = Math.max(0, self.hunger - 5); // Animate playing tween(self, { rotation: 0.1 }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { rotation: -0.1 }, { duration: 200, easing: tween.easeInOut, onFinish: function onFinish() { tween(self, { rotation: 0 }, { duration: 200, easing: tween.easeInOut }); } }); } }); LK.getSound('play').play(); self.updateStats(); }; self.clean = function () { if (!self.alive) { return; } self.cleanliness = Math.min(100, self.cleanliness + 30); // Animate cleaning tween(self.body, { tint: 0x87CEEB }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(self.body, { tint: 0xF5DEB3 }, { duration: 500, easing: tween.easeInOut }); } }); LK.getSound('wash').play(); self.updateStats(); }; self.updateStats = function () { // Update all stats in storage storage.hunger = self.hunger; storage.happiness = self.happiness; storage.cleanliness = self.cleanliness; storage.health = self.health; storage.alive = self.alive; // Calculate health based on other stats if (self.alive) { self.health = Math.max(0, self.health - (self.hunger < 20 ? 10 : 0) - (self.happiness < 20 ? 10 : 0) - (self.cleanliness < 20 ? 10 : 0)); if (self.health <= 0) { self.die(); } } // Update mood self.updateMood(); }; self.updateMood = function () { var oldMood = self.currentMood; if (!self.alive) { self.currentMood = "dead"; } else if (self.health < 30) { self.currentMood = "sick"; } else if (self.hunger < 30 || self.happiness < 30 || self.cleanliness < 30) { self.currentMood = "sad"; } else if (self.hunger > 80 && self.happiness > 80 && self.cleanliness > 80) { self.currentMood = "happy"; } else { self.currentMood = "normal"; } // Update visual appearance based on mood if (oldMood !== self.currentMood) { self.updateAppearance(); } }; self.updateAppearance = function () { // Reset any previous animations or effects tween.stop(self.body); tween.stop(self.leftEye); tween.stop(self.rightEye); tween.stop(self.mouth); self.body.tint = 0xF5DEB3; self.body.scale.set(1, 1); self.leftEye.scale.set(1, 1); self.rightEye.scale.set(1, 1); self.mouth.scale.set(1, 0.5); // Apply mood-specific appearance switch (self.currentMood) { case "happy": self.mouth.scale.set(1, 0.75); self.mouth.y = 120; LK.getSound('happy').play(); break; case "sad": self.mouth.scale.set(1, 0.25); self.mouth.y = 150; LK.getSound('sad').play(); break; case "sick": self.body.tint = 0xADD8E6; break; case "dead": self.leftEye.scale.set(1, 0.1); self.rightEye.scale.set(1, 0.1); self.mouth.scale.set(1, 0.1); self.body.tint = 0xCCCCCC; self.mouth.rotation = Math.PI; break; default: // normal self.mouth.scale.set(1, 0.5); self.mouth.y = 100; break; } }; self.updateMouthState = function () { if (self.mouthOpen) { self.mouth.scale.set(1, 1); } else { self.updateAppearance(); // Reset to mood-appropriate appearance } }; self.animateBlink = function () { tween(self.leftEye.scale, { y: 0.1 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { tween(self.leftEye.scale, { y: 1 }, { duration: 100, easing: tween.linear }); } }); tween(self.rightEye.scale, { y: 0.1 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { tween(self.rightEye.scale, { y: 1 }, { duration: 100, easing: tween.linear }); } }); }; self.die = function () { if (!self.alive) { return; } self.alive = false; storage.alive = false; // Show death animation LK.effects.flashScreen(0xFF0000, 1000); // Update appearance to show dead pet self.updateMood(); }; self.resurrect = function () { self.alive = true; storage.alive = true; self.hunger = 100; storage.hunger = 100; self.happiness = 100; storage.happiness = 100; self.cleanliness = 100; storage.cleanliness = 100; self.health = 100; storage.health = 100; // Show resurrection animation LK.effects.flashScreen(0xFFFF00, 1000); // Update appearance self.updateMood(); }; self.update = function () { if (!self.alive) { return; } // Decrease stats over time (slower rate) if (LK.ticks % 60 === 0) { // Once per second self.hunger = Math.max(0, self.hunger - 0.1); self.happiness = Math.max(0, self.happiness - 0.1); self.cleanliness = Math.max(0, self.cleanliness - 0.05); self.updateStats(); } // Occasional blinking self.blinkTimer++; if (self.blinkTimer > 180 && Math.random() < 0.02) { self.animateBlink(); self.blinkTimer = 0; } // Random mouth movements when happy if (self.currentMood === "happy" && Math.random() < 0.005) { self.mouthOpen = !self.mouthOpen; self.updateMouthState(); } }; // Initialize appearance self.updateMood(); return self; }); var StatBar = Container.expand(function (label) { var self = Container.call(this); var bg = self.attachAsset('statBar', { anchorX: 0, anchorY: 0.5 }); var fill = self.attachAsset('statFill', { anchorX: 0, anchorY: 0.5, x: 5, y: 0 }); var text = new Text2(label, { size: 40, fill: 0xFFFFFF }); text.anchor.set(0, 0.5); text.x = 10; self.addChild(text); self.setValue = function (value) { // Calculate fill width based on percentage var maxWidth = 490; var newWidth = Math.max(0, Math.min(maxWidth, maxWidth * (value / 100))); // Animate the transition tween(fill, { width: newWidth }, { duration: 300, easing: tween.easeOut }); // Update fill color based on value if (value > 70) { fill.tint = 0x4CAF50; // Green } else if (value > 30) { fill.tint = 0xFFC107; // Yellow } else { fill.tint = 0xF44336; // Red } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xE0F7FA }); /**** * Game Code ****/ // Track game state var isDragging = false; var dragObject = null; var isCodeMode = false; var messageTimeout = null; // Create pet instance var pet = game.addChild(new Pet()); pet.x = 2048 / 2; pet.y = 900; // Check time between sessions var currentTime = Date.now(); if (storage.lastVisit !== null) { var timeDifference = (currentTime - storage.lastVisit) / 1000 / 60; // in minutes // Reduce stats based on time away if (pet.alive && timeDifference > 5) { // Decay stats based on time away (capped at certain values to prevent instant death) var hungerDecay = Math.min(80, timeDifference / 15); var happinessDecay = Math.min(80, timeDifference / 20); var cleanlinessDecay = Math.min(80, timeDifference / 30); pet.hunger = Math.max(10, pet.hunger - hungerDecay); pet.happiness = Math.max(10, pet.happiness - happinessDecay); pet.cleanliness = Math.max(10, pet.cleanliness - cleanlinessDecay); // If away too long, health decreases dramatically if (timeDifference > 1440) { // More than 24 hours pet.health = Math.max(0, pet.health - 80); } else if (timeDifference > 720) { // More than 12 hours pet.health = Math.max(0, pet.health - 40); } else if (timeDifference > 360) { // More than 6 hours pet.health = Math.max(0, pet.health - 20); } pet.updateStats(); } } // Update the last visit time storage.lastVisit = currentTime; // If this is the first run, set created time if (storage.created === null) { storage.created = currentTime; } // Create stat bars var hungerBar = game.addChild(new StatBar("Hunger")); hungerBar.x = 200; hungerBar.y = 200; hungerBar.setValue(pet.hunger); var happinessBar = game.addChild(new StatBar("Happiness")); happinessBar.x = 200; happinessBar.y = 300; happinessBar.setValue(pet.happiness); var cleanlinessBar = game.addChild(new StatBar("Cleanliness")); cleanlinessBar.x = 200; cleanlinessBar.y = 400; cleanlinessBar.setValue(pet.cleanliness); var healthBar = game.addChild(new StatBar("Health")); healthBar.x = 200; healthBar.y = 500; healthBar.setValue(pet.health); // Create interaction buttons var feedButton = game.addChild(new Button("Feed", 0xE74C3C)); feedButton.x = 400; feedButton.y = 650; feedButton.up = function () { tween(this.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); if (!isCodeMode) { pet.feed(); } }; var playButton = game.addChild(new Button("Play", 0xF1C40F)); playButton.x = 1024; playButton.y = 650; playButton.up = function () { tween(this.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); if (!isCodeMode) { pet.play(); } }; var cleanButton = game.addChild(new Button("Clean", 0x3498DB)); cleanButton.x = 1648; cleanButton.y = 650; cleanButton.up = function () { tween(this.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); if (!isCodeMode) { pet.clean(); } }; // Create code button var codeButton = game.addChild(new Button("Codes", 0x9B59B6)); codeButton.x = 1024; codeButton.y = 2550; codeButton.up = function () { tween(this.scale, { x: 1, y: 1 }, { duration: 100, easing: tween.easeOut }); toggleCodeMode(); }; // Create code input interface (initially hidden) var codeInput = game.addChild(new CodeInput()); codeInput.x = 1024; codeInput.y = 1600; codeInput.visible = false; var keyboard = game.addChild(new Keyboard(codeInput)); keyboard.x = 1024; keyboard.y = 1800; keyboard.visible = false; // Create info text var infoText = new Text2("Care for your pet or it will die permanently!", { size: 50, fill: 0x333333 }); infoText.anchor.set(0.5, 0); infoText.x = 1024; infoText.y = 50; game.addChild(infoText); // Create message text (for code responses) var messageText = new Text2("", { size: 60, fill: 0xFF0000 }); messageText.anchor.set(0.5, 0); messageText.x = 1024; messageText.y = 120; messageText.visible = false; game.addChild(messageText); // Function to toggle code input mode function toggleCodeMode() { isCodeMode = !isCodeMode; codeInput.visible = isCodeMode; keyboard.visible = isCodeMode; // If exiting code mode, clear the input if (!isCodeMode) { codeInput.clear(); } } // Function to show a temporary message function showMessage(text) { messageText.setText(text); messageText.visible = true; if (messageTimeout) { LK.clearTimeout(messageTimeout); } messageTimeout = LK.setTimeout(function () { messageText.visible = false; }, 3000); } // Define event handlers game.down = function (x, y, obj) { isDragging = true; }; game.up = function (x, y, obj) { isDragging = false; dragObject = null; }; game.move = function (x, y, obj) { // Pet can be petted by dragging across it if (isDragging && !isCodeMode && pet.alive) { var localPos = pet.toLocal({ x: x, y: y }); // Check if mouse/touch is over the pet body if (Math.abs(localPos.x) < pet.body.width / 2 && Math.abs(localPos.y) < pet.body.height / 2) { // Small happiness boost when being petted if (LK.ticks % 10 === 0) { pet.happiness = Math.min(100, pet.happiness + 0.5); pet.updateStats(); } // Show visual feedback tween(pet.body, { tint: 0xFFD700 }, { duration: 100, easing: tween.linear, onFinish: function onFinish() { tween(pet.body, { tint: 0xF5DEB3 }, { duration: 100, easing: tween.linear }); } }); } } }; // Main game update loop game.update = function () { // Update stat bars to reflect current values hungerBar.setValue(pet.hunger); happinessBar.setValue(pet.happiness); cleanlinessBar.setValue(pet.cleanliness); healthBar.setValue(pet.health); // Update info text based on pet state if (!pet.alive) { infoText.setText("Your pet has died! Find the secret codes to resurrect it."); } else if (pet.health < 30) { infoText.setText("Your pet is very sick! Take better care of it!"); } else if (pet.hunger < 30) { infoText.setText("Your pet is starving! Feed it quickly!"); } else if (pet.happiness < 30) { infoText.setText("Your pet is sad! Play with it!"); } else if (pet.cleanliness < 30) { infoText.setText("Your pet is dirty! Clean it!"); } else { infoText.setText("Take good care of your pet or it will die permanently!"); } }; // Start background music LK.playMusic('bgMusic', { fade: { start: 0, end: 0.3, duration: 1000 } });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
created: "undefined",
lastVisit: "undefined",
hunger: 100,
happiness: 100,
cleanliness: 100,
health: 100,
alive: true,
discoveredCodes: []
});
/****
* Classes
****/
var Button = Container.expand(function (text, color) {
var self = Container.call(this);
var bg = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
if (color) {
bg.tint = color;
}
var label = new Text2(text, {
size: 60,
fill: 0xFFFFFF
});
label.anchor.set(0.5, 0.5);
self.addChild(label);
self.down = function () {
tween(bg.scale, {
x: 0.95,
y: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
self.up = function () {
tween(bg.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
};
return self;
});
var CodeInput = Container.expand(function () {
var self = Container.call(this);
var bg = self.attachAsset('codeInput', {
anchorX: 0.5,
anchorY: 0.5
});
self.currentCode = "";
var codeText = new Text2("CODE: ", {
size: 60,
fill: 0x333333
});
codeText.anchor.set(0.5, 0.5);
self.addChild(codeText);
self.updateText = function () {
codeText.setText("CODE: " + self.currentCode);
};
self.addCharacter = function (_char) {
if (self.currentCode.length < 10) {
self.currentCode += _char;
self.updateText();
}
};
self.backspace = function () {
if (self.currentCode.length > 0) {
self.currentCode = self.currentCode.slice(0, -1);
self.updateText();
}
};
self.clear = function () {
self.currentCode = "";
self.updateText();
};
self.checkCode = function () {
var lowerCode = self.currentCode.toLowerCase();
// Check if code has already been discovered
if (storage.discoveredCodes.indexOf(lowerCode) !== -1) {
return false;
}
// Validate code against known codes
var isValid = false;
if (lowerCode === "revenge") {
showMessage("The dead shall rise...");
isValid = true;
} else if (lowerCode === "sun" && storage.discoveredCodes.indexOf("revenge") !== -1) {
showMessage("The power of life is yours!");
isValid = true;
if (!pet.alive) {
pet.resurrect();
}
} else if (lowerCode === "eternity") {
showMessage("Time stands still...");
isValid = true;
} else if (lowerCode === "genesis") {
showMessage("A new beginning...");
isValid = true;
} else if (lowerCode === "void") {
showMessage("Emptiness consumes...");
isValid = true;
}
if (isValid) {
// Save the discovered code
storage.discoveredCodes.push(lowerCode);
LK.getSound('secretFound').play();
return true;
}
return false;
};
return self;
});
var Keyboard = Container.expand(function (codeInput) {
var self = Container.call(this);
var keys = ["QWERTYUIOP", "ASDFGHJKL", "ZXCVBNM⌫"];
var keySize = 80;
var spacing = 10;
var currentY = 0;
keys.forEach(function (row, rowIndex) {
var rowWidth = row.length * (keySize + spacing) - spacing;
var startX = -rowWidth / 2;
for (var i = 0; i < row.length; i++) {
var key = row[i];
var keyButton = new Container();
var keyBg = LK.getAsset('button', {
anchorX: 0.5,
anchorY: 0.5,
width: keySize,
height: keySize,
tint: 0x555555
});
keyButton.addChild(keyBg);
var keyText = new Text2(key, {
size: 40,
fill: 0xFFFFFF
});
keyText.anchor.set(0.5, 0.5);
keyButton.addChild(keyText);
keyButton.x = startX + i * (keySize + spacing) + keySize / 2;
keyButton.y = currentY;
keyButton.key = key;
keyButton.interactive = true;
keyButton.buttonMode = true;
keyButton.down = function () {
if (this.key === "⌫") {
codeInput.backspace();
} else {
codeInput.addCharacter(this.key);
}
LK.getSound('codeEntered').play();
tween(this.scale, {
x: 0.9,
y: 0.9
}, {
duration: 100,
easing: tween.easeOut
});
};
keyButton.up = function () {
tween(this.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
};
self.addChild(keyButton);
}
currentY += keySize + spacing;
});
// Add submit button
var submitButton = new Button("SUBMIT", 0x4CAF50);
submitButton.y = currentY + 20;
submitButton.down = function () {
tween(this.scale, {
x: 0.95,
y: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
submitButton.up = function () {
tween(this.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
if (codeInput.checkCode()) {
codeInput.clear();
}
};
self.addChild(submitButton);
// Add clear button
var clearButton = new Button("CLEAR", 0xF44336);
clearButton.x = -180;
clearButton.y = currentY + 20;
clearButton.down = function () {
tween(this.scale, {
x: 0.95,
y: 0.95
}, {
duration: 100,
easing: tween.easeOut
});
};
clearButton.up = function () {
tween(this.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
codeInput.clear();
};
self.addChild(clearButton);
return self;
});
var Pet = Container.expand(function () {
var self = Container.call(this);
// Variables to track pet state
self.hunger = storage.hunger;
self.happiness = storage.happiness;
self.cleanliness = storage.cleanliness;
self.health = storage.health;
self.alive = storage.alive;
self.moods = ["normal", "happy", "sad", "sick", "dead"];
self.currentMood = "normal";
self.blinkTimer = 0;
self.mouthMoveTimer = 0;
self.mouthOpen = false;
// Create pet body
var body = self.attachAsset('petBody', {
anchorX: 0.5,
anchorY: 0.5
});
// Define leftEye and rightEye as assets for the pet
self.leftEye = self.attachAsset('petEye', {
anchorX: 0.5,
anchorY: 0.5,
x: -100,
// Adjust position as needed
y: -100 // Adjust position as needed
});
self.rightEye = self.attachAsset('petEye', {
anchorX: 0.5,
anchorY: 0.5,
x: 100,
// Adjust position as needed
y: -100 // Adjust position as needed
});
// Define mouth as an asset for the pet
self.mouth = self.attachAsset('petMouth', {
anchorX: 0.5,
anchorY: 0.5,
y: 100 // Adjust position as needed
});
// Create pet face
self.body = body;
// Interactions
self.feed = function () {
if (!self.alive) {
return;
}
self.hunger = Math.min(100, self.hunger + 30);
self.health = Math.min(100, self.health + 5);
// Animate eating
self.mouthOpen = true;
self.updateMouthState();
LK.setTimeout(function () {
self.mouthOpen = false;
self.updateMouthState();
}, 500);
LK.getSound('eat').play();
self.updateStats();
};
self.play = function () {
if (!self.alive) {
return;
}
self.happiness = Math.min(100, self.happiness + 30);
self.hunger = Math.max(0, self.hunger - 5);
// Animate playing
tween(self, {
rotation: 0.1
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: -0.1
}, {
duration: 200,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self, {
rotation: 0
}, {
duration: 200,
easing: tween.easeInOut
});
}
});
}
});
LK.getSound('play').play();
self.updateStats();
};
self.clean = function () {
if (!self.alive) {
return;
}
self.cleanliness = Math.min(100, self.cleanliness + 30);
// Animate cleaning
tween(self.body, {
tint: 0x87CEEB
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(self.body, {
tint: 0xF5DEB3
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
LK.getSound('wash').play();
self.updateStats();
};
self.updateStats = function () {
// Update all stats in storage
storage.hunger = self.hunger;
storage.happiness = self.happiness;
storage.cleanliness = self.cleanliness;
storage.health = self.health;
storage.alive = self.alive;
// Calculate health based on other stats
if (self.alive) {
self.health = Math.max(0, self.health - (self.hunger < 20 ? 10 : 0) - (self.happiness < 20 ? 10 : 0) - (self.cleanliness < 20 ? 10 : 0));
if (self.health <= 0) {
self.die();
}
}
// Update mood
self.updateMood();
};
self.updateMood = function () {
var oldMood = self.currentMood;
if (!self.alive) {
self.currentMood = "dead";
} else if (self.health < 30) {
self.currentMood = "sick";
} else if (self.hunger < 30 || self.happiness < 30 || self.cleanliness < 30) {
self.currentMood = "sad";
} else if (self.hunger > 80 && self.happiness > 80 && self.cleanliness > 80) {
self.currentMood = "happy";
} else {
self.currentMood = "normal";
}
// Update visual appearance based on mood
if (oldMood !== self.currentMood) {
self.updateAppearance();
}
};
self.updateAppearance = function () {
// Reset any previous animations or effects
tween.stop(self.body);
tween.stop(self.leftEye);
tween.stop(self.rightEye);
tween.stop(self.mouth);
self.body.tint = 0xF5DEB3;
self.body.scale.set(1, 1);
self.leftEye.scale.set(1, 1);
self.rightEye.scale.set(1, 1);
self.mouth.scale.set(1, 0.5);
// Apply mood-specific appearance
switch (self.currentMood) {
case "happy":
self.mouth.scale.set(1, 0.75);
self.mouth.y = 120;
LK.getSound('happy').play();
break;
case "sad":
self.mouth.scale.set(1, 0.25);
self.mouth.y = 150;
LK.getSound('sad').play();
break;
case "sick":
self.body.tint = 0xADD8E6;
break;
case "dead":
self.leftEye.scale.set(1, 0.1);
self.rightEye.scale.set(1, 0.1);
self.mouth.scale.set(1, 0.1);
self.body.tint = 0xCCCCCC;
self.mouth.rotation = Math.PI;
break;
default:
// normal
self.mouth.scale.set(1, 0.5);
self.mouth.y = 100;
break;
}
};
self.updateMouthState = function () {
if (self.mouthOpen) {
self.mouth.scale.set(1, 1);
} else {
self.updateAppearance(); // Reset to mood-appropriate appearance
}
};
self.animateBlink = function () {
tween(self.leftEye.scale, {
y: 0.1
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
tween(self.leftEye.scale, {
y: 1
}, {
duration: 100,
easing: tween.linear
});
}
});
tween(self.rightEye.scale, {
y: 0.1
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
tween(self.rightEye.scale, {
y: 1
}, {
duration: 100,
easing: tween.linear
});
}
});
};
self.die = function () {
if (!self.alive) {
return;
}
self.alive = false;
storage.alive = false;
// Show death animation
LK.effects.flashScreen(0xFF0000, 1000);
// Update appearance to show dead pet
self.updateMood();
};
self.resurrect = function () {
self.alive = true;
storage.alive = true;
self.hunger = 100;
storage.hunger = 100;
self.happiness = 100;
storage.happiness = 100;
self.cleanliness = 100;
storage.cleanliness = 100;
self.health = 100;
storage.health = 100;
// Show resurrection animation
LK.effects.flashScreen(0xFFFF00, 1000);
// Update appearance
self.updateMood();
};
self.update = function () {
if (!self.alive) {
return;
}
// Decrease stats over time (slower rate)
if (LK.ticks % 60 === 0) {
// Once per second
self.hunger = Math.max(0, self.hunger - 0.1);
self.happiness = Math.max(0, self.happiness - 0.1);
self.cleanliness = Math.max(0, self.cleanliness - 0.05);
self.updateStats();
}
// Occasional blinking
self.blinkTimer++;
if (self.blinkTimer > 180 && Math.random() < 0.02) {
self.animateBlink();
self.blinkTimer = 0;
}
// Random mouth movements when happy
if (self.currentMood === "happy" && Math.random() < 0.005) {
self.mouthOpen = !self.mouthOpen;
self.updateMouthState();
}
};
// Initialize appearance
self.updateMood();
return self;
});
var StatBar = Container.expand(function (label) {
var self = Container.call(this);
var bg = self.attachAsset('statBar', {
anchorX: 0,
anchorY: 0.5
});
var fill = self.attachAsset('statFill', {
anchorX: 0,
anchorY: 0.5,
x: 5,
y: 0
});
var text = new Text2(label, {
size: 40,
fill: 0xFFFFFF
});
text.anchor.set(0, 0.5);
text.x = 10;
self.addChild(text);
self.setValue = function (value) {
// Calculate fill width based on percentage
var maxWidth = 490;
var newWidth = Math.max(0, Math.min(maxWidth, maxWidth * (value / 100)));
// Animate the transition
tween(fill, {
width: newWidth
}, {
duration: 300,
easing: tween.easeOut
});
// Update fill color based on value
if (value > 70) {
fill.tint = 0x4CAF50; // Green
} else if (value > 30) {
fill.tint = 0xFFC107; // Yellow
} else {
fill.tint = 0xF44336; // Red
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xE0F7FA
});
/****
* Game Code
****/
// Track game state
var isDragging = false;
var dragObject = null;
var isCodeMode = false;
var messageTimeout = null;
// Create pet instance
var pet = game.addChild(new Pet());
pet.x = 2048 / 2;
pet.y = 900;
// Check time between sessions
var currentTime = Date.now();
if (storage.lastVisit !== null) {
var timeDifference = (currentTime - storage.lastVisit) / 1000 / 60; // in minutes
// Reduce stats based on time away
if (pet.alive && timeDifference > 5) {
// Decay stats based on time away (capped at certain values to prevent instant death)
var hungerDecay = Math.min(80, timeDifference / 15);
var happinessDecay = Math.min(80, timeDifference / 20);
var cleanlinessDecay = Math.min(80, timeDifference / 30);
pet.hunger = Math.max(10, pet.hunger - hungerDecay);
pet.happiness = Math.max(10, pet.happiness - happinessDecay);
pet.cleanliness = Math.max(10, pet.cleanliness - cleanlinessDecay);
// If away too long, health decreases dramatically
if (timeDifference > 1440) {
// More than 24 hours
pet.health = Math.max(0, pet.health - 80);
} else if (timeDifference > 720) {
// More than 12 hours
pet.health = Math.max(0, pet.health - 40);
} else if (timeDifference > 360) {
// More than 6 hours
pet.health = Math.max(0, pet.health - 20);
}
pet.updateStats();
}
}
// Update the last visit time
storage.lastVisit = currentTime;
// If this is the first run, set created time
if (storage.created === null) {
storage.created = currentTime;
}
// Create stat bars
var hungerBar = game.addChild(new StatBar("Hunger"));
hungerBar.x = 200;
hungerBar.y = 200;
hungerBar.setValue(pet.hunger);
var happinessBar = game.addChild(new StatBar("Happiness"));
happinessBar.x = 200;
happinessBar.y = 300;
happinessBar.setValue(pet.happiness);
var cleanlinessBar = game.addChild(new StatBar("Cleanliness"));
cleanlinessBar.x = 200;
cleanlinessBar.y = 400;
cleanlinessBar.setValue(pet.cleanliness);
var healthBar = game.addChild(new StatBar("Health"));
healthBar.x = 200;
healthBar.y = 500;
healthBar.setValue(pet.health);
// Create interaction buttons
var feedButton = game.addChild(new Button("Feed", 0xE74C3C));
feedButton.x = 400;
feedButton.y = 650;
feedButton.up = function () {
tween(this.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
if (!isCodeMode) {
pet.feed();
}
};
var playButton = game.addChild(new Button("Play", 0xF1C40F));
playButton.x = 1024;
playButton.y = 650;
playButton.up = function () {
tween(this.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
if (!isCodeMode) {
pet.play();
}
};
var cleanButton = game.addChild(new Button("Clean", 0x3498DB));
cleanButton.x = 1648;
cleanButton.y = 650;
cleanButton.up = function () {
tween(this.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
if (!isCodeMode) {
pet.clean();
}
};
// Create code button
var codeButton = game.addChild(new Button("Codes", 0x9B59B6));
codeButton.x = 1024;
codeButton.y = 2550;
codeButton.up = function () {
tween(this.scale, {
x: 1,
y: 1
}, {
duration: 100,
easing: tween.easeOut
});
toggleCodeMode();
};
// Create code input interface (initially hidden)
var codeInput = game.addChild(new CodeInput());
codeInput.x = 1024;
codeInput.y = 1600;
codeInput.visible = false;
var keyboard = game.addChild(new Keyboard(codeInput));
keyboard.x = 1024;
keyboard.y = 1800;
keyboard.visible = false;
// Create info text
var infoText = new Text2("Care for your pet or it will die permanently!", {
size: 50,
fill: 0x333333
});
infoText.anchor.set(0.5, 0);
infoText.x = 1024;
infoText.y = 50;
game.addChild(infoText);
// Create message text (for code responses)
var messageText = new Text2("", {
size: 60,
fill: 0xFF0000
});
messageText.anchor.set(0.5, 0);
messageText.x = 1024;
messageText.y = 120;
messageText.visible = false;
game.addChild(messageText);
// Function to toggle code input mode
function toggleCodeMode() {
isCodeMode = !isCodeMode;
codeInput.visible = isCodeMode;
keyboard.visible = isCodeMode;
// If exiting code mode, clear the input
if (!isCodeMode) {
codeInput.clear();
}
}
// Function to show a temporary message
function showMessage(text) {
messageText.setText(text);
messageText.visible = true;
if (messageTimeout) {
LK.clearTimeout(messageTimeout);
}
messageTimeout = LK.setTimeout(function () {
messageText.visible = false;
}, 3000);
}
// Define event handlers
game.down = function (x, y, obj) {
isDragging = true;
};
game.up = function (x, y, obj) {
isDragging = false;
dragObject = null;
};
game.move = function (x, y, obj) {
// Pet can be petted by dragging across it
if (isDragging && !isCodeMode && pet.alive) {
var localPos = pet.toLocal({
x: x,
y: y
});
// Check if mouse/touch is over the pet body
if (Math.abs(localPos.x) < pet.body.width / 2 && Math.abs(localPos.y) < pet.body.height / 2) {
// Small happiness boost when being petted
if (LK.ticks % 10 === 0) {
pet.happiness = Math.min(100, pet.happiness + 0.5);
pet.updateStats();
}
// Show visual feedback
tween(pet.body, {
tint: 0xFFD700
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
tween(pet.body, {
tint: 0xF5DEB3
}, {
duration: 100,
easing: tween.linear
});
}
});
}
}
};
// Main game update loop
game.update = function () {
// Update stat bars to reflect current values
hungerBar.setValue(pet.hunger);
happinessBar.setValue(pet.happiness);
cleanlinessBar.setValue(pet.cleanliness);
healthBar.setValue(pet.health);
// Update info text based on pet state
if (!pet.alive) {
infoText.setText("Your pet has died! Find the secret codes to resurrect it.");
} else if (pet.health < 30) {
infoText.setText("Your pet is very sick! Take better care of it!");
} else if (pet.hunger < 30) {
infoText.setText("Your pet is starving! Feed it quickly!");
} else if (pet.happiness < 30) {
infoText.setText("Your pet is sad! Play with it!");
} else if (pet.cleanliness < 30) {
infoText.setText("Your pet is dirty! Clean it!");
} else {
infoText.setText("Take good care of your pet or it will die permanently!");
}
};
// Start background music
LK.playMusic('bgMusic', {
fade: {
start: 0,
end: 0.3,
duration: 1000
}
});