User prompt
oyuncu köylüye saldırırsa köylü oyuncudan kaçar veya saldırır
User prompt
köylüler zıplayabilir
User prompt
köylüler blok koyabilir ve kırabilir
User prompt
köylüleri öldürebilelim ve yerçekiminden etkilensin
User prompt
make villager to inventory
User prompt
make villager egg
User prompt
yeni biomlar = lav havuzları köyler (köylülerde var) mağralar
User prompt
başlangıç menüsü ekle
User prompt
oyuna farklı farklı başarımlar ekle
User prompt
oyuncu lav ve suyun içinden geçsin ve lavdan geçince efekt gelsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
su ve lav birleşince bir tepkime olsun
User prompt
başarımlar yerinin boyunu 2ye böl
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Achievement = Container.expand(function (achievementData) { var self = Container.call(this); // Background var bgGraphics = self.attachAsset('menuBg', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.6, scaleY: 0.3, alpha: 0.9 }); // Title text var titleText = new Text2('Achievement Unlocked!', { size: 36, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0.5); titleText.x = 0; titleText.y = -30; self.addChild(titleText); // Achievement name var nameText = new Text2(achievementData.name, { size: 28, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.x = 0; nameText.y = 0; self.addChild(nameText); // Achievement description var descText = new Text2(achievementData.description, { size: 22, fill: 0xCCCCCC }); descText.anchor.set(0.5, 0.5); descText.x = 0; descText.y = 25; self.addChild(descText); self.show = function () { self.alpha = 0; self.scaleX = 0.5; self.scaleY = 0.5; self.visible = true; tween(self, { alpha: 1, scaleX: 1, scaleY: 1 }, { duration: 300, easing: tween.easeOut }); // Auto hide after 3 seconds LK.setTimeout(function () { tween(self, { alpha: 0, scaleX: 0.8, scaleY: 0.8 }, { duration: 200, onFinish: function onFinish() { self.visible = false; } }); }, 3000); }; // Initially hidden self.visible = false; return self; }); var AchievementMenu = Container.expand(function () { var self = Container.call(this); self.isVisible = false; // Background var bgGraphics = self.attachAsset('menuBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 1.2, scaleY: 3.0 }); // Title text var titleText = new Text2('Achievements', { size: 48, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 0; titleText.y = -300; self.addChild(titleText); // Close button var closeButton = self.attachAsset('closeButton', { anchorX: 0.5, anchorY: 0.5 }); closeButton.x = 350; closeButton.y = -300; // Achievement list container var achievementList = new Container(); self.addChild(achievementList); // Page navigation buttons var prevPageButton = self.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8, scaleX: 0.8, scaleY: 0.5 }); prevPageButton.x = -200; prevPageButton.y = 300; var prevPageText = new Text2('PREV', { size: 28, fill: 0xFFFFFF }); prevPageText.anchor.set(0.5, 0.5); prevPageText.x = -200; prevPageText.y = 300; self.addChild(prevPageText); var nextPageButton = self.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8, scaleX: 0.8, scaleY: 0.5 }); nextPageButton.x = 200; nextPageButton.y = 300; var nextPageText = new Text2('NEXT', { size: 28, fill: 0xFFFFFF }); nextPageText.anchor.set(0.5, 0.5); nextPageText.x = 200; nextPageText.y = 300; self.addChild(nextPageText); // Page indicator text var pageIndicatorText = new Text2('', { size: 24, fill: 0xCCCCCC }); pageIndicatorText.anchor.set(0.5, 0.5); pageIndicatorText.x = 0; pageIndicatorText.y = 300; self.addChild(pageIndicatorText); self.updateAchievements = function () { // Clear existing achievement displays while (achievementList.children.length > 0) { achievementList.removeChild(achievementList.children[0]); } // Get all achievement IDs as array for pagination var allAchievementIds = []; for (var achievementId in achievementDefinitions) { allAchievementIds.push(achievementId); } // Calculate pagination var totalPages = Math.ceil(allAchievementIds.length / achievementsPerPage); var startIndex = currentAchievementPage * achievementsPerPage; var endIndex = Math.min(startIndex + achievementsPerPage, allAchievementIds.length); // Update page indicator pageIndicatorText.setText('Page ' + (currentAchievementPage + 1) + ' of ' + totalPages); // Update button visibility prevPageButton.alpha = currentAchievementPage > 0 ? 0.8 : 0.3; prevPageText.fill = currentAchievementPage > 0 ? 0xFFFFFF : 0x666666; nextPageButton.alpha = currentAchievementPage < totalPages - 1 ? 0.8 : 0.3; nextPageText.fill = currentAchievementPage < totalPages - 1 ? 0xFFFFFF : 0x666666; var yOffset = -200; var achievementIndex = 0; // Display achievements for current page for (var i = startIndex; i < endIndex; i++) { var achievementId = allAchievementIds[i]; var achievement = achievementDefinitions[achievementId]; var isUnlocked = achievements[achievementId] || false; // Achievement container var achievementContainer = new Container(); achievementContainer.y = yOffset + achievementIndex * 80; // Achievement background var achievementBg = achievementContainer.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, alpha: isUnlocked ? 0.8 : 0.3, scaleX: 2.8, scaleY: 0.6 }); // Achievement name var nameText = new Text2(achievement.name, { size: 32, fill: isUnlocked ? 0xFFD700 : 0x888888 }); nameText.anchor.set(0.5, 0.5); nameText.x = 0; nameText.y = -15; achievementContainer.addChild(nameText); // Achievement description var descText = new Text2(achievement.description, { size: 24, fill: isUnlocked ? 0xFFFFFF : 0x666666 }); descText.anchor.set(0.5, 0.5); descText.x = 0; descText.y = 10; achievementContainer.addChild(descText); // Status text var statusText = new Text2(isUnlocked ? 'UNLOCKED' : 'LOCKED', { size: 20, fill: isUnlocked ? 0x00FF00 : 0xFF4444 }); statusText.anchor.set(1, 0.5); statusText.x = 150; statusText.y = 0; achievementContainer.addChild(statusText); achievementList.addChild(achievementContainer); achievementIndex++; } }; // Page navigation interactions prevPageButton.down = function (x, y, obj) { if (currentAchievementPage > 0) { prevPageButton.alpha = 1.0; currentAchievementPage--; self.updateAchievements(); } }; prevPageButton.up = function (x, y, obj) { prevPageButton.alpha = currentAchievementPage > 0 ? 0.8 : 0.3; }; nextPageButton.down = function (x, y, obj) { var totalPages = Math.ceil(Object.keys(achievementDefinitions).length / achievementsPerPage); if (currentAchievementPage < totalPages - 1) { nextPageButton.alpha = 1.0; currentAchievementPage++; self.updateAchievements(); } }; nextPageButton.up = function (x, y, obj) { var totalPages = Math.ceil(Object.keys(achievementDefinitions).length / achievementsPerPage); nextPageButton.alpha = currentAchievementPage < totalPages - 1 ? 0.8 : 0.3; }; // Close button interaction closeButton.down = function (x, y, obj) { closeButton.alpha = 0.7; self.hide(); }; closeButton.up = function (x, y, obj) { closeButton.alpha = 1.0; }; self.show = function () { self.isVisible = true; currentAchievementPage = 0; // Reset to first page when opening self.updateAchievements(); self.alpha = 0; self.visible = true; tween(self, { alpha: 1 }, { duration: 200 }); }; self.hide = function () { self.isVisible = false; tween(self, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.visible = false; } }); }; // Initially hidden self.visible = false; return self; }); var Block = Container.expand(function (blockType) { var self = Container.call(this); self.blockType = blockType; self.gridX = 0; self.gridY = 0; var blockGraphics = self.attachAsset(blockType, { anchorX: 0.5, anchorY: 0.5 }); // Add a subtle border effect blockGraphics.alpha = 0.9; self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.y = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; }; return self; }); var BlockSelectionMenu = Container.expand(function () { var self = Container.call(this); self.isVisible = false; // Background var bgGraphics = self.attachAsset('menuBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleY: 4.0 }); // Title text var titleText = new Text2('Select Block Type', { size: 48, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 0; titleText.y = -400; self.addChild(titleText); // Close button var closeButton = self.attachAsset('closeButton', { anchorX: 0.5, anchorY: 0.5 }); closeButton.x = 280; closeButton.y = -400; // Block selection buttons self.menuButtons = []; var allBlockTypes = Object.keys(inventory); var buttonsPerRow = 3; var buttonSpacing = 160; for (var i = 0; i < allBlockTypes.length; i++) { var button = new Container(); // Button background var buttonBg = button.attachAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); // Block preview var blockPreview = button.attachAsset(allBlockTypes[i], { anchorX: 0.5, anchorY: 0.5, scaleX: 0.9, scaleY: 0.9 }); // Block name text var nameText = new Text2(allBlockTypes[i], { size: 26, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0); nameText.x = 0; nameText.y = 45; button.addChild(nameText); // Inventory count text var countText = new Text2(inventory[allBlockTypes[i]].toString(), { size: 24, fill: 0xFFDD44 }); countText.anchor.set(0.5, 0); countText.x = 0; countText.y = 65; button.addChild(countText); // Position button var col = i % buttonsPerRow; var row = Math.floor(i / buttonsPerRow); button.x = (col - 1) * buttonSpacing; button.y = row * buttonSpacing - 30; // Store button data button.blockType = allBlockTypes[i]; button.bgGraphics = buttonBg; button.countText = countText; // Button interaction button.down = function (x, y, obj) { this.bgGraphics.alpha = 1.0; selectedBlockType = this.blockType; updateToolbarSelection(); self.hide(); }; button.up = function (x, y, obj) { this.bgGraphics.alpha = 0.8; }; self.menuButtons.push(button); self.addChild(button); } // Close button interaction closeButton.down = function (x, y, obj) { closeButton.alpha = 0.7; self.hide(); }; closeButton.up = function (x, y, obj) { closeButton.alpha = 1.0; }; self.show = function () { self.isVisible = true; self.alpha = 0; self.visible = true; tween(self, { alpha: 1 }, { duration: 200 }); }; self.hide = function () { self.isVisible = false; tween(self, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.visible = false; } }); }; self.updateInventoryCounts = function () { for (var i = 0; i < self.menuButtons.length; i++) { var button = self.menuButtons[i]; if (button.countText && button.blockType) { button.countText.setText(inventory[button.blockType].toString()); } } }; // Initially hidden self.visible = false; return self; }); var Character = Container.expand(function () { var self = Container.call(this); var characterGraphics = self.attachAsset('character', { anchorX: 0.5, anchorY: 0.5 }); self.gridX = 0; self.gridY = 0; self.targetX = 0; self.targetY = 0; self.isMoving = false; self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.targetX = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.targetY = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; if (!self.isMoving) { self.x = self.targetX; self.y = self.targetY; } }; self.moveToGrid = function (gridX, gridY) { if (self.isMoving) return false; if (!isValidGridPosition(gridX, gridY)) return false; // Check if there's a block at the target position (only block movement if not flying) if (!isFlying && grid[gridX] && grid[gridX][gridY] !== null) return false; self.isMoving = true; self.gridX = gridX; self.gridY = gridY; self.targetX = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.targetY = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; // Reset gravity when manually moving (especially important in flying mode) if (isFlying) { characterGravity = 0; } // Adjust movement speed based on flying state var moveDuration = isFlying ? 100 : 200; tween(self, { x: self.targetX, y: self.targetY }, { duration: moveDuration, easing: isFlying ? tween.easeOut : tween.easeInOut, onFinish: function onFinish() { self.isMoving = false; // Track movement for achievements moveCount++; storage.moveCount = moveCount; // Track jumping (moving up) for boooing achievement if (gridY < self.gridY) { jumpCount++; storage.jumpCount = jumpCount; } checkAllAchievements(); } }); return true; }; self.update = function () { // Reset gravity when flying - do this first if (isFlying) { characterGravity = 0; } else { // Apply gravity if character is not moving, not supported, and not flying if (!self.isMoving) { var hasSupport = false; // Check if character has support below (block or ground) var belowY = self.gridY + 1; if (belowY >= GRID_HEIGHT) { // At bottom of world, has support hasSupport = true; } else if (grid[self.gridX] && grid[self.gridX][belowY] !== null) { // Block below, has support hasSupport = true; } if (!hasSupport) { // Character should fall characterGravity += characterGravityAcceleration; if (characterGravity > characterMaxFallSpeed) { characterGravity = characterMaxFallSpeed; } // Find where character should fall to var fallToY = self.gridY; for (var checkY = self.gridY + 1; checkY < GRID_HEIGHT; checkY++) { if (grid[self.gridX][checkY] !== null) { break; } fallToY = checkY; } // Move character down if there's a place to fall if (fallToY > self.gridY) { var targetY = Math.min(fallToY, self.gridY + Math.floor(characterGravity)); if (targetY !== self.gridY) { self.moveToGrid(self.gridX, targetY); } } } else { // Character has support, reset gravity characterGravity = 0; } } } // Check if character is touching a portal if (!self.isMoving) { for (var i = 0; i < placedBlocks.length; i++) { var block = placedBlocks[i]; if (block.blockType === 'portal' && block.gridX === self.gridX && block.gridY === self.gridY) { block.teleportCharacter(); break; } } } // Character is always on top if (self.parent) { var parent = self.parent; parent.removeChild(self); parent.addChild(self); } }; return self; }); var ControlButton = Container.expand(function (direction) { var self = Container.call(this); self.direction = direction; var bgGraphics = self.attachAsset('controlBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); var arrowGraphics = self.attachAsset('arrow' + direction.charAt(0).toUpperCase() + direction.slice(1), { anchorX: 0.5, anchorY: 0.5, scaleX: 0.7, scaleY: 0.7 }); self.down = function (x, y, obj) { bgGraphics.alpha = 1.0; var newX = character.gridX; var newY = character.gridY; if (direction === 'up') newY--;else if (direction === 'down') newY++;else if (direction === 'left') newX--;else if (direction === 'right') newX++; character.moveToGrid(newX, newY); }; self.up = function (x, y, obj) { bgGraphics.alpha = 0.7; }; return self; }); var GridCell = Container.expand(function () { var self = Container.call(this); var cellGraphics = self.attachAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, alpha: 0.1 }); self.gridX = 0; self.gridY = 0; self.isEmpty = true; self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.y = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; }; self.highlight = function () { cellGraphics.alpha = 0.3; }; self.unhighlight = function () { cellGraphics.alpha = 0.1; }; return self; }); var Lava = Container.expand(function () { var self = Container.call(this); self.blockType = 'lava'; self.gridX = 0; self.gridY = 0; self.isFlowing = false; self.flowCooldown = 0; self.damageTimer = 0; var lavaGraphics = self.attachAsset('lava', { anchorX: 0.5, anchorY: 0.5 }); // Add glowing effect lavaGraphics.alpha = 0.9; self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.y = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; }; self.update = function () { // Pulsing glow effect lavaGraphics.alpha = 0.8 + Math.sin(LK.ticks * 0.15) * 0.15; lavaGraphics.tint = 0xff4500 + Math.floor(Math.sin(LK.ticks * 0.1) * 20) * 0x010000; // Handle damage to character if (character && character.gridX === self.gridX && character.gridY === self.gridY && !character.isMoving) { self.damageTimer++; if (self.damageTimer >= 60) { // 1 second of contact // Flash character red and teleport away from lava LK.effects.flashObject(character, 0xff0000, 500); LK.effects.flashScreen(0xff0000, 300); // Move character to nearest safe position self.teleportCharacterToSafety(); self.damageTimer = 0; } } else { self.damageTimer = 0; } // Lava flowing mechanics disabled - no spreading // if (self.flowCooldown > 0) { // self.flowCooldown--; // } else { // self.tryToFlow(); // self.flowCooldown = 120; // Flow every 2 seconds // } }; self.teleportCharacterToSafety = function () { // Find nearest safe position var safePositions = []; for (var radius = 1; radius <= 5; radius++) { for (var dx = -radius; dx <= radius; dx++) { for (var dy = -radius; dy <= radius; dy++) { var checkX = self.gridX + dx; var checkY = self.gridY + dy; if (isValidGridPosition(checkX, checkY) && grid[checkX][checkY] === null) { // Check if position has ground support below var hasSupport = false; if (checkY + 1 >= GRID_HEIGHT) { hasSupport = true; } else if (grid[checkX][checkY + 1] !== null && grid[checkX][checkY + 1].blockType !== 'lava') { hasSupport = true; } if (hasSupport) { safePositions.push({ x: checkX, y: checkY }); } } } } if (safePositions.length > 0) break; } if (safePositions.length > 0) { var safePos = safePositions[0]; // Take closest safe position character.setGridPosition(safePos.x, safePos.y); } }; self.tryToFlow = function () { // Lava flows down first, then horizontally var flowDirections = [{ x: 0, y: 1 }, // Down { x: -1, y: 0 }, // Left { x: 1, y: 0 }, // Right { x: -1, y: 1 }, // Down-left { x: 1, y: 1 } // Down-right ]; for (var i = 0; i < flowDirections.length; i++) { var dir = flowDirections[i]; var targetX = self.gridX + dir.x; var targetY = self.gridY + dir.y; if (isValidGridPosition(targetX, targetY) && grid[targetX][targetY] === null) { // Only flow if there are less than 3 lava blocks already var nearbyLavaCount = 0; for (var checkX = targetX - 1; checkX <= targetX + 1; checkX++) { for (var checkY = targetY - 1; checkY <= targetY + 1; checkY++) { if (isValidGridPosition(checkX, checkY) && grid[checkX][checkY] !== null && grid[checkX][checkY].blockType === 'lava') { nearbyLavaCount++; } } } if (nearbyLavaCount < 3) { // Create new lava block var newLava = new Lava(); newLava.setGridPosition(targetX, targetY); game.addChild(newLava); grid[targetX][targetY] = newLava; placedBlocks.push(newLava); LK.effects.flashObject(newLava, 0xffff00, 300); break; } } } }; return self; }); var Portal = Container.expand(function () { var self = Container.call(this); self.blockType = 'portal'; self.gridX = 0; self.gridY = 0; self.isActive = true; self.cooldownTime = 0; var portalGraphics = self.attachAsset('portal', { anchorX: 0.5, anchorY: 0.5 }); // Add glowing effect portalGraphics.alpha = 0.8; self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.y = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; }; self.teleportCharacter = function () { if (!self.isActive || self.cooldownTime > 0) return false; if (!character || character.isMoving) return false; // Find all other active portals var otherPortals = []; for (var i = 0; i < placedBlocks.length; i++) { var block = placedBlocks[i]; if (block !== self && block.blockType === 'portal' && block.isActive && block.cooldownTime <= 0) { otherPortals.push(block); } } if (otherPortals.length === 0) { // No other portals available - teleport to heaven! // Create heaven effect with golden background and clouds game.setBackgroundColor(0xFFD700); // Golden sky // Flash screen with heavenly light LK.effects.flashScreen(0xFFFFFF, 2000); // Teleport character to top of world center var heavenX = Math.floor(GRID_WIDTH / 2); var heavenY = 0; // Top of the world character.setGridPosition(heavenX, heavenY); // Add visual effects LK.effects.flashObject(self, 0xFFD700, 1000); LK.effects.flashObject(character, 0xFFFFFF, 1000); // Play portal sound LK.getSound('portal').play(); // Set cooldown self.cooldownTime = 300; // 5 seconds cooldown // Reset background after effect LK.setTimeout(function () { game.setBackgroundColor(0x87CEEB); // Back to sky blue }, 3000); return true; } // Choose random portal to teleport to var targetPortal = otherPortals[Math.floor(Math.random() * otherPortals.length)]; // Teleport character character.setGridPosition(targetPortal.gridX, targetPortal.gridY); // Add visual effects LK.effects.flashObject(self, 0x9400d3, 500); LK.effects.flashObject(targetPortal, 0x9400d3, 500); LK.effects.flashObject(character, 0x00ffff, 300); // Play portal sound LK.getSound('portal').play(); // Set cooldown for both portals self.cooldownTime = 180; // 3 seconds at 60fps targetPortal.cooldownTime = 180; return true; }; self.update = function () { // Handle cooldown if (self.cooldownTime > 0) { self.cooldownTime--; portalGraphics.alpha = 0.3 + self.cooldownTime / 180 * 0.5; } else { portalGraphics.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2; // Pulsing effect } // Check if character is on portal if (character && character.gridX === self.gridX && character.gridY === self.gridY && !character.isMoving) { self.teleportCharacter(); } }; return self; }); var Sand = Container.expand(function () { var self = Container.call(this); self.blockType = 'sand'; self.gridX = 0; self.gridY = 0; self.isFalling = false; self.fallSpeed = 0; self.maxFallSpeed = 8; self.fallAcceleration = 0.8; var sandGraphics = self.attachAsset('sand', { anchorX: 0.5, anchorY: 0.5 }); self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.y = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; }; self.update = function () { // Check if sand should fall if (!self.isFalling) { var hasSupport = false; var belowY = self.gridY + 1; // Check if at bottom or has block below if (belowY >= GRID_HEIGHT) { hasSupport = true; } else if (grid[self.gridX] && grid[self.gridX][belowY] !== null) { hasSupport = true; } // Start falling if no support if (!hasSupport) { self.isFalling = true; self.fallSpeed = 0; } } // Handle falling physics if (self.isFalling) { self.fallSpeed += self.fallAcceleration; if (self.fallSpeed > self.maxFallSpeed) { self.fallSpeed = self.maxFallSpeed; } // Calculate new grid position var newGridY = self.gridY + Math.floor(self.fallSpeed / 4); // Check if we can fall to new position if (newGridY < GRID_HEIGHT && (grid[self.gridX][newGridY] === null || grid[self.gridX][newGridY] === self)) { // Update grid if (grid[self.gridX][self.gridY] === self) { grid[self.gridX][self.gridY] = null; } self.gridY = newGridY; grid[self.gridX][self.gridY] = self; self.setGridPosition(self.gridX, self.gridY); } else { // Stop falling - hit something or reached bottom self.isFalling = false; self.fallSpeed = 0; } } }; return self; }); var ToolbarButton = Container.expand(function (blockType) { var self = Container.call(this); self.blockType = blockType; self.isSelected = false; var bgGraphics = self.attachAsset('toolbarBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); var blockGraphics = self.attachAsset(blockType, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); var selectedBorder = self.attachAsset('selectedBorder', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.setSelected = function (selected) { self.isSelected = selected; selectedBorder.alpha = selected ? 0.8 : 0; bgGraphics.alpha = selected ? 1.0 : 0.8; }; self.down = function (x, y, obj) { selectedBlockType = self.blockType; updateToolbarSelection(); }; return self; }); var Water = Container.expand(function () { var self = Container.call(this); self.blockType = 'water'; self.gridX = 0; self.gridY = 0; self.isFlowing = false; self.flowCooldown = 0; var waterGraphics = self.attachAsset('water', { anchorX: 0.5, anchorY: 0.5 }); // Add water effects waterGraphics.alpha = 0.7; // Semi-transparent water self.setGridPosition = function (gridX, gridY) { self.gridX = gridX; self.gridY = gridY; self.x = gridX * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_X; self.y = gridY * GRID_SIZE + GRID_SIZE / 2 + GRID_OFFSET_Y; }; self.update = function () { // Gentle wave effect waterGraphics.alpha = 0.6 + Math.sin(LK.ticks * 0.08) * 0.1; waterGraphics.tint = 0x4169e1 + Math.floor(Math.sin(LK.ticks * 0.05) * 10) * 0x000100; // Check for lava collision in adjacent positions var checkPositions = [{ x: self.gridX - 1, y: self.gridY }, // Left { x: self.gridX + 1, y: self.gridY }, // Right { x: self.gridX, y: self.gridY - 1 }, // Up { x: self.gridX, y: self.gridY + 1 }, // Down { x: self.gridX - 1, y: self.gridY - 1 }, // Up-left { x: self.gridX + 1, y: self.gridY - 1 }, // Up-right { x: self.gridX - 1, y: self.gridY + 1 }, // Down-left { x: self.gridX + 1, y: self.gridY + 1 } // Down-right ]; for (var i = 0; i < checkPositions.length; i++) { var pos = checkPositions[i]; if (isValidGridPosition(pos.x, pos.y) && grid[pos.x][pos.y] !== null) { var adjacentBlock = grid[pos.x][pos.y]; if (adjacentBlock.blockType === 'lava') { // Water and lava reaction - create steam explosion effect LK.effects.flashScreen(0xFFFFFF, 800); LK.effects.flashObject(self, 0xFFFFFF, 600); LK.effects.flashObject(adjacentBlock, 0xFFFFFF, 600); // Create stone block at water position var stoneBlock = new Block('stone'); stoneBlock.setGridPosition(self.gridX, self.gridY); game.addChild(stoneBlock); grid[self.gridX][self.gridY] = stoneBlock; placedBlocks.push(stoneBlock); // Remove water block self.destroy(); for (var j = placedBlocks.length - 1; j >= 0; j--) { if (placedBlocks[j] === self) { placedBlocks.splice(j, 1); break; } } // Remove lava block adjacentBlock.destroy(); grid[pos.x][pos.y] = null; for (var k = placedBlocks.length - 1; k >= 0; k--) { if (placedBlocks[k] === adjacentBlock) { placedBlocks.splice(k, 1); break; } } // Create stone block at lava position too var stoneBlock2 = new Block('stone'); stoneBlock2.setGridPosition(pos.x, pos.y); game.addChild(stoneBlock2); grid[pos.x][pos.y] = stoneBlock2; placedBlocks.push(stoneBlock2); // Play reaction sound LK.getSound('break').play(); return; // Exit after reaction } } } // Water flowing mechanics disabled - no spreading // if (self.flowCooldown > 0) { // self.flowCooldown--; // } else { // self.tryToFlow(); // self.flowCooldown = 90; // Flow every 1.5 seconds // } }; self.tryToFlow = function () { // Water flows down first, then horizontally var flowDirections = [{ x: 0, y: 1 }, // Down { x: -1, y: 0 }, // Left { x: 1, y: 0 }, // Right { x: -1, y: 1 }, // Down-left { x: 1, y: 1 } // Down-right ]; for (var i = 0; i < flowDirections.length; i++) { var dir = flowDirections[i]; var targetX = self.gridX + dir.x; var targetY = self.gridY + dir.y; if (isValidGridPosition(targetX, targetY) && grid[targetX][targetY] === null) { // Only flow if there are less than 4 water blocks nearby var nearbyWaterCount = 0; for (var checkX = targetX - 1; checkX <= targetX + 1; checkX++) { for (var checkY = targetY - 1; checkY <= targetY + 1; checkY++) { if (isValidGridPosition(checkX, checkY) && grid[checkX][checkY] !== null && grid[checkX][checkY].blockType === 'water') { nearbyWaterCount++; } } } if (nearbyWaterCount < 4) { // Create new water block var newWater = new Water(); newWater.setGridPosition(targetX, targetY); game.addChild(newWater); grid[targetX][targetY] = newWater; placedBlocks.push(newWater); LK.effects.flashObject(newWater, 0x87ceeb, 300); break; } } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var GRID_SIZE = 80; var GRID_WIDTH = 20; var GRID_HEIGHT = 20; var GRID_OFFSET_X = (2048 - GRID_WIDTH * GRID_SIZE) / 2; var GRID_OFFSET_Y = 200; var selectedBlockType = 'dirt'; var blockTypes = ['dirt', 'stone', 'wood', 'grass', 'grassDark', 'grassLight', 'sand', 'diamond', 'gold', 'portal', 'lava', 'water']; var inventory = { dirt: 50, stone: 30, wood: 25, grass: 20, grassDark: 15, grassLight: 15, sand: 25, diamond: 5, gold: 8, portal: 3, lava: 10, water: 15 }; // Achievement system var achievements = storage.achievements || {}; var currentAchievementPage = 0; var achievementsPerPage = 8; var achievementDefinitions = { firstBlock: { name: "First Builder", description: "Place your first block", unlocked: false }, destroyer: { name: "Destroyer", description: "Break 10 blocks", unlocked: false }, architect: { name: "Architect", description: "Place 50 blocks", unlocked: false }, miner: { name: "Miner", description: "Break 50 blocks", unlocked: false }, collector: { name: "Collector", description: "Collect all block types", unlocked: false }, explorer: { name: "Explorer", description: "Move 100 times", unlocked: false }, masterBuilder: { name: "Master Builder", description: "Place 200 blocks", unlocked: false }, demolitionExpert: { name: "Demolition Expert", description: "Break 200 blocks", unlocked: false }, goldRush: { name: "Gold Rush", description: "Collect 20 gold blocks", unlocked: false }, diamondCollector: { name: "Diamond Collector", description: "Collect 15 diamond blocks", unlocked: false }, woodsman: { name: "Woodsman", description: "Collect 100 wood blocks", unlocked: false }, stoneAge: { name: "Stone Age", description: "Collect 150 stone blocks", unlocked: false }, adventurer: { name: "Adventurer", description: "Move 500 times", unlocked: false }, nomad: { name: "Nomad", description: "Move 1000 times", unlocked: false }, flightTime: { name: "Taking Flight", description: "Use flying mode 10 times", unlocked: false }, skyExplorer: { name: "Sky Explorer", description: "Spend 60 seconds in flying mode", unlocked: false }, areCrazy: { name: "are you crazy?", description: "Break each block type 10 times", unlocked: false }, boooing: { name: "boooing", description: "Jump 100 times", unlocked: false }, lavaLord: { name: "Lava Lord", description: "Place 25 lava blocks", unlocked: false }, waterMaster: { name: "Water Master", description: "Place 30 water blocks", unlocked: false } }; // Achievement counters var blocksPlaced = storage.blocksPlaced || 0; var blocksBroken = storage.blocksBroken || 0; var moveCount = storage.moveCount || 0; var goldCollected = storage.goldCollected || 0; var diamondCollected = storage.diamondCollected || 0; var woodCollected = storage.woodCollected || 0; var stoneCollected = storage.stoneCollected || 0; var flyingActivations = storage.flyingActivations || 0; var flyingStartTime = 0; var totalFlyingTime = storage.totalFlyingTime || 0; var blockTypeBrokenCount = storage.blockTypeBrokenCount || {}; var jumpCount = storage.jumpCount || 0; var lavaPlaced = storage.lavaPlaced || 0; var waterPlaced = storage.waterPlaced || 0; var grid = []; var placedBlocks = []; var toolbarButtons = []; var controlButtons = []; var pressTimer = null; var isLongPress = false; var pressStartTime = 0; var character = null; var blockSelectionMenu = null; var menuButton = null; var achievementNotification = null; var achievementMenu = null; var characterGravity = 0; // Current falling speed var characterMaxFallSpeed = 8; // Maximum falling speed var characterGravityAcceleration = 0.5; // How fast gravity accelerates var isFlying = false; // Flying mode toggle var flyingSpeed = 4; // Speed when flying var flyingVerticalSpeed = 3; // Vertical movement speed when flying function checkAchievement(achievementId) { if (achievements[achievementId]) return; var achieved = false; switch (achievementId) { case 'firstBlock': achieved = blocksPlaced >= 1; break; case 'destroyer': achieved = blocksBroken >= 10; break; case 'architect': achieved = blocksPlaced >= 50; break; case 'miner': achieved = blocksBroken >= 50; break; case 'collector': // Check if player has collected all block types var hasAllTypes = true; for (var blockType in inventory) { if (inventory[blockType] <= 0) { hasAllTypes = false; break; } } achieved = hasAllTypes; break; case 'explorer': achieved = moveCount >= 100; break; case 'masterBuilder': achieved = blocksPlaced >= 200; break; case 'demolitionExpert': achieved = blocksBroken >= 200; break; case 'goldRush': achieved = goldCollected >= 20; break; case 'diamondCollector': achieved = diamondCollected >= 15; break; case 'woodsman': achieved = woodCollected >= 100; break; case 'stoneAge': achieved = stoneCollected >= 150; break; case 'adventurer': achieved = moveCount >= 500; break; case 'nomad': achieved = moveCount >= 1000; break; case 'flightTime': achieved = flyingActivations >= 10; break; case 'skyExplorer': achieved = totalFlyingTime >= 60000; // 60 seconds in milliseconds break; case 'areCrazy': // Check if each block type has been broken at least 10 times achieved = true; for (var i = 0; i < blockTypes.length; i++) { var blockType = blockTypes[i]; var brokenCount = blockTypeBrokenCount[blockType] || 0; if (brokenCount < 10) { achieved = false; break; } } break; case 'boooing': achieved = jumpCount >= 100; break; case 'lavaLord': achieved = lavaPlaced >= 25; break; case 'waterMaster': achieved = waterPlaced >= 30; break; } if (achieved) { unlockAchievement(achievementId); } } function unlockAchievement(achievementId) { if (achievements[achievementId]) return; achievements[achievementId] = true; storage.achievements = achievements; // Update the achievement menu to show the newly unlocked achievement if (achievementMenu) { achievementMenu.updateAchievements(); // Show the achievement menu temporarily if not already visible if (!achievementMenu.isVisible) { achievementMenu.show(); // Auto-hide after a few seconds LK.setTimeout(function () { if (achievementMenu && achievementMenu.isVisible) { achievementMenu.hide(); } }, 3000); } } } function checkAllAchievements() { for (var achievementId in achievementDefinitions) { checkAchievement(achievementId); } } // Initialize grid for (var x = 0; x < GRID_WIDTH; x++) { grid[x] = []; for (var y = 0; y < GRID_HEIGHT; y++) { grid[x][y] = null; var gridCell = new GridCell(); gridCell.setGridPosition(x, y); game.addChild(gridCell); } } // Initialize character at top of world character = new Character(); var randomX = Math.floor(Math.random() * GRID_WIDTH); var topY = 0; // Always start at the very top character.setGridPosition(randomX, topY); game.addChild(character); // Create block selection menu blockSelectionMenu = new BlockSelectionMenu(); blockSelectionMenu.x = 1024; blockSelectionMenu.y = 800; LK.gui.addChild(blockSelectionMenu); // Create achievement menu at top layer achievementMenu = new AchievementMenu(); achievementMenu.x = 1024; achievementMenu.y = 400; LK.gui.addChild(achievementMenu); // Create menu button menuButton = new Container(); var menuBg = menuButton.attachAsset('toolbarBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); var menuText = new Text2('MENU', { size: 36, fill: 0xFFFFFF }); menuText.anchor.set(0.5, 0.5); menuText.x = 0; menuText.y = 0; menuButton.addChild(menuText); menuButton.x = 2048 - 80; menuButton.y = 150; menuButton.down = function (x, y, obj) { menuBg.alpha = 1.0; if (!blockSelectionMenu.isVisible) { blockSelectionMenu.show(); } }; menuButton.up = function (x, y, obj) { menuBg.alpha = 0.8; }; game.addChild(menuButton); // Create achievements button at the top var achievementsButton = new Container(); var achievementsBg = achievementsButton.attachAsset('toolbarBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); var achievementsText = new Text2('ACHIEVEMENTS', { size: 28, fill: 0xFFFFFF }); achievementsText.anchor.set(0.5, 0.5); achievementsText.x = 0; achievementsText.y = 0; achievementsButton.addChild(achievementsText); achievementsButton.x = 1024; achievementsButton.y = 50; achievementsButton.down = function (x, y, obj) { achievementsBg.alpha = 1.0; if (!achievementMenu.isVisible) { achievementMenu.show(); } }; achievementsButton.up = function (x, y, obj) { achievementsBg.alpha = 0.8; }; game.addChild(achievementsButton); // Create flying toggle button var flyingButton = new Container(); var flyingBg = flyingButton.attachAsset('toolbarBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); var flyingText = new Text2('FLY', { size: 32, fill: 0xFFFFFF }); flyingText.anchor.set(0.5, 0.5); flyingText.x = 0; flyingText.y = 0; flyingButton.addChild(flyingText); flyingButton.x = 2048 - 80; flyingButton.y = 350; flyingButton.down = function (x, y, obj) { flyingBg.alpha = 1.0; // Toggle flying mode var wasFlying = isFlying; isFlying = !isFlying; // Track flying time and activations if (isFlying && !wasFlying) { // Started flying flyingActivations++; storage.flyingActivations = flyingActivations; flyingStartTime = LK.ticks; checkAllAchievements(); } else if (!isFlying && wasFlying) { // Stopped flying if (flyingStartTime > 0) { var flyingDuration = (LK.ticks - flyingStartTime) * (1000 / 60); // Convert ticks to milliseconds totalFlyingTime += flyingDuration; storage.totalFlyingTime = totalFlyingTime; flyingStartTime = 0; checkAllAchievements(); } } // Update button appearance - recreate the background with new color flyingButton.removeChild(flyingBg); flyingBg = flyingButton.attachAsset('toolbarBg', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0 }); if (isFlying) { flyingBg.tint = 0x00FF00; } else { flyingBg.tint = 0xFFFFFF; } flyingText.setText(isFlying ? 'LAND' : 'FLY'); // Visual feedback if (isFlying) { LK.effects.flashObject(character, 0x00FFFF, 500); } }; flyingButton.up = function (x, y, obj) { flyingBg.alpha = 0.8; }; game.addChild(flyingButton); // Create flying status display var flyingStatusText = new Text2('', { size: 28, fill: 0x00FFFF }); flyingStatusText.anchor.set(0.5, 0); flyingStatusText.x = 1024; flyingStatusText.y = 100; LK.gui.addChild(flyingStatusText); // Create toolbar var toolbarY = 2732 - 120; var toolbarStartX = (2048 - blockTypes.length * 120) / 2; for (var i = 0; i < blockTypes.length; i++) { var button = new ToolbarButton(blockTypes[i]); button.x = toolbarStartX + i * 120 + 60; button.y = toolbarY; toolbarButtons.push(button); LK.gui.addChild(button); } // Create inventory display var inventoryTexts = {}; for (var i = 0; i < blockTypes.length; i++) { var blockType = blockTypes[i]; var inventoryText = new Text2(inventory[blockType].toString(), { size: 36, fill: 0xFFFFFF }); inventoryText.anchor.set(0.5, 0); inventoryText.x = toolbarStartX + i * 120 + 60; inventoryText.y = toolbarY + 60; inventoryTexts[blockType] = inventoryText; LK.gui.addChild(inventoryText); } // Create control buttons var controlButtonSize = 100; var controlPadding = 20; var controlCenterX = 150; var controlCenterY = GRID_OFFSET_Y + GRID_HEIGHT * GRID_SIZE + 150; var directions = [{ dir: 'up', x: 0, y: -1 }, { dir: 'down', x: 0, y: 1 }, { dir: 'left', x: -1, y: 0 }, { dir: 'right', x: 1, y: 0 }]; for (var i = 0; i < directions.length; i++) { var dirInfo = directions[i]; var button = new ControlButton(dirInfo.dir); button.x = controlCenterX + dirInfo.x * (controlButtonSize + controlPadding); button.y = controlCenterY + dirInfo.y * (controlButtonSize + controlPadding); controlButtons.push(button); game.addChild(button); } function updateToolbarSelection() { for (var i = 0; i < toolbarButtons.length; i++) { toolbarButtons[i].setSelected(toolbarButtons[i].blockType === selectedBlockType); } } function updateInventoryDisplay() { for (var blockType in inventoryTexts) { inventoryTexts[blockType].setText(inventory[blockType].toString()); } // Update block selection menu inventory counts if (blockSelectionMenu) { blockSelectionMenu.updateInventoryCounts(); } } function getGridPosition(worldX, worldY) { var gridX = Math.floor((worldX - GRID_OFFSET_X) / GRID_SIZE); var gridY = Math.floor((worldY - GRID_OFFSET_Y) / GRID_SIZE); return { x: gridX, y: gridY }; } function isValidGridPosition(gridX, gridY) { return gridX >= 0 && gridX < GRID_WIDTH && gridY >= 0 && gridY < GRID_HEIGHT; } function placeBlock(gridX, gridY) { if (!isValidGridPosition(gridX, gridY)) return false; if (grid[gridX][gridY] !== null) return false; if (inventory[selectedBlockType] <= 0) return false; // Don't place block on character position if (character && gridX === character.gridX && gridY === character.gridY) return false; var block; if (selectedBlockType === 'sand') { block = new Sand(); } else if (selectedBlockType === 'portal') { block = new Portal(); } else if (selectedBlockType === 'lava') { block = new Lava(); } else if (selectedBlockType === 'water') { block = new Water(); } else { block = new Block(selectedBlockType); } block.setGridPosition(gridX, gridY); game.addChild(block); grid[gridX][gridY] = block; placedBlocks.push(block); inventory[selectedBlockType]--; updateInventoryDisplay(); LK.getSound('place').play(); // Track achievement progress blocksPlaced++; storage.blocksPlaced = blocksPlaced; // Track lava placement for achievement if (selectedBlockType === 'lava') { lavaPlaced++; storage.lavaPlaced = lavaPlaced; } // Track water placement for achievement if (selectedBlockType === 'water') { waterPlaced++; storage.waterPlaced = waterPlaced; } checkAllAchievements(); return true; } function removeBlock(gridX, gridY) { if (!isValidGridPosition(gridX, gridY)) return false; if (grid[gridX][gridY] === null) return false; var block = grid[gridX][gridY]; var blockType = block.blockType; // If breaking a portal, teleport character to heaven biome if (blockType === 'portal') { // Transition to heaven biome permanently game.setBackgroundColor(0xFFD700); // Golden heaven sky // Flash screen with heavenly light LK.effects.flashScreen(0xFFFFFF, 2000); // Teleport character to top of world center var heavenX = Math.floor(GRID_WIDTH / 2); var heavenY = 0; // Top of the world character.setGridPosition(heavenX, heavenY); // Add visual effects LK.effects.flashObject(block, 0xFFD700, 1000); LK.effects.flashObject(character, 0xFFFFFF, 1000); // Play portal sound LK.getSound('portal').play(); // Clear all existing blocks to create clean heaven environment for (var x = 0; x < GRID_WIDTH; x++) { for (var y = 0; y < GRID_HEIGHT; y++) { if (grid[x][y] !== null && grid[x][y] !== block) { var existingBlock = grid[x][y]; existingBlock.destroy(); grid[x][y] = null; // Remove from placedBlocks array for (var j = placedBlocks.length - 1; j >= 0; j--) { if (placedBlocks[j] === existingBlock) { placedBlocks.splice(j, 1); break; } } } } } // Generate heaven environment with golden blocks and clouds selectedBlockType = 'gold'; // Create golden platform in heaven var heavenPlatformY = Math.floor(GRID_HEIGHT * 0.8); for (var x = 0; x < GRID_WIDTH; x++) { placeBlock(x, heavenPlatformY); if (Math.random() < 0.3) { placeBlock(x, heavenPlatformY - 1); // Add some elevation } } // Add diamond clouds scattered around selectedBlockType = 'diamond'; for (var i = 0; i < 15; i++) { var cloudX = Math.floor(Math.random() * GRID_WIDTH); var cloudY = Math.floor(Math.random() * heavenPlatformY * 0.7); if (isValidGridPosition(cloudX, cloudY) && grid[cloudX][cloudY] === null) { placeBlock(cloudX, cloudY); } } // Reset selection selectedBlockType = 'dirt'; updateToolbarSelection(); } // Create particle effects - multiple small pieces flying out for (var p = 0; p < 6; p++) { var particle = new Container(); var particleGraphics = particle.attachAsset(blockType, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.3, scaleY: 0.3 }); particle.x = block.x; particle.y = block.y; game.addChild(particle); // Random direction for each particle var angle = p / 6 * Math.PI * 2 + (Math.random() - 0.5) * 0.5; var speed = 100 + Math.random() * 80; var targetX = particle.x + Math.cos(angle) * speed; var targetY = particle.y + Math.sin(angle) * speed; // Animate particle flying out and fading tween(particle, { x: targetX, y: targetY, scaleX: 0.1, scaleY: 0.1, alpha: 0, rotation: Math.random() * Math.PI * 2 }, { duration: 300 + Math.random() * 200, easing: tween.easeOut, onFinish: function onFinish() { particle.destroy(); } }); } // Add breaking animation with flash effect and rotation LK.effects.flashObject(block, 0xFFFFFF, 200); // Add screen shake effect for impact var originalX = game.x; var originalY = game.y; var shakeIntensity = 8; tween(game, { x: originalX + shakeIntensity }, { duration: 30, easing: tween.easeOut }); LK.setTimeout(function () { tween(game, { x: originalX - shakeIntensity }, { duration: 30, easing: tween.easeOut }); }, 30); LK.setTimeout(function () { tween(game, { x: originalX, y: originalY }, { duration: 40, easing: tween.easeOut }); }, 60); // Remove from placedBlocks array for (var i = placedBlocks.length - 1; i >= 0; i--) { if (placedBlocks[i] === block) { placedBlocks.splice(i, 1); break; } } // Animate block destruction with scaling and rotation tween(block, { scaleX: 0, scaleY: 0, alpha: 0, rotation: Math.PI * 0.5 }, { duration: 150, easing: tween.easeIn, onFinish: function onFinish() { block.destroy(); } }); grid[gridX][gridY] = null; inventory[blockType]++; updateInventoryDisplay(); LK.getSound('break').play(); // Track achievement progress blocksBroken++; storage.blocksBroken = blocksBroken; // Track specific resource collection if (blockType === 'gold') { goldCollected++; storage.goldCollected = goldCollected; } else if (blockType === 'diamond') { diamondCollected++; storage.diamondCollected = diamondCollected; } else if (blockType === 'wood') { woodCollected++; storage.woodCollected = woodCollected; } else if (blockType === 'stone') { stoneCollected++; storage.stoneCollected = stoneCollected; } // Track block type breaking for 'are you crazy?' achievement if (!blockTypeBrokenCount[blockType]) { blockTypeBrokenCount[blockType] = 0; } blockTypeBrokenCount[blockType]++; storage.blockTypeBrokenCount = blockTypeBrokenCount; checkAllAchievements(); return true; } // Initialize toolbar selection updateToolbarSelection(); updateInventoryDisplay(); game.down = function (x, y, obj) { var gridPos = getGridPosition(x, y); pressStartTime = LK.ticks; isLongPress = false; // Start long press timer for breaking blocks if (pressTimer) { LK.clearTimeout(pressTimer); } pressTimer = LK.setTimeout(function () { isLongPress = true; // Break only the specific block at clicked position if (isValidGridPosition(gridPos.x, gridPos.y) && grid[gridPos.x][gridPos.y] !== null) { removeBlock(gridPos.x, gridPos.y); } }, 500); // 500ms long press }; game.up = function (x, y, obj) { // Clear the long press timer if (pressTimer) { LK.clearTimeout(pressTimer); pressTimer = null; } // If it wasn't a long press, place a block if (!isLongPress) { var gridPos = getGridPosition(x, y); if (isValidGridPosition(gridPos.x, gridPos.y)) { placeBlock(gridPos.x, gridPos.y); } } }; // Generate procedural world with biomes function generateWorld() { // Reset selected block type to dirt for generation selectedBlockType = 'dirt'; updateToolbarSelection(); // Create height map for smooth terrain var heightMap = []; var baseHeightLevel = Math.floor(GRID_HEIGHT * 0.7); // Base terrain level for (var x = 0; x < GRID_WIDTH; x++) { // Generate smooth terrain using sine waves var primary = Math.sin(x / GRID_WIDTH * Math.PI * 2) * 3; var secondary = Math.sin(x / GRID_WIDTH * Math.PI * 6) * 1.5; var noise = (Math.random() - 0.5) * 2; var height = baseHeightLevel + primary + secondary + noise; heightMap[x] = Math.floor(Math.max(5, Math.min(height, GRID_HEIGHT - 3))); } // Smooth the height map to reduce abrupt changes for (var pass = 0; pass < 2; pass++) { for (var x = 1; x < GRID_WIDTH - 1; x++) { var avg = (heightMap[x - 1] + heightMap[x] + heightMap[x + 1]) / 3; heightMap[x] = Math.floor(avg); } } // Define biome regions var biome1 = Math.floor(GRID_WIDTH * 0.33); var biome2 = Math.floor(GRID_WIDTH * 0.66); var biomes = ['plains', 'forest', 'mountains']; var currentBiomes = [biomes[Math.floor(Math.random() * biomes.length)], biomes[Math.floor(Math.random() * biomes.length)], biomes[Math.floor(Math.random() * biomes.length)]]; // Generate terrain layers for (var x = 0; x < GRID_WIDTH; x++) { var currentBiome; if (x < biome1) { currentBiome = currentBiomes[0]; } else if (x < biome2) { currentBiome = currentBiomes[1]; } else { currentBiome = currentBiomes[2]; } var baseHeight = heightMap[x]; var surfaceBlock = 'grass'; var treeChance = 0.15; var stoneChance = 0.1; // Biome-specific properties if (currentBiome === 'plains') { surfaceBlock = 'grass'; treeChance = 0.08; stoneChance = 0.05; } else if (currentBiome === 'forest') { surfaceBlock = 'grass'; treeChance = 0.25; // More trees stoneChance = 0.08; } else if (currentBiome === 'mountains') { surfaceBlock = 'stone'; // Rocky surface treeChance = 0.05; // Few trees at high altitude stoneChance = 0.25; // Very rocky // Adjust height for mountains baseHeight = Math.max(baseHeight - 3, Math.floor(GRID_HEIGHT * 0.5)); } // Place surface layer selectedBlockType = surfaceBlock; placeBlock(x, baseHeight); // Place sub-surface layers consistently selectedBlockType = 'dirt'; var dirtLayers = currentBiome === 'mountains' ? 2 : 3; for (var y = baseHeight + 1; y < Math.min(baseHeight + dirtLayers + 1, GRID_HEIGHT); y++) { placeBlock(x, y); } // Place stone in deeper layers consistently selectedBlockType = 'stone'; for (var y = baseHeight + dirtLayers + 1; y < GRID_HEIGHT; y++) { var stoneProb = currentBiome === 'mountains' ? 0.9 : 0.8; if (Math.random() < stoneProb) { placeBlock(x, y); } } // Add trees in groups for natural look if (Math.random() < treeChance && baseHeight > 2) { selectedBlockType = 'wood'; var treeHeight; if (currentBiome === 'forest') { treeHeight = Math.floor(Math.random() * 3) + 3; // Tall trees } else { treeHeight = Math.floor(Math.random() * 2) + 2; // Normal trees } for (var i = 0; i < treeHeight; i++) { var treeY = baseHeight - i - 1; if (treeY >= 0) { placeBlock(x, treeY); } } // Add tree leaves/branches if (currentBiome === 'forest' && treeHeight >= 3) { selectedBlockType = 'grassLight'; if (x > 0 && baseHeight - treeHeight >= 0) { placeBlock(x - 1, baseHeight - treeHeight + 1); } if (x < GRID_WIDTH - 1 && baseHeight - treeHeight >= 0) { placeBlock(x + 1, baseHeight - treeHeight + 1); } } } // Add surface features sparingly if (Math.random() < stoneChance && baseHeight > 0) { selectedBlockType = 'stone'; placeBlock(x, baseHeight - 1); } // Add biome-specific features occasionally if (currentBiome === 'mountains' && Math.random() < 0.1) { selectedBlockType = 'stone'; if (baseHeight > 1) { placeBlock(x, baseHeight - 1); } } } // Add minimal scattered resources in logical places for (var i = 0; i < 15; i++) { var randX = Math.floor(Math.random() * GRID_WIDTH); var surfaceY = heightMap[randX]; // Place resources near surface or in underground areas var randY = Math.random() < 0.6 ? surfaceY + Math.floor(Math.random() * 3) + 1 : Math.floor(Math.random() * (GRID_HEIGHT - surfaceY - 5)) + surfaceY + 3; if (isValidGridPosition(randX, randY) && grid[randX][randY] === null) { var resourceType; if (randY > surfaceY + 2) { // Underground resources resourceType = Math.random() < 0.6 ? 'stone' : 'dirt'; } else { // Surface resources resourceType = blockTypes[Math.floor(Math.random() * blockTypes.length)]; } selectedBlockType = resourceType; placeBlock(randX, randY); } } // Add rare precious blocks deep underground for (var i = 0; i < 3; i++) { var randX = Math.floor(Math.random() * GRID_WIDTH); var surfaceY = heightMap[randX]; // Place deep underground only var randY = Math.floor(Math.random() * 3) + GRID_HEIGHT - 5; if (isValidGridPosition(randX, randY) && grid[randX][randY] === null) { var preciousType = Math.random() < 0.4 ? 'diamond' : 'gold'; selectedBlockType = preciousType; placeBlock(randX, randY); } } // Add portals with 10% chance - place 1-2 portals randomly if (Math.random() < 0.1) { var numPortals = Math.floor(Math.random() * 2) + 1; // 1 or 2 portals for (var p = 0; p < numPortals; p++) { var attempts = 0; var portalPlaced = false; while (attempts < 20 && !portalPlaced) { var randX = Math.floor(Math.random() * GRID_WIDTH); var surfaceY = heightMap[randX]; var randY = surfaceY - Math.floor(Math.random() * 3) - 1; // Place above surface if (isValidGridPosition(randX, randY) && grid[randX][randY] === null) { selectedBlockType = 'portal'; if (placeBlock(randX, randY)) { portalPlaced = true; } } attempts++; } } } // Create a few small, deliberate caves for (var caveCount = 0; caveCount < 2; caveCount++) { var caveX = Math.floor(Math.random() * (GRID_WIDTH - 4)) + 2; var surfaceHeight = heightMap[caveX]; var caveY = surfaceHeight + Math.floor(Math.random() * 4) + 3; var caveSize = 1; // Create small hollow areas for (var cx = caveX - caveSize; cx <= caveX + caveSize; cx++) { for (var cy = caveY - caveSize; cy <= caveY + caveSize; cy++) { if (isValidGridPosition(cx, cy) && grid[cx][cy] !== null) { var block = grid[cx][cy]; if (block) { block.destroy(); grid[cx][cy] = null; // Remove from placedBlocks array for (var j = placedBlocks.length - 1; j >= 0; j--) { if (placedBlocks[j] === block) { placedBlocks.splice(j, 1); break; } } } } } } } // Reset to dirt selection selectedBlockType = 'dirt'; updateToolbarSelection(); } // Generate the world after a short delay LK.setTimeout(function () { generateWorld(); }, 500); function applyGravity() { var blocksToMove = []; // Check all blocks from bottom to top for (var y = GRID_HEIGHT - 2; y >= 0; y--) { for (var x = 0; x < GRID_WIDTH; x++) { var block = grid[x][y]; if (block !== null) { // Check if block has support below var hasSupport = false; for (var checkY = y + 1; checkY < GRID_HEIGHT; checkY++) { if (grid[x][checkY] !== null) { hasSupport = true; break; } } // If no support, mark for falling if (!hasSupport) { var fallY = y; // Find where it should fall to for (var targetY = y + 1; targetY < GRID_HEIGHT; targetY++) { if (grid[x][targetY] !== null) { break; } fallY = targetY; } if (fallY !== y) { blocksToMove.push({ block: block, fromX: x, fromY: y, toX: x, toY: fallY }); } } } } } // Move blocks that need to fall for (var i = 0; i < blocksToMove.length; i++) { var moveData = blocksToMove[i]; var block = moveData.block; // Clear old position grid[moveData.fromX][moveData.fromY] = null; // Set new position grid[moveData.toX][moveData.toY] = block; block.setGridPosition(moveData.toX, moveData.toY); } } game.update = function () { // Apply gravity every few ticks to make blocks fall if (LK.ticks % 10 === 0) { applyGravity(); } // Update flying status display if (isFlying) { flyingStatusText.setText('FLYING MODE'); flyingStatusText.visible = true; // Track flying time for achievements if (flyingStartTime > 0) { var currentFlyingTime = (LK.ticks - flyingStartTime) * (1000 / 60); if (currentFlyingTime >= 1000) { // Check every second totalFlyingTime += 1000; storage.totalFlyingTime = totalFlyingTime; flyingStartTime = LK.ticks; checkAllAchievements(); } } } else { flyingStatusText.visible = false; } // Replenish inventory slowly over time if (LK.ticks % 600 === 0) { // Every 10 seconds for (var blockType in inventory) { if (inventory[blockType] < 50) { inventory[blockType]++; } } updateInventoryDisplay(); checkAllAchievements(); } };
===================================================================
--- original.js
+++ change.js
@@ -927,8 +927,93 @@
self.update = function () {
// Gentle wave effect
waterGraphics.alpha = 0.6 + Math.sin(LK.ticks * 0.08) * 0.1;
waterGraphics.tint = 0x4169e1 + Math.floor(Math.sin(LK.ticks * 0.05) * 10) * 0x000100;
+ // Check for lava collision in adjacent positions
+ var checkPositions = [{
+ x: self.gridX - 1,
+ y: self.gridY
+ },
+ // Left
+ {
+ x: self.gridX + 1,
+ y: self.gridY
+ },
+ // Right
+ {
+ x: self.gridX,
+ y: self.gridY - 1
+ },
+ // Up
+ {
+ x: self.gridX,
+ y: self.gridY + 1
+ },
+ // Down
+ {
+ x: self.gridX - 1,
+ y: self.gridY - 1
+ },
+ // Up-left
+ {
+ x: self.gridX + 1,
+ y: self.gridY - 1
+ },
+ // Up-right
+ {
+ x: self.gridX - 1,
+ y: self.gridY + 1
+ },
+ // Down-left
+ {
+ x: self.gridX + 1,
+ y: self.gridY + 1
+ } // Down-right
+ ];
+ for (var i = 0; i < checkPositions.length; i++) {
+ var pos = checkPositions[i];
+ if (isValidGridPosition(pos.x, pos.y) && grid[pos.x][pos.y] !== null) {
+ var adjacentBlock = grid[pos.x][pos.y];
+ if (adjacentBlock.blockType === 'lava') {
+ // Water and lava reaction - create steam explosion effect
+ LK.effects.flashScreen(0xFFFFFF, 800);
+ LK.effects.flashObject(self, 0xFFFFFF, 600);
+ LK.effects.flashObject(adjacentBlock, 0xFFFFFF, 600);
+ // Create stone block at water position
+ var stoneBlock = new Block('stone');
+ stoneBlock.setGridPosition(self.gridX, self.gridY);
+ game.addChild(stoneBlock);
+ grid[self.gridX][self.gridY] = stoneBlock;
+ placedBlocks.push(stoneBlock);
+ // Remove water block
+ self.destroy();
+ for (var j = placedBlocks.length - 1; j >= 0; j--) {
+ if (placedBlocks[j] === self) {
+ placedBlocks.splice(j, 1);
+ break;
+ }
+ }
+ // Remove lava block
+ adjacentBlock.destroy();
+ grid[pos.x][pos.y] = null;
+ for (var k = placedBlocks.length - 1; k >= 0; k--) {
+ if (placedBlocks[k] === adjacentBlock) {
+ placedBlocks.splice(k, 1);
+ break;
+ }
+ }
+ // Create stone block at lava position too
+ var stoneBlock2 = new Block('stone');
+ stoneBlock2.setGridPosition(pos.x, pos.y);
+ game.addChild(stoneBlock2);
+ grid[pos.x][pos.y] = stoneBlock2;
+ placedBlocks.push(stoneBlock2);
+ // Play reaction sound
+ LK.getSound('break').play();
+ return; // Exit after reaction
+ }
+ }
+ }
// Water flowing mechanics disabled - no spreading
// if (self.flowCooldown > 0) {
// self.flowCooldown--;
// } else {