/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Animal class var Animal = Container.expand(function () { var self = Container.call(this); // Animal types var animalTypes = [{ id: 'peterPig', name: 'Peter Pig', dialog: ["Oink! Not the tummy!", "I was just snacking...", "Piggy in a python!"] }, { id: 'marvinSnake', name: 'Marvin Snake', dialog: ["Hey, cousin! Wait—", "Snakes don't eat snakes!", "This is awkward..."] }, { id: 'birdo', name: 'Birdo', dialog: ["Chirp! Not the beak!", "I believe I can fly... away!", "Tweet! Help!"] }, { id: 'shaunSnail', name: 'Shaun the Snail', dialog: ["Slow down, big guy!", "Shell shocked!", "I was just sliming by..."] }, { id: 'daisyHamster', name: 'Daisy the Hamster', dialog: ["Eek! Not the cheeks!", "I just cleaned my fur!", "Hamster wheel, activate!"] }]; // Pick a random animal type var idx = Math.floor(Math.random() * animalTypes.length); var type = animalTypes[idx]; self.type = type; // Attach animal asset var animalSprite = self.attachAsset(type.id, { anchorX: 0.5, anchorY: 0.5 }); self.animalSprite = animalSprite; // For movement self.speed = 8 + Math.random() * 8; self.direction = Math.random() * Math.PI * 2; self.escapeTimer = 0; // Ticks until animal tries to escape // Dialog shown when eaten self.getDialog = function () { var d = type.dialog; return d[Math.floor(Math.random() * d.length)]; }; // Move animal in current direction self.moveAnimal = function () { self.x += Math.cos(self.direction) * self.speed; self.y += Math.sin(self.direction) * self.speed; // Bounce off walls if (self.x < 100) { self.x = 100; self.direction = Math.PI - self.direction; } if (self.x > 2048 - 100) { self.x = 2048 - 100; self.direction = Math.PI - self.direction; } if (self.y < 200) { self.y = 200; self.direction = -self.direction; } if (self.y > 2732 - 100) { self.y = 2732 - 100; self.direction = -self.direction; } }; // Try to escape after a while self.tryEscape = function () { // After 5-8 seconds, animal flees off screen if (self.escapeTimer === 0) { self.escapeTimer = LK.ticks + 300 + Math.floor(Math.random() * 180); } if (LK.ticks > self.escapeTimer) { // Flee in random direction toward nearest edge var edgeX = self.x < 1024 ? -200 : 2248; var edgeY = self.y < 1366 ? -200 : 2932; var dx = edgeX - self.x; var dy = edgeY - self.y; self.direction = Math.atan2(dy, dx); self.speed = 22; } }; return self; }); // Dad Snake class var DadSnake = Container.expand(function () { var self = Container.call(this); // Head var head = self.attachAsset('dadSnakeHead', { anchorX: 0.5, anchorY: 0.5 }); self.head = head; // Body segments (start with 2) self.bodySegments = []; for (var i = 0; i < 2; i++) { var seg = LK.getAsset('dadSnakeBody', { anchorX: 0.5, anchorY: 0.5 }); seg.x = -((i + 1) * 130); seg.y = 0; self.addChild(seg); self.bodySegments.push(seg); } // Belly bulges (for eaten animals) self.bellyBulges = []; // Snake direction (angle in radians) self.direction = 0; // Snake speed self.speed = 18; // For dragging self.isDragging = false; // Move snake towards a target (x, y) self.moveToward = function (tx, ty) { var dx = tx - self.x; var dy = ty - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.speed) { self.x = tx; self.y = ty; return; } var angle = Math.atan2(dy, dx); self.direction = angle; self.x += Math.cos(angle) * self.speed; self.y += Math.sin(angle) * self.speed; }; // Update body segments to follow head self.updateBody = function () { var prevX = self.x; var prevY = self.y; for (var i = 0; i < self.bodySegments.length; i++) { var seg = self.bodySegments[i]; var dx = prevX - seg.x; var dy = prevY - seg.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 130) { var angle = Math.atan2(dy, dx); seg.x += Math.cos(angle) * (dist - 130); seg.y += Math.sin(angle) * (dist - 130); } prevX = seg.x; prevY = seg.y; } // Belly bulges follow body segments for (var j = 0; j < self.bellyBulges.length; j++) { var bulge = self.bellyBulges[j]; var segIdx = Math.min(j, self.bodySegments.length - 1); var seg = self.bodySegments[segIdx]; bulge.x = seg.x; bulge.y = seg.y; } }; // Add a belly bulge (when eating an animal) self.addBellyBulge = function () { var bulge = LK.getAsset('dadSnakeBelly', { anchorX: 0.5, anchorY: 0.5 }); // Place on last body segment var segIdx = Math.min(self.bellyBulges.length, self.bodySegments.length - 1); var seg = self.bodySegments[segIdx]; bulge.x = seg.x; bulge.y = seg.y; self.addChild(bulge); self.bellyBulges.push(bulge); }; // Remove all belly bulges (on reset) self.clearBellyBulges = function () { for (var i = 0; i < self.bellyBulges.length; i++) { self.bellyBulges[i].destroy(); } self.bellyBulges = []; }; return self; }); // Dialog bubble class var DialogBubble = Container.expand(function () { var self = Container.call(this); var bubble = self.attachAsset('dialogBubble', { anchorX: 0.5, anchorY: 1 }); self.bubble = bubble; var txt = new Text2('', { size: 60, fill: 0x222222 }); txt.anchor.set(0.5, 0.5); txt.x = 0; txt.y = -20; self.addChild(txt); self.txt = txt; // Show dialog at (x, y) self.show = function (text, x, y) { self.txt.setText(text); self.x = x; self.y = y; self.visible = true; // Fade in self.alpha = 0; tween(self, { alpha: 1 }, { duration: 200, easing: tween.easeIn }); // Hide after 1.2s LK.setTimeout(function () { tween(self, { alpha: 0 }, { duration: 300, easing: tween.easeOut, onFinish: function onFinish() { self.visible = false; } }); }, 1200); }; self.visible = false; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0xb3e5fc // Light blue sky }); /**** * Game Code ****/ // Dialog bubble // Animal assets (distinct colors) // Dad Snake body (green, long rectangle) // Center play area var centerX = 2048 / 2; var centerY = 2732 / 2; // Dad Snake var dadSnake = new DadSnake(); dadSnake.x = centerX; dadSnake.y = centerY + 400; game.addChild(dadSnake); // Animals array var animals = []; // Dialog bubble var dialogBubble = new DialogBubble(); game.addChild(dialogBubble); // Score text var scoreTxt = new Text2('0', { size: 120, fill: 0x222222 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Dad Snake dialog text (above head) var dadDialog = new Text2('', { size: 70, fill: 0x388E3C }); dadDialog.anchor.set(0.5, 1); dadDialog.x = 0; dadDialog.y = -120; dadSnake.addChild(dadDialog); // Game state var dragging = false; var targetX = dadSnake.x; var targetY = dadSnake.y; var animalsEaten = 0; var totalAnimals = 5; var gameOver = false; // Animal names for unique spawn var animalTypes = ['peterPig', 'marvinSnake', 'birdo', 'shaunSnail', 'daisyHamster']; // Spawn all animals at random positions function spawnAnimals() { for (var i = 0; i < animalTypes.length; i++) { var animal = new Animal(); // Place randomly, not too close to Dad Snake var placed = false; while (!placed) { animal.x = 200 + Math.random() * (2048 - 400); animal.y = 400 + Math.random() * (2732 - 800); var dx = animal.x - dadSnake.x; var dy = animal.y - dadSnake.y; if (Math.sqrt(dx * dx + dy * dy) > 500) placed = true; } animals.push(animal); game.addChild(animal); } } spawnAnimals(); // Helper: show Dad Snake dialog function showDadDialog(text) { dadDialog.setText(text); dadDialog.alpha = 1; tween(dadDialog, { alpha: 0 }, { duration: 1200, easing: tween.linear }); } // Handle dragging Dad Snake game.down = function (x, y, obj) { // Don't allow drag if game over if (gameOver) return; dragging = true; targetX = x; targetY = y; dadSnake.isDragging = true; }; game.move = function (x, y, obj) { if (dragging && !gameOver) { targetX = x; targetY = y; } }; game.up = function (x, y, obj) { dragging = false; dadSnake.isDragging = false; }; // Main update loop game.update = function () { if (gameOver) return; // Move Dad Snake toward target dadSnake.moveToward(targetX, targetY); dadSnake.updateBody(); // Move animals for (var i = animals.length - 1; i >= 0; i--) { var animal = animals[i]; animal.moveAnimal(); animal.tryEscape(); // If animal escapes off screen, game over if (animal.x < -150 || animal.x > 2048 + 150 || animal.y < -150 || animal.y > 2732 + 150) { // Show dialog dialogBubble.show(animal.type.name + " escaped!", dadSnake.x, dadSnake.y - 200); showDadDialog("Oh no! " + animal.type.name + " got away!"); LK.effects.flashScreen(0xff0000, 800); gameOver = true; LK.setTimeout(function () { LK.showGameOver(); }, 1200); return; } // Check collision with Dad Snake head if (dadSnake.head.intersects(animal.animalSprite)) { // Eat animal animalsEaten++; LK.setScore(animalsEaten); scoreTxt.setText(animalsEaten); // Show dialog dialogBubble.show(animal.getDialog(), animal.x, animal.y - 120); // Dad Snake comment var dadLines = ["Yum! That hit the spot.", "Mmm, tasty!", "Gulp! Down the hatch.", "My tummy's getting full!", "Slurp! Who's next?"]; showDadDialog(dadLines[Math.floor(Math.random() * dadLines.length)]); // Add belly bulge dadSnake.addBellyBulge(); // Add body segment for fun var seg = LK.getAsset('dadSnakeBody', { anchorX: 0.5, anchorY: 0.5 }); var lastSeg = dadSnake.bodySegments[dadSnake.bodySegments.length - 1]; seg.x = lastSeg.x - 130; seg.y = lastSeg.y; dadSnake.addChild(seg); dadSnake.bodySegments.push(seg); // Remove animal animal.destroy(); animals.splice(i, 1); // Win condition if (animalsEaten >= totalAnimals) { showDadDialog("Burp! All gone!"); LK.effects.flashScreen(0x8bc34a, 1000); gameOver = true; LK.setTimeout(function () { LK.showYouWin(); }, 1200); return; } } } }; // Reset state on game restart game.on('reset', function () { // Remove animals for (var i = 0; i < animals.length; i++) { animals[i].destroy(); } animals = []; animalsEaten = 0; LK.setScore(0); scoreTxt.setText('0'); dadSnake.x = centerX; dadSnake.y = centerY + 400; dadSnake.clearBellyBulges(); // Remove extra body segments while (dadSnake.bodySegments.length > 2) { var seg = dadSnake.bodySegments.pop(); seg.destroy(); } dialogBubble.visible = false; dadDialog.setText(''); gameOver = false; spawnAnimals(); });
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Animal class
var Animal = Container.expand(function () {
var self = Container.call(this);
// Animal types
var animalTypes = [{
id: 'peterPig',
name: 'Peter Pig',
dialog: ["Oink! Not the tummy!", "I was just snacking...", "Piggy in a python!"]
}, {
id: 'marvinSnake',
name: 'Marvin Snake',
dialog: ["Hey, cousin! Wait—", "Snakes don't eat snakes!", "This is awkward..."]
}, {
id: 'birdo',
name: 'Birdo',
dialog: ["Chirp! Not the beak!", "I believe I can fly... away!", "Tweet! Help!"]
}, {
id: 'shaunSnail',
name: 'Shaun the Snail',
dialog: ["Slow down, big guy!", "Shell shocked!", "I was just sliming by..."]
}, {
id: 'daisyHamster',
name: 'Daisy the Hamster',
dialog: ["Eek! Not the cheeks!", "I just cleaned my fur!", "Hamster wheel, activate!"]
}];
// Pick a random animal type
var idx = Math.floor(Math.random() * animalTypes.length);
var type = animalTypes[idx];
self.type = type;
// Attach animal asset
var animalSprite = self.attachAsset(type.id, {
anchorX: 0.5,
anchorY: 0.5
});
self.animalSprite = animalSprite;
// For movement
self.speed = 8 + Math.random() * 8;
self.direction = Math.random() * Math.PI * 2;
self.escapeTimer = 0; // Ticks until animal tries to escape
// Dialog shown when eaten
self.getDialog = function () {
var d = type.dialog;
return d[Math.floor(Math.random() * d.length)];
};
// Move animal in current direction
self.moveAnimal = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
// Bounce off walls
if (self.x < 100) {
self.x = 100;
self.direction = Math.PI - self.direction;
}
if (self.x > 2048 - 100) {
self.x = 2048 - 100;
self.direction = Math.PI - self.direction;
}
if (self.y < 200) {
self.y = 200;
self.direction = -self.direction;
}
if (self.y > 2732 - 100) {
self.y = 2732 - 100;
self.direction = -self.direction;
}
};
// Try to escape after a while
self.tryEscape = function () {
// After 5-8 seconds, animal flees off screen
if (self.escapeTimer === 0) {
self.escapeTimer = LK.ticks + 300 + Math.floor(Math.random() * 180);
}
if (LK.ticks > self.escapeTimer) {
// Flee in random direction toward nearest edge
var edgeX = self.x < 1024 ? -200 : 2248;
var edgeY = self.y < 1366 ? -200 : 2932;
var dx = edgeX - self.x;
var dy = edgeY - self.y;
self.direction = Math.atan2(dy, dx);
self.speed = 22;
}
};
return self;
});
// Dad Snake class
var DadSnake = Container.expand(function () {
var self = Container.call(this);
// Head
var head = self.attachAsset('dadSnakeHead', {
anchorX: 0.5,
anchorY: 0.5
});
self.head = head;
// Body segments (start with 2)
self.bodySegments = [];
for (var i = 0; i < 2; i++) {
var seg = LK.getAsset('dadSnakeBody', {
anchorX: 0.5,
anchorY: 0.5
});
seg.x = -((i + 1) * 130);
seg.y = 0;
self.addChild(seg);
self.bodySegments.push(seg);
}
// Belly bulges (for eaten animals)
self.bellyBulges = [];
// Snake direction (angle in radians)
self.direction = 0;
// Snake speed
self.speed = 18;
// For dragging
self.isDragging = false;
// Move snake towards a target (x, y)
self.moveToward = function (tx, ty) {
var dx = tx - self.x;
var dy = ty - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < self.speed) {
self.x = tx;
self.y = ty;
return;
}
var angle = Math.atan2(dy, dx);
self.direction = angle;
self.x += Math.cos(angle) * self.speed;
self.y += Math.sin(angle) * self.speed;
};
// Update body segments to follow head
self.updateBody = function () {
var prevX = self.x;
var prevY = self.y;
for (var i = 0; i < self.bodySegments.length; i++) {
var seg = self.bodySegments[i];
var dx = prevX - seg.x;
var dy = prevY - seg.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 130) {
var angle = Math.atan2(dy, dx);
seg.x += Math.cos(angle) * (dist - 130);
seg.y += Math.sin(angle) * (dist - 130);
}
prevX = seg.x;
prevY = seg.y;
}
// Belly bulges follow body segments
for (var j = 0; j < self.bellyBulges.length; j++) {
var bulge = self.bellyBulges[j];
var segIdx = Math.min(j, self.bodySegments.length - 1);
var seg = self.bodySegments[segIdx];
bulge.x = seg.x;
bulge.y = seg.y;
}
};
// Add a belly bulge (when eating an animal)
self.addBellyBulge = function () {
var bulge = LK.getAsset('dadSnakeBelly', {
anchorX: 0.5,
anchorY: 0.5
});
// Place on last body segment
var segIdx = Math.min(self.bellyBulges.length, self.bodySegments.length - 1);
var seg = self.bodySegments[segIdx];
bulge.x = seg.x;
bulge.y = seg.y;
self.addChild(bulge);
self.bellyBulges.push(bulge);
};
// Remove all belly bulges (on reset)
self.clearBellyBulges = function () {
for (var i = 0; i < self.bellyBulges.length; i++) {
self.bellyBulges[i].destroy();
}
self.bellyBulges = [];
};
return self;
});
// Dialog bubble class
var DialogBubble = Container.expand(function () {
var self = Container.call(this);
var bubble = self.attachAsset('dialogBubble', {
anchorX: 0.5,
anchorY: 1
});
self.bubble = bubble;
var txt = new Text2('', {
size: 60,
fill: 0x222222
});
txt.anchor.set(0.5, 0.5);
txt.x = 0;
txt.y = -20;
self.addChild(txt);
self.txt = txt;
// Show dialog at (x, y)
self.show = function (text, x, y) {
self.txt.setText(text);
self.x = x;
self.y = y;
self.visible = true;
// Fade in
self.alpha = 0;
tween(self, {
alpha: 1
}, {
duration: 200,
easing: tween.easeIn
});
// Hide after 1.2s
LK.setTimeout(function () {
tween(self, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
self.visible = false;
}
});
}, 1200);
};
self.visible = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xb3e5fc // Light blue sky
});
/****
* Game Code
****/
// Dialog bubble
// Animal assets (distinct colors)
// Dad Snake body (green, long rectangle)
// Center play area
var centerX = 2048 / 2;
var centerY = 2732 / 2;
// Dad Snake
var dadSnake = new DadSnake();
dadSnake.x = centerX;
dadSnake.y = centerY + 400;
game.addChild(dadSnake);
// Animals array
var animals = [];
// Dialog bubble
var dialogBubble = new DialogBubble();
game.addChild(dialogBubble);
// Score text
var scoreTxt = new Text2('0', {
size: 120,
fill: 0x222222
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Dad Snake dialog text (above head)
var dadDialog = new Text2('', {
size: 70,
fill: 0x388E3C
});
dadDialog.anchor.set(0.5, 1);
dadDialog.x = 0;
dadDialog.y = -120;
dadSnake.addChild(dadDialog);
// Game state
var dragging = false;
var targetX = dadSnake.x;
var targetY = dadSnake.y;
var animalsEaten = 0;
var totalAnimals = 5;
var gameOver = false;
// Animal names for unique spawn
var animalTypes = ['peterPig', 'marvinSnake', 'birdo', 'shaunSnail', 'daisyHamster'];
// Spawn all animals at random positions
function spawnAnimals() {
for (var i = 0; i < animalTypes.length; i++) {
var animal = new Animal();
// Place randomly, not too close to Dad Snake
var placed = false;
while (!placed) {
animal.x = 200 + Math.random() * (2048 - 400);
animal.y = 400 + Math.random() * (2732 - 800);
var dx = animal.x - dadSnake.x;
var dy = animal.y - dadSnake.y;
if (Math.sqrt(dx * dx + dy * dy) > 500) placed = true;
}
animals.push(animal);
game.addChild(animal);
}
}
spawnAnimals();
// Helper: show Dad Snake dialog
function showDadDialog(text) {
dadDialog.setText(text);
dadDialog.alpha = 1;
tween(dadDialog, {
alpha: 0
}, {
duration: 1200,
easing: tween.linear
});
}
// Handle dragging Dad Snake
game.down = function (x, y, obj) {
// Don't allow drag if game over
if (gameOver) return;
dragging = true;
targetX = x;
targetY = y;
dadSnake.isDragging = true;
};
game.move = function (x, y, obj) {
if (dragging && !gameOver) {
targetX = x;
targetY = y;
}
};
game.up = function (x, y, obj) {
dragging = false;
dadSnake.isDragging = false;
};
// Main update loop
game.update = function () {
if (gameOver) return;
// Move Dad Snake toward target
dadSnake.moveToward(targetX, targetY);
dadSnake.updateBody();
// Move animals
for (var i = animals.length - 1; i >= 0; i--) {
var animal = animals[i];
animal.moveAnimal();
animal.tryEscape();
// If animal escapes off screen, game over
if (animal.x < -150 || animal.x > 2048 + 150 || animal.y < -150 || animal.y > 2732 + 150) {
// Show dialog
dialogBubble.show(animal.type.name + " escaped!", dadSnake.x, dadSnake.y - 200);
showDadDialog("Oh no! " + animal.type.name + " got away!");
LK.effects.flashScreen(0xff0000, 800);
gameOver = true;
LK.setTimeout(function () {
LK.showGameOver();
}, 1200);
return;
}
// Check collision with Dad Snake head
if (dadSnake.head.intersects(animal.animalSprite)) {
// Eat animal
animalsEaten++;
LK.setScore(animalsEaten);
scoreTxt.setText(animalsEaten);
// Show dialog
dialogBubble.show(animal.getDialog(), animal.x, animal.y - 120);
// Dad Snake comment
var dadLines = ["Yum! That hit the spot.", "Mmm, tasty!", "Gulp! Down the hatch.", "My tummy's getting full!", "Slurp! Who's next?"];
showDadDialog(dadLines[Math.floor(Math.random() * dadLines.length)]);
// Add belly bulge
dadSnake.addBellyBulge();
// Add body segment for fun
var seg = LK.getAsset('dadSnakeBody', {
anchorX: 0.5,
anchorY: 0.5
});
var lastSeg = dadSnake.bodySegments[dadSnake.bodySegments.length - 1];
seg.x = lastSeg.x - 130;
seg.y = lastSeg.y;
dadSnake.addChild(seg);
dadSnake.bodySegments.push(seg);
// Remove animal
animal.destroy();
animals.splice(i, 1);
// Win condition
if (animalsEaten >= totalAnimals) {
showDadDialog("Burp! All gone!");
LK.effects.flashScreen(0x8bc34a, 1000);
gameOver = true;
LK.setTimeout(function () {
LK.showYouWin();
}, 1200);
return;
}
}
}
};
// Reset state on game restart
game.on('reset', function () {
// Remove animals
for (var i = 0; i < animals.length; i++) {
animals[i].destroy();
}
animals = [];
animalsEaten = 0;
LK.setScore(0);
scoreTxt.setText('0');
dadSnake.x = centerX;
dadSnake.y = centerY + 400;
dadSnake.clearBellyBulges();
// Remove extra body segments
while (dadSnake.bodySegments.length > 2) {
var seg = dadSnake.bodySegments.pop();
seg.destroy();
}
dialogBubble.visible = false;
dadDialog.setText('');
gameOver = false;
spawnAnimals();
});