/**** * Classes ****/ // BoxFood class (dangerous apple) var BoxFood = Container.expand(function () { var self = Container.call(this); var boxAsset = self.attachAsset('boxFood', { anchorX: 0.5, anchorY: 0.5 }); self.isBox = true; self.destroyedByBullet = false; return self; }); // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); var bulletAsset = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); // Default speed values (will be set on fire) self.speedX = 32; self.speedY = 0; self.update = function () { self.lastX = self.x; self.lastY = self.y; self.x += self.speedX; self.y += self.speedY; }; return self; }); // Food class var Food = Container.expand(function () { var self = Container.call(this); var foodAsset = self.attachAsset('food', { anchorX: 0.5, anchorY: 0.5 }); self.isBox = false; return self; }); // Snake segment class var Segment = Container.expand(function () { var self = Container.call(this); var segAsset = self.attachAsset('snakeSegment', { anchorX: 0.5, anchorY: 0.5 }); return self; }); // Snake class var Snake = Container.expand(function () { var self = Container.call(this); self.segments = []; self.direction = 'right'; self.nextDirection = 'right'; self.moveTimer = 0; self.moveInterval = 16; // Lower is faster, 16 = ~4 moves/sec at 60fps self.alive = true; // Initialize snake with 4 segments for (var i = 0; i < 4; i++) { var seg = new Segment(); seg.x = 1024 - i * 64; seg.y = 1366; self.addChild(seg); self.segments.push(seg); } self.update = function () { if (!self.alive) return; // Snake always moves, even if box food is active self.moveTimer++; if (self.moveTimer < self.moveInterval) return; self.moveTimer = 0; // Update direction self.direction = self.nextDirection; // Calculate new head position var head = self.segments[0]; var newX = head.x; var newY = head.y; if (self.direction === 'right') newX += 64;else if (self.direction === 'left') newX -= 64;else if (self.direction === 'up') newY -= 64;else if (self.direction === 'down') newY += 64; // Move body for (var i = self.segments.length - 1; i > 0; i--) { self.segments[i].x = self.segments[i - 1].x; self.segments[i].y = self.segments[i - 1].y; } head.x = newX; head.y = newY; }; self.grow = function () { var last = self.segments[self.segments.length - 1]; var seg = new Segment(); seg.x = last.x; seg.y = last.y; self.addChild(seg); self.segments.push(seg); }; return self; }); /**** * Initialize Game ****/ // Game variables var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // --- Main menu overlay --- var snake; var food; var scoreTxt; var gameOver = false; var bullets = []; var boxFoods = []; var boxFoodActive = false; var boxFoodObj = null; // --- Main menu overlay --- var menuContainer = new Container(); var menuBg = LK.getAsset('yourBackgroundImageId', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); menuContainer.addChild(menuBg); var menuTitle = new Text2('snaker', { size: 240, fill: 0xFFFFFF }); menuTitle.anchor.set(0.5, 0.5); menuTitle.x = 2048 / 2; menuTitle.y = 900; menuContainer.addChild(menuTitle); var tapText = new Text2('Başlamak için ekrana dokun', { size: 120, fill: 0xffffff }); tapText.anchor.set(0.5, 0.5); tapText.x = 2048 / 2; tapText.y = 1600; menuContainer.addChild(tapText); game.addChild(menuContainer); var menuActive = true; // Only allow tap anywhere to start game game.down = function (x, y, obj) { if (menuActive) { menuActive = false; menuContainer.destroy(); // After menu, allow normal game.down (fire bullet) to work game.down = function (x, y, obj) { if (gameOver) return; lastTouchX = x; lastTouchY = y; if (snake && snake.segments.length > 0) { var head = snake.segments[0]; var bullet = new Bullet(); bullet.x = head.x; bullet.y = head.y; bullet.lastX = bullet.x; // Set bullet speed and direction based on snake direction, and rotate asset accordingly if (snake.direction === 'right') { bullet.speedX = 32; bullet.speedY = 0; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = 0; } else if (snake.direction === 'left') { bullet.speedX = -32; bullet.speedY = 0; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI; } else if (snake.direction === 'up') { bullet.speedX = 0; bullet.speedY = -32; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = -Math.PI / 2; } else if (snake.direction === 'down') { bullet.speedX = 0; bullet.speedY = 32; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI / 2; } bullets.push(bullet); game.addChild(bullet); } }; return; } // If menu is not active, do nothing here (game.down will be replaced) }; // Add a bright background image (replace 'yourBackgroundImageId' with your own image asset id) var bgImage = LK.getAsset('yourBackgroundImageId', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732 }); game.addChild(bgImage); // Create snake snake = new Snake(); game.addChild(snake); // No monster at game start // Create food function spawnFood() { // Remove previous food if (food) food.destroy(); // Remove previous box food if present if (boxFoodObj) { boxFoodObj.destroy(); boxFoodObj = null; boxFoodActive = false; } // Box food spawn chance can be changed by roguelike effects if (typeof roguelike_boxFoodChance === "undefined") roguelike_boxFoodChance = 0.25; if (Math.random() < roguelike_boxFoodChance) { // Build a list of all possible grid positions var possiblePositions = []; for (var gx = 64; gx <= 2048 - 64; gx += 64) { for (var gy = 64; gy <= 2732 - 64; gy += 64) { var occupied = false; for (var i = 0; i < snake.segments.length; i++) { if (Math.abs(snake.segments[i].x - gx) < 1 && Math.abs(snake.segments[i].y - gy) < 1) { occupied = true; break; } } if (!occupied) possiblePositions.push({ x: gx, y: gy }); } } if (possiblePositions.length > 0) { var idx = Math.floor(Math.random() * possiblePositions.length); var newBoxFood = new BoxFood(); newBoxFood.x = possiblePositions[idx].x; newBoxFood.y = possiblePositions[idx].y; game.addChild(newBoxFood); boxFoods.push(newBoxFood); boxFoodObj = newBoxFood; boxFoodActive = true; // Do not spawn normal food when box food is active food = null; } } else { // Only normal food // Build a list of all possible grid positions var possiblePositions = []; for (var gx = 64; gx <= 2048 - 64; gx += 64) { for (var gy = 64; gy <= 2732 - 64; gy += 64) { var occupied = false; for (var i = 0; i < snake.segments.length; i++) { if (Math.abs(snake.segments[i].x - gx) < 1 && Math.abs(snake.segments[i].y - gy) < 1) { occupied = true; break; } } if (!occupied) possiblePositions.push({ x: gx, y: gy }); } } if (possiblePositions.length > 0) { var idx = Math.floor(Math.random() * possiblePositions.length); food = new Food(); food.x = possiblePositions[idx].x; food.y = possiblePositions[idx].y; game.addChild(food); boxFoodActive = false; boxFoodObj = null; } } } spawnFood(); // Score text scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Game update game.update = function () { if (gameOver) return; snake.update(); // Check wall collision var head = snake.segments[0]; if (head.x < 0 || head.x > 2048 || head.y < 0 || head.y > 2732) { gameOver = true; LK.showGameOver(); return; } // Check self collision for (var i = 1; i < snake.segments.length; i++) { if (Math.abs(head.x - snake.segments[i].x) < 1 && Math.abs(head.y - snake.segments[i].y) < 1) { gameOver = true; LK.showGameOver(); return; } } // Handle bullets for (var b = bullets.length - 1; b >= 0; b--) { var bullet = bullets[b]; bullet.update(); // Remove bullet if off screen if (bullet.x > 2048 + 32) { bullet.destroy(); bullets.splice(b, 1); continue; } // Check collision with box food if (boxFoodActive && boxFoodObj && !boxFoodObj._destroyed && !boxFoodObj.destroyedByBullet && bullet.intersects(boxFoodObj)) { boxFoodObj.destroyedByBullet = true; bullet.destroy(); bullets.splice(b, 1); // Remove box, spawn normal food at same position var prevX = boxFoodObj.x; var prevY = boxFoodObj.y; boxFoodObj.destroy(); boxFoodObj = null; boxFoodActive = false; // Spawn normal food at same position if (food) food.destroy(); food = new Food(); food.x = prevX; food.y = prevY; game.addChild(food); } } // Check food collision if (food && head.intersects(food)) { snake.grow(); LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); // Roguelike selection overlay every 5 points if (LK.getScore() > 0 && LK.getScore() % 5 === 0) { // --- Roguelike pool --- // Each option: { name, desc, apply, id } // Pause only snake movement (not all game logic) if (snake) snake.alive = false; // Pause snake movement // --- Monster global variable --- var monster = null; var roguelikePool = [{ id: "grow1", name: "+1 Uzama", desc: "Yılan 1 parça uzar.", apply: function apply() { snake.grow(); } }, { id: "speedup", name: "Hızlan", desc: "Yılan daha hızlı hareket eder.", apply: function apply() { if (snake.moveInterval > 2) snake.moveInterval -= 2; } }, { id: "slow3_box50", name: "-3 Hız, %50 Kutulu Elma", desc: "Yılan 3 birim yavaşlar, kutulu elma çıkma şansı %50 olur.", apply: function apply() { if (snake.moveInterval < 32) snake.moveInterval += 3; roguelike_boxFoodChance = 0.5; } }, { id: "boxFoodAlways", name: "Her zaman kutulu elma", desc: "Her yiyecek kutulu elma olur.", apply: function apply() { roguelike_boxFoodChance = 1.0; } }, { id: "normalFoodAlways", name: "Sadece normal elma", desc: "Kutulu elma çıkmaz.", apply: function apply() { roguelike_boxFoodChance = 0.0; } }, { id: "grow3", name: "+3 Uzama", desc: "Yılan 3 parça uzar.", apply: function apply() { snake.grow(); snake.grow(); snake.grow(); } }, { id: "score5", name: "+5 Puan", desc: "Anında 5 puan kazan.", apply: function apply() { LK.setScore(LK.getScore() + 5); scoreTxt.setText(LK.getScore()); } }, { id: "shorten2", name: "-2 Uzunluk", desc: "Yılan 2 parça kısalır.", apply: function apply() { for (var i = 0; i < 2; i++) { if (snake.segments.length > 1) { var seg = snake.segments.pop(); seg.destroy(); } } } }, { id: "boxFoodDoubleScore", name: "Kutulu Elma 2x Puan", desc: "Kutulu elma yersen 2 kat puan.", apply: function apply() { roguelike_boxFoodDoubleScore = true; } } // Add more options here! ]; // --- Roguelike state variables --- if (typeof roguelike_boxFoodChance === "undefined") roguelike_boxFoodChance = 0.25; if (typeof roguelike_boxFoodDoubleScore === "undefined") roguelike_boxFoodDoubleScore = false; // Pick 2 random, different options var idx1 = Math.floor(Math.random() * roguelikePool.length); var idx2; do { idx2 = Math.floor(Math.random() * roguelikePool.length); } while (idx2 === idx1); var optA = roguelikePool[idx1]; var optB = roguelikePool[idx2]; // Create overlay container var roguelikeOverlay = new Container(); // Dim background var dimBg = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2, scaleX: 20, scaleY: 20, alpha: 0.7 }); roguelikeOverlay.addChild(dimBg); // Title var rlTitle = new Text2('Roguelike Seçimi!', { size: 160, fill: 0xffffff }); rlTitle.anchor.set(0.5, 0.5); rlTitle.x = 2048 / 2; rlTitle.y = 900; roguelikeOverlay.addChild(rlTitle); // Option 1 var opt1 = new Text2(optA.name, { size: 100, fill: 0x00ff00 }); opt1.anchor.set(0.5, 0.5); opt1.x = 2048 / 2; opt1.y = 1300; roguelikeOverlay.addChild(opt1); var opt1desc = new Text2(optA.desc, { size: 60, fill: 0xffffff }); opt1desc.anchor.set(0.5, 0.5); opt1desc.x = 2048 / 2; opt1desc.y = 1400; roguelikeOverlay.addChild(opt1desc); // Option 2 var opt2 = new Text2(optB.name, { size: 100, fill: 0x00bfff }); opt2.anchor.set(0.5, 0.5); opt2.x = 2048 / 2; opt2.y = 1700; roguelikeOverlay.addChild(opt2); var opt2desc = new Text2(optB.desc, { size: 60, fill: 0xffffff }); opt2desc.anchor.set(0.5, 0.5); opt2desc.x = 2048 / 2; opt2desc.y = 1800; roguelikeOverlay.addChild(opt2desc); // Add overlay to game game.addChild(roguelikeOverlay); // Option selection logic roguelikeOverlay.down = function (x, y, obj) { // Check which option was tapped if (Math.abs(y - opt1.y) < 120) { optA.apply(); } else if (Math.abs(y - opt2.y) < 120) { optB.apply(); } else { // Not on option, ignore return; } // Remove overlay and resume game roguelikeOverlay.destroy(); // Resume popup monster if it was paused if (popupMonster && !popupMonster._destroyed) { popupMonster.tapped = false; } // --- Teleport snake to center if head is near wall --- if (snake && snake.segments.length > 0) { var head = snake.segments[0]; // Define "near wall" as within 128px of any edge var margin = 128; var centerX = 1024; var centerY = 1366; if (head.x < margin || head.x > 2048 - margin || head.y < margin || head.y > 2732 - margin) { // Calculate offset between all segments and head var dx = centerX - head.x; var dy = centerY - head.y; for (var i = 0; i < snake.segments.length; i++) { snake.segments[i].x += dx; snake.segments[i].y += dy; } } } if (snake) snake.alive = true; // Resume snake movement gameOver = false; // After roguelike selection, spawn food or box food spawnFood(); // Restore swipe and tap controls game.down = function (x, y, obj) { if (gameOver) return; // Store initial touch for swipe direction detection lastTouchX = x; lastTouchY = y; if (snake && snake.segments.length > 0) { var head = snake.segments[0]; var bullet = new Bullet(); bullet.x = head.x; bullet.y = head.y; bullet.lastX = bullet.x; // Set bullet speed and direction based on snake direction, and rotate asset accordingly if (snake.direction === 'right') { bullet.speedX = 32; bullet.speedY = 0; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = 0; } else if (snake.direction === 'left') { bullet.speedX = -32; bullet.speedY = 0; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI; } else if (snake.direction === 'up') { bullet.speedX = 0; bullet.speedY = -32; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = -Math.PI / 2; } else if (snake.direction === 'down') { bullet.speedX = 0; bullet.speedY = 32; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI / 2; } bullets.push(bullet); game.addChild(bullet); } }; }; // Forward tap events to overlay game.down = function (x, y, obj) { if (roguelikeOverlay && roguelikeOverlay.down) roguelikeOverlay.down(x, y, obj); }; // Prevent further game logic until overlay is closed return; } spawnFood(); // Speed up as snake grows (slower acceleration) if (snake.moveInterval > 6) { snake.moveInterval--; } else if (snake.moveInterval > 4 && LK.getScore() % 10 === 0) { // Only speed up every 10 points when very fast snake.moveInterval--; } } // SWORD ATTACK LOGIC if (swordActive) { swordTimer++; // Sword effect follows head if (swordEffect && snake && snake.segments.length > 0) { var head = snake.segments[0]; swordEffect.x = head.x; swordEffect.y = head.y; } // Check for box food collision with sword if (boxFoodActive && boxFoodObj && !boxFoodObj._destroyed && snake && snake.segments.length > 0) { var head = snake.segments[0]; if (head.intersects(boxFoodObj) && !boxFoodObj.destroyedByBullet) { // Defeat box food with sword snake.grow(); LK.setScore(LK.getScore() + 2); scoreTxt.setText(LK.getScore()); boxFoodObj.destroy(); boxFoodObj = null; boxFoodActive = false; spawnFood(); if (snake.moveInterval > 4) snake.moveInterval--; // End sword effect swordActive = false; swordTimer = 0; if (swordEffect) { swordEffect.destroy(); swordEffect = null; } } } // Sword duration end if (swordTimer > swordDuration) { swordActive = false; swordTimer = 0; if (swordEffect) { swordEffect.destroy(); swordEffect = null; } } } // Check box food collision if (boxFoodActive && boxFoodObj && !boxFoodObj._destroyed) { if (head.intersects(boxFoodObj)) { if (boxFoodObj.destroyedByBullet) { // Now edible snake.grow(); var boxScore = 2; if (typeof roguelike_boxFoodDoubleScore !== "undefined" && roguelike_boxFoodDoubleScore) boxScore *= 2; LK.setScore(LK.getScore() + boxScore); scoreTxt.setText(LK.getScore()); boxFoodObj.destroy(); boxFoodObj = null; boxFoodActive = false; spawnFood(); if (snake.moveInterval > 4) snake.moveInterval--; } else if (!swordActive) { // Deadly! gameOver = true; LK.showGameOver(); return; } } } }; // Touch controls var lastTouchX = null; var lastTouchY = null; // Sword attack state var swordActive = false; var swordTimer = 0; var swordDuration = 18; // ~0.3s at 60fps // Sword attack visual (simple overlay on snake head) var swordEffect = null; // Main game tap: always fire bullet in snake's direction game.down = function (x, y, obj) { if (gameOver) return; // Store initial touch for swipe direction detection lastTouchX = x; lastTouchY = y; if (snake && snake.segments.length > 0) { var head = snake.segments[0]; var bullet = new Bullet(); bullet.x = head.x; bullet.y = head.y; bullet.lastX = bullet.x; // Set bullet speed and direction based on snake direction, and rotate asset accordingly if (snake.direction === 'right') { bullet.speedX = 32; bullet.speedY = 0; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = 0; } else if (snake.direction === 'left') { bullet.speedX = -32; bullet.speedY = 0; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI; } else if (snake.direction === 'up') { bullet.speedX = 0; bullet.speedY = -32; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = -Math.PI / 2; } else if (snake.direction === 'down') { bullet.speedX = 0; bullet.speedY = 32; if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI / 2; } bullets.push(bullet); game.addChild(bullet); } }; // --- SWORD LOGIC in update (see below) --- game.up = function (x, y, obj) { if (lastTouchX === null || lastTouchY === null) return; var dx = x - lastTouchX; var dy = y - lastTouchY; if (Math.abs(dx) > Math.abs(dy)) { if (dx > 0 && snake.direction !== 'left') snake.nextDirection = 'right';else if (dx < 0 && snake.direction !== 'right') snake.nextDirection = 'left'; } else { if (dy > 0 && snake.direction !== 'up') snake.nextDirection = 'down';else if (dy < 0 && snake.direction !== 'down') snake.nextDirection = 'up'; } lastTouchX = null; lastTouchY = null; };
/****
* Classes
****/
// BoxFood class (dangerous apple)
var BoxFood = Container.expand(function () {
var self = Container.call(this);
var boxAsset = self.attachAsset('boxFood', {
anchorX: 0.5,
anchorY: 0.5
});
self.isBox = true;
self.destroyedByBullet = false;
return self;
});
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletAsset = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Default speed values (will be set on fire)
self.speedX = 32;
self.speedY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.x += self.speedX;
self.y += self.speedY;
};
return self;
});
// Food class
var Food = Container.expand(function () {
var self = Container.call(this);
var foodAsset = self.attachAsset('food', {
anchorX: 0.5,
anchorY: 0.5
});
self.isBox = false;
return self;
});
// Snake segment class
var Segment = Container.expand(function () {
var self = Container.call(this);
var segAsset = self.attachAsset('snakeSegment', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Snake class
var Snake = Container.expand(function () {
var self = Container.call(this);
self.segments = [];
self.direction = 'right';
self.nextDirection = 'right';
self.moveTimer = 0;
self.moveInterval = 16; // Lower is faster, 16 = ~4 moves/sec at 60fps
self.alive = true;
// Initialize snake with 4 segments
for (var i = 0; i < 4; i++) {
var seg = new Segment();
seg.x = 1024 - i * 64;
seg.y = 1366;
self.addChild(seg);
self.segments.push(seg);
}
self.update = function () {
if (!self.alive) return;
// Snake always moves, even if box food is active
self.moveTimer++;
if (self.moveTimer < self.moveInterval) return;
self.moveTimer = 0;
// Update direction
self.direction = self.nextDirection;
// Calculate new head position
var head = self.segments[0];
var newX = head.x;
var newY = head.y;
if (self.direction === 'right') newX += 64;else if (self.direction === 'left') newX -= 64;else if (self.direction === 'up') newY -= 64;else if (self.direction === 'down') newY += 64;
// Move body
for (var i = self.segments.length - 1; i > 0; i--) {
self.segments[i].x = self.segments[i - 1].x;
self.segments[i].y = self.segments[i - 1].y;
}
head.x = newX;
head.y = newY;
};
self.grow = function () {
var last = self.segments[self.segments.length - 1];
var seg = new Segment();
seg.x = last.x;
seg.y = last.y;
self.addChild(seg);
self.segments.push(seg);
};
return self;
});
/****
* Initialize Game
****/
// Game variables
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// --- Main menu overlay ---
var snake;
var food;
var scoreTxt;
var gameOver = false;
var bullets = [];
var boxFoods = [];
var boxFoodActive = false;
var boxFoodObj = null;
// --- Main menu overlay ---
var menuContainer = new Container();
var menuBg = LK.getAsset('yourBackgroundImageId', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
menuContainer.addChild(menuBg);
var menuTitle = new Text2('snaker', {
size: 240,
fill: 0xFFFFFF
});
menuTitle.anchor.set(0.5, 0.5);
menuTitle.x = 2048 / 2;
menuTitle.y = 900;
menuContainer.addChild(menuTitle);
var tapText = new Text2('Başlamak için ekrana dokun', {
size: 120,
fill: 0xffffff
});
tapText.anchor.set(0.5, 0.5);
tapText.x = 2048 / 2;
tapText.y = 1600;
menuContainer.addChild(tapText);
game.addChild(menuContainer);
var menuActive = true;
// Only allow tap anywhere to start game
game.down = function (x, y, obj) {
if (menuActive) {
menuActive = false;
menuContainer.destroy();
// After menu, allow normal game.down (fire bullet) to work
game.down = function (x, y, obj) {
if (gameOver) return;
lastTouchX = x;
lastTouchY = y;
if (snake && snake.segments.length > 0) {
var head = snake.segments[0];
var bullet = new Bullet();
bullet.x = head.x;
bullet.y = head.y;
bullet.lastX = bullet.x;
// Set bullet speed and direction based on snake direction, and rotate asset accordingly
if (snake.direction === 'right') {
bullet.speedX = 32;
bullet.speedY = 0;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = 0;
} else if (snake.direction === 'left') {
bullet.speedX = -32;
bullet.speedY = 0;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI;
} else if (snake.direction === 'up') {
bullet.speedX = 0;
bullet.speedY = -32;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = -Math.PI / 2;
} else if (snake.direction === 'down') {
bullet.speedX = 0;
bullet.speedY = 32;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI / 2;
}
bullets.push(bullet);
game.addChild(bullet);
}
};
return;
}
// If menu is not active, do nothing here (game.down will be replaced)
};
// Add a bright background image (replace 'yourBackgroundImageId' with your own image asset id)
var bgImage = LK.getAsset('yourBackgroundImageId', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0,
width: 2048,
height: 2732
});
game.addChild(bgImage);
// Create snake
snake = new Snake();
game.addChild(snake);
// No monster at game start
// Create food
function spawnFood() {
// Remove previous food
if (food) food.destroy();
// Remove previous box food if present
if (boxFoodObj) {
boxFoodObj.destroy();
boxFoodObj = null;
boxFoodActive = false;
}
// Box food spawn chance can be changed by roguelike effects
if (typeof roguelike_boxFoodChance === "undefined") roguelike_boxFoodChance = 0.25;
if (Math.random() < roguelike_boxFoodChance) {
// Build a list of all possible grid positions
var possiblePositions = [];
for (var gx = 64; gx <= 2048 - 64; gx += 64) {
for (var gy = 64; gy <= 2732 - 64; gy += 64) {
var occupied = false;
for (var i = 0; i < snake.segments.length; i++) {
if (Math.abs(snake.segments[i].x - gx) < 1 && Math.abs(snake.segments[i].y - gy) < 1) {
occupied = true;
break;
}
}
if (!occupied) possiblePositions.push({
x: gx,
y: gy
});
}
}
if (possiblePositions.length > 0) {
var idx = Math.floor(Math.random() * possiblePositions.length);
var newBoxFood = new BoxFood();
newBoxFood.x = possiblePositions[idx].x;
newBoxFood.y = possiblePositions[idx].y;
game.addChild(newBoxFood);
boxFoods.push(newBoxFood);
boxFoodObj = newBoxFood;
boxFoodActive = true;
// Do not spawn normal food when box food is active
food = null;
}
} else {
// Only normal food
// Build a list of all possible grid positions
var possiblePositions = [];
for (var gx = 64; gx <= 2048 - 64; gx += 64) {
for (var gy = 64; gy <= 2732 - 64; gy += 64) {
var occupied = false;
for (var i = 0; i < snake.segments.length; i++) {
if (Math.abs(snake.segments[i].x - gx) < 1 && Math.abs(snake.segments[i].y - gy) < 1) {
occupied = true;
break;
}
}
if (!occupied) possiblePositions.push({
x: gx,
y: gy
});
}
}
if (possiblePositions.length > 0) {
var idx = Math.floor(Math.random() * possiblePositions.length);
food = new Food();
food.x = possiblePositions[idx].x;
food.y = possiblePositions[idx].y;
game.addChild(food);
boxFoodActive = false;
boxFoodObj = null;
}
}
}
spawnFood();
// Score text
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Game update
game.update = function () {
if (gameOver) return;
snake.update();
// Check wall collision
var head = snake.segments[0];
if (head.x < 0 || head.x > 2048 || head.y < 0 || head.y > 2732) {
gameOver = true;
LK.showGameOver();
return;
}
// Check self collision
for (var i = 1; i < snake.segments.length; i++) {
if (Math.abs(head.x - snake.segments[i].x) < 1 && Math.abs(head.y - snake.segments[i].y) < 1) {
gameOver = true;
LK.showGameOver();
return;
}
}
// Handle bullets
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
bullet.update();
// Remove bullet if off screen
if (bullet.x > 2048 + 32) {
bullet.destroy();
bullets.splice(b, 1);
continue;
}
// Check collision with box food
if (boxFoodActive && boxFoodObj && !boxFoodObj._destroyed && !boxFoodObj.destroyedByBullet && bullet.intersects(boxFoodObj)) {
boxFoodObj.destroyedByBullet = true;
bullet.destroy();
bullets.splice(b, 1);
// Remove box, spawn normal food at same position
var prevX = boxFoodObj.x;
var prevY = boxFoodObj.y;
boxFoodObj.destroy();
boxFoodObj = null;
boxFoodActive = false;
// Spawn normal food at same position
if (food) food.destroy();
food = new Food();
food.x = prevX;
food.y = prevY;
game.addChild(food);
}
}
// Check food collision
if (food && head.intersects(food)) {
snake.grow();
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
// Roguelike selection overlay every 5 points
if (LK.getScore() > 0 && LK.getScore() % 5 === 0) {
// --- Roguelike pool ---
// Each option: { name, desc, apply, id }
// Pause only snake movement (not all game logic)
if (snake) snake.alive = false; // Pause snake movement
// --- Monster global variable ---
var monster = null;
var roguelikePool = [{
id: "grow1",
name: "+1 Uzama",
desc: "Yılan 1 parça uzar.",
apply: function apply() {
snake.grow();
}
}, {
id: "speedup",
name: "Hızlan",
desc: "Yılan daha hızlı hareket eder.",
apply: function apply() {
if (snake.moveInterval > 2) snake.moveInterval -= 2;
}
}, {
id: "slow3_box50",
name: "-3 Hız, %50 Kutulu Elma",
desc: "Yılan 3 birim yavaşlar, kutulu elma çıkma şansı %50 olur.",
apply: function apply() {
if (snake.moveInterval < 32) snake.moveInterval += 3;
roguelike_boxFoodChance = 0.5;
}
}, {
id: "boxFoodAlways",
name: "Her zaman kutulu elma",
desc: "Her yiyecek kutulu elma olur.",
apply: function apply() {
roguelike_boxFoodChance = 1.0;
}
}, {
id: "normalFoodAlways",
name: "Sadece normal elma",
desc: "Kutulu elma çıkmaz.",
apply: function apply() {
roguelike_boxFoodChance = 0.0;
}
}, {
id: "grow3",
name: "+3 Uzama",
desc: "Yılan 3 parça uzar.",
apply: function apply() {
snake.grow();
snake.grow();
snake.grow();
}
}, {
id: "score5",
name: "+5 Puan",
desc: "Anında 5 puan kazan.",
apply: function apply() {
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
}
}, {
id: "shorten2",
name: "-2 Uzunluk",
desc: "Yılan 2 parça kısalır.",
apply: function apply() {
for (var i = 0; i < 2; i++) {
if (snake.segments.length > 1) {
var seg = snake.segments.pop();
seg.destroy();
}
}
}
}, {
id: "boxFoodDoubleScore",
name: "Kutulu Elma 2x Puan",
desc: "Kutulu elma yersen 2 kat puan.",
apply: function apply() {
roguelike_boxFoodDoubleScore = true;
}
}
// Add more options here!
];
// --- Roguelike state variables ---
if (typeof roguelike_boxFoodChance === "undefined") roguelike_boxFoodChance = 0.25;
if (typeof roguelike_boxFoodDoubleScore === "undefined") roguelike_boxFoodDoubleScore = false;
// Pick 2 random, different options
var idx1 = Math.floor(Math.random() * roguelikePool.length);
var idx2;
do {
idx2 = Math.floor(Math.random() * roguelikePool.length);
} while (idx2 === idx1);
var optA = roguelikePool[idx1];
var optB = roguelikePool[idx2];
// Create overlay container
var roguelikeOverlay = new Container();
// Dim background
var dimBg = LK.getAsset('centerCircle', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 20,
scaleY: 20,
alpha: 0.7
});
roguelikeOverlay.addChild(dimBg);
// Title
var rlTitle = new Text2('Roguelike Seçimi!', {
size: 160,
fill: 0xffffff
});
rlTitle.anchor.set(0.5, 0.5);
rlTitle.x = 2048 / 2;
rlTitle.y = 900;
roguelikeOverlay.addChild(rlTitle);
// Option 1
var opt1 = new Text2(optA.name, {
size: 100,
fill: 0x00ff00
});
opt1.anchor.set(0.5, 0.5);
opt1.x = 2048 / 2;
opt1.y = 1300;
roguelikeOverlay.addChild(opt1);
var opt1desc = new Text2(optA.desc, {
size: 60,
fill: 0xffffff
});
opt1desc.anchor.set(0.5, 0.5);
opt1desc.x = 2048 / 2;
opt1desc.y = 1400;
roguelikeOverlay.addChild(opt1desc);
// Option 2
var opt2 = new Text2(optB.name, {
size: 100,
fill: 0x00bfff
});
opt2.anchor.set(0.5, 0.5);
opt2.x = 2048 / 2;
opt2.y = 1700;
roguelikeOverlay.addChild(opt2);
var opt2desc = new Text2(optB.desc, {
size: 60,
fill: 0xffffff
});
opt2desc.anchor.set(0.5, 0.5);
opt2desc.x = 2048 / 2;
opt2desc.y = 1800;
roguelikeOverlay.addChild(opt2desc);
// Add overlay to game
game.addChild(roguelikeOverlay);
// Option selection logic
roguelikeOverlay.down = function (x, y, obj) {
// Check which option was tapped
if (Math.abs(y - opt1.y) < 120) {
optA.apply();
} else if (Math.abs(y - opt2.y) < 120) {
optB.apply();
} else {
// Not on option, ignore
return;
}
// Remove overlay and resume game
roguelikeOverlay.destroy();
// Resume popup monster if it was paused
if (popupMonster && !popupMonster._destroyed) {
popupMonster.tapped = false;
}
// --- Teleport snake to center if head is near wall ---
if (snake && snake.segments.length > 0) {
var head = snake.segments[0];
// Define "near wall" as within 128px of any edge
var margin = 128;
var centerX = 1024;
var centerY = 1366;
if (head.x < margin || head.x > 2048 - margin || head.y < margin || head.y > 2732 - margin) {
// Calculate offset between all segments and head
var dx = centerX - head.x;
var dy = centerY - head.y;
for (var i = 0; i < snake.segments.length; i++) {
snake.segments[i].x += dx;
snake.segments[i].y += dy;
}
}
}
if (snake) snake.alive = true; // Resume snake movement
gameOver = false;
// After roguelike selection, spawn food or box food
spawnFood();
// Restore swipe and tap controls
game.down = function (x, y, obj) {
if (gameOver) return;
// Store initial touch for swipe direction detection
lastTouchX = x;
lastTouchY = y;
if (snake && snake.segments.length > 0) {
var head = snake.segments[0];
var bullet = new Bullet();
bullet.x = head.x;
bullet.y = head.y;
bullet.lastX = bullet.x;
// Set bullet speed and direction based on snake direction, and rotate asset accordingly
if (snake.direction === 'right') {
bullet.speedX = 32;
bullet.speedY = 0;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = 0;
} else if (snake.direction === 'left') {
bullet.speedX = -32;
bullet.speedY = 0;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI;
} else if (snake.direction === 'up') {
bullet.speedX = 0;
bullet.speedY = -32;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = -Math.PI / 2;
} else if (snake.direction === 'down') {
bullet.speedX = 0;
bullet.speedY = 32;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI / 2;
}
bullets.push(bullet);
game.addChild(bullet);
}
};
};
// Forward tap events to overlay
game.down = function (x, y, obj) {
if (roguelikeOverlay && roguelikeOverlay.down) roguelikeOverlay.down(x, y, obj);
};
// Prevent further game logic until overlay is closed
return;
}
spawnFood();
// Speed up as snake grows (slower acceleration)
if (snake.moveInterval > 6) {
snake.moveInterval--;
} else if (snake.moveInterval > 4 && LK.getScore() % 10 === 0) {
// Only speed up every 10 points when very fast
snake.moveInterval--;
}
}
// SWORD ATTACK LOGIC
if (swordActive) {
swordTimer++;
// Sword effect follows head
if (swordEffect && snake && snake.segments.length > 0) {
var head = snake.segments[0];
swordEffect.x = head.x;
swordEffect.y = head.y;
}
// Check for box food collision with sword
if (boxFoodActive && boxFoodObj && !boxFoodObj._destroyed && snake && snake.segments.length > 0) {
var head = snake.segments[0];
if (head.intersects(boxFoodObj) && !boxFoodObj.destroyedByBullet) {
// Defeat box food with sword
snake.grow();
LK.setScore(LK.getScore() + 2);
scoreTxt.setText(LK.getScore());
boxFoodObj.destroy();
boxFoodObj = null;
boxFoodActive = false;
spawnFood();
if (snake.moveInterval > 4) snake.moveInterval--;
// End sword effect
swordActive = false;
swordTimer = 0;
if (swordEffect) {
swordEffect.destroy();
swordEffect = null;
}
}
}
// Sword duration end
if (swordTimer > swordDuration) {
swordActive = false;
swordTimer = 0;
if (swordEffect) {
swordEffect.destroy();
swordEffect = null;
}
}
}
// Check box food collision
if (boxFoodActive && boxFoodObj && !boxFoodObj._destroyed) {
if (head.intersects(boxFoodObj)) {
if (boxFoodObj.destroyedByBullet) {
// Now edible
snake.grow();
var boxScore = 2;
if (typeof roguelike_boxFoodDoubleScore !== "undefined" && roguelike_boxFoodDoubleScore) boxScore *= 2;
LK.setScore(LK.getScore() + boxScore);
scoreTxt.setText(LK.getScore());
boxFoodObj.destroy();
boxFoodObj = null;
boxFoodActive = false;
spawnFood();
if (snake.moveInterval > 4) snake.moveInterval--;
} else if (!swordActive) {
// Deadly!
gameOver = true;
LK.showGameOver();
return;
}
}
}
};
// Touch controls
var lastTouchX = null;
var lastTouchY = null;
// Sword attack state
var swordActive = false;
var swordTimer = 0;
var swordDuration = 18; // ~0.3s at 60fps
// Sword attack visual (simple overlay on snake head)
var swordEffect = null;
// Main game tap: always fire bullet in snake's direction
game.down = function (x, y, obj) {
if (gameOver) return;
// Store initial touch for swipe direction detection
lastTouchX = x;
lastTouchY = y;
if (snake && snake.segments.length > 0) {
var head = snake.segments[0];
var bullet = new Bullet();
bullet.x = head.x;
bullet.y = head.y;
bullet.lastX = bullet.x;
// Set bullet speed and direction based on snake direction, and rotate asset accordingly
if (snake.direction === 'right') {
bullet.speedX = 32;
bullet.speedY = 0;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = 0;
} else if (snake.direction === 'left') {
bullet.speedX = -32;
bullet.speedY = 0;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI;
} else if (snake.direction === 'up') {
bullet.speedX = 0;
bullet.speedY = -32;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = -Math.PI / 2;
} else if (snake.direction === 'down') {
bullet.speedX = 0;
bullet.speedY = 32;
if (bullet.children && bullet.children.length > 0) bullet.children[0].rotation = Math.PI / 2;
}
bullets.push(bullet);
game.addChild(bullet);
}
};
// --- SWORD LOGIC in update (see below) ---
game.up = function (x, y, obj) {
if (lastTouchX === null || lastTouchY === null) return;
var dx = x - lastTouchX;
var dy = y - lastTouchY;
if (Math.abs(dx) > Math.abs(dy)) {
if (dx > 0 && snake.direction !== 'left') snake.nextDirection = 'right';else if (dx < 0 && snake.direction !== 'right') snake.nextDirection = 'left';
} else {
if (dy > 0 && snake.direction !== 'up') snake.nextDirection = 'down';else if (dy < 0 && snake.direction !== 'down') snake.nextDirection = 'up';
}
lastTouchX = null;
lastTouchY = null;
};
Bir top pixel art yeşil renkli. In-Game asset. 2d. High contrast. No shadows
Pixel art bullet. In-Game asset. 2d. High contrast. No shadows
Pixel art apple. In-Game asset. 2d. High contrast. No shadows
Çimen ama bütün elranı kaplıyor . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Kırmızı bir pixel art oyun tuşu. In-Game asset. 2d. High contrast. No shadows
2D pixel art para kasası. In-Game asset. High contrast. No shadows
A red MONSTER . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat