User prompt
yukarı aşaşğı gibi davranıyor
User prompt
yukarı gitmesini hani eksiden yukarısına tıkldııyorduk ya ordaki gibi olsum
User prompt
yukarı butonu bozuk yine aşağı götüryor ve bu sefer o bir buttonlarıda bozma
User prompt
yukarı aşağı götürüyor
User prompt
bu seferde yukarı bozuldu aşağı çalışıyor ama 2 sinide bozma
User prompt
şimdide aşağı butonu bozuldu
User prompt
yukarı gitme butonu aşağı götürüyor
User prompt
snkaeTrail olmaycak
User prompt
yılanın bedeni olmayacak sadce kafası olacak
User prompt
yılan uzamayacak sadce başı olacak
User prompt
yılan gittiği yerde kendisi bırakıyor ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yine ynalış
User prompt
aynı düzelt buton yanlış götürüyor
User prompt
yukarı butonu ters kontol ediyor
User prompt
yukarı butonu aşağıya götürüyor
User prompt
yıollanın haraket etmesi. butonlar yap yukarı aşağı sağa sola
User prompt
oyun dost yılllanlar ekle 10 sanitye içinde gelsinler ve yem bıraksınlar ama level 2 yem normal değil ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
yılanın vücudu olmasın
User prompt
yılan kontrolleri geç alıgılıyor
User prompt
yılanın kafa ile vücdü birleştiren vücut parçasını sil
User prompt
odadaki duvarlar belli değil oyuncyular anlmaz
Code edit (1 edits merged)
Please save this source code
User prompt
Classic Snake
Initial prompt
bana bir yılan oyunu yap klasik
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var DirectionalButton = Container.expand(function (direction, assetId) { var self = Container.call(this); var graphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.direction = direction; // Add visual feedback when pressed self.down = function (x, y, obj) { if (!isGameRunning) { return; } // Prevent multiple rapid presses if (self.isPressed) { return; } self.isPressed = true; // Visual feedback - make button slightly smaller tween(self, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); // Change snake direction immediately changeDirection(self.direction); }; self.up = function (x, y, obj) { // Reset pressed state self.isPressed = false; // Return button to normal size tween(self, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); }; return self; }); var EnemySnake = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('enemySnake', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0xff4444; // Red tint for enemy self.moveSpeed = 1.5; self.direction = Math.random() * Math.PI * 2; self.chaseTimer = 0; self.isBeingRepelled = false; self.repelTimer = 0; self.update = function () { // Check if being repelled by friendly snakes self.isBeingRepelled = false; for (var i = 0; i < friendlySnakes.length; i++) { var friendlySnake = friendlySnakes[i]; var dist = Math.sqrt(Math.pow(self.x - friendlySnake.x, 2) + Math.pow(self.y - friendlySnake.y, 2)); if (dist < 150) { // Repel range self.isBeingRepelled = true; // Move away from friendly snake var angle = Math.atan2(self.y - friendlySnake.y, self.x - friendlySnake.x); self.direction = angle; break; } } // If not being repelled, chase the player if (!self.isBeingRepelled && snake.length > 0) { self.chaseTimer++; if (self.chaseTimer >= 30) { // Update chase direction every 0.5 seconds var playerHead = snake[0]; var playerScreenPos = gridToScreen(playerHead.x, playerHead.y); var angle = Math.atan2(playerScreenPos.y - self.y, playerScreenPos.x - self.x); self.direction = angle; self.chaseTimer = 0; } } // Move in current direction self.x += Math.cos(self.direction) * self.moveSpeed; self.y += Math.sin(self.direction) * self.moveSpeed; // Bounce off walls if (self.x < boardOffsetX || self.x > boardOffsetX + BOARD_WIDTH * GRID_SIZE) { self.direction = Math.PI - self.direction; } if (self.y < boardOffsetY || self.y > boardOffsetY + BOARD_HEIGHT * GRID_SIZE) { self.direction = -self.direction; } // Keep within bounds self.x = Math.max(boardOffsetX, Math.min(boardOffsetX + BOARD_WIDTH * GRID_SIZE, self.x)); self.y = Math.max(boardOffsetY, Math.min(boardOffsetY + BOARD_HEIGHT * GRID_SIZE, self.y)); }; return self; }); var Food = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('food', { anchorX: 0.5, anchorY: 0.5 }); self.update = function () { // Simple pulsing animation var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.1; self.scaleX = scale; self.scaleY = scale; }; return self; }); var FriendlySnake = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('friendlySnake', { anchorX: 0.5, anchorY: 0.5 }); self.moveSpeed = 2; self.direction = Math.random() * Math.PI * 2; self.dropTimer = 0; self.maxDrops = 3; self.dropsLeft = 3; self.hasKilledEnemy = false; self.update = function () { // Check for nearby enemy snakes to chase var isChasing = false; var closestEnemy = null; var closestDistance = Infinity; for (var i = 0; i < enemySnakes.length; i++) { var enemySnake = enemySnakes[i]; var dist = Math.sqrt(Math.pow(self.x - enemySnake.x, 2) + Math.pow(self.y - enemySnake.y, 2)); if (dist < 200) { // Detection range - notify GIGACHAD! if (!gigaChadNotified && enemySnakes.length > 0) { gigaChadNotified = true; if (!gigaChad) { gigaChad = game.addChild(new GigaChad()); } gigaChad.summon(); } if (dist < closestDistance) { closestDistance = dist; closestEnemy = enemySnake; isChasing = true; } } } // If chasing an enemy, move towards it if (isChasing && closestEnemy) { var angle = Math.atan2(closestEnemy.y - self.y, closestEnemy.x - self.x); self.direction = angle; self.moveSpeed = 3; // Increase speed when chasing } else { self.moveSpeed = 2; // Normal speed when not chasing } // Move in current direction self.x += Math.cos(self.direction) * self.moveSpeed; self.y += Math.sin(self.direction) * self.moveSpeed; // Check if we killed an enemy snake for (var i = enemySnakes.length - 1; i >= 0; i--) { var enemySnake = enemySnakes[i]; var dist = Math.sqrt(Math.pow(self.x - enemySnake.x, 2) + Math.pow(self.y - enemySnake.y, 2)); if (dist < 50) { // Kill range // Enemy snake is killed enemySnake.destroy(); enemySnakes.splice(i, 1); var coins = storage.coins || 0; storage.coins = coins + 100; // Bonus for friendly snake killing enemy scoreTxt.setText('SCOİN: ' + storage.coins); // Mark this friendly snake as having killed an enemy self.hasKilledEnemy = true; break; } } // Bounce off walls if (self.x < boardOffsetX || self.x > boardOffsetX + BOARD_WIDTH * GRID_SIZE) { self.direction = Math.PI - self.direction; } if (self.y < boardOffsetY || self.y > boardOffsetY + BOARD_HEIGHT * GRID_SIZE) { self.direction = -self.direction; } // Keep within bounds self.x = Math.max(boardOffsetX, Math.min(boardOffsetX + BOARD_WIDTH * GRID_SIZE, self.x)); self.y = Math.max(boardOffsetY, Math.min(boardOffsetY + BOARD_HEIGHT * GRID_SIZE, self.y)); // Drop food periodically self.dropTimer++; if (self.dropTimer >= 120 && self.dropsLeft > 0) { // Every 2 seconds self.dropFood(); self.dropTimer = 0; self.dropsLeft--; } // Remove after all drops are done - but only if hasn't killed an enemy if (self.dropsLeft <= 0 && !self.hasKilledEnemy) { tween(self, { alpha: 0 }, { duration: 1000, onFinish: function onFinish() { self.destroy(); var index = friendlySnakes.indexOf(self); if (index > -1) { friendlySnakes.splice(index, 1); } } }); } }; self.dropFood = function () { var dropType = Math.random() < 0.3 ? 'level2' : 'normal'; var newFood; if (dropType === 'level2') { newFood = game.addChild(new Level2Food()); } else { newFood = game.addChild(new Food()); } // Convert screen position to grid position and clamp to board bounds var gridX = Math.round((self.x - boardOffsetX) / GRID_SIZE); var gridY = Math.round((self.y - boardOffsetY) / GRID_SIZE); // Ensure food stays within board bounds gridX = Math.max(0, Math.min(BOARD_WIDTH - 1, gridX)); gridY = Math.max(0, Math.min(BOARD_HEIGHT - 1, gridY)); // Set food position based on clamped grid coordinates var screenPos = gridToScreen(gridX, gridY); newFood.x = screenPos.x; newFood.y = screenPos.y; newFood.gridX = gridX; newFood.gridY = gridY; // Add to food array foodItems.push(newFood); }; return self; }); var GigaChad = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('gigachad', { anchorX: 0.5, anchorY: 0.5 }); self.isActive = false; self.destroyTimer = 0; self.destroyDelay = shopEffects.speedGigachad.active ? 180 : 600; // 3 seconds if fast, 10 seconds normal self.summon = function () { if (self.isActive) { return; } // Already summoned self.isActive = true; self.destroyTimer = 0; // Position GIGACHAD at center of board self.x = boardOffsetX + BOARD_WIDTH * GRID_SIZE / 2; self.y = boardOffsetY + BOARD_HEIGHT * GRID_SIZE / 2; // Make GIGACHAD appear with dramatic effect self.alpha = 0; self.scaleX = 0.1; self.scaleY = 0.1; tween(self, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.bounceOut }); // Play summon sound LK.getSound('gigachadSummon').play(); // Flash screen to show GIGACHAD arrival LK.effects.flashScreen(0xFFD700, 1000); // Gold flash // Destroy all enemies immediately upon arrival self.destroyAllEnemies(); }; self.update = function () { if (!self.isActive) { return; } self.destroyTimer++; // Update destroy delay based on current speed effect status self.destroyDelay = shopEffects.speedGigachad.active ? 180 : 600; // Pulsing effect while active var pulse = 1 + Math.sin(LK.ticks * 0.2) * 0.1; self.scaleX = pulse; self.scaleY = pulse; // Auto-deactivate after completing task (enemies destroyed immediately on summon) if (self.destroyTimer >= self.destroyDelay) { // GIGACHAD disappears after completing his task tween(self, { alpha: 0, scaleX: 0.1, scaleY: 0.1 }, { duration: 1000, easing: tween.easeIn, onFinish: function onFinish() { self.isActive = false; self.destroyTimer = 0; } }); } }; self.destroyAllEnemies = function () { // Destroy all enemy snakes immediately for (var i = enemySnakes.length - 1; i >= 0; i--) { var enemySnake = enemySnakes[i]; // Flash enemy red before destroying tween(enemySnake, { tint: 0xFF0000, alpha: 0 }, { duration: 200, onFinish: function onFinish() { enemySnake.destroy(); } }); } // Clear enemy snakes array enemySnakes = []; // Play destroy sound LK.getSound('gigachadDestroy').play(); // Flash screen red for destruction LK.effects.flashScreen(0xFF0000, 1500); // Add massive score bonus var coins = storage.coins || 0; storage.coins = coins + 500; scoreTxt.setText('SCOİN: ' + storage.coins); }; return self; }); var Level2Food = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('level2Food', { anchorX: 0.5, anchorY: 0.5 }); self.foodType = 'level2'; self.update = function () { // Special pulsing animation for level 2 food var scale = 1 + Math.sin(LK.ticks * 0.15) * 0.3; self.scaleX = scale; self.scaleY = scale; // Color cycling effect var colorPhase = LK.ticks * 0.1 % (Math.PI * 2); var red = Math.floor(128 + 127 * Math.sin(colorPhase)); var green = Math.floor(128 + 127 * Math.sin(colorPhase + Math.PI * 2 / 3)); var blue = Math.floor(128 + 127 * Math.sin(colorPhase + Math.PI * 4 / 3)); graphics.tint = red << 16 | green << 8 | blue; }; return self; }); var Merchant = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('friendlySnake', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0xFFD700; // Gold tint for merchant // Shop items with costs self.shopItems = { slowdown: { cost: 150, name: "Slowdown (5min)", active: false, duration: 18000 }, // 5 minutes at 60fps speedGigachad: { cost: 200, name: "Fast GIGACHAD", active: false }, doublePoints: { cost: 200, name: "2x Points", active: false, duration: 18000 } // 5 minutes at 60fps }; self.down = function (x, y, obj) { self.openShop(); }; self.openShop = function () { // Simple shop interface using score display var playerCoins = storage.coins || 0; var shopText = "SHOP (SCOİN: " + playerCoins + ")\n"; shopText += "1. Slowdown 5min - " + self.shopItems.slowdown.cost + " SCOİN\n"; shopText += "2. Fast GIGACHAD - " + self.shopItems.speedGigachad.cost + " SCOİN\n"; shopText += "3. 2x Points - " + self.shopItems.doublePoints.cost + " SCOİN"; // Flash screen to show shop is open LK.effects.flashScreen(0xFFD700, 500); }; return self; }); var ShopButton = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('shopButton', { anchorX: 0.5, anchorY: 0.5 }); graphics.tint = 0x4CAF50; // Green tint for shop button self.down = function (x, y, obj) { if (!isGameRunning && !isShopOpen) { return; } // Visual feedback - make button slightly smaller tween(self, { scaleX: 0.9, scaleY: 0.9 }, { duration: 100 }); // Toggle shop - close if open, open if closed if (isShopOpen) { self.closeShop(); } else { isShopOpen = true; self.openFullScreenShop(); } }; self.up = function (x, y, obj) { // Return button to normal size tween(self, { scaleX: 1.0, scaleY: 1.0 }, { duration: 100 }); }; self.openFullScreenShop = function () { // Create full-screen shop container shopContainer = new Container(); shopContainer.x = 0; shopContainer.y = 0; game.addChild(shopContainer); // Create semi-transparent background var shopBg = LK.getAsset('shopButton', { anchorX: 0, anchorY: 0, scaleX: 10.24, scaleY: 34.15 }); shopBg.tint = 0x000000; shopBg.alpha = 0.8; shopContainer.addChild(shopBg); // Get player coins var playerCoins = storage.coins || 0; // Create shop title var titleText = new Text2('SHOP', { size: 150, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 300; shopContainer.addChild(titleText); // Create coins display var coinsText = new Text2('SCOİN: ' + playerCoins, { size: 80, fill: 0xFFFFFF }); coinsText.anchor.set(0.5, 0.5); coinsText.x = 1024; coinsText.y = 450; shopContainer.addChild(coinsText); // Create shop items var yPos = 700; var itemSpacing = 200; // Slowdown item var slowdownButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5 }); slowdownButton.x = 1024; slowdownButton.y = yPos; slowdownButton.tint = playerCoins >= 150 ? 0x4CAF50 : 0x666666; shopContainer.addChild(slowdownButton); var slowdownText = new Text2('Fast GIGACHAD - 200 SCOİN', { size: 50, fill: 0xFFFFFF }); slowdownText.anchor.set(0.5, 0.5); slowdownText.x = 1024; slowdownText.y = yPos; shopContainer.addChild(slowdownText); // Speed GIGACHAD item yPos += itemSpacing; var speedButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5 }); speedButton.x = 1024; speedButton.y = yPos; speedButton.tint = playerCoins >= 200 ? 0x4CAF50 : 0x666666; shopContainer.addChild(speedButton); var speedText = new Text2('Slowdown 5min - 150 SCOİN', { size: 50, fill: 0xFFFFFF }); speedText.anchor.set(0.5, 0.5); speedText.x = 1024; speedText.y = yPos; shopContainer.addChild(speedText); // Double Points item yPos += itemSpacing; var doubleButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5 }); doubleButton.x = 1024; doubleButton.y = yPos; doubleButton.tint = playerCoins >= 200 ? 0x4CAF50 : 0x666666; shopContainer.addChild(doubleButton); var doubleText = new Text2('2x Points - 200 SCOİN', { size: 50, fill: 0xFFFFFF }); doubleText.anchor.set(0.5, 0.5); doubleText.x = 1024; doubleText.y = yPos; shopContainer.addChild(doubleText); // Add shop interaction handlers self.handleShopClick = function (x, y) { // Get fresh coin data for purchase validation var currentCoins = storage.coins || 0; // Check which button was clicked using global coordinates var itemY = 700; // First button (Fast GIGACHAD) - covers almost entire screen width if (Math.abs(y - itemY) < 100) { if (currentCoins >= 200) { // Initialize inventory if needed if (!storage.inventory) { storage.inventory = { slowdown: 0, speedGigachad: 0, doublePoints: 0 }; } // Complete the purchase storage.coins = currentCoins - 200; storage.inventory.speedGigachad = (storage.inventory.speedGigachad || 0) + 1; // Close shop and give feedback self.closeShop(); LK.effects.flashScreen(0x4CAF50, 500); // Green flash for successful purchase } else { // Not enough coins - red flash LK.effects.flashScreen(0xFF0000, 300); } return; } // Second button (Slowdown) itemY += 200; if (Math.abs(y - itemY) < 100) { if (currentCoins >= 150) { // Initialize inventory if needed if (!storage.inventory) { storage.inventory = { slowdown: 0, speedGigachad: 0, doublePoints: 0 }; } // Complete the purchase storage.coins = currentCoins - 150; storage.inventory.slowdown = (storage.inventory.slowdown || 0) + 1; // Close shop and give feedback self.closeShop(); LK.effects.flashScreen(0x4CAF50, 500); // Green flash for successful purchase } else { // Not enough coins - red flash LK.effects.flashScreen(0xFF0000, 300); } return; } // Double points button itemY += 200; if (Math.abs(y - itemY) < 100) { if (currentCoins >= 200) { // Initialize inventory if needed if (!storage.inventory) { storage.inventory = { slowdown: 0, speedGigachad: 0, doublePoints: 0 }; } // Complete the purchase storage.coins = currentCoins - 200; storage.inventory.doublePoints = (storage.inventory.doublePoints || 0) + 1; // Close shop and give feedback self.closeShop(); LK.effects.flashScreen(0x4CAF50, 500); // Green flash for successful purchase } else { // Not enough coins - red flash LK.effects.flashScreen(0xFF0000, 300); } return; } }; self.closeShop = function () { isShopOpen = false; isGameRunning = true; // Resume game when closing shop if (shopContainer) { shopContainer.destroy(); shopContainer = null; } }; }; return self; }); var Snake = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('snakeHead', { anchorX: 0.5, anchorY: 0.5 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ // Game configuration var GRID_SIZE = 40; var BOARD_WIDTH = 35; var BOARD_HEIGHT = 50; var MOVE_DELAY = 8; // Frames between moves // Game state variables var snake = []; var snakeDirection = { x: 1, y: 0 }; var nextDirection = { x: 1, y: 0 }; var food = null; var moveCounter = 0; var isGameRunning = true; var friendlySnakes = []; var friendlySnakeTimer = 0; var enemySnakes = []; var enemySnakeTimer = 0; var foodItems = []; var gigaChad = null; var gigaChadNotified = false; var shopButton = null; var shopEffects = { slowdown: { active: false, timer: 0 }, speedGigachad: { active: false }, doublePoints: { active: false, timer: 0 } }; var isShopOpen = false; var shopContainer = null; // Calculate board position to center it horizontally and leave space for controls at bottom var boardOffsetX = (2048 - BOARD_WIDTH * GRID_SIZE) / 2; var boardOffsetY = 100; // Start closer to top, leaving space for controls at bottom // Initialize SCOİN storage if (!storage.coins) { storage.coins = 0; } // Create score display var scoreTxt = new Text2('SCOİN: 0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0.5); // Position score centered horizontally and at control buttons level scoreTxt.x = 2048 / 2; // Center horizontally scoreTxt.y = 2732 - 300; // Same vertical level as control buttons game.addChild(scoreTxt); // Create power-up timer display var powerUpTimerTxt = new Text2('', { size: 60, fill: 0x4CAF50 }); powerUpTimerTxt.anchor.set(0.5, 0.5); powerUpTimerTxt.x = 2048 / 2; // Center horizontally powerUpTimerTxt.y = 2732 - 200; // Above score display (score is at 2732 - 300, so this puts timer above it) game.addChild(powerUpTimerTxt); // Initialize snake with only head function initializeSnake() { snake = []; // Clear death flag when starting fresh game hadPowerUpsOnDeath = false; // Create head using new Snake class var head = game.addChild(new Snake()); head.x = boardOffsetX + 12 * GRID_SIZE; head.y = boardOffsetY + 25 * GRID_SIZE; snake.push({ x: 12, y: 25, obj: head }); } // Convert grid coordinates to screen coordinates function gridToScreen(gridX, gridY) { return { x: boardOffsetX + gridX * GRID_SIZE, y: boardOffsetY + gridY * GRID_SIZE }; } // Generate random food position function spawnFood() { var validPositions = []; // Find all valid positions (not occupied by snake) for (var x = 0; x < BOARD_WIDTH; x++) { for (var y = 0; y < BOARD_HEIGHT; y++) { var occupied = false; for (var i = 0; i < snake.length; i++) { if (snake[i].x === x && snake[i].y === y) { occupied = true; break; } } if (!occupied) { validPositions.push({ x: x, y: y }); } } } if (validPositions.length > 0) { var randomIndex = Math.floor(Math.random() * validPositions.length); var pos = validPositions[randomIndex]; if (food) { food.destroy(); } food = game.addChild(new Food()); var screenPos = gridToScreen(pos.x, pos.y); food.x = screenPos.x; food.y = screenPos.y; food.gridX = pos.x; food.gridY = pos.y; foodItems.push(food); } } // Check if position is valid (within bounds and not colliding with snake) function isValidPosition(x, y) { // Check bounds if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) { return false; } // No body collision check needed for head-only snake return true; } // Move snake function moveSnake() { if (!isGameRunning) { return; } // Direction is already updated immediately in changeDirection function // Calculate new head position var head = snake[0]; var newHeadX = head.x + snakeDirection.x; var newHeadY = head.y + snakeDirection.y; // Check if new position is valid if (!isValidPosition(newHeadX, newHeadY)) { // Game over isGameRunning = false; // Check if player had any active power-ups before clearing them hadPowerUpsOnDeath = shopEffects.slowdown.active || shopEffects.speedGigachad.active || shopEffects.doublePoints.active; // Clear all active power-up effects on death shopEffects.slowdown.active = false; shopEffects.slowdown.timer = 0; shopEffects.speedGigachad.active = false; shopEffects.doublePoints.active = false; shopEffects.doublePoints.timer = 0; LK.getSound('gameOver').play(); LK.showGameOver(); return; } // Check if any food is eaten var ateFood = false; for (var i = foodItems.length - 1; i >= 0; i--) { var currentFood = foodItems[i]; if (currentFood && newHeadX === currentFood.gridX && newHeadY === currentFood.gridY) { ateFood = true; var baseCoins = currentFood.foodType === 'level2' ? 50 : 10; var coinGain = baseCoins; // Apply double points effect if active if (shopEffects.doublePoints.active) { coinGain = baseCoins * 2; } var coins = storage.coins || 0; storage.coins = coins + coinGain; scoreTxt.setText('SCOİN: ' + storage.coins); LK.getSound('eat').play(); // Flash food before removing tween(currentFood, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { currentFood.destroy(); } }); foodItems.splice(i, 1); if (currentFood === food) { food = null; spawnFood(); } break; } } // Simply move the existing head to new position (no growth) var headObj = snake[0].obj; var screenPos = gridToScreen(newHeadX, newHeadY); headObj.x = screenPos.x; headObj.y = screenPos.y; snake[0].x = newHeadX; snake[0].y = newHeadY; } // Handle direction changes function changeDirection(newDir) { // Prevent immediate reversal if (newDir.x === -snakeDirection.x && newDir.y === -snakeDirection.y) { return; } // Prevent diagonal movement - only allow pure horizontal or vertical movement if (newDir.x !== 0 && newDir.y !== 0) { return; } // Apply direction change immediately for responsive controls snakeDirection.x = newDir.x; snakeDirection.y = newDir.y; nextDirection.x = newDir.x; nextDirection.y = newDir.y; } // Remove touch controls - snake can only be controlled by buttons // Create visible walls around the game board function createWalls() { // Top and bottom walls for (var x = -1; x <= BOARD_WIDTH; x++) { // Top wall var topWall = game.addChild(LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5 })); topWall.x = boardOffsetX + x * GRID_SIZE; topWall.y = boardOffsetY - GRID_SIZE; // Bottom wall var bottomWall = game.addChild(LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5 })); bottomWall.x = boardOffsetX + x * GRID_SIZE; bottomWall.y = boardOffsetY + BOARD_HEIGHT * GRID_SIZE; } // Left and right walls for (var y = -1; y <= BOARD_HEIGHT; y++) { // Left wall var leftWall = game.addChild(LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5 })); leftWall.x = boardOffsetX - GRID_SIZE; leftWall.y = boardOffsetY + y * GRID_SIZE; // Right wall var rightWall = game.addChild(LK.getAsset('wall', { anchorX: 0.5, anchorY: 0.5 })); rightWall.x = boardOffsetX + BOARD_WIDTH * GRID_SIZE; rightWall.y = boardOffsetY + y * GRID_SIZE; } } // Create directional control buttons var upButton = game.addChild(new DirectionalButton({ x: 0, y: -1 }, 'upButton')); var downButton = game.addChild(new DirectionalButton({ x: 0, y: 1 }, 'downButton')); var leftButton = game.addChild(new DirectionalButton({ x: -1, y: 0 }, 'leftButton')); var rightButton = game.addChild(new DirectionalButton({ x: 1, y: 0 }, 'rightButton')); // Position buttons in bottom right corner var buttonSpacing = 140; var buttonBaseX = 2048 - 200; var buttonBaseY = 2732 - 300; // Up button upButton.x = buttonBaseX; upButton.y = buttonBaseY - buttonSpacing; // Down button downButton.x = buttonBaseX; downButton.y = buttonBaseY + buttonSpacing; // Left button leftButton.x = buttonBaseX - buttonSpacing; leftButton.y = buttonBaseY; // Right button rightButton.x = buttonBaseX + buttonSpacing; rightButton.y = buttonBaseY; // Add text labels to buttons var upText = new Text2('↑', { size: 60, fill: 0xFFFFFF }); upText.anchor.set(0.5, 0.5); upText.x = upButton.x; upText.y = upButton.y; game.addChild(upText); var downText = new Text2('↓', { size: 60, fill: 0xFFFFFF }); downText.anchor.set(0.5, 0.5); downText.x = downButton.x; downText.y = downButton.y; game.addChild(downText); var leftText = new Text2('←', { size: 60, fill: 0xFFFFFF }); leftText.anchor.set(0.5, 0.5); leftText.x = leftButton.x; leftText.y = leftButton.y; game.addChild(leftText); var rightText = new Text2('→', { size: 60, fill: 0xFFFFFF }); rightText.anchor.set(0.5, 0.5); rightText.x = rightButton.x; rightText.y = rightButton.y; game.addChild(rightText); // Initialize game createWalls(); initializeSnake(); spawnFood(); // Game mode variables var gameMode = 'menu'; // 'menu', 'normal' // Create main menu overlay var instructionContainer = new Container(); instructionContainer.x = 0; instructionContainer.y = 0; game.addChild(instructionContainer); // Create semi-transparent background var instructionBg = LK.getAsset('shopButton', { anchorX: 0, anchorY: 0, scaleX: 10.24, scaleY: 34.15 }); instructionBg.tint = 0x000000; instructionBg.alpha = 0.9; instructionContainer.addChild(instructionBg); // Create main menu title var menuTitle = new Text2('THE SNAKE GAME 2077', { size: 150, fill: 0xFFD700 }); menuTitle.anchor.set(0.5, 0.5); menuTitle.x = 1024; menuTitle.y = 300; instructionContainer.addChild(menuTitle); // Create game mode buttons var normalModeButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.0 }); normalModeButton.x = 1024; normalModeButton.y = 800; normalModeButton.tint = 0x4CAF50; instructionContainer.addChild(normalModeButton); var normalModeText = new Text2('NORMAL MODE', { size: 60, fill: 0xFFFFFF }); normalModeText.anchor.set(0.5, 0.5); normalModeText.x = normalModeButton.x; normalModeText.y = normalModeButton.y; instructionContainer.addChild(normalModeText); var otherButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.0 }); otherButton.x = 1024; otherButton.y = 1000; otherButton.tint = 0xFF5722; instructionContainer.addChild(otherButton); var otherText = new Text2('DİE', { size: 60, fill: 0xFFFFFF }); otherText.anchor.set(0.5, 0.5); otherText.x = otherButton.x; otherText.y = otherButton.y; instructionContainer.addChild(otherText); // How to play button var howToPlayButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 0.8 }); howToPlayButton.x = 1024; howToPlayButton.y = 1200; howToPlayButton.tint = 0x9C27B0; instructionContainer.addChild(howToPlayButton); var howToPlayText = new Text2('HOW TO PLAY', { size: 50, fill: 0xFFFFFF }); howToPlayText.anchor.set(0.5, 0.5); howToPlayText.x = howToPlayButton.x; howToPlayText.y = howToPlayButton.y; instructionContainer.addChild(howToPlayText); // Pause game initially to show menu isGameRunning = false; gameMode = 'menu'; // Add click handler for menu instructionContainer.down = function (x, y, obj) { // Check normal mode button if (Math.abs(x - normalModeButton.x) < 150 && Math.abs(y - normalModeButton.y) < 50) { startNormalMode(); return; } // Check other button if (Math.abs(x - otherButton.x) < 150 && Math.abs(y - otherButton.y) < 50) { showOther(); return; } // Check how to play button if (Math.abs(x - howToPlayButton.x) < 120 && Math.abs(y - howToPlayButton.y) < 40) { showHowToPlayWithOther(); return; } }; // Function to start normal mode function startNormalMode() { gameMode = 'normal'; isCompetitionMode = false; // Remove menu overlay instructionContainer.destroy(); instructionContainer = null; // Start the game isGameRunning = true; // Start background music LK.playMusic('backgroundMusic'); // Flash screen green to indicate game start LK.effects.flashScreen(0x4CAF50, 500); } // Function to show other function showOther() { // Flash screen to indicate URL opening attempt LK.effects.flashScreen(0xFF5722, 500); // Since window.open doesn't work in this environment, use LK.showGameOver as workaround // In a real implementation, this would open https://upit.com/@karasavasci127 LK.showGameOver(); } // Function to show how to play with other URL function showHowToPlayWithOther() { // Clear current menu content while (instructionContainer.children.length > 0) { instructionContainer.removeChild(instructionContainer.children[0]); } // Add background back instructionContainer.addChild(instructionBg); // Create instruction title var instructionTitle = new Text2('HOW TO PLAY', { size: 120, fill: 0xFFD700 }); instructionTitle.anchor.set(0.5, 0.5); instructionTitle.x = 1024; instructionTitle.y = 300; instructionContainer.addChild(instructionTitle); // Create instruction text var instructionText = new Text2('• Use arrow buttons to move snake\n• Collect food to earn SCOİN\n• Normal food = 10 SCOİN\n• Level 2 food = 50 SCOİN\n• Avoid red enemy snakes\n• Gold friendly snakes protect you\n• Buy power-ups in SHOP\n• Use items from INVENTORY', { size: 50, fill: 0xFFFFFF }); instructionText.anchor.set(0.5, 0.5); instructionText.x = 1024; instructionText.y = 1100; instructionContainer.addChild(instructionText); // Create Other URL text below instructions var otherUrlText = new Text2('Other: https://upit.com/@karasavasci127', { size: 60, fill: 0xFF5722 }); otherUrlText.anchor.set(0.5, 0.5); otherUrlText.x = 1024; otherUrlText.y = 1400; instructionContainer.addChild(otherUrlText); // Back to menu button var backButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.0, scaleY: 0.8 }); backButton.x = 1024; backButton.y = 1900; backButton.tint = 0x666666; instructionContainer.addChild(backButton); var backText = new Text2('BACK TO MENU', { size: 50, fill: 0xFFFFFF }); backText.anchor.set(0.5, 0.5); backText.x = backButton.x; backText.y = backButton.y; instructionContainer.addChild(backText); // Update click handler for back button and Other URL instructionContainer.down = function (x, y, obj) { if (Math.abs(x - backButton.x) < 100 && Math.abs(y - backButton.y) < 40) { // Go back to main menu LK.showGameOver(); // Reset game state and return to main menu } else if (Math.abs(x - otherUrlText.x) < 300 && Math.abs(y - otherUrlText.y) < 50) { // Other URL clicked LK.effects.flashScreen(0xFF5722, 500); LK.showGameOver(); } }; } // Don't start background music immediately - wait for instructions to be dismissed // Merchant functionality is handled through the shop button // Create shop button at bottom center shopButton = game.addChild(new ShopButton()); shopButton.x = 2048 / 2; // Center horizontally shopButton.y = 2732 - 150; // Bottom of screen with some margin // Add shop button text var shopText = new Text2('SHOP', { size: 40, fill: 0xFFFFFF }); shopText.anchor.set(0.5, 0.5); shopText.x = shopButton.x; shopText.y = shopButton.y; game.addChild(shopText); // Create hidden money cheat button above score var hiddenMoneyButton = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.3 }); hiddenMoneyButton.x = scoreTxt.x; // Same x position as score hiddenMoneyButton.y = scoreTxt.y - 100; // 100 pixels above score hiddenMoneyButton.alpha = 0; // Make completely invisible game.addChild(hiddenMoneyButton); // Add click handler for hidden money button hiddenMoneyButton.down = function (x, y, obj) { // Give player 999999 coins storage.coins = (storage.coins || 0) + 999999; // Flash screen gold to indicate cheat activated LK.effects.flashScreen(0xFFD700, 500); }; // Initialize inventory storage if (!storage.inventory) { storage.inventory = { slowdown: 0, speedGigachad: 0, doublePoints: 0 }; } // Create inventory button var inventoryButton = game.addChild(LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 })); inventoryButton.x = 2048 / 2 - 250; // Left of shop button inventoryButton.y = 2732 - 150; // Same level as shop button inventoryButton.tint = 0x9C27B0; // Purple tint for inventory // Add inventory button text var inventoryText = new Text2('INVENTORY', { size: 30, fill: 0xFFFFFF }); inventoryText.anchor.set(0.5, 0.5); inventoryText.x = inventoryButton.x; inventoryText.y = inventoryButton.y; game.addChild(inventoryText); // Create reset SCOİN button var resetCoinButton = game.addChild(LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 })); resetCoinButton.x = 2048 / 2 + 250; // Right of shop button (opposite side from inventory) resetCoinButton.y = 2732 - 150; // Same level as shop and inventory buttons resetCoinButton.tint = 0xFF5722; // Orange-red tint for reset button // Add reset button text var resetText = new Text2('RESET SCOİN', { size: 30, fill: 0xFFFFFF }); resetText.anchor.set(0.5, 0.5); resetText.x = resetCoinButton.x; resetText.y = resetCoinButton.y; game.addChild(resetText); // Add reset button functionality resetCoinButton.down = function (x, y, obj) { // Visual feedback tween(resetCoinButton, { scaleX: 0.7, scaleY: 0.7 }, { duration: 100 }); // Reset SCOİN to 0 storage.coins = 0; // Update score display scoreTxt.setText('SCOİN: ' + storage.coins); // Flash screen orange to indicate reset LK.effects.flashScreen(0xFF5722, 500); }; resetCoinButton.up = function (x, y, obj) { // Return to normal size tween(resetCoinButton, { scaleX: 0.8, scaleY: 0.8 }, { duration: 100 }); }; // Inventory system variables var isInventoryOpen = false; var inventoryContainer = null; var hadPowerUpsOnDeath = false; // Track if player had power-ups when they died // Add inventory button functionality inventoryButton.down = function (x, y, obj) { // Visual feedback tween(inventoryButton, { scaleX: 0.7, scaleY: 0.7 }, { duration: 100 }); // Toggle inventory if (isInventoryOpen) { closeInventory(); } else { openInventory(); } }; inventoryButton.up = function (x, y, obj) { // Return to normal size tween(inventoryButton, { scaleX: 0.8, scaleY: 0.8 }, { duration: 100 }); }; // Function to open inventory function openInventory() { if (isInventoryOpen) { return; } isInventoryOpen = true; isGameRunning = false; // Pause game // Create inventory container inventoryContainer = new Container(); inventoryContainer.x = 0; inventoryContainer.y = 0; game.addChild(inventoryContainer); // Create background var inventoryBg = LK.getAsset('shopButton', { anchorX: 0, anchorY: 0, scaleX: 10.24, scaleY: 34.15 }); inventoryBg.tint = 0x2E2E2E; inventoryBg.alpha = 0.9; inventoryContainer.addChild(inventoryBg); // Title var titleText = new Text2('INVENTORY', { size: 120, fill: 0x9C27B0 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 300; inventoryContainer.addChild(titleText); // Current coins display var coinsText = new Text2('SCOİN: ' + (storage.coins || 0), { size: 60, fill: 0xFFD700 }); coinsText.anchor.set(0.5, 0.5); coinsText.x = 1024; coinsText.y = 400; inventoryContainer.addChild(coinsText); // Inventory items section - GIGACHAD at top center, others below var yPos = 500; var itemSpacing = 120; // Fast GIGACHAD items - positioned at top center var speedGigachadCount = storage.inventory.speedGigachad || 0; var speedStatusText = shopEffects.speedGigachad.active ? ' (ACTIVE)' : ''; var speedItemText = new Text2('Fast GIGACHAD: ' + speedGigachadCount + speedStatusText, { size: 60, fill: shopEffects.speedGigachad.active ? 0x4CAF50 : 0xFFFFFF }); speedItemText.anchor.set(0.5, 0.5); speedItemText.x = 1024; // Centered speedItemText.y = yPos; inventoryContainer.addChild(speedItemText); // Use button for speed GIGACHAD - centered below text if (speedGigachadCount > 0 && !shopEffects.speedGigachad.active && !hadPowerUpsOnDeath) { var useSpeedBtn = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); useSpeedBtn.x = 1024; // Centered useSpeedBtn.y = yPos + 60; useSpeedBtn.tint = 0x4CAF50; inventoryContainer.addChild(useSpeedBtn); var useSpeedText = new Text2('USE', { size: 40, fill: 0xFFFFFF }); useSpeedText.anchor.set(0.5, 0.5); useSpeedText.x = useSpeedBtn.x; useSpeedText.y = useSpeedBtn.y; inventoryContainer.addChild(useSpeedText); } // Slowdown items - positioned below GIGACHAD yPos += itemSpacing + 60; var slowdownCount = storage.inventory.slowdown || 0; var slowdownStatusText = shopEffects.slowdown.active ? ' (ACTIVE - ' + Math.ceil((18000 - shopEffects.slowdown.timer) / 60) + 's left)' : ''; var slowdownItemText = new Text2('Slowdown 5min: ' + slowdownCount + slowdownStatusText, { size: 45, fill: shopEffects.slowdown.active ? 0x4CAF50 : 0xFFFFFF }); slowdownItemText.anchor.set(0.5, 0.5); slowdownItemText.x = 1024; slowdownItemText.y = yPos; inventoryContainer.addChild(slowdownItemText); // Use button for slowdown if (slowdownCount > 0 && !shopEffects.slowdown.active && !hadPowerUpsOnDeath) { var useSlowdownBtn = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); useSlowdownBtn.x = 1024 + 200; useSlowdownBtn.y = yPos; useSlowdownBtn.tint = 0x4CAF50; inventoryContainer.addChild(useSlowdownBtn); var useSlowdownText = new Text2('USE', { size: 30, fill: 0xFFFFFF }); useSlowdownText.anchor.set(0.5, 0.5); useSlowdownText.x = useSlowdownBtn.x; useSlowdownText.y = useSlowdownBtn.y; inventoryContainer.addChild(useSlowdownText); } // Double Points items - positioned at bottom yPos += itemSpacing; var doublePointsCount = storage.inventory.doublePoints || 0; var doubleStatusText = shopEffects.doublePoints.active ? ' (ACTIVE - ' + Math.ceil((18000 - shopEffects.doublePoints.timer) / 60) + 's left)' : ''; var doubleItemText = new Text2('2x Points: ' + doublePointsCount + doubleStatusText, { size: 45, fill: shopEffects.doublePoints.active ? 0x4CAF50 : 0xFFFFFF }); doubleItemText.anchor.set(0.5, 0.5); doubleItemText.x = 1024; doubleItemText.y = yPos; inventoryContainer.addChild(doubleItemText); // Use button for double points if (doublePointsCount > 0 && !shopEffects.doublePoints.active && !hadPowerUpsOnDeath) { var useDoubleBtn = LK.getAsset('shopButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); useDoubleBtn.x = 1024 + 200; useDoubleBtn.y = yPos; useDoubleBtn.tint = 0x4CAF50; inventoryContainer.addChild(useDoubleBtn); var useDoubleText = new Text2('USE', { size: 30, fill: 0xFFFFFF }); useDoubleText.anchor.set(0.5, 0.5); useDoubleText.x = useDoubleBtn.x; useDoubleText.y = useDoubleBtn.y; inventoryContainer.addChild(useDoubleText); } } // Function to close inventory function closeInventory() { isInventoryOpen = false; isGameRunning = true; if (inventoryContainer) { inventoryContainer.destroy(); inventoryContainer = null; } } // Function to handle inventory item usage function handleInventoryClick(x, y) { if (!isInventoryOpen || !inventoryContainer) { return; } // Prevent using inventory if player had power-ups when they died if (hadPowerUpsOnDeath) { LK.effects.flashScreen(0xFF0000, 300); // Red flash to indicate blocked return; } // Check use buttons with correct global positions var itemSpacing = 120; var startY = 500; // Speed GIGACHAD use button - centered at top (1024, startY + 60) var speedButtonX = 1024; var speedButtonY = startY + 60; if (Math.abs(x - speedButtonX) < 150 && Math.abs(y - speedButtonY) < 50) { if ((storage.inventory.speedGigachad || 0) > 0 && !shopEffects.speedGigachad.active) { storage.inventory.speedGigachad--; shopEffects.speedGigachad.active = true; // Save inventory changes storage.inventory = { slowdown: storage.inventory.slowdown || 0, speedGigachad: storage.inventory.speedGigachad, doublePoints: storage.inventory.doublePoints || 0 }; closeInventory(); LK.effects.flashScreen(0x4CAF50, 500); } return; } // Slowdown use button - positioned at (1024 + 200, slowdownY) var slowdownY = startY + itemSpacing + 60; var slowdownButtonX = 1024 + 200; if (Math.abs(x - slowdownButtonX) < 100 && Math.abs(y - slowdownY) < 50) { if ((storage.inventory.slowdown || 0) > 0 && !shopEffects.slowdown.active) { storage.inventory.slowdown--; shopEffects.slowdown.active = true; shopEffects.slowdown.timer = 0; // Save inventory changes storage.inventory = { slowdown: storage.inventory.slowdown, speedGigachad: storage.inventory.speedGigachad || 0, doublePoints: storage.inventory.doublePoints || 0 }; closeInventory(); LK.effects.flashScreen(0x4CAF50, 500); } return; } // Double Points use button - positioned at (1024 + 200, doubleY) var doubleY = startY + itemSpacing * 2 + 60; var doubleButtonX = 1024 + 200; if (Math.abs(x - doubleButtonX) < 100 && Math.abs(y - doubleY) < 50) { if ((storage.inventory.doublePoints || 0) > 0 && !shopEffects.doublePoints.active) { storage.inventory.doublePoints--; shopEffects.doublePoints.active = true; shopEffects.doublePoints.timer = 0; // Save inventory changes storage.inventory = { slowdown: storage.inventory.slowdown || 0, speedGigachad: storage.inventory.speedGigachad || 0, doublePoints: storage.inventory.doublePoints }; closeInventory(); LK.effects.flashScreen(0x4CAF50, 500); } return; } } // Add shop interaction handler game.down = function (x, y, obj) { if (isShopOpen && shopButton) { shopButton.handleShopClick(x, y); } else if (isInventoryOpen) { handleInventoryClick(x, y); } }; // Main game loop game.update = function () { if (!isGameRunning || isShopOpen || isInventoryOpen) { return; } moveCounter++; var currentMoveDelay = MOVE_DELAY; if (shopEffects.slowdown.active) { currentMoveDelay = MOVE_DELAY * 2; // Double the delay for slowdown effect } if (moveCounter >= currentMoveDelay) { moveCounter = 0; moveSnake(); } // Spawn friendly snakes every 10 seconds (600 frames at 60fps) friendlySnakeTimer++; if (friendlySnakeTimer >= 600) { friendlySnakeTimer = 0; var friendlySnake = game.addChild(new FriendlySnake()); // Spawn at random edge position within board bounds only var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top - ensure spawn within board width friendlySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE; friendlySnake.y = boardOffsetY + GRID_SIZE; break; case 1: // Right - ensure spawn within board height friendlySnake.x = boardOffsetX + (BOARD_WIDTH - 1) * GRID_SIZE; friendlySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE; break; case 2: // Bottom - ensure spawn within board width friendlySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE; friendlySnake.y = boardOffsetY + (BOARD_HEIGHT - 1) * GRID_SIZE; break; case 3: // Left - ensure spawn within board height friendlySnake.x = boardOffsetX + GRID_SIZE; friendlySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE; break; } friendlySnakes.push(friendlySnake); } // Spawn enemy snakes every 8 seconds (480 frames at 60fps) enemySnakeTimer++; if (enemySnakeTimer >= 480) { enemySnakeTimer = 0; var enemySnake = game.addChild(new EnemySnake()); // Spawn at random edge position within board bounds only var edge = Math.floor(Math.random() * 4); switch (edge) { case 0: // Top - ensure spawn within board width enemySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE; enemySnake.y = boardOffsetY + GRID_SIZE; break; case 1: // Right - ensure spawn within board height enemySnake.x = boardOffsetX + (BOARD_WIDTH - 1) * GRID_SIZE; enemySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE; break; case 2: // Bottom - ensure spawn within board width enemySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE; enemySnake.y = boardOffsetY + (BOARD_HEIGHT - 1) * GRID_SIZE; break; case 3: // Left - ensure spawn within board height enemySnake.x = boardOffsetX + GRID_SIZE; enemySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE; break; } enemySnakes.push(enemySnake); } // Check collision between player and enemy snakes if (snake.length > 0) { var playerHead = snake[0]; var playerScreenPos = gridToScreen(playerHead.x, playerHead.y); for (var i = enemySnakes.length - 1; i >= 0; i--) { var enemySnake = enemySnakes[i]; var dist = Math.sqrt(Math.pow(playerScreenPos.x - enemySnake.x, 2) + Math.pow(playerScreenPos.y - enemySnake.y, 2)); if (dist < 60) { // Collision detected // Check if friendly snake is protecting var isProtected = false; for (var j = 0; j < friendlySnakes.length; j++) { var friendlySnake = friendlySnakes[j]; var friendlyDist = Math.sqrt(Math.pow(playerScreenPos.x - friendlySnake.x, 2) + Math.pow(playerScreenPos.y - friendlySnake.y, 2)); if (friendlyDist < 100) { // Protection range isProtected = true; // Remove the enemy snake as it's defeated by friendly snake enemySnake.destroy(); enemySnakes.splice(i, 1); var coins = storage.coins || 0; storage.coins = coins + 50; // Bonus for protection scoreTxt.setText('SCOİN: ' + storage.coins); break; } } if (!isProtected) { // Game over - player eaten by enemy snake isGameRunning = false; // Check if player had any active power-ups before clearing them hadPowerUpsOnDeath = shopEffects.slowdown.active || shopEffects.speedGigachad.active || shopEffects.doublePoints.active; // Clear all active power-up effects on death shopEffects.slowdown.active = false; shopEffects.slowdown.timer = 0; shopEffects.speedGigachad.active = false; shopEffects.doublePoints.active = false; shopEffects.doublePoints.timer = 0; LK.getSound('gameOver').play(); LK.showGameOver(); return; } } } } // Reset GIGACHAD notification if no enemies remain if (enemySnakes.length === 0) { gigaChadNotified = false; } // Update shop effects if (shopEffects.slowdown.active) { shopEffects.slowdown.timer++; if (shopEffects.slowdown.timer >= 18000) { // 5 minutes shopEffects.slowdown.active = false; shopEffects.slowdown.timer = 0; } } if (shopEffects.doublePoints.active) { shopEffects.doublePoints.timer++; if (shopEffects.doublePoints.timer >= 18000) { // 5 minutes shopEffects.doublePoints.active = false; shopEffects.doublePoints.timer = 0; } } // Update power-up timer display var timerText = ""; var activeEffects = []; if (shopEffects.slowdown.active) { var slowdownTimeLeft = Math.ceil((18000 - shopEffects.slowdown.timer) / 60); activeEffects.push("Slowdown: " + slowdownTimeLeft + "s"); } if (shopEffects.speedGigachad.active) { activeEffects.push("Fast GIGACHAD: ACTIVE"); } if (shopEffects.doublePoints.active) { var doublePointsTimeLeft = Math.ceil((18000 - shopEffects.doublePoints.timer) / 60); activeEffects.push("2x Points: " + doublePointsTimeLeft + "s"); } if (activeEffects.length > 0) { timerText = activeEffects.join(" | "); powerUpTimerTxt.setText(timerText); powerUpTimerTxt.alpha = 1; } else { powerUpTimerTxt.setText(""); powerUpTimerTxt.alpha = 0; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var DirectionalButton = Container.expand(function (direction, assetId) {
var self = Container.call(this);
var graphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = direction;
// Add visual feedback when pressed
self.down = function (x, y, obj) {
if (!isGameRunning) {
return;
}
// Prevent multiple rapid presses
if (self.isPressed) {
return;
}
self.isPressed = true;
// Visual feedback - make button slightly smaller
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
// Change snake direction immediately
changeDirection(self.direction);
};
self.up = function (x, y, obj) {
// Reset pressed state
self.isPressed = false;
// Return button to normal size
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
};
return self;
});
var EnemySnake = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemySnake', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = 0xff4444; // Red tint for enemy
self.moveSpeed = 1.5;
self.direction = Math.random() * Math.PI * 2;
self.chaseTimer = 0;
self.isBeingRepelled = false;
self.repelTimer = 0;
self.update = function () {
// Check if being repelled by friendly snakes
self.isBeingRepelled = false;
for (var i = 0; i < friendlySnakes.length; i++) {
var friendlySnake = friendlySnakes[i];
var dist = Math.sqrt(Math.pow(self.x - friendlySnake.x, 2) + Math.pow(self.y - friendlySnake.y, 2));
if (dist < 150) {
// Repel range
self.isBeingRepelled = true;
// Move away from friendly snake
var angle = Math.atan2(self.y - friendlySnake.y, self.x - friendlySnake.x);
self.direction = angle;
break;
}
}
// If not being repelled, chase the player
if (!self.isBeingRepelled && snake.length > 0) {
self.chaseTimer++;
if (self.chaseTimer >= 30) {
// Update chase direction every 0.5 seconds
var playerHead = snake[0];
var playerScreenPos = gridToScreen(playerHead.x, playerHead.y);
var angle = Math.atan2(playerScreenPos.y - self.y, playerScreenPos.x - self.x);
self.direction = angle;
self.chaseTimer = 0;
}
}
// Move in current direction
self.x += Math.cos(self.direction) * self.moveSpeed;
self.y += Math.sin(self.direction) * self.moveSpeed;
// Bounce off walls
if (self.x < boardOffsetX || self.x > boardOffsetX + BOARD_WIDTH * GRID_SIZE) {
self.direction = Math.PI - self.direction;
}
if (self.y < boardOffsetY || self.y > boardOffsetY + BOARD_HEIGHT * GRID_SIZE) {
self.direction = -self.direction;
}
// Keep within bounds
self.x = Math.max(boardOffsetX, Math.min(boardOffsetX + BOARD_WIDTH * GRID_SIZE, self.x));
self.y = Math.max(boardOffsetY, Math.min(boardOffsetY + BOARD_HEIGHT * GRID_SIZE, self.y));
};
return self;
});
var Food = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Simple pulsing animation
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.1;
self.scaleX = scale;
self.scaleY = scale;
};
return self;
});
var FriendlySnake = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('friendlySnake', {
anchorX: 0.5,
anchorY: 0.5
});
self.moveSpeed = 2;
self.direction = Math.random() * Math.PI * 2;
self.dropTimer = 0;
self.maxDrops = 3;
self.dropsLeft = 3;
self.hasKilledEnemy = false;
self.update = function () {
// Check for nearby enemy snakes to chase
var isChasing = false;
var closestEnemy = null;
var closestDistance = Infinity;
for (var i = 0; i < enemySnakes.length; i++) {
var enemySnake = enemySnakes[i];
var dist = Math.sqrt(Math.pow(self.x - enemySnake.x, 2) + Math.pow(self.y - enemySnake.y, 2));
if (dist < 200) {
// Detection range - notify GIGACHAD!
if (!gigaChadNotified && enemySnakes.length > 0) {
gigaChadNotified = true;
if (!gigaChad) {
gigaChad = game.addChild(new GigaChad());
}
gigaChad.summon();
}
if (dist < closestDistance) {
closestDistance = dist;
closestEnemy = enemySnake;
isChasing = true;
}
}
}
// If chasing an enemy, move towards it
if (isChasing && closestEnemy) {
var angle = Math.atan2(closestEnemy.y - self.y, closestEnemy.x - self.x);
self.direction = angle;
self.moveSpeed = 3; // Increase speed when chasing
} else {
self.moveSpeed = 2; // Normal speed when not chasing
}
// Move in current direction
self.x += Math.cos(self.direction) * self.moveSpeed;
self.y += Math.sin(self.direction) * self.moveSpeed;
// Check if we killed an enemy snake
for (var i = enemySnakes.length - 1; i >= 0; i--) {
var enemySnake = enemySnakes[i];
var dist = Math.sqrt(Math.pow(self.x - enemySnake.x, 2) + Math.pow(self.y - enemySnake.y, 2));
if (dist < 50) {
// Kill range
// Enemy snake is killed
enemySnake.destroy();
enemySnakes.splice(i, 1);
var coins = storage.coins || 0;
storage.coins = coins + 100; // Bonus for friendly snake killing enemy
scoreTxt.setText('SCOİN: ' + storage.coins);
// Mark this friendly snake as having killed an enemy
self.hasKilledEnemy = true;
break;
}
}
// Bounce off walls
if (self.x < boardOffsetX || self.x > boardOffsetX + BOARD_WIDTH * GRID_SIZE) {
self.direction = Math.PI - self.direction;
}
if (self.y < boardOffsetY || self.y > boardOffsetY + BOARD_HEIGHT * GRID_SIZE) {
self.direction = -self.direction;
}
// Keep within bounds
self.x = Math.max(boardOffsetX, Math.min(boardOffsetX + BOARD_WIDTH * GRID_SIZE, self.x));
self.y = Math.max(boardOffsetY, Math.min(boardOffsetY + BOARD_HEIGHT * GRID_SIZE, self.y));
// Drop food periodically
self.dropTimer++;
if (self.dropTimer >= 120 && self.dropsLeft > 0) {
// Every 2 seconds
self.dropFood();
self.dropTimer = 0;
self.dropsLeft--;
}
// Remove after all drops are done - but only if hasn't killed an enemy
if (self.dropsLeft <= 0 && !self.hasKilledEnemy) {
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
var index = friendlySnakes.indexOf(self);
if (index > -1) {
friendlySnakes.splice(index, 1);
}
}
});
}
};
self.dropFood = function () {
var dropType = Math.random() < 0.3 ? 'level2' : 'normal';
var newFood;
if (dropType === 'level2') {
newFood = game.addChild(new Level2Food());
} else {
newFood = game.addChild(new Food());
}
// Convert screen position to grid position and clamp to board bounds
var gridX = Math.round((self.x - boardOffsetX) / GRID_SIZE);
var gridY = Math.round((self.y - boardOffsetY) / GRID_SIZE);
// Ensure food stays within board bounds
gridX = Math.max(0, Math.min(BOARD_WIDTH - 1, gridX));
gridY = Math.max(0, Math.min(BOARD_HEIGHT - 1, gridY));
// Set food position based on clamped grid coordinates
var screenPos = gridToScreen(gridX, gridY);
newFood.x = screenPos.x;
newFood.y = screenPos.y;
newFood.gridX = gridX;
newFood.gridY = gridY;
// Add to food array
foodItems.push(newFood);
};
return self;
});
var GigaChad = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('gigachad', {
anchorX: 0.5,
anchorY: 0.5
});
self.isActive = false;
self.destroyTimer = 0;
self.destroyDelay = shopEffects.speedGigachad.active ? 180 : 600; // 3 seconds if fast, 10 seconds normal
self.summon = function () {
if (self.isActive) {
return;
} // Already summoned
self.isActive = true;
self.destroyTimer = 0;
// Position GIGACHAD at center of board
self.x = boardOffsetX + BOARD_WIDTH * GRID_SIZE / 2;
self.y = boardOffsetY + BOARD_HEIGHT * GRID_SIZE / 2;
// Make GIGACHAD appear with dramatic effect
self.alpha = 0;
self.scaleX = 0.1;
self.scaleY = 0.1;
tween(self, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.bounceOut
});
// Play summon sound
LK.getSound('gigachadSummon').play();
// Flash screen to show GIGACHAD arrival
LK.effects.flashScreen(0xFFD700, 1000); // Gold flash
// Destroy all enemies immediately upon arrival
self.destroyAllEnemies();
};
self.update = function () {
if (!self.isActive) {
return;
}
self.destroyTimer++;
// Update destroy delay based on current speed effect status
self.destroyDelay = shopEffects.speedGigachad.active ? 180 : 600;
// Pulsing effect while active
var pulse = 1 + Math.sin(LK.ticks * 0.2) * 0.1;
self.scaleX = pulse;
self.scaleY = pulse;
// Auto-deactivate after completing task (enemies destroyed immediately on summon)
if (self.destroyTimer >= self.destroyDelay) {
// GIGACHAD disappears after completing his task
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1000,
easing: tween.easeIn,
onFinish: function onFinish() {
self.isActive = false;
self.destroyTimer = 0;
}
});
}
};
self.destroyAllEnemies = function () {
// Destroy all enemy snakes immediately
for (var i = enemySnakes.length - 1; i >= 0; i--) {
var enemySnake = enemySnakes[i];
// Flash enemy red before destroying
tween(enemySnake, {
tint: 0xFF0000,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
enemySnake.destroy();
}
});
}
// Clear enemy snakes array
enemySnakes = [];
// Play destroy sound
LK.getSound('gigachadDestroy').play();
// Flash screen red for destruction
LK.effects.flashScreen(0xFF0000, 1500);
// Add massive score bonus
var coins = storage.coins || 0;
storage.coins = coins + 500;
scoreTxt.setText('SCOİN: ' + storage.coins);
};
return self;
});
var Level2Food = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('level2Food', {
anchorX: 0.5,
anchorY: 0.5
});
self.foodType = 'level2';
self.update = function () {
// Special pulsing animation for level 2 food
var scale = 1 + Math.sin(LK.ticks * 0.15) * 0.3;
self.scaleX = scale;
self.scaleY = scale;
// Color cycling effect
var colorPhase = LK.ticks * 0.1 % (Math.PI * 2);
var red = Math.floor(128 + 127 * Math.sin(colorPhase));
var green = Math.floor(128 + 127 * Math.sin(colorPhase + Math.PI * 2 / 3));
var blue = Math.floor(128 + 127 * Math.sin(colorPhase + Math.PI * 4 / 3));
graphics.tint = red << 16 | green << 8 | blue;
};
return self;
});
var Merchant = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('friendlySnake', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = 0xFFD700; // Gold tint for merchant
// Shop items with costs
self.shopItems = {
slowdown: {
cost: 150,
name: "Slowdown (5min)",
active: false,
duration: 18000
},
// 5 minutes at 60fps
speedGigachad: {
cost: 200,
name: "Fast GIGACHAD",
active: false
},
doublePoints: {
cost: 200,
name: "2x Points",
active: false,
duration: 18000
} // 5 minutes at 60fps
};
self.down = function (x, y, obj) {
self.openShop();
};
self.openShop = function () {
// Simple shop interface using score display
var playerCoins = storage.coins || 0;
var shopText = "SHOP (SCOİN: " + playerCoins + ")\n";
shopText += "1. Slowdown 5min - " + self.shopItems.slowdown.cost + " SCOİN\n";
shopText += "2. Fast GIGACHAD - " + self.shopItems.speedGigachad.cost + " SCOİN\n";
shopText += "3. 2x Points - " + self.shopItems.doublePoints.cost + " SCOİN";
// Flash screen to show shop is open
LK.effects.flashScreen(0xFFD700, 500);
};
return self;
});
var ShopButton = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = 0x4CAF50; // Green tint for shop button
self.down = function (x, y, obj) {
if (!isGameRunning && !isShopOpen) {
return;
}
// Visual feedback - make button slightly smaller
tween(self, {
scaleX: 0.9,
scaleY: 0.9
}, {
duration: 100
});
// Toggle shop - close if open, open if closed
if (isShopOpen) {
self.closeShop();
} else {
isShopOpen = true;
self.openFullScreenShop();
}
};
self.up = function (x, y, obj) {
// Return button to normal size
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100
});
};
self.openFullScreenShop = function () {
// Create full-screen shop container
shopContainer = new Container();
shopContainer.x = 0;
shopContainer.y = 0;
game.addChild(shopContainer);
// Create semi-transparent background
var shopBg = LK.getAsset('shopButton', {
anchorX: 0,
anchorY: 0,
scaleX: 10.24,
scaleY: 34.15
});
shopBg.tint = 0x000000;
shopBg.alpha = 0.8;
shopContainer.addChild(shopBg);
// Get player coins
var playerCoins = storage.coins || 0;
// Create shop title
var titleText = new Text2('SHOP', {
size: 150,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
shopContainer.addChild(titleText);
// Create coins display
var coinsText = new Text2('SCOİN: ' + playerCoins, {
size: 80,
fill: 0xFFFFFF
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 450;
shopContainer.addChild(coinsText);
// Create shop items
var yPos = 700;
var itemSpacing = 200;
// Slowdown item
var slowdownButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5
});
slowdownButton.x = 1024;
slowdownButton.y = yPos;
slowdownButton.tint = playerCoins >= 150 ? 0x4CAF50 : 0x666666;
shopContainer.addChild(slowdownButton);
var slowdownText = new Text2('Fast GIGACHAD - 200 SCOİN', {
size: 50,
fill: 0xFFFFFF
});
slowdownText.anchor.set(0.5, 0.5);
slowdownText.x = 1024;
slowdownText.y = yPos;
shopContainer.addChild(slowdownText);
// Speed GIGACHAD item
yPos += itemSpacing;
var speedButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5
});
speedButton.x = 1024;
speedButton.y = yPos;
speedButton.tint = playerCoins >= 200 ? 0x4CAF50 : 0x666666;
shopContainer.addChild(speedButton);
var speedText = new Text2('Slowdown 5min - 150 SCOİN', {
size: 50,
fill: 0xFFFFFF
});
speedText.anchor.set(0.5, 0.5);
speedText.x = 1024;
speedText.y = yPos;
shopContainer.addChild(speedText);
// Double Points item
yPos += itemSpacing;
var doubleButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5
});
doubleButton.x = 1024;
doubleButton.y = yPos;
doubleButton.tint = playerCoins >= 200 ? 0x4CAF50 : 0x666666;
shopContainer.addChild(doubleButton);
var doubleText = new Text2('2x Points - 200 SCOİN', {
size: 50,
fill: 0xFFFFFF
});
doubleText.anchor.set(0.5, 0.5);
doubleText.x = 1024;
doubleText.y = yPos;
shopContainer.addChild(doubleText);
// Add shop interaction handlers
self.handleShopClick = function (x, y) {
// Get fresh coin data for purchase validation
var currentCoins = storage.coins || 0;
// Check which button was clicked using global coordinates
var itemY = 700;
// First button (Fast GIGACHAD) - covers almost entire screen width
if (Math.abs(y - itemY) < 100) {
if (currentCoins >= 200) {
// Initialize inventory if needed
if (!storage.inventory) {
storage.inventory = {
slowdown: 0,
speedGigachad: 0,
doublePoints: 0
};
}
// Complete the purchase
storage.coins = currentCoins - 200;
storage.inventory.speedGigachad = (storage.inventory.speedGigachad || 0) + 1;
// Close shop and give feedback
self.closeShop();
LK.effects.flashScreen(0x4CAF50, 500); // Green flash for successful purchase
} else {
// Not enough coins - red flash
LK.effects.flashScreen(0xFF0000, 300);
}
return;
}
// Second button (Slowdown)
itemY += 200;
if (Math.abs(y - itemY) < 100) {
if (currentCoins >= 150) {
// Initialize inventory if needed
if (!storage.inventory) {
storage.inventory = {
slowdown: 0,
speedGigachad: 0,
doublePoints: 0
};
}
// Complete the purchase
storage.coins = currentCoins - 150;
storage.inventory.slowdown = (storage.inventory.slowdown || 0) + 1;
// Close shop and give feedback
self.closeShop();
LK.effects.flashScreen(0x4CAF50, 500); // Green flash for successful purchase
} else {
// Not enough coins - red flash
LK.effects.flashScreen(0xFF0000, 300);
}
return;
}
// Double points button
itemY += 200;
if (Math.abs(y - itemY) < 100) {
if (currentCoins >= 200) {
// Initialize inventory if needed
if (!storage.inventory) {
storage.inventory = {
slowdown: 0,
speedGigachad: 0,
doublePoints: 0
};
}
// Complete the purchase
storage.coins = currentCoins - 200;
storage.inventory.doublePoints = (storage.inventory.doublePoints || 0) + 1;
// Close shop and give feedback
self.closeShop();
LK.effects.flashScreen(0x4CAF50, 500); // Green flash for successful purchase
} else {
// Not enough coins - red flash
LK.effects.flashScreen(0xFF0000, 300);
}
return;
}
};
self.closeShop = function () {
isShopOpen = false;
isGameRunning = true; // Resume game when closing shop
if (shopContainer) {
shopContainer.destroy();
shopContainer = null;
}
};
};
return self;
});
var Snake = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('snakeHead', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a1a
});
/****
* Game Code
****/
// Game configuration
var GRID_SIZE = 40;
var BOARD_WIDTH = 35;
var BOARD_HEIGHT = 50;
var MOVE_DELAY = 8; // Frames between moves
// Game state variables
var snake = [];
var snakeDirection = {
x: 1,
y: 0
};
var nextDirection = {
x: 1,
y: 0
};
var food = null;
var moveCounter = 0;
var isGameRunning = true;
var friendlySnakes = [];
var friendlySnakeTimer = 0;
var enemySnakes = [];
var enemySnakeTimer = 0;
var foodItems = [];
var gigaChad = null;
var gigaChadNotified = false;
var shopButton = null;
var shopEffects = {
slowdown: {
active: false,
timer: 0
},
speedGigachad: {
active: false
},
doublePoints: {
active: false,
timer: 0
}
};
var isShopOpen = false;
var shopContainer = null;
// Calculate board position to center it horizontally and leave space for controls at bottom
var boardOffsetX = (2048 - BOARD_WIDTH * GRID_SIZE) / 2;
var boardOffsetY = 100; // Start closer to top, leaving space for controls at bottom
// Initialize SCOİN storage
if (!storage.coins) {
storage.coins = 0;
}
// Create score display
var scoreTxt = new Text2('SCOİN: 0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0.5);
// Position score centered horizontally and at control buttons level
scoreTxt.x = 2048 / 2; // Center horizontally
scoreTxt.y = 2732 - 300; // Same vertical level as control buttons
game.addChild(scoreTxt);
// Create power-up timer display
var powerUpTimerTxt = new Text2('', {
size: 60,
fill: 0x4CAF50
});
powerUpTimerTxt.anchor.set(0.5, 0.5);
powerUpTimerTxt.x = 2048 / 2; // Center horizontally
powerUpTimerTxt.y = 2732 - 200; // Above score display (score is at 2732 - 300, so this puts timer above it)
game.addChild(powerUpTimerTxt);
// Initialize snake with only head
function initializeSnake() {
snake = [];
// Clear death flag when starting fresh game
hadPowerUpsOnDeath = false;
// Create head using new Snake class
var head = game.addChild(new Snake());
head.x = boardOffsetX + 12 * GRID_SIZE;
head.y = boardOffsetY + 25 * GRID_SIZE;
snake.push({
x: 12,
y: 25,
obj: head
});
}
// Convert grid coordinates to screen coordinates
function gridToScreen(gridX, gridY) {
return {
x: boardOffsetX + gridX * GRID_SIZE,
y: boardOffsetY + gridY * GRID_SIZE
};
}
// Generate random food position
function spawnFood() {
var validPositions = [];
// Find all valid positions (not occupied by snake)
for (var x = 0; x < BOARD_WIDTH; x++) {
for (var y = 0; y < BOARD_HEIGHT; y++) {
var occupied = false;
for (var i = 0; i < snake.length; i++) {
if (snake[i].x === x && snake[i].y === y) {
occupied = true;
break;
}
}
if (!occupied) {
validPositions.push({
x: x,
y: y
});
}
}
}
if (validPositions.length > 0) {
var randomIndex = Math.floor(Math.random() * validPositions.length);
var pos = validPositions[randomIndex];
if (food) {
food.destroy();
}
food = game.addChild(new Food());
var screenPos = gridToScreen(pos.x, pos.y);
food.x = screenPos.x;
food.y = screenPos.y;
food.gridX = pos.x;
food.gridY = pos.y;
foodItems.push(food);
}
}
// Check if position is valid (within bounds and not colliding with snake)
function isValidPosition(x, y) {
// Check bounds
if (x < 0 || x >= BOARD_WIDTH || y < 0 || y >= BOARD_HEIGHT) {
return false;
}
// No body collision check needed for head-only snake
return true;
}
// Move snake
function moveSnake() {
if (!isGameRunning) {
return;
}
// Direction is already updated immediately in changeDirection function
// Calculate new head position
var head = snake[0];
var newHeadX = head.x + snakeDirection.x;
var newHeadY = head.y + snakeDirection.y;
// Check if new position is valid
if (!isValidPosition(newHeadX, newHeadY)) {
// Game over
isGameRunning = false;
// Check if player had any active power-ups before clearing them
hadPowerUpsOnDeath = shopEffects.slowdown.active || shopEffects.speedGigachad.active || shopEffects.doublePoints.active;
// Clear all active power-up effects on death
shopEffects.slowdown.active = false;
shopEffects.slowdown.timer = 0;
shopEffects.speedGigachad.active = false;
shopEffects.doublePoints.active = false;
shopEffects.doublePoints.timer = 0;
LK.getSound('gameOver').play();
LK.showGameOver();
return;
}
// Check if any food is eaten
var ateFood = false;
for (var i = foodItems.length - 1; i >= 0; i--) {
var currentFood = foodItems[i];
if (currentFood && newHeadX === currentFood.gridX && newHeadY === currentFood.gridY) {
ateFood = true;
var baseCoins = currentFood.foodType === 'level2' ? 50 : 10;
var coinGain = baseCoins;
// Apply double points effect if active
if (shopEffects.doublePoints.active) {
coinGain = baseCoins * 2;
}
var coins = storage.coins || 0;
storage.coins = coins + coinGain;
scoreTxt.setText('SCOİN: ' + storage.coins);
LK.getSound('eat').play();
// Flash food before removing
tween(currentFood, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
currentFood.destroy();
}
});
foodItems.splice(i, 1);
if (currentFood === food) {
food = null;
spawnFood();
}
break;
}
}
// Simply move the existing head to new position (no growth)
var headObj = snake[0].obj;
var screenPos = gridToScreen(newHeadX, newHeadY);
headObj.x = screenPos.x;
headObj.y = screenPos.y;
snake[0].x = newHeadX;
snake[0].y = newHeadY;
}
// Handle direction changes
function changeDirection(newDir) {
// Prevent immediate reversal
if (newDir.x === -snakeDirection.x && newDir.y === -snakeDirection.y) {
return;
}
// Prevent diagonal movement - only allow pure horizontal or vertical movement
if (newDir.x !== 0 && newDir.y !== 0) {
return;
}
// Apply direction change immediately for responsive controls
snakeDirection.x = newDir.x;
snakeDirection.y = newDir.y;
nextDirection.x = newDir.x;
nextDirection.y = newDir.y;
}
// Remove touch controls - snake can only be controlled by buttons
// Create visible walls around the game board
function createWalls() {
// Top and bottom walls
for (var x = -1; x <= BOARD_WIDTH; x++) {
// Top wall
var topWall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
}));
topWall.x = boardOffsetX + x * GRID_SIZE;
topWall.y = boardOffsetY - GRID_SIZE;
// Bottom wall
var bottomWall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
}));
bottomWall.x = boardOffsetX + x * GRID_SIZE;
bottomWall.y = boardOffsetY + BOARD_HEIGHT * GRID_SIZE;
}
// Left and right walls
for (var y = -1; y <= BOARD_HEIGHT; y++) {
// Left wall
var leftWall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
}));
leftWall.x = boardOffsetX - GRID_SIZE;
leftWall.y = boardOffsetY + y * GRID_SIZE;
// Right wall
var rightWall = game.addChild(LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
}));
rightWall.x = boardOffsetX + BOARD_WIDTH * GRID_SIZE;
rightWall.y = boardOffsetY + y * GRID_SIZE;
}
}
// Create directional control buttons
var upButton = game.addChild(new DirectionalButton({
x: 0,
y: -1
}, 'upButton'));
var downButton = game.addChild(new DirectionalButton({
x: 0,
y: 1
}, 'downButton'));
var leftButton = game.addChild(new DirectionalButton({
x: -1,
y: 0
}, 'leftButton'));
var rightButton = game.addChild(new DirectionalButton({
x: 1,
y: 0
}, 'rightButton'));
// Position buttons in bottom right corner
var buttonSpacing = 140;
var buttonBaseX = 2048 - 200;
var buttonBaseY = 2732 - 300;
// Up button
upButton.x = buttonBaseX;
upButton.y = buttonBaseY - buttonSpacing;
// Down button
downButton.x = buttonBaseX;
downButton.y = buttonBaseY + buttonSpacing;
// Left button
leftButton.x = buttonBaseX - buttonSpacing;
leftButton.y = buttonBaseY;
// Right button
rightButton.x = buttonBaseX + buttonSpacing;
rightButton.y = buttonBaseY;
// Add text labels to buttons
var upText = new Text2('↑', {
size: 60,
fill: 0xFFFFFF
});
upText.anchor.set(0.5, 0.5);
upText.x = upButton.x;
upText.y = upButton.y;
game.addChild(upText);
var downText = new Text2('↓', {
size: 60,
fill: 0xFFFFFF
});
downText.anchor.set(0.5, 0.5);
downText.x = downButton.x;
downText.y = downButton.y;
game.addChild(downText);
var leftText = new Text2('←', {
size: 60,
fill: 0xFFFFFF
});
leftText.anchor.set(0.5, 0.5);
leftText.x = leftButton.x;
leftText.y = leftButton.y;
game.addChild(leftText);
var rightText = new Text2('→', {
size: 60,
fill: 0xFFFFFF
});
rightText.anchor.set(0.5, 0.5);
rightText.x = rightButton.x;
rightText.y = rightButton.y;
game.addChild(rightText);
// Initialize game
createWalls();
initializeSnake();
spawnFood();
// Game mode variables
var gameMode = 'menu'; // 'menu', 'normal'
// Create main menu overlay
var instructionContainer = new Container();
instructionContainer.x = 0;
instructionContainer.y = 0;
game.addChild(instructionContainer);
// Create semi-transparent background
var instructionBg = LK.getAsset('shopButton', {
anchorX: 0,
anchorY: 0,
scaleX: 10.24,
scaleY: 34.15
});
instructionBg.tint = 0x000000;
instructionBg.alpha = 0.9;
instructionContainer.addChild(instructionBg);
// Create main menu title
var menuTitle = new Text2('THE SNAKE GAME 2077', {
size: 150,
fill: 0xFFD700
});
menuTitle.anchor.set(0.5, 0.5);
menuTitle.x = 1024;
menuTitle.y = 300;
instructionContainer.addChild(menuTitle);
// Create game mode buttons
var normalModeButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.0
});
normalModeButton.x = 1024;
normalModeButton.y = 800;
normalModeButton.tint = 0x4CAF50;
instructionContainer.addChild(normalModeButton);
var normalModeText = new Text2('NORMAL MODE', {
size: 60,
fill: 0xFFFFFF
});
normalModeText.anchor.set(0.5, 0.5);
normalModeText.x = normalModeButton.x;
normalModeText.y = normalModeButton.y;
instructionContainer.addChild(normalModeText);
var otherButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.0
});
otherButton.x = 1024;
otherButton.y = 1000;
otherButton.tint = 0xFF5722;
instructionContainer.addChild(otherButton);
var otherText = new Text2('DİE', {
size: 60,
fill: 0xFFFFFF
});
otherText.anchor.set(0.5, 0.5);
otherText.x = otherButton.x;
otherText.y = otherButton.y;
instructionContainer.addChild(otherText);
// How to play button
var howToPlayButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.8
});
howToPlayButton.x = 1024;
howToPlayButton.y = 1200;
howToPlayButton.tint = 0x9C27B0;
instructionContainer.addChild(howToPlayButton);
var howToPlayText = new Text2('HOW TO PLAY', {
size: 50,
fill: 0xFFFFFF
});
howToPlayText.anchor.set(0.5, 0.5);
howToPlayText.x = howToPlayButton.x;
howToPlayText.y = howToPlayButton.y;
instructionContainer.addChild(howToPlayText);
// Pause game initially to show menu
isGameRunning = false;
gameMode = 'menu';
// Add click handler for menu
instructionContainer.down = function (x, y, obj) {
// Check normal mode button
if (Math.abs(x - normalModeButton.x) < 150 && Math.abs(y - normalModeButton.y) < 50) {
startNormalMode();
return;
}
// Check other button
if (Math.abs(x - otherButton.x) < 150 && Math.abs(y - otherButton.y) < 50) {
showOther();
return;
}
// Check how to play button
if (Math.abs(x - howToPlayButton.x) < 120 && Math.abs(y - howToPlayButton.y) < 40) {
showHowToPlayWithOther();
return;
}
};
// Function to start normal mode
function startNormalMode() {
gameMode = 'normal';
isCompetitionMode = false;
// Remove menu overlay
instructionContainer.destroy();
instructionContainer = null;
// Start the game
isGameRunning = true;
// Start background music
LK.playMusic('backgroundMusic');
// Flash screen green to indicate game start
LK.effects.flashScreen(0x4CAF50, 500);
}
// Function to show other
function showOther() {
// Flash screen to indicate URL opening attempt
LK.effects.flashScreen(0xFF5722, 500);
// Since window.open doesn't work in this environment, use LK.showGameOver as workaround
// In a real implementation, this would open https://upit.com/@karasavasci127
LK.showGameOver();
}
// Function to show how to play with other URL
function showHowToPlayWithOther() {
// Clear current menu content
while (instructionContainer.children.length > 0) {
instructionContainer.removeChild(instructionContainer.children[0]);
}
// Add background back
instructionContainer.addChild(instructionBg);
// Create instruction title
var instructionTitle = new Text2('HOW TO PLAY', {
size: 120,
fill: 0xFFD700
});
instructionTitle.anchor.set(0.5, 0.5);
instructionTitle.x = 1024;
instructionTitle.y = 300;
instructionContainer.addChild(instructionTitle);
// Create instruction text
var instructionText = new Text2('• Use arrow buttons to move snake\n• Collect food to earn SCOİN\n• Normal food = 10 SCOİN\n• Level 2 food = 50 SCOİN\n• Avoid red enemy snakes\n• Gold friendly snakes protect you\n• Buy power-ups in SHOP\n• Use items from INVENTORY', {
size: 50,
fill: 0xFFFFFF
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 1100;
instructionContainer.addChild(instructionText);
// Create Other URL text below instructions
var otherUrlText = new Text2('Other: https://upit.com/@karasavasci127', {
size: 60,
fill: 0xFF5722
});
otherUrlText.anchor.set(0.5, 0.5);
otherUrlText.x = 1024;
otherUrlText.y = 1400;
instructionContainer.addChild(otherUrlText);
// Back to menu button
var backButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.0,
scaleY: 0.8
});
backButton.x = 1024;
backButton.y = 1900;
backButton.tint = 0x666666;
instructionContainer.addChild(backButton);
var backText = new Text2('BACK TO MENU', {
size: 50,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = backButton.x;
backText.y = backButton.y;
instructionContainer.addChild(backText);
// Update click handler for back button and Other URL
instructionContainer.down = function (x, y, obj) {
if (Math.abs(x - backButton.x) < 100 && Math.abs(y - backButton.y) < 40) {
// Go back to main menu
LK.showGameOver(); // Reset game state and return to main menu
} else if (Math.abs(x - otherUrlText.x) < 300 && Math.abs(y - otherUrlText.y) < 50) {
// Other URL clicked
LK.effects.flashScreen(0xFF5722, 500);
LK.showGameOver();
}
};
}
// Don't start background music immediately - wait for instructions to be dismissed
// Merchant functionality is handled through the shop button
// Create shop button at bottom center
shopButton = game.addChild(new ShopButton());
shopButton.x = 2048 / 2; // Center horizontally
shopButton.y = 2732 - 150; // Bottom of screen with some margin
// Add shop button text
var shopText = new Text2('SHOP', {
size: 40,
fill: 0xFFFFFF
});
shopText.anchor.set(0.5, 0.5);
shopText.x = shopButton.x;
shopText.y = shopButton.y;
game.addChild(shopText);
// Create hidden money cheat button above score
var hiddenMoneyButton = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.3
});
hiddenMoneyButton.x = scoreTxt.x; // Same x position as score
hiddenMoneyButton.y = scoreTxt.y - 100; // 100 pixels above score
hiddenMoneyButton.alpha = 0; // Make completely invisible
game.addChild(hiddenMoneyButton);
// Add click handler for hidden money button
hiddenMoneyButton.down = function (x, y, obj) {
// Give player 999999 coins
storage.coins = (storage.coins || 0) + 999999;
// Flash screen gold to indicate cheat activated
LK.effects.flashScreen(0xFFD700, 500);
};
// Initialize inventory storage
if (!storage.inventory) {
storage.inventory = {
slowdown: 0,
speedGigachad: 0,
doublePoints: 0
};
}
// Create inventory button
var inventoryButton = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
inventoryButton.x = 2048 / 2 - 250; // Left of shop button
inventoryButton.y = 2732 - 150; // Same level as shop button
inventoryButton.tint = 0x9C27B0; // Purple tint for inventory
// Add inventory button text
var inventoryText = new Text2('INVENTORY', {
size: 30,
fill: 0xFFFFFF
});
inventoryText.anchor.set(0.5, 0.5);
inventoryText.x = inventoryButton.x;
inventoryText.y = inventoryButton.y;
game.addChild(inventoryText);
// Create reset SCOİN button
var resetCoinButton = game.addChild(LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
resetCoinButton.x = 2048 / 2 + 250; // Right of shop button (opposite side from inventory)
resetCoinButton.y = 2732 - 150; // Same level as shop and inventory buttons
resetCoinButton.tint = 0xFF5722; // Orange-red tint for reset button
// Add reset button text
var resetText = new Text2('RESET SCOİN', {
size: 30,
fill: 0xFFFFFF
});
resetText.anchor.set(0.5, 0.5);
resetText.x = resetCoinButton.x;
resetText.y = resetCoinButton.y;
game.addChild(resetText);
// Add reset button functionality
resetCoinButton.down = function (x, y, obj) {
// Visual feedback
tween(resetCoinButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100
});
// Reset SCOİN to 0
storage.coins = 0;
// Update score display
scoreTxt.setText('SCOİN: ' + storage.coins);
// Flash screen orange to indicate reset
LK.effects.flashScreen(0xFF5722, 500);
};
resetCoinButton.up = function (x, y, obj) {
// Return to normal size
tween(resetCoinButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
};
// Inventory system variables
var isInventoryOpen = false;
var inventoryContainer = null;
var hadPowerUpsOnDeath = false; // Track if player had power-ups when they died
// Add inventory button functionality
inventoryButton.down = function (x, y, obj) {
// Visual feedback
tween(inventoryButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100
});
// Toggle inventory
if (isInventoryOpen) {
closeInventory();
} else {
openInventory();
}
};
inventoryButton.up = function (x, y, obj) {
// Return to normal size
tween(inventoryButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100
});
};
// Function to open inventory
function openInventory() {
if (isInventoryOpen) {
return;
}
isInventoryOpen = true;
isGameRunning = false; // Pause game
// Create inventory container
inventoryContainer = new Container();
inventoryContainer.x = 0;
inventoryContainer.y = 0;
game.addChild(inventoryContainer);
// Create background
var inventoryBg = LK.getAsset('shopButton', {
anchorX: 0,
anchorY: 0,
scaleX: 10.24,
scaleY: 34.15
});
inventoryBg.tint = 0x2E2E2E;
inventoryBg.alpha = 0.9;
inventoryContainer.addChild(inventoryBg);
// Title
var titleText = new Text2('INVENTORY', {
size: 120,
fill: 0x9C27B0
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
inventoryContainer.addChild(titleText);
// Current coins display
var coinsText = new Text2('SCOİN: ' + (storage.coins || 0), {
size: 60,
fill: 0xFFD700
});
coinsText.anchor.set(0.5, 0.5);
coinsText.x = 1024;
coinsText.y = 400;
inventoryContainer.addChild(coinsText);
// Inventory items section - GIGACHAD at top center, others below
var yPos = 500;
var itemSpacing = 120;
// Fast GIGACHAD items - positioned at top center
var speedGigachadCount = storage.inventory.speedGigachad || 0;
var speedStatusText = shopEffects.speedGigachad.active ? ' (ACTIVE)' : '';
var speedItemText = new Text2('Fast GIGACHAD: ' + speedGigachadCount + speedStatusText, {
size: 60,
fill: shopEffects.speedGigachad.active ? 0x4CAF50 : 0xFFFFFF
});
speedItemText.anchor.set(0.5, 0.5);
speedItemText.x = 1024; // Centered
speedItemText.y = yPos;
inventoryContainer.addChild(speedItemText);
// Use button for speed GIGACHAD - centered below text
if (speedGigachadCount > 0 && !shopEffects.speedGigachad.active && !hadPowerUpsOnDeath) {
var useSpeedBtn = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
useSpeedBtn.x = 1024; // Centered
useSpeedBtn.y = yPos + 60;
useSpeedBtn.tint = 0x4CAF50;
inventoryContainer.addChild(useSpeedBtn);
var useSpeedText = new Text2('USE', {
size: 40,
fill: 0xFFFFFF
});
useSpeedText.anchor.set(0.5, 0.5);
useSpeedText.x = useSpeedBtn.x;
useSpeedText.y = useSpeedBtn.y;
inventoryContainer.addChild(useSpeedText);
}
// Slowdown items - positioned below GIGACHAD
yPos += itemSpacing + 60;
var slowdownCount = storage.inventory.slowdown || 0;
var slowdownStatusText = shopEffects.slowdown.active ? ' (ACTIVE - ' + Math.ceil((18000 - shopEffects.slowdown.timer) / 60) + 's left)' : '';
var slowdownItemText = new Text2('Slowdown 5min: ' + slowdownCount + slowdownStatusText, {
size: 45,
fill: shopEffects.slowdown.active ? 0x4CAF50 : 0xFFFFFF
});
slowdownItemText.anchor.set(0.5, 0.5);
slowdownItemText.x = 1024;
slowdownItemText.y = yPos;
inventoryContainer.addChild(slowdownItemText);
// Use button for slowdown
if (slowdownCount > 0 && !shopEffects.slowdown.active && !hadPowerUpsOnDeath) {
var useSlowdownBtn = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
useSlowdownBtn.x = 1024 + 200;
useSlowdownBtn.y = yPos;
useSlowdownBtn.tint = 0x4CAF50;
inventoryContainer.addChild(useSlowdownBtn);
var useSlowdownText = new Text2('USE', {
size: 30,
fill: 0xFFFFFF
});
useSlowdownText.anchor.set(0.5, 0.5);
useSlowdownText.x = useSlowdownBtn.x;
useSlowdownText.y = useSlowdownBtn.y;
inventoryContainer.addChild(useSlowdownText);
}
// Double Points items - positioned at bottom
yPos += itemSpacing;
var doublePointsCount = storage.inventory.doublePoints || 0;
var doubleStatusText = shopEffects.doublePoints.active ? ' (ACTIVE - ' + Math.ceil((18000 - shopEffects.doublePoints.timer) / 60) + 's left)' : '';
var doubleItemText = new Text2('2x Points: ' + doublePointsCount + doubleStatusText, {
size: 45,
fill: shopEffects.doublePoints.active ? 0x4CAF50 : 0xFFFFFF
});
doubleItemText.anchor.set(0.5, 0.5);
doubleItemText.x = 1024;
doubleItemText.y = yPos;
inventoryContainer.addChild(doubleItemText);
// Use button for double points
if (doublePointsCount > 0 && !shopEffects.doublePoints.active && !hadPowerUpsOnDeath) {
var useDoubleBtn = LK.getAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
useDoubleBtn.x = 1024 + 200;
useDoubleBtn.y = yPos;
useDoubleBtn.tint = 0x4CAF50;
inventoryContainer.addChild(useDoubleBtn);
var useDoubleText = new Text2('USE', {
size: 30,
fill: 0xFFFFFF
});
useDoubleText.anchor.set(0.5, 0.5);
useDoubleText.x = useDoubleBtn.x;
useDoubleText.y = useDoubleBtn.y;
inventoryContainer.addChild(useDoubleText);
}
}
// Function to close inventory
function closeInventory() {
isInventoryOpen = false;
isGameRunning = true;
if (inventoryContainer) {
inventoryContainer.destroy();
inventoryContainer = null;
}
}
// Function to handle inventory item usage
function handleInventoryClick(x, y) {
if (!isInventoryOpen || !inventoryContainer) {
return;
}
// Prevent using inventory if player had power-ups when they died
if (hadPowerUpsOnDeath) {
LK.effects.flashScreen(0xFF0000, 300); // Red flash to indicate blocked
return;
}
// Check use buttons with correct global positions
var itemSpacing = 120;
var startY = 500;
// Speed GIGACHAD use button - centered at top (1024, startY + 60)
var speedButtonX = 1024;
var speedButtonY = startY + 60;
if (Math.abs(x - speedButtonX) < 150 && Math.abs(y - speedButtonY) < 50) {
if ((storage.inventory.speedGigachad || 0) > 0 && !shopEffects.speedGigachad.active) {
storage.inventory.speedGigachad--;
shopEffects.speedGigachad.active = true;
// Save inventory changes
storage.inventory = {
slowdown: storage.inventory.slowdown || 0,
speedGigachad: storage.inventory.speedGigachad,
doublePoints: storage.inventory.doublePoints || 0
};
closeInventory();
LK.effects.flashScreen(0x4CAF50, 500);
}
return;
}
// Slowdown use button - positioned at (1024 + 200, slowdownY)
var slowdownY = startY + itemSpacing + 60;
var slowdownButtonX = 1024 + 200;
if (Math.abs(x - slowdownButtonX) < 100 && Math.abs(y - slowdownY) < 50) {
if ((storage.inventory.slowdown || 0) > 0 && !shopEffects.slowdown.active) {
storage.inventory.slowdown--;
shopEffects.slowdown.active = true;
shopEffects.slowdown.timer = 0;
// Save inventory changes
storage.inventory = {
slowdown: storage.inventory.slowdown,
speedGigachad: storage.inventory.speedGigachad || 0,
doublePoints: storage.inventory.doublePoints || 0
};
closeInventory();
LK.effects.flashScreen(0x4CAF50, 500);
}
return;
}
// Double Points use button - positioned at (1024 + 200, doubleY)
var doubleY = startY + itemSpacing * 2 + 60;
var doubleButtonX = 1024 + 200;
if (Math.abs(x - doubleButtonX) < 100 && Math.abs(y - doubleY) < 50) {
if ((storage.inventory.doublePoints || 0) > 0 && !shopEffects.doublePoints.active) {
storage.inventory.doublePoints--;
shopEffects.doublePoints.active = true;
shopEffects.doublePoints.timer = 0;
// Save inventory changes
storage.inventory = {
slowdown: storage.inventory.slowdown || 0,
speedGigachad: storage.inventory.speedGigachad || 0,
doublePoints: storage.inventory.doublePoints
};
closeInventory();
LK.effects.flashScreen(0x4CAF50, 500);
}
return;
}
}
// Add shop interaction handler
game.down = function (x, y, obj) {
if (isShopOpen && shopButton) {
shopButton.handleShopClick(x, y);
} else if (isInventoryOpen) {
handleInventoryClick(x, y);
}
};
// Main game loop
game.update = function () {
if (!isGameRunning || isShopOpen || isInventoryOpen) {
return;
}
moveCounter++;
var currentMoveDelay = MOVE_DELAY;
if (shopEffects.slowdown.active) {
currentMoveDelay = MOVE_DELAY * 2; // Double the delay for slowdown effect
}
if (moveCounter >= currentMoveDelay) {
moveCounter = 0;
moveSnake();
}
// Spawn friendly snakes every 10 seconds (600 frames at 60fps)
friendlySnakeTimer++;
if (friendlySnakeTimer >= 600) {
friendlySnakeTimer = 0;
var friendlySnake = game.addChild(new FriendlySnake());
// Spawn at random edge position within board bounds only
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top - ensure spawn within board width
friendlySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE;
friendlySnake.y = boardOffsetY + GRID_SIZE;
break;
case 1:
// Right - ensure spawn within board height
friendlySnake.x = boardOffsetX + (BOARD_WIDTH - 1) * GRID_SIZE;
friendlySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE;
break;
case 2:
// Bottom - ensure spawn within board width
friendlySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE;
friendlySnake.y = boardOffsetY + (BOARD_HEIGHT - 1) * GRID_SIZE;
break;
case 3:
// Left - ensure spawn within board height
friendlySnake.x = boardOffsetX + GRID_SIZE;
friendlySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE;
break;
}
friendlySnakes.push(friendlySnake);
}
// Spawn enemy snakes every 8 seconds (480 frames at 60fps)
enemySnakeTimer++;
if (enemySnakeTimer >= 480) {
enemySnakeTimer = 0;
var enemySnake = game.addChild(new EnemySnake());
// Spawn at random edge position within board bounds only
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top - ensure spawn within board width
enemySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE;
enemySnake.y = boardOffsetY + GRID_SIZE;
break;
case 1:
// Right - ensure spawn within board height
enemySnake.x = boardOffsetX + (BOARD_WIDTH - 1) * GRID_SIZE;
enemySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE;
break;
case 2:
// Bottom - ensure spawn within board width
enemySnake.x = boardOffsetX + (Math.random() * (BOARD_WIDTH - 2) + 1) * GRID_SIZE;
enemySnake.y = boardOffsetY + (BOARD_HEIGHT - 1) * GRID_SIZE;
break;
case 3:
// Left - ensure spawn within board height
enemySnake.x = boardOffsetX + GRID_SIZE;
enemySnake.y = boardOffsetY + (Math.random() * (BOARD_HEIGHT - 2) + 1) * GRID_SIZE;
break;
}
enemySnakes.push(enemySnake);
}
// Check collision between player and enemy snakes
if (snake.length > 0) {
var playerHead = snake[0];
var playerScreenPos = gridToScreen(playerHead.x, playerHead.y);
for (var i = enemySnakes.length - 1; i >= 0; i--) {
var enemySnake = enemySnakes[i];
var dist = Math.sqrt(Math.pow(playerScreenPos.x - enemySnake.x, 2) + Math.pow(playerScreenPos.y - enemySnake.y, 2));
if (dist < 60) {
// Collision detected
// Check if friendly snake is protecting
var isProtected = false;
for (var j = 0; j < friendlySnakes.length; j++) {
var friendlySnake = friendlySnakes[j];
var friendlyDist = Math.sqrt(Math.pow(playerScreenPos.x - friendlySnake.x, 2) + Math.pow(playerScreenPos.y - friendlySnake.y, 2));
if (friendlyDist < 100) {
// Protection range
isProtected = true;
// Remove the enemy snake as it's defeated by friendly snake
enemySnake.destroy();
enemySnakes.splice(i, 1);
var coins = storage.coins || 0;
storage.coins = coins + 50; // Bonus for protection
scoreTxt.setText('SCOİN: ' + storage.coins);
break;
}
}
if (!isProtected) {
// Game over - player eaten by enemy snake
isGameRunning = false;
// Check if player had any active power-ups before clearing them
hadPowerUpsOnDeath = shopEffects.slowdown.active || shopEffects.speedGigachad.active || shopEffects.doublePoints.active;
// Clear all active power-up effects on death
shopEffects.slowdown.active = false;
shopEffects.slowdown.timer = 0;
shopEffects.speedGigachad.active = false;
shopEffects.doublePoints.active = false;
shopEffects.doublePoints.timer = 0;
LK.getSound('gameOver').play();
LK.showGameOver();
return;
}
}
}
}
// Reset GIGACHAD notification if no enemies remain
if (enemySnakes.length === 0) {
gigaChadNotified = false;
}
// Update shop effects
if (shopEffects.slowdown.active) {
shopEffects.slowdown.timer++;
if (shopEffects.slowdown.timer >= 18000) {
// 5 minutes
shopEffects.slowdown.active = false;
shopEffects.slowdown.timer = 0;
}
}
if (shopEffects.doublePoints.active) {
shopEffects.doublePoints.timer++;
if (shopEffects.doublePoints.timer >= 18000) {
// 5 minutes
shopEffects.doublePoints.active = false;
shopEffects.doublePoints.timer = 0;
}
}
// Update power-up timer display
var timerText = "";
var activeEffects = [];
if (shopEffects.slowdown.active) {
var slowdownTimeLeft = Math.ceil((18000 - shopEffects.slowdown.timer) / 60);
activeEffects.push("Slowdown: " + slowdownTimeLeft + "s");
}
if (shopEffects.speedGigachad.active) {
activeEffects.push("Fast GIGACHAD: ACTIVE");
}
if (shopEffects.doublePoints.active) {
var doublePointsTimeLeft = Math.ceil((18000 - shopEffects.doublePoints.timer) / 60);
activeEffects.push("2x Points: " + doublePointsTimeLeft + "s");
}
if (activeEffects.length > 0) {
timerText = activeEffects.join(" | ");
powerUpTimerTxt.setText(timerText);
powerUpTimerTxt.alpha = 1;
} else {
powerUpTimerTxt.setText("");
powerUpTimerTxt.alpha = 0;
}
};
robotik yap
wall block. In-Game asset. 2d. High contrast. No shadows
energy ball. In-Game asset. 2d. High contrast. No shadows
frendly robotic snake. In-Game asset. 2d. High contrast. No shadows
rainbow energy. In-Game asset. 2d. High contrast. No shadows
enemy robotic snake. In-Game asset. 2d. High contrast. No shadows
Robotic GigaChad snake. In-Game asset. 2d. High contrast. No shadows
yellow and orange cube 2d. In-Game asset. 2d. High contrast. No shadows
button red 2d. In-Game asset. 2d. High contrast. No shadows