/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Food = Container.expand(function () {
var self = Container.call(this);
var foodGraphics = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var GridBorder = Container.expand(function () {
var self = Container.call(this);
var borderGraphics = self.attachAsset('gridBorder', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var SnakeHead = Container.expand(function () {
var self = Container.call(this);
var headGraphics = self.attachAsset('snakeHead', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var SnakeTail = Container.expand(function () {
var self = Container.call(this);
var tailGraphics = self.attachAsset('snakeTail', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2d5016
});
/****
* Game Code
****/
// Grid configuration
var gridSize = 40;
var gridWidth = 20;
var gridHeight = 25;
var gameAreaWidth = gridWidth * gridSize;
var gameAreaHeight = gridHeight * gridSize;
var offsetX = (2048 - gameAreaWidth) / 2;
var offsetY = (2732 - gameAreaHeight) / 2 - 200;
// Snake variables
var snake = [];
var direction = {
x: 1,
y: 0
};
var nextDirection = {
x: 1,
y: 0
};
var food = null;
var gameRunning = false;
var moveTimer = 0;
var moveInterval = 200;
// Create border walls
var borders = [];
for (var x = -1; x <= gridWidth; x++) {
for (var y = -1; y <= gridHeight; y++) {
if (x === -1 || x === gridWidth || y === -1 || y === gridHeight) {
var border = new GridBorder();
border.x = offsetX + x * gridSize + gridSize / 2;
border.y = offsetY + y * gridSize + gridSize / 2;
borders.push(border);
game.addChild(border);
}
}
}
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 50;
// Initialize snake
function initializeSnake() {
// Clear existing snake
for (var i = 0; i < snake.length; i++) {
snake[i].destroy();
}
snake = [];
// Create snake head at center
var head = new SnakeHead();
head.gridX = Math.floor(gridWidth / 2);
head.gridY = Math.floor(gridHeight / 2);
head.x = offsetX + head.gridX * gridSize + gridSize / 2;
head.y = offsetY + head.gridY * gridSize + gridSize / 2;
snake.push(head);
game.addChild(head);
// Add initial tail segments
for (var i = 1; i < 3; i++) {
var tail = new SnakeTail();
tail.gridX = head.gridX - i;
tail.gridY = head.gridY;
tail.x = offsetX + tail.gridX * gridSize + gridSize / 2;
tail.y = offsetY + tail.gridY * gridSize + gridSize / 2;
snake.push(tail);
game.addChild(tail);
}
direction = {
x: 1,
y: 0
};
nextDirection = {
x: 1,
y: 0
};
gameRunning = true;
LK.setScore(0);
scoreTxt.setText('Score: 0');
spawnFood();
}
function spawnFood() {
if (food) {
food.destroy();
}
var validPositions = [];
for (var x = 0; x < gridWidth; x++) {
for (var y = 0; y < gridHeight; y++) {
var occupied = false;
for (var i = 0; i < snake.length; i++) {
if (snake[i].gridX === x && snake[i].gridY === y) {
occupied = true;
break;
}
}
if (!occupied) {
validPositions.push({
x: x,
y: y
});
}
}
}
if (validPositions.length > 0) {
var randomPos = validPositions[Math.floor(Math.random() * validPositions.length)];
food = new Food();
food.gridX = randomPos.x;
food.gridY = randomPos.y;
food.x = offsetX + food.gridX * gridSize + gridSize / 2;
food.y = offsetY + food.gridY * gridSize + gridSize / 2;
game.addChild(food);
}
}
function moveSnake() {
if (!gameRunning) return;
direction = nextDirection;
var head = snake[0];
var newX = head.gridX + direction.x;
var newY = head.gridY + direction.y;
// Check border collision
if (newX < 0 || newX >= gridWidth || newY < 0 || newY >= gridHeight) {
gameOver();
return;
}
// Check tail collision
for (var i = 1; i < snake.length; i++) {
if (snake[i].gridX === newX && snake[i].gridY === newY) {
gameOver();
return;
}
}
// Check food collision
var ateFood = false;
if (food && food.gridX === newX && food.gridY === newY) {
ateFood = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('eat').play();
// Add new tail segment at current tail position
var lastTail = snake[snake.length - 1];
var newTail = new SnakeTail();
newTail.gridX = lastTail.gridX;
newTail.gridY = lastTail.gridY;
newTail.x = offsetX + newTail.gridX * gridSize + gridSize / 2;
newTail.y = offsetY + newTail.gridY * gridSize + gridSize / 2;
snake.push(newTail);
game.addChild(newTail);
spawnFood();
}
// Move snake body
for (var i = snake.length - 1; i > 0; i--) {
snake[i].gridX = snake[i - 1].gridX;
snake[i].gridY = snake[i - 1].gridY;
var bodyNewX = offsetX + snake[i].gridX * gridSize + gridSize / 2;
var bodyNewY = offsetY + snake[i].gridY * gridSize + gridSize / 2;
tween(snake[i], {
x: bodyNewX,
y: bodyNewY
}, {
duration: 100,
easing: tween.easeOut
});
}
// Move head
head.gridX = newX;
head.gridY = newY;
var headNewX = offsetX + head.gridX * gridSize + gridSize / 2;
var headNewY = offsetY + head.gridY * gridSize + gridSize / 2;
tween(head, {
x: headNewX,
y: headNewY
}, {
duration: 100,
easing: tween.easeOut
});
}
function gameOver() {
gameRunning = false;
LK.getSound('gameOver').play();
LK.effects.flashScreen(0xff0000, 500);
LK.setTimeout(function () {
LK.showGameOver(initializeSnake);
}, 500);
}
// Touch controls
var startTouchX = 0;
var startTouchY = 0;
var touchStarted = false;
game.down = function (x, y, obj) {
if (!gameRunning) return;
startTouchX = x;
startTouchY = y;
touchStarted = true;
};
game.up = function (x, y, obj) {
if (!gameRunning || !touchStarted) return;
touchStarted = false;
var deltaX = x - startTouchX;
var deltaY = y - startTouchY;
var minSwipeDistance = 50;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
if (Math.abs(deltaX) > minSwipeDistance) {
if (deltaX > 0 && direction.x !== -1) {
nextDirection = {
x: 1,
y: 0
}; // Right
} else if (deltaX < 0 && direction.x !== 1) {
nextDirection = {
x: -1,
y: 0
}; // Left
}
}
} else {
// Vertical swipe
if (Math.abs(deltaY) > minSwipeDistance) {
if (deltaY > 0 && direction.y !== -1) {
nextDirection = {
x: 0,
y: 1
}; // Down
} else if (deltaY < 0 && direction.y !== 1) {
nextDirection = {
x: 0,
y: -1
}; // Up
}
}
}
};
// Game update loop with automatic movement
game.update = function () {
if (!gameRunning) return;
moveTimer += 16.67; // Approximate milliseconds per frame at 60 FPS
if (moveTimer >= moveInterval) {
moveTimer = 0;
moveSnake();
}
};
// Initialize the game
initializeSnake(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Food = Container.expand(function () {
var self = Container.call(this);
var foodGraphics = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var GridBorder = Container.expand(function () {
var self = Container.call(this);
var borderGraphics = self.attachAsset('gridBorder', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var SnakeHead = Container.expand(function () {
var self = Container.call(this);
var headGraphics = self.attachAsset('snakeHead', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var SnakeTail = Container.expand(function () {
var self = Container.call(this);
var tailGraphics = self.attachAsset('snakeTail', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2d5016
});
/****
* Game Code
****/
// Grid configuration
var gridSize = 40;
var gridWidth = 20;
var gridHeight = 25;
var gameAreaWidth = gridWidth * gridSize;
var gameAreaHeight = gridHeight * gridSize;
var offsetX = (2048 - gameAreaWidth) / 2;
var offsetY = (2732 - gameAreaHeight) / 2 - 200;
// Snake variables
var snake = [];
var direction = {
x: 1,
y: 0
};
var nextDirection = {
x: 1,
y: 0
};
var food = null;
var gameRunning = false;
var moveTimer = 0;
var moveInterval = 200;
// Create border walls
var borders = [];
for (var x = -1; x <= gridWidth; x++) {
for (var y = -1; y <= gridHeight; y++) {
if (x === -1 || x === gridWidth || y === -1 || y === gridHeight) {
var border = new GridBorder();
border.x = offsetX + x * gridSize + gridSize / 2;
border.y = offsetY + y * gridSize + gridSize / 2;
borders.push(border);
game.addChild(border);
}
}
}
// Create score display
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
scoreTxt.y = 50;
// Initialize snake
function initializeSnake() {
// Clear existing snake
for (var i = 0; i < snake.length; i++) {
snake[i].destroy();
}
snake = [];
// Create snake head at center
var head = new SnakeHead();
head.gridX = Math.floor(gridWidth / 2);
head.gridY = Math.floor(gridHeight / 2);
head.x = offsetX + head.gridX * gridSize + gridSize / 2;
head.y = offsetY + head.gridY * gridSize + gridSize / 2;
snake.push(head);
game.addChild(head);
// Add initial tail segments
for (var i = 1; i < 3; i++) {
var tail = new SnakeTail();
tail.gridX = head.gridX - i;
tail.gridY = head.gridY;
tail.x = offsetX + tail.gridX * gridSize + gridSize / 2;
tail.y = offsetY + tail.gridY * gridSize + gridSize / 2;
snake.push(tail);
game.addChild(tail);
}
direction = {
x: 1,
y: 0
};
nextDirection = {
x: 1,
y: 0
};
gameRunning = true;
LK.setScore(0);
scoreTxt.setText('Score: 0');
spawnFood();
}
function spawnFood() {
if (food) {
food.destroy();
}
var validPositions = [];
for (var x = 0; x < gridWidth; x++) {
for (var y = 0; y < gridHeight; y++) {
var occupied = false;
for (var i = 0; i < snake.length; i++) {
if (snake[i].gridX === x && snake[i].gridY === y) {
occupied = true;
break;
}
}
if (!occupied) {
validPositions.push({
x: x,
y: y
});
}
}
}
if (validPositions.length > 0) {
var randomPos = validPositions[Math.floor(Math.random() * validPositions.length)];
food = new Food();
food.gridX = randomPos.x;
food.gridY = randomPos.y;
food.x = offsetX + food.gridX * gridSize + gridSize / 2;
food.y = offsetY + food.gridY * gridSize + gridSize / 2;
game.addChild(food);
}
}
function moveSnake() {
if (!gameRunning) return;
direction = nextDirection;
var head = snake[0];
var newX = head.gridX + direction.x;
var newY = head.gridY + direction.y;
// Check border collision
if (newX < 0 || newX >= gridWidth || newY < 0 || newY >= gridHeight) {
gameOver();
return;
}
// Check tail collision
for (var i = 1; i < snake.length; i++) {
if (snake[i].gridX === newX && snake[i].gridY === newY) {
gameOver();
return;
}
}
// Check food collision
var ateFood = false;
if (food && food.gridX === newX && food.gridY === newY) {
ateFood = true;
LK.setScore(LK.getScore() + 1);
scoreTxt.setText('Score: ' + LK.getScore());
LK.getSound('eat').play();
// Add new tail segment at current tail position
var lastTail = snake[snake.length - 1];
var newTail = new SnakeTail();
newTail.gridX = lastTail.gridX;
newTail.gridY = lastTail.gridY;
newTail.x = offsetX + newTail.gridX * gridSize + gridSize / 2;
newTail.y = offsetY + newTail.gridY * gridSize + gridSize / 2;
snake.push(newTail);
game.addChild(newTail);
spawnFood();
}
// Move snake body
for (var i = snake.length - 1; i > 0; i--) {
snake[i].gridX = snake[i - 1].gridX;
snake[i].gridY = snake[i - 1].gridY;
var bodyNewX = offsetX + snake[i].gridX * gridSize + gridSize / 2;
var bodyNewY = offsetY + snake[i].gridY * gridSize + gridSize / 2;
tween(snake[i], {
x: bodyNewX,
y: bodyNewY
}, {
duration: 100,
easing: tween.easeOut
});
}
// Move head
head.gridX = newX;
head.gridY = newY;
var headNewX = offsetX + head.gridX * gridSize + gridSize / 2;
var headNewY = offsetY + head.gridY * gridSize + gridSize / 2;
tween(head, {
x: headNewX,
y: headNewY
}, {
duration: 100,
easing: tween.easeOut
});
}
function gameOver() {
gameRunning = false;
LK.getSound('gameOver').play();
LK.effects.flashScreen(0xff0000, 500);
LK.setTimeout(function () {
LK.showGameOver(initializeSnake);
}, 500);
}
// Touch controls
var startTouchX = 0;
var startTouchY = 0;
var touchStarted = false;
game.down = function (x, y, obj) {
if (!gameRunning) return;
startTouchX = x;
startTouchY = y;
touchStarted = true;
};
game.up = function (x, y, obj) {
if (!gameRunning || !touchStarted) return;
touchStarted = false;
var deltaX = x - startTouchX;
var deltaY = y - startTouchY;
var minSwipeDistance = 50;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
if (Math.abs(deltaX) > minSwipeDistance) {
if (deltaX > 0 && direction.x !== -1) {
nextDirection = {
x: 1,
y: 0
}; // Right
} else if (deltaX < 0 && direction.x !== 1) {
nextDirection = {
x: -1,
y: 0
}; // Left
}
}
} else {
// Vertical swipe
if (Math.abs(deltaY) > minSwipeDistance) {
if (deltaY > 0 && direction.y !== -1) {
nextDirection = {
x: 0,
y: 1
}; // Down
} else if (deltaY < 0 && direction.y !== 1) {
nextDirection = {
x: 0,
y: -1
}; // Up
}
}
}
};
// Game update loop with automatic movement
game.update = function () {
if (!gameRunning) return;
moveTimer += 16.67; // Approximate milliseconds per frame at 60 FPS
if (moveTimer >= moveInterval) {
moveTimer = 0;
moveSnake();
}
};
// Initialize the game
initializeSnake();