/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Animal class
var Animal = Container.expand(function () {
var self = Container.call(this);
self.type = null;
self.asset = null;
self.setType = function (type) {
self.type = type;
if (self.asset) {
self.removeChild(self.asset);
}
self.asset = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
// Snake Segment (body or head)
var SnakeSegment = Container.expand(function () {
var self = Container.call(this);
self.asset = null;
self.setType = function (type) {
if (self.asset) {
self.removeChild(self.asset);
}
var assetId = type === 'head' ? 'snakeHead' : 'snakeBody';
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.setType('body');
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Animal assets: pig, cat, bee, frog (box/ellipse with different colors)
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var SNAKE_START_LENGTH = 3;
var SNAKE_START_SPEED = 8; // pixels per tick
var SNAKE_SPEED_INCREMENT = 1.5; // speed up per sequence
var SNAKE_MAX_SPEED = 32;
var SEGMENT_SPACING = 90; // px between segments
var ANIMAL_TYPES = ['pig', 'cat', 'bee', 'frog'];
var ANIMAL_NAMES = {
pig: "Pig",
cat: "Cat",
bee: "Bee",
frog: "Frog"
};
// Game state
var snake = [];
var snakeDir = {
x: 0,
y: -1
}; // start moving up
var snakeNextDir = {
x: 0,
y: -1
};
var snakeSpeed = SNAKE_START_SPEED;
var snakePositions = []; // for body following
var animals = [];
var currentTargetIndex = 0; // which animal in sequence to eat next
var score = 0;
var sequenceCount = 0;
var isGameOver = false;
var moveCooldown = 0; // for swipe input
var dragStart = null;
// GUI
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var orderTxt = new Text2('', {
size: 70,
fill: "#fff"
});
orderTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(orderTxt);
orderTxt.y = 130;
// Helper: get random position for animal, not too close to snake head
function getRandomAnimalPos() {
var margin = 180;
var tries = 0;
while (tries < 20) {
var x = margin + Math.random() * (GAME_WIDTH - 2 * margin);
var y = margin + Math.random() * (GAME_HEIGHT - 2 * margin);
// Avoid spawning too close to snake head
var dx = x - snake[0].x;
var dy = y - snake[0].y;
if (dx * dx + dy * dy > 400 * 400) {
return {
x: x,
y: y
};
}
tries++;
}
// fallback
return {
x: margin + Math.random() * (GAME_WIDTH - 2 * margin),
y: margin + Math.random() * (GAME_HEIGHT - 2 * margin)
};
}
// Helper: update order text
function updateOrderText() {
var s = '';
for (var i = 0; i < ANIMAL_TYPES.length; i++) {
if (i === currentTargetIndex) {
s += '[b]' + ANIMAL_NAMES[ANIMAL_TYPES[i]] + '[/b] ';
} else {
s += ANIMAL_NAMES[ANIMAL_TYPES[i]] + ' ';
}
}
orderTxt.setText(s.trim());
}
// Helper: spawn all animals
function spawnAnimals() {
// Remove old
for (var i = 0; i < animals.length; i++) {
animals[i].destroy();
}
animals = [];
for (var i = 0; i < ANIMAL_TYPES.length; i++) {
var animal = new Animal();
animal.setType(ANIMAL_TYPES[i]);
var pos = getRandomAnimalPos();
animal.x = pos.x;
animal.y = pos.y;
animals.push(animal);
game.addChild(animal);
}
}
// Helper: reset snake
function resetSnake() {
for (var i = 0; i < snake.length; i++) {
snake[i].destroy();
}
snake = [];
snakePositions = [];
var startX = GAME_WIDTH / 2;
var startY = GAME_HEIGHT / 2 + 300;
for (var i = 0; i < SNAKE_START_LENGTH; i++) {
var seg = new SnakeSegment();
seg.setType(i === 0 ? 'head' : 'body');
seg.x = startX;
seg.y = startY + i * SEGMENT_SPACING;
snake.push(seg);
game.addChild(seg);
snakePositions.push({
x: seg.x,
y: seg.y
});
}
snakeDir = {
x: 0,
y: -1
};
snakeNextDir = {
x: 0,
y: -1
};
}
// Helper: grow snake
function growSnake() {
var last = snake[snake.length - 1];
var seg = new SnakeSegment();
seg.setType('body');
seg.x = last.x;
seg.y = last.y;
snake.push(seg);
game.addChild(seg);
snakePositions.push({
x: seg.x,
y: seg.y
});
}
// Helper: check self collision
function checkSelfCollision() {
var head = snake[0];
for (var i = 2; i < snake.length; i++) {
var seg = snake[i];
var dx = head.x - seg.x;
var dy = head.y - seg.y;
if (dx * dx + dy * dy < 60 * 60) {
return true;
}
}
return false;
}
// Helper: check wall collision
function checkWallCollision() {
var head = snake[0];
var margin = 40;
if (head.x < margin || head.x > GAME_WIDTH - margin || head.y < margin || head.y > GAME_HEIGHT - margin) {
return true;
}
return false;
}
// Helper: check animal collision
function checkAnimalCollision() {
var head = snake[0];
for (var i = 0; i < animals.length; i++) {
var animal = animals[i];
var dx = head.x - animal.x;
var dy = head.y - animal.y;
if (dx * dx + dy * dy < 80 * 80) {
return i;
}
}
return -1;
}
// Helper: handle eating animal
function eatAnimal(idx) {
var animal = animals[idx];
if (animal.type === ANIMAL_TYPES[currentTargetIndex]) {
// Correct animal
growSnake();
score++;
scoreTxt.setText(score);
// Remove and respawn this animal
animal.destroy();
animals.splice(idx, 1);
// Next in sequence
currentTargetIndex++;
if (currentTargetIndex >= ANIMAL_TYPES.length) {
// Sequence complete
sequenceCount++;
currentTargetIndex = 0;
// Speed up
snakeSpeed = Math.min(snakeSpeed + SNAKE_SPEED_INCREMENT, SNAKE_MAX_SPEED);
// Respawn all animals
spawnAnimals();
// Flash green
LK.effects.flashScreen(0x00ff00, 400);
} else {
// Only respawn this animal
var newAnimal = new Animal();
newAnimal.setType(animal.type);
var pos = getRandomAnimalPos();
newAnimal.x = pos.x;
newAnimal.y = pos.y;
animals.push(newAnimal);
game.addChild(newAnimal);
}
updateOrderText();
} else {
// Wrong animal: game over
LK.effects.flashScreen(0xff0000, 800);
isGameOver = true;
LK.showGameOver();
}
}
// Helper: handle game over
function handleGameOver() {
isGameOver = true;
// LK.showGameOver() already called
}
// Input: swipe to change direction
function getSwipeDir(dx, dy) {
if (Math.abs(dx) > Math.abs(dy)) {
return {
x: dx > 0 ? 1 : -1,
y: 0
};
} else {
return {
x: 0,
y: dy > 0 ? 1 : -1
};
}
}
// Input: touch/drag
game.down = function (x, y, obj) {
dragStart = {
x: x,
y: y
};
};
game.up = function (x, y, obj) {
dragStart = null;
};
game.move = function (x, y, obj) {
if (dragStart && !isGameOver) {
var dx = x - dragStart.x;
var dy = y - dragStart.y;
if (dx * dx + dy * dy > 80 * 80) {
var dir = getSwipeDir(dx, dy);
// Prevent reversing
if (!(dir.x === -snakeDir.x && dir.y === -snakeDir.y)) {
snakeNextDir = dir;
}
dragStart = null;
}
}
};
// Main update loop
game.update = function () {
if (isGameOver) return;
// Move snake
// Update direction
if (snakeNextDir.x !== snakeDir.x || snakeNextDir.y !== snakeDir.y) {
snakeDir = {
x: snakeNextDir.x,
y: snakeNextDir.y
};
}
// Calculate new head position
var head = snake[0];
var newX = head.x + snakeDir.x * snakeSpeed;
var newY = head.y + snakeDir.y * snakeSpeed;
// Store previous positions
snakePositions.unshift({
x: newX,
y: newY
});
if (snakePositions.length > snake.length * SEGMENT_SPACING / snakeSpeed + 2) {
snakePositions.pop();
}
// Move segments
for (var i = 0; i < snake.length; i++) {
var posIdx = Math.min(i * Math.floor(SEGMENT_SPACING / snakeSpeed), snakePositions.length - 1);
var pos = snakePositions[posIdx];
snake[i].x = pos.x;
snake[i].y = pos.y;
}
// Check wall collision
if (checkWallCollision()) {
LK.effects.flashScreen(0xff0000, 800);
handleGameOver();
LK.showGameOver();
return;
}
// Check self collision
if (checkSelfCollision()) {
LK.effects.flashScreen(0xff0000, 800);
handleGameOver();
LK.showGameOver();
return;
}
// Check animal collision
var animalIdx = checkAnimalCollision();
if (animalIdx !== -1) {
eatAnimal(animalIdx);
}
};
// Game start/reset
function startGame() {
isGameOver = false;
score = 0;
sequenceCount = 0;
snakeSpeed = SNAKE_START_SPEED;
currentTargetIndex = 0;
scoreTxt.setText(score);
updateOrderText();
resetSnake();
spawnAnimals();
}
startGame(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,381 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Animal class
+var Animal = Container.expand(function () {
+ var self = Container.call(this);
+ self.type = null;
+ self.asset = null;
+ self.setType = function (type) {
+ self.type = type;
+ if (self.asset) {
+ self.removeChild(self.asset);
+ }
+ self.asset = self.attachAsset(type, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ };
+ return self;
+});
+// Snake Segment (body or head)
+var SnakeSegment = Container.expand(function () {
+ var self = Container.call(this);
+ self.asset = null;
+ self.setType = function (type) {
+ if (self.asset) {
+ self.removeChild(self.asset);
+ }
+ var assetId = type === 'head' ? 'snakeHead' : 'snakeBody';
+ self.asset = self.attachAsset(assetId, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ };
+ self.setType('body');
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x222222
+});
+
+/****
+* Game Code
+****/
+// Animal assets: pig, cat, bee, frog (box/ellipse with different colors)
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var SNAKE_START_LENGTH = 3;
+var SNAKE_START_SPEED = 8; // pixels per tick
+var SNAKE_SPEED_INCREMENT = 1.5; // speed up per sequence
+var SNAKE_MAX_SPEED = 32;
+var SEGMENT_SPACING = 90; // px between segments
+var ANIMAL_TYPES = ['pig', 'cat', 'bee', 'frog'];
+var ANIMAL_NAMES = {
+ pig: "Pig",
+ cat: "Cat",
+ bee: "Bee",
+ frog: "Frog"
+};
+// Game state
+var snake = [];
+var snakeDir = {
+ x: 0,
+ y: -1
+}; // start moving up
+var snakeNextDir = {
+ x: 0,
+ y: -1
+};
+var snakeSpeed = SNAKE_START_SPEED;
+var snakePositions = []; // for body following
+var animals = [];
+var currentTargetIndex = 0; // which animal in sequence to eat next
+var score = 0;
+var sequenceCount = 0;
+var isGameOver = false;
+var moveCooldown = 0; // for swipe input
+var dragStart = null;
+// GUI
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+var orderTxt = new Text2('', {
+ size: 70,
+ fill: "#fff"
+});
+orderTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(orderTxt);
+orderTxt.y = 130;
+// Helper: get random position for animal, not too close to snake head
+function getRandomAnimalPos() {
+ var margin = 180;
+ var tries = 0;
+ while (tries < 20) {
+ var x = margin + Math.random() * (GAME_WIDTH - 2 * margin);
+ var y = margin + Math.random() * (GAME_HEIGHT - 2 * margin);
+ // Avoid spawning too close to snake head
+ var dx = x - snake[0].x;
+ var dy = y - snake[0].y;
+ if (dx * dx + dy * dy > 400 * 400) {
+ return {
+ x: x,
+ y: y
+ };
+ }
+ tries++;
+ }
+ // fallback
+ return {
+ x: margin + Math.random() * (GAME_WIDTH - 2 * margin),
+ y: margin + Math.random() * (GAME_HEIGHT - 2 * margin)
+ };
+}
+// Helper: update order text
+function updateOrderText() {
+ var s = '';
+ for (var i = 0; i < ANIMAL_TYPES.length; i++) {
+ if (i === currentTargetIndex) {
+ s += '[b]' + ANIMAL_NAMES[ANIMAL_TYPES[i]] + '[/b] ';
+ } else {
+ s += ANIMAL_NAMES[ANIMAL_TYPES[i]] + ' ';
+ }
+ }
+ orderTxt.setText(s.trim());
+}
+// Helper: spawn all animals
+function spawnAnimals() {
+ // Remove old
+ for (var i = 0; i < animals.length; i++) {
+ animals[i].destroy();
+ }
+ animals = [];
+ for (var i = 0; i < ANIMAL_TYPES.length; i++) {
+ var animal = new Animal();
+ animal.setType(ANIMAL_TYPES[i]);
+ var pos = getRandomAnimalPos();
+ animal.x = pos.x;
+ animal.y = pos.y;
+ animals.push(animal);
+ game.addChild(animal);
+ }
+}
+// Helper: reset snake
+function resetSnake() {
+ for (var i = 0; i < snake.length; i++) {
+ snake[i].destroy();
+ }
+ snake = [];
+ snakePositions = [];
+ var startX = GAME_WIDTH / 2;
+ var startY = GAME_HEIGHT / 2 + 300;
+ for (var i = 0; i < SNAKE_START_LENGTH; i++) {
+ var seg = new SnakeSegment();
+ seg.setType(i === 0 ? 'head' : 'body');
+ seg.x = startX;
+ seg.y = startY + i * SEGMENT_SPACING;
+ snake.push(seg);
+ game.addChild(seg);
+ snakePositions.push({
+ x: seg.x,
+ y: seg.y
+ });
+ }
+ snakeDir = {
+ x: 0,
+ y: -1
+ };
+ snakeNextDir = {
+ x: 0,
+ y: -1
+ };
+}
+// Helper: grow snake
+function growSnake() {
+ var last = snake[snake.length - 1];
+ var seg = new SnakeSegment();
+ seg.setType('body');
+ seg.x = last.x;
+ seg.y = last.y;
+ snake.push(seg);
+ game.addChild(seg);
+ snakePositions.push({
+ x: seg.x,
+ y: seg.y
+ });
+}
+// Helper: check self collision
+function checkSelfCollision() {
+ var head = snake[0];
+ for (var i = 2; i < snake.length; i++) {
+ var seg = snake[i];
+ var dx = head.x - seg.x;
+ var dy = head.y - seg.y;
+ if (dx * dx + dy * dy < 60 * 60) {
+ return true;
+ }
+ }
+ return false;
+}
+// Helper: check wall collision
+function checkWallCollision() {
+ var head = snake[0];
+ var margin = 40;
+ if (head.x < margin || head.x > GAME_WIDTH - margin || head.y < margin || head.y > GAME_HEIGHT - margin) {
+ return true;
+ }
+ return false;
+}
+// Helper: check animal collision
+function checkAnimalCollision() {
+ var head = snake[0];
+ for (var i = 0; i < animals.length; i++) {
+ var animal = animals[i];
+ var dx = head.x - animal.x;
+ var dy = head.y - animal.y;
+ if (dx * dx + dy * dy < 80 * 80) {
+ return i;
+ }
+ }
+ return -1;
+}
+// Helper: handle eating animal
+function eatAnimal(idx) {
+ var animal = animals[idx];
+ if (animal.type === ANIMAL_TYPES[currentTargetIndex]) {
+ // Correct animal
+ growSnake();
+ score++;
+ scoreTxt.setText(score);
+ // Remove and respawn this animal
+ animal.destroy();
+ animals.splice(idx, 1);
+ // Next in sequence
+ currentTargetIndex++;
+ if (currentTargetIndex >= ANIMAL_TYPES.length) {
+ // Sequence complete
+ sequenceCount++;
+ currentTargetIndex = 0;
+ // Speed up
+ snakeSpeed = Math.min(snakeSpeed + SNAKE_SPEED_INCREMENT, SNAKE_MAX_SPEED);
+ // Respawn all animals
+ spawnAnimals();
+ // Flash green
+ LK.effects.flashScreen(0x00ff00, 400);
+ } else {
+ // Only respawn this animal
+ var newAnimal = new Animal();
+ newAnimal.setType(animal.type);
+ var pos = getRandomAnimalPos();
+ newAnimal.x = pos.x;
+ newAnimal.y = pos.y;
+ animals.push(newAnimal);
+ game.addChild(newAnimal);
+ }
+ updateOrderText();
+ } else {
+ // Wrong animal: game over
+ LK.effects.flashScreen(0xff0000, 800);
+ isGameOver = true;
+ LK.showGameOver();
+ }
+}
+// Helper: handle game over
+function handleGameOver() {
+ isGameOver = true;
+ // LK.showGameOver() already called
+}
+// Input: swipe to change direction
+function getSwipeDir(dx, dy) {
+ if (Math.abs(dx) > Math.abs(dy)) {
+ return {
+ x: dx > 0 ? 1 : -1,
+ y: 0
+ };
+ } else {
+ return {
+ x: 0,
+ y: dy > 0 ? 1 : -1
+ };
+ }
+}
+// Input: touch/drag
+game.down = function (x, y, obj) {
+ dragStart = {
+ x: x,
+ y: y
+ };
+};
+game.up = function (x, y, obj) {
+ dragStart = null;
+};
+game.move = function (x, y, obj) {
+ if (dragStart && !isGameOver) {
+ var dx = x - dragStart.x;
+ var dy = y - dragStart.y;
+ if (dx * dx + dy * dy > 80 * 80) {
+ var dir = getSwipeDir(dx, dy);
+ // Prevent reversing
+ if (!(dir.x === -snakeDir.x && dir.y === -snakeDir.y)) {
+ snakeNextDir = dir;
+ }
+ dragStart = null;
+ }
+ }
+};
+// Main update loop
+game.update = function () {
+ if (isGameOver) return;
+ // Move snake
+ // Update direction
+ if (snakeNextDir.x !== snakeDir.x || snakeNextDir.y !== snakeDir.y) {
+ snakeDir = {
+ x: snakeNextDir.x,
+ y: snakeNextDir.y
+ };
+ }
+ // Calculate new head position
+ var head = snake[0];
+ var newX = head.x + snakeDir.x * snakeSpeed;
+ var newY = head.y + snakeDir.y * snakeSpeed;
+ // Store previous positions
+ snakePositions.unshift({
+ x: newX,
+ y: newY
+ });
+ if (snakePositions.length > snake.length * SEGMENT_SPACING / snakeSpeed + 2) {
+ snakePositions.pop();
+ }
+ // Move segments
+ for (var i = 0; i < snake.length; i++) {
+ var posIdx = Math.min(i * Math.floor(SEGMENT_SPACING / snakeSpeed), snakePositions.length - 1);
+ var pos = snakePositions[posIdx];
+ snake[i].x = pos.x;
+ snake[i].y = pos.y;
+ }
+ // Check wall collision
+ if (checkWallCollision()) {
+ LK.effects.flashScreen(0xff0000, 800);
+ handleGameOver();
+ LK.showGameOver();
+ return;
+ }
+ // Check self collision
+ if (checkSelfCollision()) {
+ LK.effects.flashScreen(0xff0000, 800);
+ handleGameOver();
+ LK.showGameOver();
+ return;
+ }
+ // Check animal collision
+ var animalIdx = checkAnimalCollision();
+ if (animalIdx !== -1) {
+ eatAnimal(animalIdx);
+ }
+};
+// Game start/reset
+function startGame() {
+ isGameOver = false;
+ score = 0;
+ sequenceCount = 0;
+ snakeSpeed = SNAKE_START_SPEED;
+ currentTargetIndex = 0;
+ scoreTxt.setText(score);
+ updateOrderText();
+ resetSnake();
+ spawnAnimals();
+}
+startGame();
\ No newline at end of file