/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BodyPart = Container.expand(function () {
var self = Container.call(this);
var bodyPart = self.attachAsset('head', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0x00FFFF // Cyan tint for better visibility
});
// Add animation properties
self.originalScale = 1.2; // Larger scale
self.isAnimating = false;
self.animationDirection = 1;
// Rotate the body part based on direction
self.setDirection = function (direction) {
if (direction === 'up') {
bodyPart.rotation = 0;
} else if (direction === 'down') {
bodyPart.rotation = Math.PI;
} else if (direction === 'left') {
bodyPart.rotation = -Math.PI / 2;
} else if (direction === 'right') {
bodyPart.rotation = Math.PI / 2;
}
};
// Start wiggle animation for body parts
self.startWiggleAnimation = function () {
if (self.isAnimating) return;
self.isAnimating = true;
self.animateWiggle();
};
// Stop wiggle animation
self.stopWiggleAnimation = function () {
self.isAnimating = false;
tween.stop(bodyPart, {
scaleX: true,
scaleY: true
});
bodyPart.scaleX = self.originalScale;
bodyPart.scaleY = self.originalScale;
};
// Animate wiggle effect
self.animateWiggle = function () {
if (!self.isAnimating) return;
var scaleOffset = 0.05;
var duration = 250;
// Determine which axis to animate based on direction
var direction = self.animationDirection;
var targetScaleX = self.originalScale;
var targetScaleY = self.originalScale;
// Wiggle based on body orientation
if (bodyPart.rotation === 0 || bodyPart.rotation === Math.PI) {
// For up/down movement, wiggle horizontally
targetScaleX = self.originalScale + scaleOffset * direction;
} else {
// For left/right movement, wiggle vertically
targetScaleY = self.originalScale + scaleOffset * direction;
}
tween(bodyPart, {
scaleX: targetScaleX,
scaleY: targetScaleY
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.animationDirection *= -1;
if (self.isAnimating) {
self.animateWiggle();
}
}
});
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
// Create a bomb obstacle using rock image asset with red tint
var bomb = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF0000,
// Red tint to distinguish from rocks
scaleX: 0.8,
scaleY: 0.8
});
return self;
});
var BonusFood = Container.expand(function () {
var self = Container.call(this);
// Create the bonus food
var bonusFood = self.attachAsset('bonusFood', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Food = Container.expand(function () {
var self = Container.call(this);
// Create the food
var food = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var HealthBar = Container.expand(function () {
var self = Container.call(this);
// Create the health bar container box
var barContainer = self.attachAsset('healbar', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.7,
scaleX: 2,
scaleY: 0.5
});
// Create the bar background (red)
var barBg = self.attachAsset('healbar', {
anchorX: 0,
anchorY: 0.5,
tint: 0xFF0000,
scaleX: 1.9,
scaleY: 0.4,
x: -barContainer.width / 2 + 5,
y: 0
});
// Create the health indicator (green)
var healthIndicator = self.attachAsset('healbar', {
anchorX: 0,
anchorY: 0.5,
tint: 0x00FF00,
scaleX: 1.9,
scaleY: 0.4,
x: -barContainer.width / 2 + 5,
y: 0
});
self.updateHealth = function (health) {
// Health ranges from 0 to 200, convert to scale between 0 and 1.9 (max bar width)
var healthWidth = health / 200 * 1.9;
healthIndicator.scaleX = healthWidth;
};
return self;
});
var KOCAM = Container.expand(function () {
var self = Container.call(this);
// Create the life
var life = self.attachAsset('life', {
anchorX: 0.5,
anchorY: 0.5
});
});
var LevelUpMessage = Container.expand(function () {
var self = Container.call(this);
// Create the level up message background
var background = self.attachAsset('healbar', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.8,
scaleX: 20,
scaleY: 8
});
// Create the level up message text
var message = new Text2('', {
size: 64,
fill: 0xFFFFFF
});
message.anchor.set(0.5, 0.5);
self.addChild(message);
// Method to update the text
self.setLevel = function (level) {
message.setText('Çok yeteneklisin bebi');
};
// Method to show the message with animation
self.show = function () {
self.alpha = 0;
self.scaleX = 0.5;
self.scaleY = 0.5;
// Animate message appearance
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOutElastic
});
};
// Method to hide the message with animation
self.hide = function (callback) {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
if (callback) callback();
}
});
};
return self;
});
var Pause = Container.expand(function () {
var self = Container.call(this);
// Create the pause button
var pause = self.attachAsset('pause', {
anchorX: 0.5,
anchorY: 0.5
});
// Event handler called when a press happens on element.
self.down = function (x, y, obj) {
if (!game.paused) {
game.paused = true;
pause.id = 'resume';
} else {
game.paused = false;
pause.id = 'pause';
}
};
return self;
});
// Poison class has been removed
var Rock = Container.expand(function () {
var self = Container.call(this);
// Create a rock obstacle using rock image asset
var rock = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
return self;
});
var Snake = Container.expand(function () {
var self = Container.call(this);
// Create the head of the snake
var head = self.attachAsset('head', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize the snake's direction and speed
self.direction = 'up';
self.speed = 5;
self.previousPositions = [];
// Update the head rotation based on direction
self.updateHeadRotation = function () {
if (self.direction === 'up') {
head.rotation = 0;
} else if (self.direction === 'down') {
head.rotation = Math.PI;
} else if (self.direction === 'left') {
head.rotation = -Math.PI / 2;
} else if (self.direction === 'right') {
head.rotation = Math.PI / 2;
}
};
self.moveHead = function (newDirection) {
if (newDirection === 'up' && this.direction !== 'down') {
this.direction = 'up';
self.updateHeadRotation();
} else if (newDirection === 'down' && this.direction !== 'up') {
this.direction = 'down';
self.updateHeadRotation();
} else if (newDirection === 'left' && this.direction !== 'right') {
this.direction = 'left';
self.updateHeadRotation();
} else if (newDirection === 'right' && this.direction !== 'left') {
this.direction = 'right';
self.updateHeadRotation();
}
};
// Initialize with the correct rotation
self.updateHeadRotation();
return self;
});
var StarTrail = Container.expand(function () {
var self = Container.call(this);
// Create a star-like shape using an asset
var star = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Set initial properties
self.alpha = 1;
self.fadeSpeed = 0.03; // Slower fade for more visibility
self.rotationSpeed = 0.1;
self.tailLength = 0;
self.maxTailLength = 45; // Longer tail
self.growSpeed = 0.8; // Grow faster
self.tailColor = 0xFFFF00; // Bright yellow for tail
star.tint = 0xFFFFFF; // White for star head
// Update method to handle fading, rotation and tail growth
self.update = function () {
// Rotate the star
star.rotation += self.rotationSpeed;
// Fade out more slowly
self.alpha -= self.fadeSpeed;
// Grow tail initially
if (self.tailLength < self.maxTailLength) {
self.tailLength += self.growSpeed;
}
// If fully transparent, mark for removal
if (self.alpha <= 0) {
self.shouldRemove = true;
}
};
return self;
});
/****
* Initialize Game
****/
//<Assets used in the game will automatically appear here>
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
// Add a background to the game
// Import tween plugin for animations
var background = game.addChildAt(LK.getAsset('newBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0.7 // Reduce opacity to improve visibility of game elements
}), 0); // Add background as the bottom-most layer
// Start playing background music as soon as the game begins
LK.playMusic('gameOverMusic');
// Initialize pause button
var pause = game.addChild(new Pause());
// Position the pause button a little to the left from the top right corner of the game
pause.x = 2048 - pause.width;
pause.y = 50; // Move the pause button a little down
var snake = game.addChild(new Snake());
snake.body = [];
// Position the snake at the center of the game
snake.x = 2048 / 2;
snake.y = 2732 / 2;
// Initialize food
var food = game.addChild(new Food());
// Position the food at a random location within the game
food.x = Math.random() * 2048;
food.y = Math.random() * 2732;
// Initialize poison
var bonusFood = game.addChild(new BonusFood());
// Poison food item has been removed
bonusFood.x = -100;
bonusFood.y = -100;
var life = game.addChild(new KOCAM());
// Hide the life when the game starts
life.x = -100;
life.y = -100;
// Hide the poison when the game starts
game.update = function () {
if (game.paused) {
return;
}
// Update the snake's position based on its direction and speed
if (snake.direction === 'up') {
snake.y -= snake.speed * 2.25;
} else if (snake.direction === 'down') {
snake.y += snake.speed * 2.25;
} else if (snake.direction === 'left') {
snake.x -= snake.speed * 2.25;
} else if (snake.direction === 'right') {
snake.x += snake.speed * 2.25;
}
// Level 2+ mechanics - Moving bombs
if (enableMovingBombs && bombs.length > 0) {
for (var mb = 0; mb < bombs.length; mb++) {
// Move bombs toward snake occasionally
if (LK.ticks % 60 === 0) {
// Target the snake with a chance
if (Math.random() < 0.5) {
// Calculate direction toward snake
var dx = snake.x - bombs[mb].x;
var dy = snake.y - bombs[mb].y;
// Normalize and apply speed
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
bombs[mb].x += dx / dist * bombSpeed;
bombs[mb].y += dy / dist * bombSpeed;
}
} else {
// Random movement
bombs[mb].x += (Math.random() * 2 - 1) * bombSpeed * 2;
bombs[mb].y += (Math.random() * 2 - 1) * bombSpeed * 2;
}
}
}
}
// Level 2+ mechanics - Teleporting food
if (enableFoodTeleport && LK.ticks % 180 === 0 && food && food.parent) {
// 5% chance food will teleport every 3 seconds
if (Math.random() < 0.05) {
// Teleport food to a new location
do {
food.x = Math.random() * (2048 - food.width) + food.width / 2;
food.y = Math.random() * (2732 - food.height) + food.height / 2;
} while (
// Ensure food doesn't spawn at the border
(food.x < 100 || food.x > 1948) && (food.y < 100 || food.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(food, bonusFood, 100) || checkOverlap(food, life, 100) || positionOverlapsAny(food.x, food.y, [rocks, bombs], 100));
// Visual effect for teleportation
LK.effects.flashObject(food, 0x00FFFF, 300);
}
}
// Level 2+ mechanics - Random rock spawning based on level
if (level >= 2 && Math.random() < rockSpawnRate && !game.paused) {
var randomRock = new Rock();
do {
randomRock.x = Math.random() * (2048 - 200) + 100;
randomRock.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure random rock doesn't spawn near snake
Math.abs(randomRock.x - snake.x) < 200 && Math.abs(randomRock.y - snake.y) < 200 ||
// Ensure random rock doesn't overlap with other game objects
checkOverlap(randomRock, food, 100) || checkOverlap(randomRock, bonusFood, 100) || checkOverlap(randomRock, life, 100) || positionOverlapsAny(randomRock.x, randomRock.y, [rocks, bombs], 100));
game.addChild(randomRock);
rocks.push(randomRock);
// Remove the rock after the current item duration
LK.setTimeout(function () {
if (rocks.includes(randomRock) && randomRock.parent) {
// Remove rock from array and game
for (var i = 0; i < rocks.length; i++) {
if (rocks[i] === randomRock) {
rocks[i].destroy();
rocks.splice(i, 1);
break;
}
}
}
}, itemDuration / 2); // Half duration for random rocks to make them more challenging
}
// Store the current position of the snake head
snake.previousPositions.unshift({
x: snake.x,
y: snake.y,
direction: snake.direction
});
// Limit the previous positions array to the length of the body plus some buffer
if (snake.previousPositions.length > snake.body.length + 10) {
snake.previousPositions.pop();
}
// Update the position of the body parts to follow the head's previous positions
for (var i = 0; i < snake.body.length; i++) {
if (i + 1 < snake.previousPositions.length) {
// Make sure the body part is added to the game at the bottom layer
// to ensure it stays behind the head
game.addChildAt(snake.body[i], 0);
// Position the body part based on the previous position of the head
snake.body[i].x = snake.previousPositions[i + 1].x;
snake.body[i].y = snake.previousPositions[i + 1].y;
snake.body[i].setDirection(snake.previousPositions[i + 1].direction);
// Manage animation for body parts
// Start animation if not already animating
if (!snake.body[i].isAnimating) {
snake.body[i].startWiggleAnimation();
}
// Set animation phase offset based on position in snake body
// This creates a wave-like effect through the snake's body
snake.body[i].animationDirection = i % 2 === 0 ? 1 : -1;
// Create star trail effect behind each body part for more visibility (once every few frames)
if (LK.ticks % 2 === 0) {
// More frequent trails
var star = new StarTrail();
star.x = snake.body[i].x;
star.y = snake.body[i].y;
// Less randomness for more consistent tail appearance
star.x += Math.random() * 6 - 3;
star.y += Math.random() * 6 - 3;
// Place star trail behind the snake but above the background
game.addChildAt(star, game.getChildIndex(background) + 1);
if (!starTrails) {
starTrails = [];
}
starTrails.push(star);
}
}
}
// Update and clean up star trails
if (starTrails) {
for (var j = starTrails.length - 1; j >= 0; j--) {
starTrails[j].update();
// Create comet trail effect with gradual color change
if (starTrails[j].tailLength > 0 && LK.ticks % 2 === 0) {
// Calculate color based on alpha
var colorIntensity = Math.floor(starTrails[j].alpha * 255);
var tailColor = colorIntensity << 16 | colorIntensity << 8 | Math.floor(colorIntensity * 0.7);
// Apply color tint to create glowing effect
if (starTrails[j].children[0]) {
starTrails[j].children[0].tint = tailColor;
}
// Scale effect for comet-like appearance
var scaleFactor = 0.5 + starTrails[j].alpha * 0.5;
starTrails[j].scaleX = scaleFactor;
starTrails[j].scaleY = scaleFactor;
}
if (starTrails[j].shouldRemove) {
starTrails[j].destroy();
starTrails.splice(j, 1);
}
}
}
// Check if the snake's head intersects with the food
if (snake.intersects(food)) {
// Increase the score by 50 instead of 10
score += 50;
// Update the score text
scoreTxt.setText('Score: ' + score);
// Check if player reached 800 points to win
if (score >= 800) {
// Show win message
var winMessage = new LevelUpMessage();
winMessage.setLevel(level);
winMessage.x = 2048 / 2;
winMessage.y = 2732 / 2;
game.addChild(winMessage);
winMessage.show();
// Flash screen green for win
LK.effects.flashScreen(0x00FF00, 500);
// Show "You win" with custom message
LK.showYouWin("Eline sağlık yavrum kazandın");
return;
}
// Check for level up (every 500 points)
if (!isLevelingUp && score >= lastLevelUpScore + 500) {
// Level up!
level++;
lastLevelUpScore = Math.floor(score / 500) * 500;
// Increase item duration by 5 seconds per level
itemDuration = baseItemDuration + (level - 1) * 5000;
// Increase food spawn count with level
foodSpawnCount = Math.min(level, 4); // Cap at 4 food items
// Pause the game during level up
game.paused = true;
isLevelingUp = true;
// Create and display level up message
var levelMessage = new LevelUpMessage();
levelMessage.setLevel(level);
levelMessage.x = 2048 / 2;
levelMessage.y = 2732 / 2;
game.addChild(levelMessage);
levelMessage.show();
// Update level text
updateLevelText();
// Flash screen green for level up
LK.effects.flashScreen(0x00FF00, 300);
// If reaching level 2 or higher, apply more challenging behaviors
if (level >= 2) {
// Update bomb speed increases
bombSpeed = 3;
// Enable moving bombs
enableMovingBombs = true;
// Enable food teleportation
enableFoodTeleport = true;
// Make rock spawning more frequent
rockSpawnRate = 0.01;
}
// Resume game after 2 seconds
LK.setTimeout(function () {
levelMessage.hide(function () {
levelMessage.destroy();
game.paused = false;
isLevelingUp = false;
// Spawn additional food based on level
spawnMultipleFood();
});
}, 2000);
}
// Increase the food consumed count
foodConsumed += 1;
// Track normal food items for poison spawning
normalFoodCount += 1;
// Every 3 normal food items, trigger spawning of 3 poison items
if (normalFoodCount >= 3) {
poisonToSpawn += 3;
normalFoodCount = 0;
}
// Increase health by 10, up to maximum 200
health = Math.min(health + 10, 200);
// Update health bar
updateHealthBar();
// Add a new body part to the snake
var newBodyPart = new BodyPart();
// Set the direction of the new body part
newBodyPart.setDirection(snake.direction);
// If no previous positions exist, create initial position
if (snake.previousPositions.length <= snake.body.length) {
var lastPos;
if (snake.body.length === 0) {
lastPos = {
x: snake.x,
y: snake.y
};
} else {
var lastBodyPart = snake.body[snake.body.length - 1];
lastPos = {
x: lastBodyPart.x,
y: lastBodyPart.y
};
}
// Calculate position based on direction
if (snake.direction === 'up') {
newBodyPart.x = lastPos.x;
newBodyPart.y = lastPos.y + 50; // Use a fixed offset
} else if (snake.direction === 'down') {
newBodyPart.x = lastPos.x;
newBodyPart.y = lastPos.y - 50;
} else if (snake.direction === 'left') {
newBodyPart.x = lastPos.x + 50;
newBodyPart.y = lastPos.y;
} else if (snake.direction === 'right') {
newBodyPart.x = lastPos.x - 50;
newBodyPart.y = lastPos.y;
}
} else {
// Use the position from previous positions array
var pos = snake.previousPositions[snake.body.length];
newBodyPart.x = pos.x;
newBodyPart.y = pos.y;
}
// Initialize animation properties and start animation for the new body part
newBodyPart.startWiggleAnimation();
// Add scale animation when adding new body part
newBodyPart.scaleX = 0;
newBodyPart.scaleY = 0;
tween(newBodyPart, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOutElastic
});
snake.body.push(newBodyPart);
game.addChild(newBodyPart);
// Create an initial burst of star trail when a new body part is added
for (var s = 0; s < 10; s++) {
var star = new StarTrail();
star.x = newBodyPart.x + (Math.random() * 60 - 30);
star.y = newBodyPart.y + (Math.random() * 60 - 30);
star.alpha = 0.8 + Math.random() * 0.2;
star.fadeSpeed = 0.03 + Math.random() * 0.02;
star.rotationSpeed = 0.05 + Math.random() * 0.1;
// Place star above background but below game elements
game.addChildAt(star, game.getChildIndex(background) + 1);
starTrails.push(star);
}
// Check if it's time to show the bonus food
if (score % 150 === 0) {
// Position the bonus food at a new random location within the game, ensuring it does not appear on the border or overlap other objects
do {
bonusFood.x = Math.random() * (2048 - bonusFood.width) + bonusFood.width / 2;
bonusFood.y = Math.random() * (2732 - bonusFood.height) + bonusFood.height / 2;
} while (
// Ensure bonus food doesn't spawn at the border
(bonusFood.x < 100 || bonusFood.x > 1948) && (bonusFood.y < 100 || bonusFood.y > 2632) ||
// Ensure bonus food doesn't overlap with other game objects
checkOverlap(bonusFood, food, 100) || checkOverlap(bonusFood, life, 100) || positionOverlapsAny(bonusFood.x, bonusFood.y, [rocks, bombs], 100));
// Show the bonus food for the current item duration
LK.setTimeout(function () {
bonusFood.x = -100;
bonusFood.y = -100;
}, itemDuration);
}
// Display "Seni seviyorum" message inside the health bar
if (score >= 300 && !messageDisplayed) {
// Create a flag to track whether the message has been displayed
messageDisplayed = true;
// Show the message inside the health bar
var loveMessage = new Text2('Seni seviyorum', {
size: 32,
fill: 0xFFFFFF
});
// Center the message
loveMessage.anchor.set(0.5, 0.5);
// Add message to the health bar
healthBar.addChild(loveMessage);
// Start with zero scale and fade in
loveMessage.scaleX = 0;
loveMessage.scaleY = 0;
loveMessage.alpha = 0;
// Animate the message appearance
tween(loveMessage, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 500,
easing: tween.elasticOut
});
// Keep the message visible permanently
}
// Check if it's time to show the life - increased frequency from every 100 points to every 50 points
if (score !== 0 && score % 50 === 0 && score != previousScore) {
previousScore = score;
// Position the life at a new random location within the game, ensuring it does not appear on the border or overlap other objects
do {
life.x = Math.random() * (2048 - life.width) + life.width / 2;
life.y = Math.random() * (2732 - life.height) + life.height / 2;
} while (
// Ensure life doesn't spawn at the border
(life.x < 100 || life.x > 1948) && (life.y < 100 || life.y > 2632) ||
// Ensure life doesn't overlap with other game objects
checkOverlap(life, food, 100) || checkOverlap(life, bonusFood, 100) || positionOverlapsAny(life.x, life.y, [rocks, bombs], 100));
// Show the life for the current item duration
LK.setTimeout(function () {
life.x = -100;
life.y = -100;
}, itemDuration);
}
// Randomly spawn additional life items during gameplay (independent of score)
if (Math.random() < 0.005 && !game.paused) {
// 0.5% chance per frame
var randomLife = new KOCAM();
do {
randomLife.x = Math.random() * (2048 - 200) + 100;
randomLife.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure random life doesn't spawn near snake
Math.abs(randomLife.x - snake.x) < 200 && Math.abs(randomLife.y - snake.y) < 200 ||
// Ensure random life doesn't overlap with other game objects
checkOverlap(randomLife, food, 100) || checkOverlap(randomLife, bonusFood, 100) || checkOverlap(randomLife, life, 100) || positionOverlapsAny(randomLife.x, randomLife.y, [rocks, bombs], 100));
game.addChild(randomLife);
// Remove the life after the current item duration if not collected
LK.setTimeout(function () {
randomLife.destroy();
}, itemDuration);
}
// Poison spawning has been removed
// Spawn rocks and bombs when score passes various thresholds, starting with fewer and increasing
if (score > 100 && score < 200 && rocks.length === 0) {
// Start with fewer rocks (2 initially) and increase with score
var rockCount = 2;
// Adjust rock count based on score
if (score > 150) rockCount = 3;
// Spawn rocks in random positions
for (var r = 0; r < rockCount; r++) {
var rock = new Rock();
// Position rocks randomly but avoid placing directly on snake
do {
rock.x = Math.random() * (2048 - 200) + 100;
rock.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure rock doesn't spawn near snake
Math.abs(rock.x - snake.x) < 200 && Math.abs(rock.y - snake.y) < 200 ||
// Ensure rock doesn't overlap with other game objects
checkOverlap(rock, food, 100) || checkOverlap(rock, bonusFood, 100) || checkOverlap(rock, life, 100) || positionOverlapsAny(rock.x, rock.y, [rocks, bombs], 100));
game.addChild(rock);
rocks.push(rock);
// Set timeout to remove rock after the current item duration if not collided with
LK.setTimeout(function () {
// Check if rock still exists in the array and game
if (rocks.includes(rock) && rock.parent) {
// Remove rock from array and game
for (var i = 0; i < rocks.length; i++) {
if (rocks[i] === rock) {
rocks[i].destroy();
rocks.splice(i, 1);
break;
}
}
}
}, itemDuration);
}
// Gradually increase bomb count based on score
var bombCount = 2; // Start with fewer bombs
// Adjust bomb count based on score
if (score > 150) bombCount = 3;
// Add bomb obstacles
for (var b = 0; b < bombCount; b++) {
var bomb = new Bomb();
// Position bombs randomly but avoid placing directly on snake
do {
bomb.x = Math.random() * (2048 - 200) + 100;
bomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure bomb doesn't spawn near snake
Math.abs(bomb.x - snake.x) < 200 && Math.abs(bomb.y - snake.y) < 200 ||
// Ensure bomb doesn't overlap with other game objects
checkOverlap(bomb, food, 100) || checkOverlap(bomb, bonusFood, 100) || checkOverlap(bomb, life, 100) || positionOverlapsAny(bomb.x, bomb.y, [rocks, bombs], 100));
game.addChild(bomb);
bombs.push(bomb);
}
}
// Additional bombs when score reaches higher thresholds - with reduced initial counts
if (score > 200 && score < 300 && !bombsSpawned200 || score > 300 && score < 400 && !bombsSpawned300 || score > 400 && !bombsSpawned400) {
// Set the appropriate flag
if (score > 200 && score < 300) bombsSpawned200 = true;else if (score > 300 && score < 400) bombsSpawned300 = true;else if (score > 400) bombsSpawned400 = true;
// Number of bombs increases with score, but starts lower
var bombCount = 3; // Start with fewer bombs at 200 points
if (score > 300) bombCount = 5; // Moderate increase at 300 points
if (score > 400) bombCount = 8; // Larger increase at 400 points
// Spawn bombs
for (var b = 0; b < bombCount; b++) {
var difficultyBomb = new Bomb();
do {
difficultyBomb.x = Math.random() * (2048 - 200) + 100;
difficultyBomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure difficulty bomb doesn't spawn near snake
Math.abs(difficultyBomb.x - snake.x) < 200 && Math.abs(difficultyBomb.y - snake.y) < 200 ||
// Ensure difficulty bomb doesn't overlap with other game objects
checkOverlap(difficultyBomb, food, 100) || checkOverlap(difficultyBomb, bonusFood, 100) || checkOverlap(difficultyBomb, life, 100) || positionOverlapsAny(difficultyBomb.x, difficultyBomb.y, [rocks, bombs], 100));
game.addChild(difficultyBomb);
bombs.push(difficultyBomb);
}
}
// Remove rocks when score reaches 200
if (score >= 200 && rocks.length > 0) {
// Remove all rocks
for (var i = rocks.length - 1; i >= 0; i--) {
rocks[i].destroy();
rocks.splice(i, 1);
}
}
// Spawn bombs at milestone scores, with increasing frequency as score increases
if (score > 100 && score % 50 === 0 && score !== previousBombScore) {
previousBombScore = score;
// Start with fewer bombs and increase with score
var bombCount;
if (score <= 150) {
bombCount = 1; // Just 1 bomb initially
} else if (score <= 250) {
bombCount = 1 + Math.floor(Math.random() * 2); // 1-2 bombs
} else if (score <= 350) {
bombCount = 2; // 2 bombs
} else {
bombCount = 2 + Math.floor(Math.random() * 2); // 2-3 bombs
}
for (var i = 0; i < bombCount; i++) {
var bomb = new Bomb();
// Position the bomb randomly but avoid placing directly on snake
do {
bomb.x = Math.random() * (2048 - 200) + 100;
bomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure bomb doesn't spawn near snake
Math.abs(bomb.x - snake.x) < 200 && Math.abs(bomb.y - snake.y) < 200 ||
// Ensure bomb doesn't overlap with other game objects
checkOverlap(bomb, food, 100) || checkOverlap(bomb, bonusFood, 100) || checkOverlap(bomb, life, 100) || positionOverlapsAny(bomb.x, bomb.y, [rocks, bombs], 100));
game.addChild(bomb);
bombs.push(bomb);
// Remove the bomb after the current item duration
LK.setTimeout(function () {
if (bombs.length > 0) {
for (var i = 0; i < bombs.length; i++) {
if (bombs[i] === bomb) {
bombs[i].destroy();
bombs.splice(i, 1);
break;
}
}
}
}, itemDuration);
}
}
// Randomly spawn additional bombs during gameplay with probability based on score
if (Math.random() < getBombSpawnProbability() && !game.paused) {
// Dynamic probability based on score
var randomBomb = new Bomb();
do {
randomBomb.x = Math.random() * (2048 - 200) + 100;
randomBomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure random bomb doesn't spawn near snake
Math.abs(randomBomb.x - snake.x) < 200 && Math.abs(randomBomb.y - snake.y) < 200 ||
// Ensure random bomb doesn't overlap with other game objects
checkOverlap(randomBomb, food, 100) || checkOverlap(randomBomb, bonusFood, 100) || checkOverlap(randomBomb, life, 100) || positionOverlapsAny(randomBomb.x, randomBomb.y, [rocks, bombs], 100));
game.addChild(randomBomb);
bombs.push(randomBomb);
// Remove the bomb after the current item duration
LK.setTimeout(function () {
if (bombs.length > 0) {
for (var j = 0; j < bombs.length; j++) {
if (bombs[j] === randomBomb) {
bombs[j].destroy();
bombs.splice(j, 1);
break;
}
}
}
}, itemDuration);
}
// Position the food at a new random location within the game, ensuring it does not appear on the border or overlap with other objects
do {
food.x = Math.random() * (2048 - food.width) + food.width / 2;
food.y = Math.random() * (2732 - food.height) + food.height / 2;
} while (
// Ensure food doesn't spawn at the border
(food.x < 100 || food.x > 1948) && (food.y < 100 || food.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(food, bonusFood, 100) || checkOverlap(food, life, 100) || positionOverlapsAny(food.x, food.y, [rocks, bombs], 100));
// Set a timeout to remove food after the current item duration if not eaten
LK.setTimeout(function () {
// Only reposition if the food is still in the game (hasn't been eaten)
if (food && food.parent) {
// Position food offscreen
food.x = -100;
food.y = -100;
// Spawn new food
do {
food.x = Math.random() * (2048 - food.width) + food.width / 2;
food.y = Math.random() * (2732 - food.height) + food.height / 2;
} while (
// Ensure food doesn't spawn at the border
(food.x < 100 || food.x > 1948) && (food.y < 100 || food.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(food, bonusFood, 100) || checkOverlap(food, life, 100) || positionOverlapsAny(food.x, food.y, [rocks, bombs], 100));
}
}, itemDuration);
// Play baby sound when food is eaten
LK.getSound('yiyecek').play();
}
// Check if the snake's head intersects with the bonus food
if (snake.intersects(bonusFood)) {
// Increase the score by 50
score += 50;
// Update the score text
scoreTxt.setText('Score: ' + score);
// Play the bonus food sound
LK.getSound('bonusfood').play();
// In level 2+, destroy the bonus food rather than just hiding it
if (level >= 2) {
// Create a replacement bonus food
bonusFood.destroy();
bonusFood = game.addChild(new BonusFood());
bonusFood.x = -100;
bonusFood.y = -100;
} else {
// Hide the bonus food
bonusFood.x = -100;
bonusFood.y = -100;
}
}
// Check if the snake's head intersects with the life
if (snake.intersects(life)) {
// Increase the lives by 1, up to a maximum of 8
if (lives < 8) {
lives += 1;
// Update the lives text
livesTxt.setText('Lives: ' + lives);
// Update health bar
updateHealthBar();
// Play the life sound
LK.getSound('life').play();
}
// In level 2+, destroy the life rather than just hiding it
if (level >= 2) {
// Create a replacement life
life.destroy();
life = game.addChild(new KOCAM());
life.x = -100;
life.y = -100;
} else {
// Hide the life
life.x = -100;
life.y = -100;
}
}
// Poison food item has been removed
// Check if the snake's head has moved out of the screen
if (snake.x < 0) {
snake.x = 2048;
} else if (snake.x > 2048) {
snake.x = 0;
} else if (snake.y < 0) {
snake.y = 2732;
} else if (snake.y > 2732) {
snake.y = 0;
}
// Check for collision with rocks
for (var r = 0; r < rocks.length; r++) {
if (snake.intersects(rocks[r])) {
// Play cat sound when snake hits rocks
LK.getSound('cat').play();
// Track if this is the first or second collision
if (!snake.rockCollision) {
// First collision - reduce health by 70
snake.rockCollision = true;
health -= 70;
// Ensure health doesn't go below 0
if (health < 0) health = 0;
// Update the health bar
updateHealthBar();
// Flash screen red for visual feedback
LK.effects.flashScreen(0xFF0000, 300);
// Push snake back a bit from the rock
if (snake.direction === 'up') {
snake.y += 50;
} else if (snake.direction === 'down') {
snake.y -= 50;
} else if (snake.direction === 'left') {
snake.x += 50;
} else if (snake.direction === 'right') {
snake.x -= 50;
}
// Make the rock disappear
rocks[r].destroy();
rocks.splice(r, 1);
} else {
// Second collision - snake dies
// Stop any currently playing music
LK.stopMusic();
// Play game over music that will continue until player presses Play Again
LK.playMusic('gameOverMusic');
// Flash screen red for visual feedback
LK.effects.flashScreen(0xFF0000, 500);
LK.showGameOver();
}
break;
}
}
// Check for collision with bombs
for (var b = 0; b < bombs.length; b++) {
if (snake.intersects(bombs[b])) {
// Increase damage - decrease health by 30 for bomb collision (up from 20)
health -= 30;
// Ensure health doesn't go below 0
if (health < 0) health = 0;
// Update health bar
updateHealthBar();
// Flash screen red for visual feedback with longer duration
LK.effects.flashScreen(0xFF0000, 300);
// Play the poison sound
LK.getSound('poison').play();
// Make bomb explosion effect
LK.effects.flashObject(bombs[b], 0xFF0000, 200);
// Remove the bomb after collision
bombs[b].destroy();
bombs.splice(b, 1);
// Check if health has hit 0
if (health === 0) {
// Stop any currently playing music
LK.stopMusic();
// Play game over music that will continue until player presses Play Again
LK.playMusic('gameOverMusic');
// Show game over screen
LK.showGameOver();
}
break;
}
}
};
// Initialize lives, score, food consumed
var lives = 3;
var score = 0;
var previousScore = 0;
var previousBombScore = 0;
var foodConsumed = 0;
var normalFoodCount = 0; // Initialize normalFoodCount
var poisonToSpawn = 0; // Initialize poisonToSpawn
var starTrails = [];
var rocks = []; // Array to hold rock obstacles
var bombs = []; // Array to hold bomb obstacles
var messageDisplayed = false; // Flag to track if "I love you" message has been displayed
// Variables to track bomb spawning at different score thresholds
var bombsSpawned200 = false;
var bombsSpawned300 = false;
var bombsSpawned400 = false;
var lastBombSpawnTime = 0; // Track when bombs were last spawned
// Level system variables - level increases every 500 points
var level = 1;
var lastLevelUpScore = 0;
var isLevelingUp = false;
var baseItemDuration = 7000; // Base duration for items in milliseconds
var itemDuration = baseItemDuration; // Current duration for items, will increase with level
var foodSpawnCount = 1; // Number of food items to spawn
// Level 2+ difficulty variables
var bombSpeed = 0; // Speed at which bombs move
var enableMovingBombs = false; // Whether bombs should move
var enableFoodTeleport = false; // Whether food should teleport
var rockSpawnRate = 0.002; // Base rate for spawning rocks
var lastFoodTeleportTime = 0; // Track when food last teleported
// Function to check if two objects overlap
function checkOverlap(obj1, obj2, minDistance) {
if (!obj1 || !obj2) return false;
var dx = Math.abs(obj1.x - obj2.x);
var dy = Math.abs(obj1.y - obj2.y);
return dx < minDistance && dy < minDistance;
}
// Function to check if a position overlaps with any objects in arrays
function positionOverlapsAny(x, y, objectArrays, minDistance) {
for (var i = 0; i < objectArrays.length; i++) {
var array = objectArrays[i];
if (!array) continue;
for (var j = 0; j < array.length; j++) {
var obj = array[j];
if (!obj) continue;
var dx = Math.abs(x - obj.x);
var dy = Math.abs(y - obj.y);
if (dx < minDistance && dy < minDistance) {
return true;
}
}
}
return false;
}
// Create lives text
var livesTxt = new Text2('Lives: ' + lives, {
size: 32,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesTxt);
// Create score text
var scoreTxt = new Text2('Score: ' + score, {
size: 32,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create level text
var levelTxt = new Text2('Level: ' + level, {
size: 32,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
levelTxt.x = -10; // Offset from right edge
LK.gui.topRight.addChild(levelTxt);
// Initialize health
var health = 200;
// Create and position health bar
var healthBar = game.addChild(new HealthBar());
healthBar.x = 2048 / 2;
healthBar.y = 50;
// Function to update health bar
function updateHealthBar() {
healthBar.updateHealth(health);
}
// Function to calculate bomb spawn probability based on score
function getBombSpawnProbability() {
// Start with a very low probability
if (score < 100) {
return 0.001; // 0.1% chance
} else if (score < 200) {
return 0.003; // 0.3% chance
} else if (score < 300) {
return 0.005; // 0.5% chance
} else if (score < 400) {
return 0.007; // 0.7% chance
} else {
return 0.01; // 1% chance - same as original
}
}
// Function to spawn multiple food items based on the current level
function spawnMultipleFood() {
// We always keep the main food item
// Spawn additional food items based on level
for (var i = 0; i < foodSpawnCount - 1; i++) {
// Create additional food item
var additionalFood = new Food();
// Position at random location that doesn't overlap with other objects
do {
additionalFood.x = Math.random() * (2048 - additionalFood.width) + additionalFood.width / 2;
additionalFood.y = Math.random() * (2732 - additionalFood.height) + additionalFood.height / 2;
} while (
// Ensure food doesn't spawn at the border
(additionalFood.x < 100 || additionalFood.x > 1948) && (additionalFood.y < 100 || additionalFood.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(additionalFood, food, 100) || checkOverlap(additionalFood, bonusFood, 100) || checkOverlap(additionalFood, life, 100) || positionOverlapsAny(additionalFood.x, additionalFood.y, [rocks, bombs], 100));
// Add food to game
game.addChild(additionalFood);
// Set timeout to remove food after the current item duration
LK.setTimeout(function () {
if (additionalFood && additionalFood.parent) {
additionalFood.destroy();
}
}, itemDuration);
}
}
// Function to update level text
function updateLevelText() {
levelTxt.setText('Level: ' + level);
}
// Initialize health bar display
updateHealthBar();
// Initialize level text
updateLevelText();
game.down = function (x, y, obj) {
if (game.paused) {
return;
}
// Change the snake's direction to always move in the direction of the front area of the snake head which is not connected to the snake body
if (x > snake.x && snake.direction !== 'left' && snake.direction !== 'right') {
snake.moveHead('right');
} else if (x < snake.x && snake.direction !== 'right' && snake.direction !== 'left') {
snake.moveHead('left');
} else if (y > snake.y && snake.direction !== 'up' && snake.direction !== 'down') {
snake.moveHead('down');
} else if (y < snake.y && snake.direction !== 'down' && snake.direction !== 'up') {
snake.moveHead('up');
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BodyPart = Container.expand(function () {
var self = Container.call(this);
var bodyPart = self.attachAsset('head', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2,
tint: 0x00FFFF // Cyan tint for better visibility
});
// Add animation properties
self.originalScale = 1.2; // Larger scale
self.isAnimating = false;
self.animationDirection = 1;
// Rotate the body part based on direction
self.setDirection = function (direction) {
if (direction === 'up') {
bodyPart.rotation = 0;
} else if (direction === 'down') {
bodyPart.rotation = Math.PI;
} else if (direction === 'left') {
bodyPart.rotation = -Math.PI / 2;
} else if (direction === 'right') {
bodyPart.rotation = Math.PI / 2;
}
};
// Start wiggle animation for body parts
self.startWiggleAnimation = function () {
if (self.isAnimating) return;
self.isAnimating = true;
self.animateWiggle();
};
// Stop wiggle animation
self.stopWiggleAnimation = function () {
self.isAnimating = false;
tween.stop(bodyPart, {
scaleX: true,
scaleY: true
});
bodyPart.scaleX = self.originalScale;
bodyPart.scaleY = self.originalScale;
};
// Animate wiggle effect
self.animateWiggle = function () {
if (!self.isAnimating) return;
var scaleOffset = 0.05;
var duration = 250;
// Determine which axis to animate based on direction
var direction = self.animationDirection;
var targetScaleX = self.originalScale;
var targetScaleY = self.originalScale;
// Wiggle based on body orientation
if (bodyPart.rotation === 0 || bodyPart.rotation === Math.PI) {
// For up/down movement, wiggle horizontally
targetScaleX = self.originalScale + scaleOffset * direction;
} else {
// For left/right movement, wiggle vertically
targetScaleY = self.originalScale + scaleOffset * direction;
}
tween(bodyPart, {
scaleX: targetScaleX,
scaleY: targetScaleY
}, {
duration: duration,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.animationDirection *= -1;
if (self.isAnimating) {
self.animateWiggle();
}
}
});
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
// Create a bomb obstacle using rock image asset with red tint
var bomb = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF0000,
// Red tint to distinguish from rocks
scaleX: 0.8,
scaleY: 0.8
});
return self;
});
var BonusFood = Container.expand(function () {
var self = Container.call(this);
// Create the bonus food
var bonusFood = self.attachAsset('bonusFood', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var Food = Container.expand(function () {
var self = Container.call(this);
// Create the food
var food = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
var HealthBar = Container.expand(function () {
var self = Container.call(this);
// Create the health bar container box
var barContainer = self.attachAsset('healbar', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.7,
scaleX: 2,
scaleY: 0.5
});
// Create the bar background (red)
var barBg = self.attachAsset('healbar', {
anchorX: 0,
anchorY: 0.5,
tint: 0xFF0000,
scaleX: 1.9,
scaleY: 0.4,
x: -barContainer.width / 2 + 5,
y: 0
});
// Create the health indicator (green)
var healthIndicator = self.attachAsset('healbar', {
anchorX: 0,
anchorY: 0.5,
tint: 0x00FF00,
scaleX: 1.9,
scaleY: 0.4,
x: -barContainer.width / 2 + 5,
y: 0
});
self.updateHealth = function (health) {
// Health ranges from 0 to 200, convert to scale between 0 and 1.9 (max bar width)
var healthWidth = health / 200 * 1.9;
healthIndicator.scaleX = healthWidth;
};
return self;
});
var KOCAM = Container.expand(function () {
var self = Container.call(this);
// Create the life
var life = self.attachAsset('life', {
anchorX: 0.5,
anchorY: 0.5
});
});
var LevelUpMessage = Container.expand(function () {
var self = Container.call(this);
// Create the level up message background
var background = self.attachAsset('healbar', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.8,
scaleX: 20,
scaleY: 8
});
// Create the level up message text
var message = new Text2('', {
size: 64,
fill: 0xFFFFFF
});
message.anchor.set(0.5, 0.5);
self.addChild(message);
// Method to update the text
self.setLevel = function (level) {
message.setText('Çok yeteneklisin bebi');
};
// Method to show the message with animation
self.show = function () {
self.alpha = 0;
self.scaleX = 0.5;
self.scaleY = 0.5;
// Animate message appearance
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOutElastic
});
};
// Method to hide the message with animation
self.hide = function (callback) {
tween(self, {
alpha: 0,
scaleX: 0.5,
scaleY: 0.5
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
if (callback) callback();
}
});
};
return self;
});
var Pause = Container.expand(function () {
var self = Container.call(this);
// Create the pause button
var pause = self.attachAsset('pause', {
anchorX: 0.5,
anchorY: 0.5
});
// Event handler called when a press happens on element.
self.down = function (x, y, obj) {
if (!game.paused) {
game.paused = true;
pause.id = 'resume';
} else {
game.paused = false;
pause.id = 'pause';
}
};
return self;
});
// Poison class has been removed
var Rock = Container.expand(function () {
var self = Container.call(this);
// Create a rock obstacle using rock image asset
var rock = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
return self;
});
var Snake = Container.expand(function () {
var self = Container.call(this);
// Create the head of the snake
var head = self.attachAsset('head', {
anchorX: 0.5,
anchorY: 0.5
});
// Initialize the snake's direction and speed
self.direction = 'up';
self.speed = 5;
self.previousPositions = [];
// Update the head rotation based on direction
self.updateHeadRotation = function () {
if (self.direction === 'up') {
head.rotation = 0;
} else if (self.direction === 'down') {
head.rotation = Math.PI;
} else if (self.direction === 'left') {
head.rotation = -Math.PI / 2;
} else if (self.direction === 'right') {
head.rotation = Math.PI / 2;
}
};
self.moveHead = function (newDirection) {
if (newDirection === 'up' && this.direction !== 'down') {
this.direction = 'up';
self.updateHeadRotation();
} else if (newDirection === 'down' && this.direction !== 'up') {
this.direction = 'down';
self.updateHeadRotation();
} else if (newDirection === 'left' && this.direction !== 'right') {
this.direction = 'left';
self.updateHeadRotation();
} else if (newDirection === 'right' && this.direction !== 'left') {
this.direction = 'right';
self.updateHeadRotation();
}
};
// Initialize with the correct rotation
self.updateHeadRotation();
return self;
});
var StarTrail = Container.expand(function () {
var self = Container.call(this);
// Create a star-like shape using an asset
var star = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
// Set initial properties
self.alpha = 1;
self.fadeSpeed = 0.03; // Slower fade for more visibility
self.rotationSpeed = 0.1;
self.tailLength = 0;
self.maxTailLength = 45; // Longer tail
self.growSpeed = 0.8; // Grow faster
self.tailColor = 0xFFFF00; // Bright yellow for tail
star.tint = 0xFFFFFF; // White for star head
// Update method to handle fading, rotation and tail growth
self.update = function () {
// Rotate the star
star.rotation += self.rotationSpeed;
// Fade out more slowly
self.alpha -= self.fadeSpeed;
// Grow tail initially
if (self.tailLength < self.maxTailLength) {
self.tailLength += self.growSpeed;
}
// If fully transparent, mark for removal
if (self.alpha <= 0) {
self.shouldRemove = true;
}
};
return self;
});
/****
* Initialize Game
****/
//<Assets used in the game will automatically appear here>
var game = new LK.Game({
backgroundColor: 0x000000 //Init game with black background
});
/****
* Game Code
****/
// Add a background to the game
// Import tween plugin for animations
var background = game.addChildAt(LK.getAsset('newBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
alpha: 0.7 // Reduce opacity to improve visibility of game elements
}), 0); // Add background as the bottom-most layer
// Start playing background music as soon as the game begins
LK.playMusic('gameOverMusic');
// Initialize pause button
var pause = game.addChild(new Pause());
// Position the pause button a little to the left from the top right corner of the game
pause.x = 2048 - pause.width;
pause.y = 50; // Move the pause button a little down
var snake = game.addChild(new Snake());
snake.body = [];
// Position the snake at the center of the game
snake.x = 2048 / 2;
snake.y = 2732 / 2;
// Initialize food
var food = game.addChild(new Food());
// Position the food at a random location within the game
food.x = Math.random() * 2048;
food.y = Math.random() * 2732;
// Initialize poison
var bonusFood = game.addChild(new BonusFood());
// Poison food item has been removed
bonusFood.x = -100;
bonusFood.y = -100;
var life = game.addChild(new KOCAM());
// Hide the life when the game starts
life.x = -100;
life.y = -100;
// Hide the poison when the game starts
game.update = function () {
if (game.paused) {
return;
}
// Update the snake's position based on its direction and speed
if (snake.direction === 'up') {
snake.y -= snake.speed * 2.25;
} else if (snake.direction === 'down') {
snake.y += snake.speed * 2.25;
} else if (snake.direction === 'left') {
snake.x -= snake.speed * 2.25;
} else if (snake.direction === 'right') {
snake.x += snake.speed * 2.25;
}
// Level 2+ mechanics - Moving bombs
if (enableMovingBombs && bombs.length > 0) {
for (var mb = 0; mb < bombs.length; mb++) {
// Move bombs toward snake occasionally
if (LK.ticks % 60 === 0) {
// Target the snake with a chance
if (Math.random() < 0.5) {
// Calculate direction toward snake
var dx = snake.x - bombs[mb].x;
var dy = snake.y - bombs[mb].y;
// Normalize and apply speed
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
bombs[mb].x += dx / dist * bombSpeed;
bombs[mb].y += dy / dist * bombSpeed;
}
} else {
// Random movement
bombs[mb].x += (Math.random() * 2 - 1) * bombSpeed * 2;
bombs[mb].y += (Math.random() * 2 - 1) * bombSpeed * 2;
}
}
}
}
// Level 2+ mechanics - Teleporting food
if (enableFoodTeleport && LK.ticks % 180 === 0 && food && food.parent) {
// 5% chance food will teleport every 3 seconds
if (Math.random() < 0.05) {
// Teleport food to a new location
do {
food.x = Math.random() * (2048 - food.width) + food.width / 2;
food.y = Math.random() * (2732 - food.height) + food.height / 2;
} while (
// Ensure food doesn't spawn at the border
(food.x < 100 || food.x > 1948) && (food.y < 100 || food.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(food, bonusFood, 100) || checkOverlap(food, life, 100) || positionOverlapsAny(food.x, food.y, [rocks, bombs], 100));
// Visual effect for teleportation
LK.effects.flashObject(food, 0x00FFFF, 300);
}
}
// Level 2+ mechanics - Random rock spawning based on level
if (level >= 2 && Math.random() < rockSpawnRate && !game.paused) {
var randomRock = new Rock();
do {
randomRock.x = Math.random() * (2048 - 200) + 100;
randomRock.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure random rock doesn't spawn near snake
Math.abs(randomRock.x - snake.x) < 200 && Math.abs(randomRock.y - snake.y) < 200 ||
// Ensure random rock doesn't overlap with other game objects
checkOverlap(randomRock, food, 100) || checkOverlap(randomRock, bonusFood, 100) || checkOverlap(randomRock, life, 100) || positionOverlapsAny(randomRock.x, randomRock.y, [rocks, bombs], 100));
game.addChild(randomRock);
rocks.push(randomRock);
// Remove the rock after the current item duration
LK.setTimeout(function () {
if (rocks.includes(randomRock) && randomRock.parent) {
// Remove rock from array and game
for (var i = 0; i < rocks.length; i++) {
if (rocks[i] === randomRock) {
rocks[i].destroy();
rocks.splice(i, 1);
break;
}
}
}
}, itemDuration / 2); // Half duration for random rocks to make them more challenging
}
// Store the current position of the snake head
snake.previousPositions.unshift({
x: snake.x,
y: snake.y,
direction: snake.direction
});
// Limit the previous positions array to the length of the body plus some buffer
if (snake.previousPositions.length > snake.body.length + 10) {
snake.previousPositions.pop();
}
// Update the position of the body parts to follow the head's previous positions
for (var i = 0; i < snake.body.length; i++) {
if (i + 1 < snake.previousPositions.length) {
// Make sure the body part is added to the game at the bottom layer
// to ensure it stays behind the head
game.addChildAt(snake.body[i], 0);
// Position the body part based on the previous position of the head
snake.body[i].x = snake.previousPositions[i + 1].x;
snake.body[i].y = snake.previousPositions[i + 1].y;
snake.body[i].setDirection(snake.previousPositions[i + 1].direction);
// Manage animation for body parts
// Start animation if not already animating
if (!snake.body[i].isAnimating) {
snake.body[i].startWiggleAnimation();
}
// Set animation phase offset based on position in snake body
// This creates a wave-like effect through the snake's body
snake.body[i].animationDirection = i % 2 === 0 ? 1 : -1;
// Create star trail effect behind each body part for more visibility (once every few frames)
if (LK.ticks % 2 === 0) {
// More frequent trails
var star = new StarTrail();
star.x = snake.body[i].x;
star.y = snake.body[i].y;
// Less randomness for more consistent tail appearance
star.x += Math.random() * 6 - 3;
star.y += Math.random() * 6 - 3;
// Place star trail behind the snake but above the background
game.addChildAt(star, game.getChildIndex(background) + 1);
if (!starTrails) {
starTrails = [];
}
starTrails.push(star);
}
}
}
// Update and clean up star trails
if (starTrails) {
for (var j = starTrails.length - 1; j >= 0; j--) {
starTrails[j].update();
// Create comet trail effect with gradual color change
if (starTrails[j].tailLength > 0 && LK.ticks % 2 === 0) {
// Calculate color based on alpha
var colorIntensity = Math.floor(starTrails[j].alpha * 255);
var tailColor = colorIntensity << 16 | colorIntensity << 8 | Math.floor(colorIntensity * 0.7);
// Apply color tint to create glowing effect
if (starTrails[j].children[0]) {
starTrails[j].children[0].tint = tailColor;
}
// Scale effect for comet-like appearance
var scaleFactor = 0.5 + starTrails[j].alpha * 0.5;
starTrails[j].scaleX = scaleFactor;
starTrails[j].scaleY = scaleFactor;
}
if (starTrails[j].shouldRemove) {
starTrails[j].destroy();
starTrails.splice(j, 1);
}
}
}
// Check if the snake's head intersects with the food
if (snake.intersects(food)) {
// Increase the score by 50 instead of 10
score += 50;
// Update the score text
scoreTxt.setText('Score: ' + score);
// Check if player reached 800 points to win
if (score >= 800) {
// Show win message
var winMessage = new LevelUpMessage();
winMessage.setLevel(level);
winMessage.x = 2048 / 2;
winMessage.y = 2732 / 2;
game.addChild(winMessage);
winMessage.show();
// Flash screen green for win
LK.effects.flashScreen(0x00FF00, 500);
// Show "You win" with custom message
LK.showYouWin("Eline sağlık yavrum kazandın");
return;
}
// Check for level up (every 500 points)
if (!isLevelingUp && score >= lastLevelUpScore + 500) {
// Level up!
level++;
lastLevelUpScore = Math.floor(score / 500) * 500;
// Increase item duration by 5 seconds per level
itemDuration = baseItemDuration + (level - 1) * 5000;
// Increase food spawn count with level
foodSpawnCount = Math.min(level, 4); // Cap at 4 food items
// Pause the game during level up
game.paused = true;
isLevelingUp = true;
// Create and display level up message
var levelMessage = new LevelUpMessage();
levelMessage.setLevel(level);
levelMessage.x = 2048 / 2;
levelMessage.y = 2732 / 2;
game.addChild(levelMessage);
levelMessage.show();
// Update level text
updateLevelText();
// Flash screen green for level up
LK.effects.flashScreen(0x00FF00, 300);
// If reaching level 2 or higher, apply more challenging behaviors
if (level >= 2) {
// Update bomb speed increases
bombSpeed = 3;
// Enable moving bombs
enableMovingBombs = true;
// Enable food teleportation
enableFoodTeleport = true;
// Make rock spawning more frequent
rockSpawnRate = 0.01;
}
// Resume game after 2 seconds
LK.setTimeout(function () {
levelMessage.hide(function () {
levelMessage.destroy();
game.paused = false;
isLevelingUp = false;
// Spawn additional food based on level
spawnMultipleFood();
});
}, 2000);
}
// Increase the food consumed count
foodConsumed += 1;
// Track normal food items for poison spawning
normalFoodCount += 1;
// Every 3 normal food items, trigger spawning of 3 poison items
if (normalFoodCount >= 3) {
poisonToSpawn += 3;
normalFoodCount = 0;
}
// Increase health by 10, up to maximum 200
health = Math.min(health + 10, 200);
// Update health bar
updateHealthBar();
// Add a new body part to the snake
var newBodyPart = new BodyPart();
// Set the direction of the new body part
newBodyPart.setDirection(snake.direction);
// If no previous positions exist, create initial position
if (snake.previousPositions.length <= snake.body.length) {
var lastPos;
if (snake.body.length === 0) {
lastPos = {
x: snake.x,
y: snake.y
};
} else {
var lastBodyPart = snake.body[snake.body.length - 1];
lastPos = {
x: lastBodyPart.x,
y: lastBodyPart.y
};
}
// Calculate position based on direction
if (snake.direction === 'up') {
newBodyPart.x = lastPos.x;
newBodyPart.y = lastPos.y + 50; // Use a fixed offset
} else if (snake.direction === 'down') {
newBodyPart.x = lastPos.x;
newBodyPart.y = lastPos.y - 50;
} else if (snake.direction === 'left') {
newBodyPart.x = lastPos.x + 50;
newBodyPart.y = lastPos.y;
} else if (snake.direction === 'right') {
newBodyPart.x = lastPos.x - 50;
newBodyPart.y = lastPos.y;
}
} else {
// Use the position from previous positions array
var pos = snake.previousPositions[snake.body.length];
newBodyPart.x = pos.x;
newBodyPart.y = pos.y;
}
// Initialize animation properties and start animation for the new body part
newBodyPart.startWiggleAnimation();
// Add scale animation when adding new body part
newBodyPart.scaleX = 0;
newBodyPart.scaleY = 0;
tween(newBodyPart, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeOutElastic
});
snake.body.push(newBodyPart);
game.addChild(newBodyPart);
// Create an initial burst of star trail when a new body part is added
for (var s = 0; s < 10; s++) {
var star = new StarTrail();
star.x = newBodyPart.x + (Math.random() * 60 - 30);
star.y = newBodyPart.y + (Math.random() * 60 - 30);
star.alpha = 0.8 + Math.random() * 0.2;
star.fadeSpeed = 0.03 + Math.random() * 0.02;
star.rotationSpeed = 0.05 + Math.random() * 0.1;
// Place star above background but below game elements
game.addChildAt(star, game.getChildIndex(background) + 1);
starTrails.push(star);
}
// Check if it's time to show the bonus food
if (score % 150 === 0) {
// Position the bonus food at a new random location within the game, ensuring it does not appear on the border or overlap other objects
do {
bonusFood.x = Math.random() * (2048 - bonusFood.width) + bonusFood.width / 2;
bonusFood.y = Math.random() * (2732 - bonusFood.height) + bonusFood.height / 2;
} while (
// Ensure bonus food doesn't spawn at the border
(bonusFood.x < 100 || bonusFood.x > 1948) && (bonusFood.y < 100 || bonusFood.y > 2632) ||
// Ensure bonus food doesn't overlap with other game objects
checkOverlap(bonusFood, food, 100) || checkOverlap(bonusFood, life, 100) || positionOverlapsAny(bonusFood.x, bonusFood.y, [rocks, bombs], 100));
// Show the bonus food for the current item duration
LK.setTimeout(function () {
bonusFood.x = -100;
bonusFood.y = -100;
}, itemDuration);
}
// Display "Seni seviyorum" message inside the health bar
if (score >= 300 && !messageDisplayed) {
// Create a flag to track whether the message has been displayed
messageDisplayed = true;
// Show the message inside the health bar
var loveMessage = new Text2('Seni seviyorum', {
size: 32,
fill: 0xFFFFFF
});
// Center the message
loveMessage.anchor.set(0.5, 0.5);
// Add message to the health bar
healthBar.addChild(loveMessage);
// Start with zero scale and fade in
loveMessage.scaleX = 0;
loveMessage.scaleY = 0;
loveMessage.alpha = 0;
// Animate the message appearance
tween(loveMessage, {
scaleX: 1,
scaleY: 1,
alpha: 1
}, {
duration: 500,
easing: tween.elasticOut
});
// Keep the message visible permanently
}
// Check if it's time to show the life - increased frequency from every 100 points to every 50 points
if (score !== 0 && score % 50 === 0 && score != previousScore) {
previousScore = score;
// Position the life at a new random location within the game, ensuring it does not appear on the border or overlap other objects
do {
life.x = Math.random() * (2048 - life.width) + life.width / 2;
life.y = Math.random() * (2732 - life.height) + life.height / 2;
} while (
// Ensure life doesn't spawn at the border
(life.x < 100 || life.x > 1948) && (life.y < 100 || life.y > 2632) ||
// Ensure life doesn't overlap with other game objects
checkOverlap(life, food, 100) || checkOverlap(life, bonusFood, 100) || positionOverlapsAny(life.x, life.y, [rocks, bombs], 100));
// Show the life for the current item duration
LK.setTimeout(function () {
life.x = -100;
life.y = -100;
}, itemDuration);
}
// Randomly spawn additional life items during gameplay (independent of score)
if (Math.random() < 0.005 && !game.paused) {
// 0.5% chance per frame
var randomLife = new KOCAM();
do {
randomLife.x = Math.random() * (2048 - 200) + 100;
randomLife.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure random life doesn't spawn near snake
Math.abs(randomLife.x - snake.x) < 200 && Math.abs(randomLife.y - snake.y) < 200 ||
// Ensure random life doesn't overlap with other game objects
checkOverlap(randomLife, food, 100) || checkOverlap(randomLife, bonusFood, 100) || checkOverlap(randomLife, life, 100) || positionOverlapsAny(randomLife.x, randomLife.y, [rocks, bombs], 100));
game.addChild(randomLife);
// Remove the life after the current item duration if not collected
LK.setTimeout(function () {
randomLife.destroy();
}, itemDuration);
}
// Poison spawning has been removed
// Spawn rocks and bombs when score passes various thresholds, starting with fewer and increasing
if (score > 100 && score < 200 && rocks.length === 0) {
// Start with fewer rocks (2 initially) and increase with score
var rockCount = 2;
// Adjust rock count based on score
if (score > 150) rockCount = 3;
// Spawn rocks in random positions
for (var r = 0; r < rockCount; r++) {
var rock = new Rock();
// Position rocks randomly but avoid placing directly on snake
do {
rock.x = Math.random() * (2048 - 200) + 100;
rock.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure rock doesn't spawn near snake
Math.abs(rock.x - snake.x) < 200 && Math.abs(rock.y - snake.y) < 200 ||
// Ensure rock doesn't overlap with other game objects
checkOverlap(rock, food, 100) || checkOverlap(rock, bonusFood, 100) || checkOverlap(rock, life, 100) || positionOverlapsAny(rock.x, rock.y, [rocks, bombs], 100));
game.addChild(rock);
rocks.push(rock);
// Set timeout to remove rock after the current item duration if not collided with
LK.setTimeout(function () {
// Check if rock still exists in the array and game
if (rocks.includes(rock) && rock.parent) {
// Remove rock from array and game
for (var i = 0; i < rocks.length; i++) {
if (rocks[i] === rock) {
rocks[i].destroy();
rocks.splice(i, 1);
break;
}
}
}
}, itemDuration);
}
// Gradually increase bomb count based on score
var bombCount = 2; // Start with fewer bombs
// Adjust bomb count based on score
if (score > 150) bombCount = 3;
// Add bomb obstacles
for (var b = 0; b < bombCount; b++) {
var bomb = new Bomb();
// Position bombs randomly but avoid placing directly on snake
do {
bomb.x = Math.random() * (2048 - 200) + 100;
bomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure bomb doesn't spawn near snake
Math.abs(bomb.x - snake.x) < 200 && Math.abs(bomb.y - snake.y) < 200 ||
// Ensure bomb doesn't overlap with other game objects
checkOverlap(bomb, food, 100) || checkOverlap(bomb, bonusFood, 100) || checkOverlap(bomb, life, 100) || positionOverlapsAny(bomb.x, bomb.y, [rocks, bombs], 100));
game.addChild(bomb);
bombs.push(bomb);
}
}
// Additional bombs when score reaches higher thresholds - with reduced initial counts
if (score > 200 && score < 300 && !bombsSpawned200 || score > 300 && score < 400 && !bombsSpawned300 || score > 400 && !bombsSpawned400) {
// Set the appropriate flag
if (score > 200 && score < 300) bombsSpawned200 = true;else if (score > 300 && score < 400) bombsSpawned300 = true;else if (score > 400) bombsSpawned400 = true;
// Number of bombs increases with score, but starts lower
var bombCount = 3; // Start with fewer bombs at 200 points
if (score > 300) bombCount = 5; // Moderate increase at 300 points
if (score > 400) bombCount = 8; // Larger increase at 400 points
// Spawn bombs
for (var b = 0; b < bombCount; b++) {
var difficultyBomb = new Bomb();
do {
difficultyBomb.x = Math.random() * (2048 - 200) + 100;
difficultyBomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure difficulty bomb doesn't spawn near snake
Math.abs(difficultyBomb.x - snake.x) < 200 && Math.abs(difficultyBomb.y - snake.y) < 200 ||
// Ensure difficulty bomb doesn't overlap with other game objects
checkOverlap(difficultyBomb, food, 100) || checkOverlap(difficultyBomb, bonusFood, 100) || checkOverlap(difficultyBomb, life, 100) || positionOverlapsAny(difficultyBomb.x, difficultyBomb.y, [rocks, bombs], 100));
game.addChild(difficultyBomb);
bombs.push(difficultyBomb);
}
}
// Remove rocks when score reaches 200
if (score >= 200 && rocks.length > 0) {
// Remove all rocks
for (var i = rocks.length - 1; i >= 0; i--) {
rocks[i].destroy();
rocks.splice(i, 1);
}
}
// Spawn bombs at milestone scores, with increasing frequency as score increases
if (score > 100 && score % 50 === 0 && score !== previousBombScore) {
previousBombScore = score;
// Start with fewer bombs and increase with score
var bombCount;
if (score <= 150) {
bombCount = 1; // Just 1 bomb initially
} else if (score <= 250) {
bombCount = 1 + Math.floor(Math.random() * 2); // 1-2 bombs
} else if (score <= 350) {
bombCount = 2; // 2 bombs
} else {
bombCount = 2 + Math.floor(Math.random() * 2); // 2-3 bombs
}
for (var i = 0; i < bombCount; i++) {
var bomb = new Bomb();
// Position the bomb randomly but avoid placing directly on snake
do {
bomb.x = Math.random() * (2048 - 200) + 100;
bomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure bomb doesn't spawn near snake
Math.abs(bomb.x - snake.x) < 200 && Math.abs(bomb.y - snake.y) < 200 ||
// Ensure bomb doesn't overlap with other game objects
checkOverlap(bomb, food, 100) || checkOverlap(bomb, bonusFood, 100) || checkOverlap(bomb, life, 100) || positionOverlapsAny(bomb.x, bomb.y, [rocks, bombs], 100));
game.addChild(bomb);
bombs.push(bomb);
// Remove the bomb after the current item duration
LK.setTimeout(function () {
if (bombs.length > 0) {
for (var i = 0; i < bombs.length; i++) {
if (bombs[i] === bomb) {
bombs[i].destroy();
bombs.splice(i, 1);
break;
}
}
}
}, itemDuration);
}
}
// Randomly spawn additional bombs during gameplay with probability based on score
if (Math.random() < getBombSpawnProbability() && !game.paused) {
// Dynamic probability based on score
var randomBomb = new Bomb();
do {
randomBomb.x = Math.random() * (2048 - 200) + 100;
randomBomb.y = Math.random() * (2732 - 200) + 100;
} while (
// Ensure random bomb doesn't spawn near snake
Math.abs(randomBomb.x - snake.x) < 200 && Math.abs(randomBomb.y - snake.y) < 200 ||
// Ensure random bomb doesn't overlap with other game objects
checkOverlap(randomBomb, food, 100) || checkOverlap(randomBomb, bonusFood, 100) || checkOverlap(randomBomb, life, 100) || positionOverlapsAny(randomBomb.x, randomBomb.y, [rocks, bombs], 100));
game.addChild(randomBomb);
bombs.push(randomBomb);
// Remove the bomb after the current item duration
LK.setTimeout(function () {
if (bombs.length > 0) {
for (var j = 0; j < bombs.length; j++) {
if (bombs[j] === randomBomb) {
bombs[j].destroy();
bombs.splice(j, 1);
break;
}
}
}
}, itemDuration);
}
// Position the food at a new random location within the game, ensuring it does not appear on the border or overlap with other objects
do {
food.x = Math.random() * (2048 - food.width) + food.width / 2;
food.y = Math.random() * (2732 - food.height) + food.height / 2;
} while (
// Ensure food doesn't spawn at the border
(food.x < 100 || food.x > 1948) && (food.y < 100 || food.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(food, bonusFood, 100) || checkOverlap(food, life, 100) || positionOverlapsAny(food.x, food.y, [rocks, bombs], 100));
// Set a timeout to remove food after the current item duration if not eaten
LK.setTimeout(function () {
// Only reposition if the food is still in the game (hasn't been eaten)
if (food && food.parent) {
// Position food offscreen
food.x = -100;
food.y = -100;
// Spawn new food
do {
food.x = Math.random() * (2048 - food.width) + food.width / 2;
food.y = Math.random() * (2732 - food.height) + food.height / 2;
} while (
// Ensure food doesn't spawn at the border
(food.x < 100 || food.x > 1948) && (food.y < 100 || food.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(food, bonusFood, 100) || checkOverlap(food, life, 100) || positionOverlapsAny(food.x, food.y, [rocks, bombs], 100));
}
}, itemDuration);
// Play baby sound when food is eaten
LK.getSound('yiyecek').play();
}
// Check if the snake's head intersects with the bonus food
if (snake.intersects(bonusFood)) {
// Increase the score by 50
score += 50;
// Update the score text
scoreTxt.setText('Score: ' + score);
// Play the bonus food sound
LK.getSound('bonusfood').play();
// In level 2+, destroy the bonus food rather than just hiding it
if (level >= 2) {
// Create a replacement bonus food
bonusFood.destroy();
bonusFood = game.addChild(new BonusFood());
bonusFood.x = -100;
bonusFood.y = -100;
} else {
// Hide the bonus food
bonusFood.x = -100;
bonusFood.y = -100;
}
}
// Check if the snake's head intersects with the life
if (snake.intersects(life)) {
// Increase the lives by 1, up to a maximum of 8
if (lives < 8) {
lives += 1;
// Update the lives text
livesTxt.setText('Lives: ' + lives);
// Update health bar
updateHealthBar();
// Play the life sound
LK.getSound('life').play();
}
// In level 2+, destroy the life rather than just hiding it
if (level >= 2) {
// Create a replacement life
life.destroy();
life = game.addChild(new KOCAM());
life.x = -100;
life.y = -100;
} else {
// Hide the life
life.x = -100;
life.y = -100;
}
}
// Poison food item has been removed
// Check if the snake's head has moved out of the screen
if (snake.x < 0) {
snake.x = 2048;
} else if (snake.x > 2048) {
snake.x = 0;
} else if (snake.y < 0) {
snake.y = 2732;
} else if (snake.y > 2732) {
snake.y = 0;
}
// Check for collision with rocks
for (var r = 0; r < rocks.length; r++) {
if (snake.intersects(rocks[r])) {
// Play cat sound when snake hits rocks
LK.getSound('cat').play();
// Track if this is the first or second collision
if (!snake.rockCollision) {
// First collision - reduce health by 70
snake.rockCollision = true;
health -= 70;
// Ensure health doesn't go below 0
if (health < 0) health = 0;
// Update the health bar
updateHealthBar();
// Flash screen red for visual feedback
LK.effects.flashScreen(0xFF0000, 300);
// Push snake back a bit from the rock
if (snake.direction === 'up') {
snake.y += 50;
} else if (snake.direction === 'down') {
snake.y -= 50;
} else if (snake.direction === 'left') {
snake.x += 50;
} else if (snake.direction === 'right') {
snake.x -= 50;
}
// Make the rock disappear
rocks[r].destroy();
rocks.splice(r, 1);
} else {
// Second collision - snake dies
// Stop any currently playing music
LK.stopMusic();
// Play game over music that will continue until player presses Play Again
LK.playMusic('gameOverMusic');
// Flash screen red for visual feedback
LK.effects.flashScreen(0xFF0000, 500);
LK.showGameOver();
}
break;
}
}
// Check for collision with bombs
for (var b = 0; b < bombs.length; b++) {
if (snake.intersects(bombs[b])) {
// Increase damage - decrease health by 30 for bomb collision (up from 20)
health -= 30;
// Ensure health doesn't go below 0
if (health < 0) health = 0;
// Update health bar
updateHealthBar();
// Flash screen red for visual feedback with longer duration
LK.effects.flashScreen(0xFF0000, 300);
// Play the poison sound
LK.getSound('poison').play();
// Make bomb explosion effect
LK.effects.flashObject(bombs[b], 0xFF0000, 200);
// Remove the bomb after collision
bombs[b].destroy();
bombs.splice(b, 1);
// Check if health has hit 0
if (health === 0) {
// Stop any currently playing music
LK.stopMusic();
// Play game over music that will continue until player presses Play Again
LK.playMusic('gameOverMusic');
// Show game over screen
LK.showGameOver();
}
break;
}
}
};
// Initialize lives, score, food consumed
var lives = 3;
var score = 0;
var previousScore = 0;
var previousBombScore = 0;
var foodConsumed = 0;
var normalFoodCount = 0; // Initialize normalFoodCount
var poisonToSpawn = 0; // Initialize poisonToSpawn
var starTrails = [];
var rocks = []; // Array to hold rock obstacles
var bombs = []; // Array to hold bomb obstacles
var messageDisplayed = false; // Flag to track if "I love you" message has been displayed
// Variables to track bomb spawning at different score thresholds
var bombsSpawned200 = false;
var bombsSpawned300 = false;
var bombsSpawned400 = false;
var lastBombSpawnTime = 0; // Track when bombs were last spawned
// Level system variables - level increases every 500 points
var level = 1;
var lastLevelUpScore = 0;
var isLevelingUp = false;
var baseItemDuration = 7000; // Base duration for items in milliseconds
var itemDuration = baseItemDuration; // Current duration for items, will increase with level
var foodSpawnCount = 1; // Number of food items to spawn
// Level 2+ difficulty variables
var bombSpeed = 0; // Speed at which bombs move
var enableMovingBombs = false; // Whether bombs should move
var enableFoodTeleport = false; // Whether food should teleport
var rockSpawnRate = 0.002; // Base rate for spawning rocks
var lastFoodTeleportTime = 0; // Track when food last teleported
// Function to check if two objects overlap
function checkOverlap(obj1, obj2, minDistance) {
if (!obj1 || !obj2) return false;
var dx = Math.abs(obj1.x - obj2.x);
var dy = Math.abs(obj1.y - obj2.y);
return dx < minDistance && dy < minDistance;
}
// Function to check if a position overlaps with any objects in arrays
function positionOverlapsAny(x, y, objectArrays, minDistance) {
for (var i = 0; i < objectArrays.length; i++) {
var array = objectArrays[i];
if (!array) continue;
for (var j = 0; j < array.length; j++) {
var obj = array[j];
if (!obj) continue;
var dx = Math.abs(x - obj.x);
var dy = Math.abs(y - obj.y);
if (dx < minDistance && dy < minDistance) {
return true;
}
}
}
return false;
}
// Create lives text
var livesTxt = new Text2('Lives: ' + lives, {
size: 32,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesTxt);
// Create score text
var scoreTxt = new Text2('Score: ' + score, {
size: 32,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create level text
var levelTxt = new Text2('Level: ' + level, {
size: 32,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
levelTxt.x = -10; // Offset from right edge
LK.gui.topRight.addChild(levelTxt);
// Initialize health
var health = 200;
// Create and position health bar
var healthBar = game.addChild(new HealthBar());
healthBar.x = 2048 / 2;
healthBar.y = 50;
// Function to update health bar
function updateHealthBar() {
healthBar.updateHealth(health);
}
// Function to calculate bomb spawn probability based on score
function getBombSpawnProbability() {
// Start with a very low probability
if (score < 100) {
return 0.001; // 0.1% chance
} else if (score < 200) {
return 0.003; // 0.3% chance
} else if (score < 300) {
return 0.005; // 0.5% chance
} else if (score < 400) {
return 0.007; // 0.7% chance
} else {
return 0.01; // 1% chance - same as original
}
}
// Function to spawn multiple food items based on the current level
function spawnMultipleFood() {
// We always keep the main food item
// Spawn additional food items based on level
for (var i = 0; i < foodSpawnCount - 1; i++) {
// Create additional food item
var additionalFood = new Food();
// Position at random location that doesn't overlap with other objects
do {
additionalFood.x = Math.random() * (2048 - additionalFood.width) + additionalFood.width / 2;
additionalFood.y = Math.random() * (2732 - additionalFood.height) + additionalFood.height / 2;
} while (
// Ensure food doesn't spawn at the border
(additionalFood.x < 100 || additionalFood.x > 1948) && (additionalFood.y < 100 || additionalFood.y > 2632) ||
// Ensure food doesn't overlap with other game objects
checkOverlap(additionalFood, food, 100) || checkOverlap(additionalFood, bonusFood, 100) || checkOverlap(additionalFood, life, 100) || positionOverlapsAny(additionalFood.x, additionalFood.y, [rocks, bombs], 100));
// Add food to game
game.addChild(additionalFood);
// Set timeout to remove food after the current item duration
LK.setTimeout(function () {
if (additionalFood && additionalFood.parent) {
additionalFood.destroy();
}
}, itemDuration);
}
}
// Function to update level text
function updateLevelText() {
levelTxt.setText('Level: ' + level);
}
// Initialize health bar display
updateHealthBar();
// Initialize level text
updateLevelText();
game.down = function (x, y, obj) {
if (game.paused) {
return;
}
// Change the snake's direction to always move in the direction of the front area of the snake head which is not connected to the snake body
if (x > snake.x && snake.direction !== 'left' && snake.direction !== 'right') {
snake.moveHead('right');
} else if (x < snake.x && snake.direction !== 'right' && snake.direction !== 'left') {
snake.moveHead('left');
} else if (y > snake.y && snake.direction !== 'up' && snake.direction !== 'down') {
snake.moveHead('down');
} else if (y < snake.y && snake.direction !== 'down' && snake.direction !== 'up') {
snake.moveHead('up');
}
};
Pause icon. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows.
havuç. In-Game asset. 2d. High contrast. No shadows
çilek. In-Game asset. 2d. High contrast. No shadows
boynuna bir kurdele ve eline de uçan bir balon
böğürtlen ormanı. In-Game asset. 2d. High contrast. No shadows
taş. In-Game asset. 2d. High contrast. No shadows
mesaj kutusu. In-Game asset. 2d. High contrast. No shadows