/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Mouse = Container.expand(function () {
var self = Container.call(this);
var mouseGraphics = self.attachAsset('mouse', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
// Spawn within arena bounds
self.x = 124 + 50 + Math.random() * (1800 - 100);
self.y = 166 + 50 + Math.random() * (2400 - 100);
};
return self;
});
var PoisonApple = Container.expand(function () {
var self = Container.call(this);
var appleGraphics = self.attachAsset('poisonApple', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
// Spawn within arena bounds
self.x = 124 + 50 + Math.random() * (1800 - 100);
self.y = 166 + 50 + Math.random() * (2400 - 100);
};
return self;
});
var Snake = Container.expand(function () {
var self = Container.call(this);
self.segments = [];
self.direction = {
x: 1,
y: 0
};
self.speed = 4;
self.segmentSize = 60;
// Create initial snake with 3 segments
for (var i = 0; i < 3; i++) {
var segment;
if (i === 0) {
segment = self.attachAsset('snakeHead', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
segment = self.attachAsset('snakeSegment', {
anchorX: 0.5,
anchorY: 0.5
});
}
segment.x = 1024 - i * self.segmentSize;
segment.y = 1366;
self.segments.push(segment);
}
self.update = function () {
// Move head
var head = self.segments[0];
head.x += self.direction.x * self.speed;
head.y += self.direction.y * self.speed;
// Keep snake within arena bounds
if (head.x < 124 + 30) head.x = 124 + 30;
if (head.x > 1924 - 30) head.x = 1924 - 30;
if (head.y < 166 + 30) head.y = 166 + 30;
if (head.y > 2566 - 30) head.y = 2566 - 30;
// Move body segments
for (var i = 1; i < self.segments.length; i++) {
var segment = self.segments[i];
var prevSegment = self.segments[i - 1];
var dx = prevSegment.x - segment.x;
var dy = prevSegment.y - segment.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.segmentSize) {
segment.x += dx / distance * self.speed;
segment.y += dy / distance * self.speed;
}
}
};
self.getHead = function () {
return self.segments[0];
};
self.grow = function () {
var lastSegment = self.segments[self.segments.length - 1];
var newSegment = self.attachAsset('snakeSegment', {
anchorX: 0.5,
anchorY: 0.5
});
newSegment.x = lastSegment.x;
newSegment.y = lastSegment.y;
self.segments.push(newSegment);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E7D32
});
/****
* Game Code
****/
// Game arena
var arena = game.attachAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
// Game variables
var snake = game.addChild(new Snake());
var mice = [];
var maxMice = 8;
var poisonApples = [];
var maxPoisonApples = 2;
var stamina = 30;
var maxStamina = 30;
var staminaDrainTimer = 0;
var mouseSpawnTimer = 0;
var poisonAppleSpawnTimer = 0;
var gameRunning = true;
var isPoisoned = false;
var poisonTimer = 0;
var poisonDuration = 600; // 10 seconds at 60 FPS
// UI Elements
var staminaBarBg = LK.getAsset('arena', {
anchorX: 0,
anchorY: 0,
scaleX: 0.28,
scaleY: 0.04,
x: 0,
y: 0
});
staminaBarBg.tint = 0x333333;
LK.gui.topLeft.addChild(staminaBarBg);
var staminaBarFill = LK.getAsset('arena', {
anchorX: 0,
anchorY: 0,
scaleX: 0.28,
scaleY: 0.04,
x: 0,
y: 0
});
staminaBarFill.tint = 0xFF4444;
LK.gui.topLeft.addChild(staminaBarFill);
var staminaText = new Text2('Stamina: 30', {
size: 60,
fill: 0xFFFFFF
});
staminaText.anchor.set(0, 0);
staminaText.x = 0;
staminaText.y = 120;
LK.gui.topLeft.addChild(staminaText);
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Initialize mice
function spawnMouse() {
if (mice.length < maxMice) {
var mouse = new Mouse();
mouse.spawn();
mice.push(mouse);
game.addChild(mouse);
}
}
// Spawn poison apple function
function spawnPoisonApple() {
if (poisonApples.length < maxPoisonApples) {
var poisonApple = new PoisonApple();
poisonApple.spawn();
poisonApples.push(poisonApple);
game.addChild(poisonApple);
}
}
// Initial mouse spawning
for (var i = 0; i < maxMice; i++) {
spawnMouse();
}
// Initial poison apple spawning
for (var i = 0; i < maxPoisonApples; i++) {
spawnPoisonApple();
}
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var isTouch = false;
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
isTouch = true;
};
game.up = function (x, y, obj) {
if (!gameRunning || !isTouch) return;
var deltaX = x - touchStartX;
var deltaY = y - touchStartY;
var minSwipeDistance = 50;
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > minSwipeDistance) {
// Horizontal swipe
if (deltaX > 0 && snake.direction.x !== -1) {
snake.direction = {
x: 1,
y: 0
}; // Right
} else if (deltaX < 0 && snake.direction.x !== 1) {
snake.direction = {
x: -1,
y: 0
}; // Left
}
} else if (Math.abs(deltaY) > minSwipeDistance) {
// Vertical swipe
if (deltaY > 0 && snake.direction.y !== -1) {
snake.direction = {
x: 0,
y: 1
}; // Down
} else if (deltaY < 0 && snake.direction.y !== 1) {
snake.direction = {
x: 0,
y: -1
}; // Up
}
}
isTouch = false;
};
function updateStaminaBar() {
var staminaPercentage = stamina / maxStamina;
staminaBarFill.scaleX = 0.28 * staminaPercentage;
// Change color based on stamina level
if (staminaPercentage > 0.6) {
staminaBarFill.tint = 0x4CAF50; // Green
} else if (staminaPercentage > 0.3) {
staminaBarFill.tint = 0xFFC107; // Yellow
} else {
staminaBarFill.tint = 0xFF4444; // Red
}
}
function checkMouseCollisions() {
var head = snake.getHead();
for (var i = mice.length - 1; i >= 0; i--) {
var mouse = mice[i];
if (head.intersects(mouse)) {
// Eat mouse
stamina = Math.min(maxStamina, stamina + 2);
LK.setScore(LK.getScore() + 10);
scoreText.setText('Score: ' + LK.getScore());
staminaText.setText('Stamina: ' + Math.ceil(stamina));
// Visual feedback
LK.effects.flashObject(mouse, 0xFFFFFF, 200);
// Play eat sound
LK.getSound('eat').play();
// Remove mouse and spawn new one
mouse.destroy();
mice.splice(i, 1);
// Grow snake slightly
snake.grow();
break;
}
}
}
function checkPoisonAppleCollisions() {
var head = snake.getHead();
for (var i = poisonApples.length - 1; i >= 0; i--) {
var poisonApple = poisonApples[i];
if (head.intersects(poisonApple)) {
// Apply poison effect
isPoisoned = true;
poisonTimer = poisonDuration;
// Visual feedback - flash red and scale effect
LK.effects.flashObject(poisonApple, 0xFF0000, 300);
tween(snake.getHead(), {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(snake.getHead(), {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
// Remove poison apple
poisonApple.destroy();
poisonApples.splice(i, 1);
break;
}
}
}
game.update = function () {
if (!gameRunning) return;
// Update poison timer
if (isPoisoned) {
poisonTimer--;
if (poisonTimer <= 0) {
isPoisoned = false;
// Visual feedback when poison wears off
tween(snake.getHead(), {
tint: 0xFFFFFF
}, {
duration: 500,
easing: tween.easeOut
});
} else {
// Keep snake tinted while poisoned
snake.getHead().tint = 0xFF6666;
}
}
// Update stamina drain timer
staminaDrainTimer++;
var drainRate = isPoisoned ? 2 : 1; // Double drain when poisoned
if (staminaDrainTimer >= 60) {
// 1 second at 60 FPS
var oldStamina = stamina;
stamina -= drainRate;
staminaDrainTimer = 0;
staminaText.setText('Stamina: ' + Math.ceil(stamina));
// Update snake size based on stamina level
var staminaPercentage = Math.max(0.1, stamina / maxStamina); // Minimum 10% size
var targetScale = 0.4 + staminaPercentage * 0.6; // Scale from 0.4 to 1.0
// Apply smooth scaling transition to all snake segments
for (var s = 0; s < snake.segments.length; s++) {
tween(snake.segments[s], {
scaleX: targetScale,
scaleY: targetScale
}, {
duration: 200,
easing: tween.easeOut
});
}
if (stamina <= 0) {
gameRunning = false;
LK.getSound('gameOver').play();
LK.showGameOver();
return;
}
}
// Update stamina bar
updateStaminaBar();
// Check mouse collisions
checkMouseCollisions();
// Check poison apple collisions
checkPoisonAppleCollisions();
// Spawn new mice periodically
mouseSpawnTimer++;
if (mouseSpawnTimer >= 180 && mice.length < maxMice) {
// Every 3 seconds
spawnMouse();
mouseSpawnTimer = 0;
}
// Spawn new poison apples periodically
poisonAppleSpawnTimer++;
if (poisonAppleSpawnTimer >= 300 && poisonApples.length < maxPoisonApples) {
// Every 5 seconds
spawnPoisonApple();
poisonAppleSpawnTimer = 0;
}
// Update score based on survival time
if (LK.ticks % 60 === 0) {
// Every second
LK.setScore(LK.getScore() + 1);
scoreText.setText('Score: ' + LK.getScore());
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Mouse = Container.expand(function () {
var self = Container.call(this);
var mouseGraphics = self.attachAsset('mouse', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
// Spawn within arena bounds
self.x = 124 + 50 + Math.random() * (1800 - 100);
self.y = 166 + 50 + Math.random() * (2400 - 100);
};
return self;
});
var PoisonApple = Container.expand(function () {
var self = Container.call(this);
var appleGraphics = self.attachAsset('poisonApple', {
anchorX: 0.5,
anchorY: 0.5
});
self.spawn = function () {
// Spawn within arena bounds
self.x = 124 + 50 + Math.random() * (1800 - 100);
self.y = 166 + 50 + Math.random() * (2400 - 100);
};
return self;
});
var Snake = Container.expand(function () {
var self = Container.call(this);
self.segments = [];
self.direction = {
x: 1,
y: 0
};
self.speed = 4;
self.segmentSize = 60;
// Create initial snake with 3 segments
for (var i = 0; i < 3; i++) {
var segment;
if (i === 0) {
segment = self.attachAsset('snakeHead', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
segment = self.attachAsset('snakeSegment', {
anchorX: 0.5,
anchorY: 0.5
});
}
segment.x = 1024 - i * self.segmentSize;
segment.y = 1366;
self.segments.push(segment);
}
self.update = function () {
// Move head
var head = self.segments[0];
head.x += self.direction.x * self.speed;
head.y += self.direction.y * self.speed;
// Keep snake within arena bounds
if (head.x < 124 + 30) head.x = 124 + 30;
if (head.x > 1924 - 30) head.x = 1924 - 30;
if (head.y < 166 + 30) head.y = 166 + 30;
if (head.y > 2566 - 30) head.y = 2566 - 30;
// Move body segments
for (var i = 1; i < self.segments.length; i++) {
var segment = self.segments[i];
var prevSegment = self.segments[i - 1];
var dx = prevSegment.x - segment.x;
var dy = prevSegment.y - segment.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.segmentSize) {
segment.x += dx / distance * self.speed;
segment.y += dy / distance * self.speed;
}
}
};
self.getHead = function () {
return self.segments[0];
};
self.grow = function () {
var lastSegment = self.segments[self.segments.length - 1];
var newSegment = self.attachAsset('snakeSegment', {
anchorX: 0.5,
anchorY: 0.5
});
newSegment.x = lastSegment.x;
newSegment.y = lastSegment.y;
self.segments.push(newSegment);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E7D32
});
/****
* Game Code
****/
// Game arena
var arena = game.attachAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
// Game variables
var snake = game.addChild(new Snake());
var mice = [];
var maxMice = 8;
var poisonApples = [];
var maxPoisonApples = 2;
var stamina = 30;
var maxStamina = 30;
var staminaDrainTimer = 0;
var mouseSpawnTimer = 0;
var poisonAppleSpawnTimer = 0;
var gameRunning = true;
var isPoisoned = false;
var poisonTimer = 0;
var poisonDuration = 600; // 10 seconds at 60 FPS
// UI Elements
var staminaBarBg = LK.getAsset('arena', {
anchorX: 0,
anchorY: 0,
scaleX: 0.28,
scaleY: 0.04,
x: 0,
y: 0
});
staminaBarBg.tint = 0x333333;
LK.gui.topLeft.addChild(staminaBarBg);
var staminaBarFill = LK.getAsset('arena', {
anchorX: 0,
anchorY: 0,
scaleX: 0.28,
scaleY: 0.04,
x: 0,
y: 0
});
staminaBarFill.tint = 0xFF4444;
LK.gui.topLeft.addChild(staminaBarFill);
var staminaText = new Text2('Stamina: 30', {
size: 60,
fill: 0xFFFFFF
});
staminaText.anchor.set(0, 0);
staminaText.x = 0;
staminaText.y = 120;
LK.gui.topLeft.addChild(staminaText);
var scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Initialize mice
function spawnMouse() {
if (mice.length < maxMice) {
var mouse = new Mouse();
mouse.spawn();
mice.push(mouse);
game.addChild(mouse);
}
}
// Spawn poison apple function
function spawnPoisonApple() {
if (poisonApples.length < maxPoisonApples) {
var poisonApple = new PoisonApple();
poisonApple.spawn();
poisonApples.push(poisonApple);
game.addChild(poisonApple);
}
}
// Initial mouse spawning
for (var i = 0; i < maxMice; i++) {
spawnMouse();
}
// Initial poison apple spawning
for (var i = 0; i < maxPoisonApples; i++) {
spawnPoisonApple();
}
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var isTouch = false;
game.down = function (x, y, obj) {
touchStartX = x;
touchStartY = y;
isTouch = true;
};
game.up = function (x, y, obj) {
if (!gameRunning || !isTouch) return;
var deltaX = x - touchStartX;
var deltaY = y - touchStartY;
var minSwipeDistance = 50;
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > minSwipeDistance) {
// Horizontal swipe
if (deltaX > 0 && snake.direction.x !== -1) {
snake.direction = {
x: 1,
y: 0
}; // Right
} else if (deltaX < 0 && snake.direction.x !== 1) {
snake.direction = {
x: -1,
y: 0
}; // Left
}
} else if (Math.abs(deltaY) > minSwipeDistance) {
// Vertical swipe
if (deltaY > 0 && snake.direction.y !== -1) {
snake.direction = {
x: 0,
y: 1
}; // Down
} else if (deltaY < 0 && snake.direction.y !== 1) {
snake.direction = {
x: 0,
y: -1
}; // Up
}
}
isTouch = false;
};
function updateStaminaBar() {
var staminaPercentage = stamina / maxStamina;
staminaBarFill.scaleX = 0.28 * staminaPercentage;
// Change color based on stamina level
if (staminaPercentage > 0.6) {
staminaBarFill.tint = 0x4CAF50; // Green
} else if (staminaPercentage > 0.3) {
staminaBarFill.tint = 0xFFC107; // Yellow
} else {
staminaBarFill.tint = 0xFF4444; // Red
}
}
function checkMouseCollisions() {
var head = snake.getHead();
for (var i = mice.length - 1; i >= 0; i--) {
var mouse = mice[i];
if (head.intersects(mouse)) {
// Eat mouse
stamina = Math.min(maxStamina, stamina + 2);
LK.setScore(LK.getScore() + 10);
scoreText.setText('Score: ' + LK.getScore());
staminaText.setText('Stamina: ' + Math.ceil(stamina));
// Visual feedback
LK.effects.flashObject(mouse, 0xFFFFFF, 200);
// Play eat sound
LK.getSound('eat').play();
// Remove mouse and spawn new one
mouse.destroy();
mice.splice(i, 1);
// Grow snake slightly
snake.grow();
break;
}
}
}
function checkPoisonAppleCollisions() {
var head = snake.getHead();
for (var i = poisonApples.length - 1; i >= 0; i--) {
var poisonApple = poisonApples[i];
if (head.intersects(poisonApple)) {
// Apply poison effect
isPoisoned = true;
poisonTimer = poisonDuration;
// Visual feedback - flash red and scale effect
LK.effects.flashObject(poisonApple, 0xFF0000, 300);
tween(snake.getHead(), {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut
});
tween(snake.getHead(), {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
// Remove poison apple
poisonApple.destroy();
poisonApples.splice(i, 1);
break;
}
}
}
game.update = function () {
if (!gameRunning) return;
// Update poison timer
if (isPoisoned) {
poisonTimer--;
if (poisonTimer <= 0) {
isPoisoned = false;
// Visual feedback when poison wears off
tween(snake.getHead(), {
tint: 0xFFFFFF
}, {
duration: 500,
easing: tween.easeOut
});
} else {
// Keep snake tinted while poisoned
snake.getHead().tint = 0xFF6666;
}
}
// Update stamina drain timer
staminaDrainTimer++;
var drainRate = isPoisoned ? 2 : 1; // Double drain when poisoned
if (staminaDrainTimer >= 60) {
// 1 second at 60 FPS
var oldStamina = stamina;
stamina -= drainRate;
staminaDrainTimer = 0;
staminaText.setText('Stamina: ' + Math.ceil(stamina));
// Update snake size based on stamina level
var staminaPercentage = Math.max(0.1, stamina / maxStamina); // Minimum 10% size
var targetScale = 0.4 + staminaPercentage * 0.6; // Scale from 0.4 to 1.0
// Apply smooth scaling transition to all snake segments
for (var s = 0; s < snake.segments.length; s++) {
tween(snake.segments[s], {
scaleX: targetScale,
scaleY: targetScale
}, {
duration: 200,
easing: tween.easeOut
});
}
if (stamina <= 0) {
gameRunning = false;
LK.getSound('gameOver').play();
LK.showGameOver();
return;
}
}
// Update stamina bar
updateStaminaBar();
// Check mouse collisions
checkMouseCollisions();
// Check poison apple collisions
checkPoisonAppleCollisions();
// Spawn new mice periodically
mouseSpawnTimer++;
if (mouseSpawnTimer >= 180 && mice.length < maxMice) {
// Every 3 seconds
spawnMouse();
mouseSpawnTimer = 0;
}
// Spawn new poison apples periodically
poisonAppleSpawnTimer++;
if (poisonAppleSpawnTimer >= 300 && poisonApples.length < maxPoisonApples) {
// Every 5 seconds
spawnPoisonApple();
poisonAppleSpawnTimer = 0;
}
// Update score based on survival time
if (LK.ticks % 60 === 0) {
// Every second
LK.setScore(LK.getScore() + 1);
scoreText.setText('Score: ' + LK.getScore());
}
};