User prompt
change the moon image with my "moon" image
User prompt
make sun and moon move's slower
User prompt
change the moon and clouds image's with my "sun" and "cloud" image
User prompt
change sun image with my "sun" image
User prompt
develop the game by yourself and make it good
User prompt
use my direction images for direction buttons
User prompt
polish the game
User prompt
add control buttons (up,left and right) to the left down
User prompt
move control buttons to the left down
User prompt
add move control buttons
User prompt
character cant get in blocks
User prompt
Make world load system same like pixel world
User prompt
add in-game the direction button right button, left button and up button
User prompt
add direction buttons to the game and make it available
User prompt
add diection buttons
User prompt
make players cant get outside the world and make block breakable (not bedrock and main door)
User prompt
remove bedrocks from lef right and up
User prompt
add bedrocks skins
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { worldData: "undefined", playerPosition: { x: 1024, y: 1600 }, inventory: {} }); /**** * Classes ****/ var Block = Container.expand(function (type, size) { var self = Container.call(this); self.type = type; self.size = size || 64; // Use 'bedrock' skin for bedrock blocks, otherwise use type as asset var assetType = type === 'bedrock' ? 'bedrock' : type; var graphics = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5, width: self.size, height: self.size }); self.down = function (x, y, obj) { if (currentTool === 'break') { self.breakBlock(); } }; self.breakBlock = function () { // Make main door and bedrock blocks unbreakable if (self.type === 'main_door' || self.type === 'bedrock') { // Optionally play a sound or show a message here return; } // Add to inventory inventory[self.type] = (inventory[self.type] || 0) + 1; updateInventoryDisplay(); // Play break sound LK.getSound('break').play(); // Remove from world var gridX = Math.floor(self.x / blockSize); var gridY = Math.floor(self.y / blockSize); if (worldData[gridY] && worldData[gridY][gridX] !== undefined && worldData[gridY][gridX] !== null) { worldData[gridY][gridX] = null; self.destroy(); } // Save world data // Convert worldData to string before storing storage.worldData = JSON.stringify(worldData); }; return self; }); var Button = Container.expand(function (text, callback) { var self = Container.call(this); var background = self.attachAsset('buttonBg', { anchorX: 0.5, anchorY: 0.5 }); self.buttonText = new Text2(text, { size: 36, fill: 0xFFFFFF }); self.buttonText.anchor.set(0.5, 0.5); self.addChild(self.buttonText); self.callback = callback; self.down = function (x, y, obj) { if (self.callback) { self.callback(); } }; return self; }); var Character = Container.expand(function () { var self = Container.call(this); // Create character sprite var sprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 1.0, width: 80, height: 100 }); // Character properties self.direction = 1; // 1 = right, -1 = left self.isMoving = false; self.speed = 4; // Animation properties self.frameTime = 0; self.frameRate = 8; // frames per second // Change direction method self.faceDirection = function (dir) { if (dir !== self.direction) { self.direction = dir; sprite.scale.x = self.direction; } }; // Start/stop movement self.startMoving = function (dir) { self.isMoving = true; self.faceDirection(dir); }; self.stopMoving = function () { self.isMoving = false; }; // Update method - called every frame self.update = function () { // Store last position for collision detection var lastY = self.y; var lastX = self.x; // Handle movement if (self.isMoving) { self.x += self.speed * self.direction; // Update animation self.frameTime += 1 / 60; if (self.frameTime >= 1 / self.frameRate) { self.frameTime = 0; // We would change animation frame here if we had sprite frames } } // Keep character in bounds if (self.x < 50) self.x = 50; if (self.x > 2000) self.x = 2000; // --- Begin Physics for Character --- if (typeof self.velocityY === "undefined") self.velocityY = 0; if (typeof self.lastOnGround === "undefined") self.lastOnGround = false; // Gravity var gravityForce = 1.2; self.velocityY += gravityForce; // Limit max fall speed if (self.velocityY > 32) self.velocityY = 32; // Move vertically self.y += self.velocityY; // Check for ground collision var gridX = Math.floor(self.x / blockSize); var gridY = Math.floor((self.y + 10) / blockSize); var onGround = false; for (var checkX = gridX - 1; checkX <= gridX + 1; checkX++) { if (checkX >= 0 && gridY >= 0 && gridY < worldData.length && checkX < (worldData[gridY] ? worldData[gridY].length : 0) && worldData[gridY] && worldData[gridY][checkX] && worldData[gridY][checkX] !== 'water') { var distX = Math.abs(self.x - (checkX * blockSize + blockSize / 2)); if (distX < blockSize * 0.8) { // Snap to top of block self.y = gridY * blockSize - 10; self.velocityY = 0; onGround = true; break; } } } // Check if we just landed on a platform if (!self.lastOnGround && onGround) { self.velocityY = 0; self.y = Math.floor(self.y / blockSize) * blockSize - 10; } self.lastOnGround = onGround; // --- End Physics for Character --- // Check for horizontal collisions if (lastX !== self.x) { var checkGridY = Math.floor((self.y - 50) / blockSize); // Check at character's mid height var newGridX = Math.floor(self.x / blockSize); // Check if there's a block at character's new position if (checkGridY >= 0 && checkGridY < worldData.length && newGridX >= 0 && newGridX < worldData[checkGridY].length && worldData[checkGridY][newGridX]) { // Collision detected, revert to previous position self.x = lastX; self.isMoving = false; } } }; // Interactive events self.down = function (x, y, obj) { // Handle touch down on character self.startDrag(); // Convert to world container's coordinate system for proper positioning var worldX = obj.parent.toGlobal(obj.position).x; var worldY = obj.parent.toGlobal(obj.position).y; // Determine initial direction based on touch position if (x > self.width / 2) { self.faceDirection(1); // Face right } else { self.faceDirection(-1); // Face left } }; // Add touch controls for character self.startDrag = function () { self.isDragging = true; }; self.stopDrag = function () { self.isDragging = false; self.isMoving = false; }; // Add jump functionality self.jump = function () { // Find where the player is standing var gridX = Math.floor(self.x / blockSize); var gridY = Math.floor((self.y + 10) / blockSize); // Check if character is on ground var onGround = false; for (var checkX = gridX - 1; checkX <= gridX + 1; checkX++) { if (checkX >= 0 && gridY >= 0 && gridY < worldData.length && checkX < (worldData[gridY] ? worldData[gridY].length : 0) && worldData[gridY] && worldData[gridY][checkX] && worldData[gridY][checkX] !== 'water') { var distX = Math.abs(self.x - (checkX * blockSize + blockSize / 2)); if (distX < blockSize * 0.8) { onGround = true; break; } } } if (onGround) { // Apply upward force when jumping self.velocityY = -22; } }; self.drag = function (x, y) { if (self.isDragging) { // Convert global coordinates to character's local frame var localX = x - game.toLocal(self.parent.toGlobal(self.position)).x + self.x; // Calculate difference for movement threshold var diffX = localX - self.x; // Determine direction based on current position and touch position if (diffX > 10) { self.faceDirection(1); self.isMoving = true; } else if (diffX < -10) { self.faceDirection(-1); self.isMoving = true; } else { self.isMoving = false; } } }; return self; }); var ControlButton = Container.expand(function (text, callback, width, height) { var self = Container.call(this); width = width || 150; height = height || 150; // Create button background var background = self.attachAsset('buttonBg', { anchorX: 0.5, anchorY: 0.5, width: width, height: height }); // Create button text self.buttonText = new Text2(text, { size: 48, fill: 0xFFFFFF }); self.buttonText.anchor.set(0.5, 0.5); self.addChild(self.buttonText); // Store callback function self.callback = callback; // Add control type to identify button function self.controlType = ''; if (text === '←') self.controlType = 'left';else if (text === '→') self.controlType = 'right';else if (text === '↑') self.controlType = 'jump';else if (text === '■') self.controlType = 'stop'; // Button interaction self.down = function (x, y, obj) { if (self.callback) { background.alpha = 0.7; self.callback(); // Set control state for continuous button press if (self.controlType && controlState) { if (self.controlType === 'left') { controlState.left = true; controlState.right = false; } else if (self.controlType === 'right') { controlState.right = true; controlState.left = false; } else if (self.controlType === 'jump') { controlState.jump = true; } else if (self.controlType === 'stop') { controlState.left = false; controlState.right = false; } } } }; self.up = function (x, y, obj) { background.alpha = 1.0; // Clear control state when button is released if (self.controlType && controlState) { if (self.controlType === 'left') { controlState.left = false; } else if (self.controlType === 'right') { controlState.right = false; } else if (self.controlType === 'jump') { controlState.jump = false; } } }; return self; }); var InventorySlot = Container.expand(function (index, type) { var self = Container.call(this); self.index = index; self.type = type; var background = self.attachAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5 }); if (type) { var blockIcon = self.attachAsset(type, { anchorX: 0.5, anchorY: 0.5, width: 60, height: 60 }); } self.countText = new Text2("0", { size: 24, fill: 0xFFFFFF }); self.countText.anchor.set(1, 1); self.countText.x = 30; self.countText.y = 30; self.addChild(self.countText); self.updateCount = function (count) { self.countText.setText(count.toString()); }; self.down = function (x, y, obj) { selectInventorySlot(self.index); }; return self; }); var MainMenu = Container.expand(function () { var self = Container.call(this); // Create a semi-transparent background overlay var overlay = LK.getAsset('buttonBg', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 0.7 }); overlay.tint = 0x000000; self.addChild(overlay); // Game title self.title = new Text2("Pixel Realms", { size: 120, fill: 0xFFFFFF }); self.title.anchor.set(0.5, 0.5); self.title.x = 2048 / 2; self.title.y = 800; self.addChild(self.title); // Start game button self.startButton = new Button("Start Game", function () { self.hide(); worldEnterMenu.show(); }); self.startButton.x = 2048 / 2; self.startButton.y = 1200; self.addChild(self.startButton); // Add animated elements self.show = function () { self.visible = true; // Reset positions for animation self.title.y = 600; self.title.alpha = 0; self.startButton.y = 1300; self.startButton.alpha = 0; // Animate title tween(self.title, { y: 800, alpha: 1 }, { duration: 800, easing: tween.easeOutBack }); // Animate button with slight delay tween(self.startButton, { y: 1200, alpha: 1 }, { duration: 800, easing: tween.easeOutBack }); }; self.hide = function () { // Animate out tween(self.title, { y: 600, alpha: 0 }, { duration: 500, easing: tween.easeInBack }); tween(self.startButton, { y: 1300, alpha: 0 }, { duration: 500, easing: tween.easeInBack, onFinish: function onFinish() { self.visible = false; } }); }; return self; }); var Platform = Container.expand(function (width, height) { var self = Container.call(this); self.width = width || 5; self.height = height || 1; // Create platform blocks for (var x = 0; x < self.width; x++) { for (var y = 0; y < self.height; y++) { var block = new Block('stone', blockSize); block.x = x * blockSize + blockSize / 2; block.y = y * blockSize + blockSize / 2; self.addChild(block); } } return self; }); var Player = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 1, width: 60, height: 120 }); // Movement properties self.speed = 5; self.velocity = { x: 0, y: 0 }; self.gravity = 0.5; self.jumping = false; self.grounded = false; self.move = function (direction) { if (direction === 'left') { self.velocity.x = -self.speed; } else if (direction === 'right') { self.velocity.x = self.speed; } }; self.stopMove = function () { self.velocity.x = 0; }; self.jump = function () { if (self.grounded) { self.velocity.y = -22; self.grounded = false; self.jumping = true; } }; self.update = function () { // --- Begin Physics for Player --- if (typeof self.velocity === "undefined") self.velocity = { x: 0, y: 0 }; if (typeof self.gravity === "undefined") self.gravity = 1.2; if (typeof self.grounded === "undefined") self.grounded = false; if (!self.grounded) { self.velocity.y += self.gravity; if (self.velocity.y > 32) self.velocity.y = 32; } self.x += self.velocity.x; self.y += self.velocity.y; // --- End Physics for Player --- // Check for ground collision var gridX = Math.floor(self.x / blockSize); var gridY = Math.floor((self.y + 10) / blockSize); // Simple collision check with the block below if (gridY >= 0 && gridY < worldData.length && gridX >= 0 && worldData[gridY] && gridX < worldData[gridY].length && worldData[gridY][gridX] && worldData[gridY][gridX] !== 'water') { if (self.velocity.y > 0) { self.y = gridY * blockSize - 10; self.velocity.y = 0; self.grounded = true; self.jumping = false; } } else { self.grounded = false; } // Update camera to follow player updateCamera(); // Save player position periodically if (LK.ticks % 60 === 0) { storage.playerPosition = { x: self.x, y: self.y }; } }; return self; }); var WorldEnterMenu = Container.expand(function () { var self = Container.call(this); // Create a semi-transparent background var overlay = LK.getAsset('buttonBg', { anchorX: 0.5, anchorY: 0.5, width: 2048, height: 2732, alpha: 0.8 }); overlay.tint = 0x000022; self.addChild(overlay); // World title self.title = new Text2("Enter World", { size: 100, fill: 0xFFFFFF }); self.title.anchor.set(0.5, 0.5); self.title.x = 2048 / 2; self.title.y = 600; self.addChild(self.title); // World description self.description = new Text2("Select your world to start building", { size: 48, fill: 0xCCCCCC }); self.description.anchor.set(0.5, 0.5); self.description.x = 2048 / 2; self.description.y = 720; self.addChild(self.description); // World selection buttons self.createWorldButton = new Button("Create New World", function () { // Prompt for world name (simple prompt, can be improved) var worldName = "world" + Math.floor(Math.random() * 10000); // Generate new world and save with name var newWorldData = generateWorld(); pixelWorlds.saveWorld(worldName, newWorldData); worldData = newWorldData; pixelWorlds.currentWorld = worldName; // Reset player position player.x = 1024; player.y = 1600; storage.playerPosition = { x: player.x, y: player.y }; // Move character to main door entrance (bottom center) on new world creation if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") { setCharacterToMainDoor(); } // Reset inventory inventory = { "grass": 10, "stone": 10, "wood": 10, "water": 5 }; storage.inventory = inventory; // Start game self.hide(); gameStarted = true; initializeWorld(); setupUI(); }); self.createWorldButton.x = 2048 / 2; self.createWorldButton.y = 1000; self.addChild(self.createWorldButton); // Add a world selection menu for pixel worlds self.loadWorldButton = new Button("Select World", function () { // Show a simple world selection overlay var overlay = new Container(); var bg = LK.getAsset('buttonBg', { anchorX: 0.5, anchorY: 0.5, width: 1200, height: 1000, alpha: 0.95 }); bg.tint = 0x222244; overlay.addChild(bg); overlay.x = 2048 / 2; overlay.y = 1200; // List all worlds var worlds = pixelWorlds.listWorlds(); if (worlds.length === 0) { var noWorlds = new Text2("No worlds found", { size: 60, fill: 0xffffff }); noWorlds.anchor.set(0.5, 0.5); noWorlds.y = 0; overlay.addChild(noWorlds); } else { for (var i = 0; i < worlds.length; i++) { (function (worldName, idx) { var btn = new Button(worldName, function () { // Switch to selected world pixelWorlds.switchWorld(worldName); // Move character to main door entrance (bottom center) on world select if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") { setCharacterToMainDoor(); } overlay.visible = false; self.hide(); gameStarted = true; }); btn.x = 0; btn.y = -400 + idx * 120; overlay.addChild(btn); })(worlds[i], i); } } // Add close button var closeBtn = new Button("Close", function () { overlay.visible = false; }); closeBtn.x = 0; closeBtn.y = 500; overlay.addChild(closeBtn); LK.gui.center.addChild(overlay); }); self.loadWorldButton.x = 2048 / 2; self.loadWorldButton.y = 1150; self.addChild(self.loadWorldButton); self.backButton = new Button("Back to Menu", function () { self.hide(); mainMenu.show(); }); self.backButton.x = 2048 / 2; self.backButton.y = 1400; self.addChild(self.backButton); // Show animation self.show = function () { self.visible = true; // Reset positions for animation self.title.y = 400; self.title.alpha = 0; self.description.y = 620; self.description.alpha = 0; self.createWorldButton.y = 1100; self.createWorldButton.alpha = 0; self.loadWorldButton.y = 1250; self.loadWorldButton.alpha = 0; self.backButton.y = 1500; self.backButton.alpha = 0; // Animate title tween(self.title, { y: 600, alpha: 1 }, { duration: 600, easing: tween.easeOutBack }); // Animate description tween(self.description, { y: 720, alpha: 1 }, { duration: 600, delay: 100, easing: tween.easeOutBack }); // Animate buttons tween(self.createWorldButton, { y: 1000, alpha: 1 }, { duration: 600, delay: 200, easing: tween.easeOutBack }); tween(self.loadWorldButton, { y: 1150, alpha: 1 }, { duration: 600, delay: 300, easing: tween.easeOutBack }); tween(self.backButton, { y: 1400, alpha: 1 }, { duration: 600, delay: 400, easing: tween.easeOutBack }); }; // Hide animation self.hide = function () { // Animate out tween(self.title, { y: 400, alpha: 0 }, { duration: 400, easing: tween.easeInBack }); tween(self.description, { y: 620, alpha: 0 }, { duration: 400, easing: tween.easeInBack }); tween(self.createWorldButton, { y: 1100, alpha: 0 }, { duration: 400, easing: tween.easeInBack }); tween(self.loadWorldButton, { y: 1250, alpha: 0 }, { duration: 400, easing: tween.easeInBack }); tween(self.backButton, { y: 1500, alpha: 0 }, { duration: 400, easing: tween.easeInBack, onFinish: function onFinish() { self.visible = false; } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ //{bedrock_skin} // Make sure JSON is defined for storage operations // Game constants function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var JSON = { parse: function parse(text) { return LK.parseJSON(text); }, stringify: function stringify(obj) { // Convert JavaScript object to a JSON string var str = ''; if (obj === null) return 'null'; if (typeof obj === 'undefined') return undefined; if (typeof obj === 'string') return '"' + obj.replace(/"/g, '\\"') + '"'; if (typeof obj === 'number' || typeof obj === 'boolean') return obj.toString(); if (Array.isArray(obj)) { str = '['; for (var i = 0; i < obj.length; i++) { str += (i > 0 ? ',' : '') + JSON.stringify(obj[i]); } return str + ']'; } if (_typeof(obj) === 'object') { str = '{'; var keys = Object.keys(obj); for (var i = 0; i < keys.length; i++) { var key = keys[i]; str += (i > 0 ? ',' : '') + '"' + key + '":' + JSON.stringify(obj[key]); } return str + '}'; } return ''; } }; var WorldGenerator = function WorldGenerator() { // Generate a new world with more advanced terrain features this.generate = function (width, height, blockSize) { var data = []; // Initialize with empty arrays for (var y = 0; y < height; y++) { data[y] = []; for (var x = 0; x < width; x++) { data[y][x] = null; } } // Add bedrock border (unbreakable) around the world for (var y = 0; y < height; y++) { for (var x = 0; x < width; x++) { if (y === 0 || y === height - 1 || x === 0 || x === width - 1) { data[y][x] = 'bedrock'; } } } // Generate terrain using simple noise var terrain = this.generateTerrain(width, height); // Apply terrain to world data for (var x = 0; x < width; x++) { var groundHeight = Math.floor(terrain[x] * height * 0.4) + Math.floor(height * 0.5); // Fill all blocks below the surface with 'ground' (dirt) for (var y = groundHeight; y < height; y++) { if (y === groundHeight) { // Don't overwrite bedrock border if (data[y][x] !== 'bedrock') data[y][x] = 'grass'; } else { if (data[y][x] !== 'bedrock') data[y][x] = 'ground'; } } // Generate caves this.generateCaves(data, x, groundHeight, height); } // Add trees this.addTrees(data, width, height); // Add water bodies this.addWater(data, width, height); return data; }; // Generate basic terrain height map using simple noise this.generateTerrain = function (width, height) { var terrain = []; var smoothness = 8; // Higher = smoother terrain // Start with random height terrain[0] = Math.random(); // Generate rest using midpoint displacement-like approach for (var x = 1; x < width; x++) { // Get previous height with some randomness var prevHeight = terrain[x - 1]; var randomFactor = (Math.random() - 0.5) * 2 / smoothness; // New height with constraints terrain[x] = Math.max(0.1, Math.min(0.9, prevHeight + randomFactor)); // Add some hills/mountains occasionally if (Math.random() < 0.05) { var hillHeight = 0.1 + Math.random() * 0.2; var hillWidth = 3 + Math.floor(Math.random() * 5); // Create a hill centered at x for (var h = 0; h < hillWidth && x + h < width; h++) { var offset = hillHeight * Math.sin(h / hillWidth * Math.PI); if (x + h < width) { terrain[x + h] = Math.max(0.1, Math.min(0.9, terrain[x + h] - offset)); } } // Skip ahead x += hillWidth; } } return terrain; }; // Add random caves under the terrain this.generateCaves = function (data, x, groundHeight, height) { // Random caves deeper underground if (groundHeight + 5 < height) { for (var c = 0; c < 2; c++) { if (Math.random() < 0.05) { var caveY = groundHeight + 5 + Math.floor(Math.random() * (height - groundHeight - 10)); var caveSize = 1 + Math.floor(Math.random() * 3); for (var cy = caveY; cy < caveY + caveSize && cy < height; cy++) { if (data[cy] && data[cy][x]) { data[cy][x] = null; } } } } } }; // Add trees on the surface this.addTrees = function (data, width, height) { for (var x = 0; x < width; x++) { // Find the ground level var groundY = 0; for (var y = 0; y < height; y++) { if (data[y] && data[y][x] === 'grass') { groundY = y; break; } } // Add random trees (if we found ground and not at the edge) if (groundY > 0 && x > 2 && x < width - 2 && Math.random() < 0.1) { var treeHeight = 3 + Math.floor(Math.random() * 3); // Remove grass block below the tree (set to null) if (groundY + 1 < height && data[groundY + 1][x] === 'grass') { data[groundY + 1][x] = null; } // Tree trunk for (var ty = 1; ty <= treeHeight; ty++) { if (groundY - ty >= 0) { data[groundY - ty][x] = 'wood'; } } // Tree top (add leaves here) var treeTop = groundY - treeHeight - 1; if (treeTop >= 0) { // Add leaves in a 3x3 area centered on the trunk top for (var ly = -1; ly <= 1; ly++) { for (var lx = -1; lx <= 1; lx++) { var leafX = x + lx; var leafY = treeTop + ly; if (leafX >= 0 && leafX < width && leafY >= 0 && leafY < height && (ly !== 0 || lx !== 0) // Don't overwrite trunk top ) { data[leafY][leafX] = 'Leaf'; // Use 'Leaf' as leaf block } } } // Place trunk top (wood) in the center data[treeTop][x] = 'wood'; // Optionally, add a single leaf block above the trunk top if (treeTop - 1 >= 0) { data[treeTop - 1][x] = 'Leaf'; } } } } }; // Add water bodies (lakes, rivers) this.addWater = function (data, width, height) { // Add some water pools/lakes var lakeAttempts = Math.floor(width / 20); for (var l = 0; l < lakeAttempts; l++) { var lakeX = 5 + Math.floor(Math.random() * (width - 10)); var lakeWidth = 3 + Math.floor(Math.random() * 5); // Find ground level at lakeX var lakeY = 0; for (var y = 0; y < height; y++) { if (data[y] && data[y][lakeX] === 'grass') { lakeY = y; break; } } // Create lake if (lakeY > 0) { for (var wx = 0; wx < lakeWidth && lakeX + wx < width; wx++) { if (data[lakeY] && data[lakeY][lakeX + wx]) { data[lakeY][lakeX + wx] = 'water'; // Sometimes make deeper water if (Math.random() < 0.5 && lakeY + 1 < height) { data[lakeY + 1][lakeX + wx] = 'water'; } } } } } }; return this; }; var blockSize = 64; var worldWidth = 100; // 100 blocks horizontal var worldHeight = 54; // 54 blocks vertical var gravity = 0; // Game state var gameStarted = false; // Parse worldData from storage if it exists, checking for undefined/null values // Pixel World System: Support for multiple worlds and world switching var pixelWorlds = { currentWorld: "default", worlds: {}, // Load world data from storage or generate new loadWorld: function loadWorld(worldName) { var key = "pixelWorld_" + worldName; var data; try { data = storage[key] && storage[key] !== "undefined" ? JSON.parse(storage[key]) : null; } catch (e) { data = null; } if (!data) { data = generateWorld(); storage[key] = JSON.stringify(data); } this.worlds[worldName] = data; this.currentWorld = worldName; return data; }, // Save current world data to storage saveWorld: function saveWorld(worldName, data) { var key = "pixelWorld_" + worldName; storage[key] = JSON.stringify(data); this.worlds[worldName] = data; }, // Switch to a different world switchWorld: function switchWorld(worldName) { worldData = this.loadWorld(worldName); this.currentWorld = worldName; initializeWorld(); // Move character to main door entrance (bottom center) on world switch if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") { setCharacterToMainDoor(); } setupUI(); }, // List all saved worlds (by checking storage keys) listWorlds: function listWorlds() { var result = []; for (var k in storage) { if (k.indexOf("pixelWorld_") === 0) { result.push(k.replace("pixelWorld_", "")); } } return result; } }; // Use pixelWorlds to load the default world at start var worldData = pixelWorlds.loadWorld("default"); var inventory = storage.inventory || { "grass": 0, "stone": 0, "wood": 0, "water": 0 }; var currentTool = 'place'; // 'place' or 'break' var selectedBlockType = 'grass'; var selectedInventorySlot = 0; // Game containers var worldContainer = new Container(); var uiContainer = new Container(); var inventoryContainer = new Container(); var toolbarContainer = new Container(); game.addChild(worldContainer); game.addChild(uiContainer); // Create player var player = new Player(); player.x = storage.playerPosition ? storage.playerPosition.x : 1024; player.y = storage.playerPosition ? storage.playerPosition.y : 1600; worldContainer.addChild(player); // Create character at the main door entrance (bottom center) var character = new Character(); // Find the main door entrance (bottom center) function setCharacterToMainDoor() { var doorGridX = Math.floor(worldWidth / 2); var doorGridY = worldHeight - 2; character.x = doorGridX * blockSize + blockSize / 2; character.y = doorGridY * blockSize + blockSize / 2; } setCharacterToMainDoor(); worldContainer.addChild(character); // Initialize world blocks function initializeWorld() { // Clear any existing blocks while (worldContainer.children.length > 1) { // Keep player worldContainer.removeChildAt(1); } // Place blocks based on worldData for (var y = 0; y < worldData.length; y++) { for (var x = 0; x < worldData[y].length; x++) { if (worldData[y][x]) { var blockType = worldData[y][x]; // If this is a main door location, use 'main_door' type if (blockType === 'main_door') { var block = new Block('main_door', blockSize); } else { var block = new Block(blockType, blockSize); } block.x = x * blockSize + blockSize / 2; block.y = y * blockSize + blockSize / 2; worldContainer.addChild(block); } } } // Place a main door at all world enter locations if not present // For this game, we define the main doors as blocks at the bottom center, top center, left center, and right center of the world var entrances = [{ x: Math.floor(worldWidth / 2), y: worldHeight - 2 }, // bottom center { x: Math.floor(worldWidth / 2), y: 1 }, // top center { x: 1, y: Math.floor(worldHeight / 2) }, // left center { x: worldWidth - 2, y: Math.floor(worldHeight / 2) } // right center ]; for (var i = 0; i < entrances.length; i++) { var ex = entrances[i].x; var ey = entrances[i].y; if (!worldData[ey]) worldData[ey] = []; if (worldData[ey][ex] !== 'main_door') { worldData[ey][ex] = 'main_door'; var mainDoorBlock = new Block('main_door', blockSize); mainDoorBlock.x = ex * blockSize + blockSize / 2; mainDoorBlock.y = ey * blockSize + blockSize / 2; worldContainer.addChild(mainDoorBlock); } } // Create platforms if this is a new world if (!storage.platformsCreated) { createPlatforms(); storage.platformsCreated = true; } } // Generate a new world function generateWorld() { var worldGen = new WorldGenerator(); var data = worldGen.generate(worldWidth, worldHeight, blockSize); // Place a main door at the bottom center of the world var doorGridX = Math.floor(worldWidth / 2); var doorGridY = worldHeight - 2; if (!data[doorGridY]) data[doorGridY] = []; data[doorGridY][doorGridX] = 'main_door'; // Place main doors at all four world entrances (bottom center, top center, left center, right center) var entrances = [{ x: Math.floor(worldWidth / 2), y: worldHeight - 2 }, // bottom center { x: Math.floor(worldWidth / 2), y: 1 }, // top center { x: 1, y: Math.floor(worldHeight / 2) }, // left center { x: worldWidth - 2, y: Math.floor(worldHeight / 2) } // right center ]; for (var i = 0; i < entrances.length; i++) { var ex = entrances[i].x; var ey = entrances[i].y; if (!data[ey]) data[ey] = []; data[ey][ex] = 'main_door'; } // Save the generated world pixelWorlds.saveWorld(pixelWorlds.currentWorld, data); // Give player some starter blocks inventory = { "grass": 10, "stone": 10, "wood": 10, "water": 5 }; storage.inventory = inventory; return data; } // Setup UI function setupUI() { // Create inventory bar setupInventory(); // Create tool selection buttons setupToolbar(); // Create control buttons (left, right, jump) setupControls(); // Create main menu button setupMainMenuButton(); } // Add main menu button to return to menu function setupMainMenuButton() { var menuButton = new Button("Menu", function () { // Hide game elements gameStarted = false; // Show main menu mainMenu.show(); }); menuButton.x = 120; menuButton.y = 100; LK.gui.topRight.addChild(menuButton); // Add a Change World button for switching between 'old world' and 'new world' var changeWorldButton = new Button("Change World", function () { // If current world is 'old world', switch to 'new world', else switch to 'old world' var nextWorld = pixelWorlds.currentWorld === "old world" ? "new world" : "old world"; // If the world does not exist, generate it if (!pixelWorlds.worlds[nextWorld]) { var newWorldData = generateWorld(); pixelWorlds.saveWorld(nextWorld, newWorldData); } pixelWorlds.switchWorld(nextWorld); // Optionally, reset player position for new world player.x = 1024; player.y = 1600; storage.playerPosition = { x: player.x, y: player.y }; // Move character to main door entrance (bottom center) on Change World if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") { setCharacterToMainDoor(); } }); // Move the button to the top left, but not in the top 100x100 area changeWorldButton.x = 120; changeWorldButton.y = 200; LK.gui.topLeft.addChild(changeWorldButton); // Add a character control button var characterButton = new Button("Character", function () { // Show character info or focus on character var targetX = -character.x + 2048 / 2; var targetY = -character.y + 2732 / 2; // Animate the camera movement to the character tween(worldContainer, { x: targetX, y: targetY }, { duration: 500, easing: tween.easeOutQuad }); }); characterButton.x = 120; characterButton.y = 200; LK.gui.topRight.addChild(characterButton); } function setupInventory() { inventoryContainer = new Container(); var blockTypes = ['grass', 'stone', 'wood', 'water']; var slotSpacing = 100; // Create the background for selected slot var selectedSlotBg = LK.getAsset('selectedSlot', { anchorX: 0.5, anchorY: 0.5 }); inventoryContainer.addChild(selectedSlotBg); // Create inventory slots for (var i = 0; i < blockTypes.length; i++) { var slot = new InventorySlot(i, blockTypes[i]); slot.x = i * slotSpacing; slot.countText.setText((inventory[blockTypes[i]] || 0).toString()); inventoryContainer.addChild(slot); } // Position the inventory at the top center inventoryContainer.x = 2048 / 2 - (blockTypes.length - 1) * slotSpacing / 2; inventoryContainer.y = 100; // Create inventory title var inventoryTitle = new Text2("Inventory", { size: 40, fill: 0xFFFFFF }); inventoryTitle.anchor.set(0.5, 1); inventoryTitle.x = (blockTypes.length - 1) * slotSpacing / 2; inventoryTitle.y = -20; inventoryContainer.addChild(inventoryTitle); // Update selected slot visual updateSelectedSlot(); LK.gui.top.addChild(inventoryContainer); } function setupToolbar() { toolbarContainer = new Container(); // Place tool var placeToolBtn = new Button("Place", function () { currentTool = 'place'; updateToolbarSelection(); }); placeToolBtn.x = 0; toolbarContainer.addChild(placeToolBtn); // Break tool var breakToolBtn = new Button("Break", function () { currentTool = 'break'; updateToolbarSelection(); }); breakToolBtn.x = 250; toolbarContainer.addChild(breakToolBtn); // Position toolbar at bottom right toolbarContainer.x = 2048 - 400; toolbarContainer.y = 2732 - 100; LK.gui.bottomRight.addChild(toolbarContainer); // Update the initial tool selection updateToolbarSelection(); } function setupControls() { // Container for player movement controls (bottom left) var moveControls = new Container(); // Player Left var leftBtn = new ControlButton("←", function () { player.move('left'); }); leftBtn.x = 0; leftBtn.y = 0; moveControls.addChild(leftBtn); // Player Stop var stopBtn = new ControlButton("■", function () { player.stopMove(); }); stopBtn.x = 100; stopBtn.y = 0; moveControls.addChild(stopBtn); // Player Right var rightBtn = new ControlButton("→", function () { player.move('right'); }); rightBtn.x = 200; rightBtn.y = 0; moveControls.addChild(rightBtn); // Position at bottom left moveControls.x = 150; moveControls.y = 2732 - 100; LK.gui.bottomLeft.addChild(moveControls); // Container for character controls (bottom left, above player controls) var characterControls = new Container(); // Character Left var charLeftBtn = new ControlButton("←", function () { controlState.left = true; controlState.right = false; }, 150, 150); charLeftBtn.x = 0; charLeftBtn.y = 0; characterControls.addChild(charLeftBtn); // Character Stop var charStopBtn = new ControlButton("■", function () { controlState.left = false; controlState.right = false; }, 150, 150); charStopBtn.x = 100; charStopBtn.y = 0; characterControls.addChild(charStopBtn); // Character Right var charRightBtn = new ControlButton("→", function () { controlState.right = true; controlState.left = false; }, 150, 150); charRightBtn.x = 200; charRightBtn.y = 0; characterControls.addChild(charRightBtn); // Character Jump var charJumpBtn = new ControlButton("↑", function () { controlState.jump = true; }, 150, 150); charJumpBtn.x = 300; charJumpBtn.y = 0; characterControls.addChild(charJumpBtn); // Position above player controls characterControls.x = 150; characterControls.y = 2732 - 250; LK.gui.bottomLeft.addChild(characterControls); // Container for action controls (bottom right) var actionControls = new Container(); // Player Jump var jumpBtn = new ControlButton("↑", function () { player.jump(); }); jumpBtn.x = 0; jumpBtn.y = 0; actionControls.addChild(jumpBtn); // Character Jump (alternative) var characterJumpBtn = new ControlButton("C↑", function () { character.jump(); controlState.jump = true; }); characterJumpBtn.x = -200; characterJumpBtn.y = 0; actionControls.addChild(characterJumpBtn); // Position at bottom right actionControls.x = 2048 - 150; actionControls.y = 2732 - 100; LK.gui.bottomRight.addChild(actionControls); } function updateSelectedSlot() { var selectedSlotBg = inventoryContainer.getChildAt(0); var slot = inventoryContainer.getChildAt(selectedInventorySlot + 1); if (slot) { selectedSlotBg.x = slot.x; selectedSlotBg.y = slot.y; selectedBlockType = slot.type; } } function updateToolbarSelection() { var placeToolBtn = toolbarContainer.getChildAt(0); var breakToolBtn = toolbarContainer.getChildAt(1); if (currentTool === 'place') { if (placeToolBtn && placeToolBtn.buttonText) { placeToolBtn.buttonText.style = { fill: 0xFFFF00 }; } if (breakToolBtn && breakToolBtn.buttonText) { breakToolBtn.buttonText.style = { fill: 0xFFFFFF }; } } else { if (placeToolBtn && placeToolBtn.buttonText) { placeToolBtn.buttonText.style = { fill: 0xFFFFFF }; } if (breakToolBtn && breakToolBtn.buttonText) { breakToolBtn.buttonText.style = { fill: 0xFFFF00 }; } } } function selectInventorySlot(index) { selectedInventorySlot = index; updateSelectedSlot(); // Play select sound LK.getSound('select').play(); } function updateInventoryDisplay() { for (var i = 1; i < inventoryContainer.children.length; i++) { var slot = inventoryContainer.getChildAt(i); if (slot && typeof slot.updateCount === 'function') { slot.updateCount(inventory[slot.type] || 0); } else if (slot && slot.countText) { slot.countText.setText((inventory[slot.type] || 0).toString()); } } } function updateCamera() { // Calculate how much to offset the world to center the player var targetX = -player.x + 2048 / 2; var targetY = -player.y + 2732 / 2; // Add bounds to prevent seeing outside the world targetX = Math.min(0, Math.max(targetX, -(worldWidth * blockSize - 2048))); targetY = Math.min(0, Math.max(targetY, -(worldHeight * blockSize - 2732))); // Smooth camera movement worldContainer.x = targetX; worldContainer.y = targetY; } function placeBlock(x, y) { // Convert screen position to world position var worldX = x - worldContainer.x; var worldY = y - worldContainer.y; // Convert world position to grid position var gridX = Math.floor(worldX / blockSize); var gridY = Math.floor(worldY / blockSize); // Check if we have this block type in inventory if (inventory[selectedBlockType] <= 0) { return; } // Check if position is valid if (gridX < 0 || gridX >= worldWidth || gridY < 0 || gridY >= worldHeight) { return; } // Check if space is empty if (!worldData[gridY] || gridX >= worldData[gridY].length || gridX < 0 || gridY < 0 || worldData[gridY][gridX] !== null) { return; } // Don't allow placing blocks where the player is standing var playerGridX = Math.floor(player.x / blockSize); var playerGridY = Math.floor(player.y / blockSize); var playerGridYBottom = Math.floor((player.y - 60) / blockSize); // Check player's head position too if (gridX === playerGridX && (gridY === playerGridY || gridY === playerGridYBottom)) { return; // Can't place block where player is standing } // Place the block worldData[gridY][gridX] = selectedBlockType; // Remove from inventory inventory[selectedBlockType]--; updateInventoryDisplay(); // Create the block visually var block = new Block(selectedBlockType, blockSize); block.x = gridX * blockSize + blockSize / 2; block.y = gridY * blockSize + blockSize / 2; worldContainer.addChild(block); // Play place sound LK.getSound('place').play(); // Save world data // Save the data directly to storage pixelWorlds.saveWorld(pixelWorlds.currentWorld, worldData); storage.inventory = inventory; } // Game event handlers game.down = function (x, y, obj) { if (!gameStarted) return; // Don't handle interactions if game hasn't started if (currentTool === 'place') { placeBlock(x, y); } // Check if we clicked on the character if (obj && (obj === character || obj.parent === character)) { character.startDrag(); dragTarget = character; // Prevent placing blocks when clicking character return; } }; // Add move handler for dragging character game.move = function (x, y, obj) { if (dragTarget === character) { // Convert global coordinates to character's local space var localX = x - worldContainer.x; var localY = y - worldContainer.y; // Determine movement direction based on touch position relative to character if (localX > character.x + 10) { character.startMoving(1); // Move right } else if (localX < character.x - 10) { character.startMoving(-1); // Move left } else { character.stopMoving(); // Stop if touch is directly on character } } }; // Add up handler to stop dragging game.up = function (x, y, obj) { if (dragTarget === character) { character.stopDrag(); character.stopMoving(); // Make sure character stops moving when touch is released dragTarget = null; } }; // Initialize drag target variable var dragTarget = null; // Track control state for continuous button presses var controlState = { left: false, right: false, jump: false }; // Create platforms in the world function createPlatforms() { // Create several platforms at different positions var platforms = [{ x: 10, y: 20, width: 8, height: 1 }, { x: 25, y: 18, width: 6, height: 1 }, { x: 5, y: 15, width: 4, height: 1 }, { x: 15, y: 12, width: 5, height: 1 }, { x: 30, y: 10, width: 7, height: 1 }]; for (var i = 0; i < platforms.length; i++) { var p = platforms[i]; var platform = new Platform(p.width, p.height); platform.x = p.x * blockSize; platform.y = p.y * blockSize; worldContainer.addChild(platform); // Add platform blocks to worldData for (var x = 0; x < p.width; x++) { for (var y = 0; y < p.height; y++) { var gridX = p.x + x; var gridY = p.y + y; if (gridY < worldHeight && gridX < worldWidth) { if (!worldData[gridY]) worldData[gridY] = []; worldData[gridY][gridX] = 'stone'; } } } } // Save world data after creating platforms pixelWorlds.saveWorld(pixelWorlds.currentWorld, worldData); } // Main game loop game.update = function () { // Only update game elements if the game has started if (gameStarted) { // --- Main Door Logic Start --- // Find all main door blocks in the world and check if player is at any of them if (typeof player.lastWasAtDoor === "undefined") player.lastWasAtDoor = false; var atDoor = false; for (var y = 0; y < worldData.length; y++) { for (var x = 0; x < worldData[y].length; x++) { if (worldData[y][x] === 'main_door') { var doorX = x * blockSize + blockSize / 2; var doorY = y * blockSize + blockSize / 2; var dx = Math.abs(player.x - doorX); var dy = Math.abs(player.y - doorY); if (dx < blockSize * 0.7 && dy < blockSize * 0.7) { atDoor = true; } } } } // Trigger world enter menu on entering any main door if (!player.lastWasAtDoor && atDoor) { worldEnterMenu.show(); gameStarted = false; } player.lastWasAtDoor = atDoor; // --- Main Door Logic End --- // Update player player.update(); // Update character // Handle character movement based on controlState if (controlState) { if (controlState.left) { character.startMoving(-1); } else if (controlState.right) { character.startMoving(1); } else { character.stopMoving(); } if (controlState.jump) { character.jump(); controlState.jump = false; // Only jump once per press } } character.update(); // Simple AI: Make character move back and forth if (LK.ticks % 120 === 0 && !dragTarget) { // Change direction every 2 seconds (only if not being controlled by player) character.startMoving(character.direction * -1); } // Save game data periodically if (LK.ticks % 300 === 0) { // Convert worldData to string before storing pixelWorlds.saveWorld(pixelWorlds.currentWorld, worldData); storage.inventory = inventory; } } }; // Create main menu var mainMenu = new MainMenu(); mainMenu.x = 0; mainMenu.y = 0; game.addChild(mainMenu); // Create world enter menu var worldEnterMenu = new WorldEnterMenu(); worldEnterMenu.x = 0; worldEnterMenu.y = 0; worldEnterMenu.visible = false; game.addChild(worldEnterMenu); // Show main menu to start mainMenu.show(); // Remove auto-show of worldEnterMenu. Instead, show it when player enters the main door. // Start background music LK.playMusic('bgmusic'); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
worldData: "undefined",
playerPosition: {
x: 1024,
y: 1600
},
inventory: {}
});
/****
* Classes
****/
var Block = Container.expand(function (type, size) {
var self = Container.call(this);
self.type = type;
self.size = size || 64;
// Use 'bedrock' skin for bedrock blocks, otherwise use type as asset
var assetType = type === 'bedrock' ? 'bedrock' : type;
var graphics = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5,
width: self.size,
height: self.size
});
self.down = function (x, y, obj) {
if (currentTool === 'break') {
self.breakBlock();
}
};
self.breakBlock = function () {
// Make main door and bedrock blocks unbreakable
if (self.type === 'main_door' || self.type === 'bedrock') {
// Optionally play a sound or show a message here
return;
}
// Add to inventory
inventory[self.type] = (inventory[self.type] || 0) + 1;
updateInventoryDisplay();
// Play break sound
LK.getSound('break').play();
// Remove from world
var gridX = Math.floor(self.x / blockSize);
var gridY = Math.floor(self.y / blockSize);
if (worldData[gridY] && worldData[gridY][gridX] !== undefined && worldData[gridY][gridX] !== null) {
worldData[gridY][gridX] = null;
self.destroy();
}
// Save world data
// Convert worldData to string before storing
storage.worldData = JSON.stringify(worldData);
};
return self;
});
var Button = Container.expand(function (text, callback) {
var self = Container.call(this);
var background = self.attachAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5
});
self.buttonText = new Text2(text, {
size: 36,
fill: 0xFFFFFF
});
self.buttonText.anchor.set(0.5, 0.5);
self.addChild(self.buttonText);
self.callback = callback;
self.down = function (x, y, obj) {
if (self.callback) {
self.callback();
}
};
return self;
});
var Character = Container.expand(function () {
var self = Container.call(this);
// Create character sprite
var sprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0,
width: 80,
height: 100
});
// Character properties
self.direction = 1; // 1 = right, -1 = left
self.isMoving = false;
self.speed = 4;
// Animation properties
self.frameTime = 0;
self.frameRate = 8; // frames per second
// Change direction method
self.faceDirection = function (dir) {
if (dir !== self.direction) {
self.direction = dir;
sprite.scale.x = self.direction;
}
};
// Start/stop movement
self.startMoving = function (dir) {
self.isMoving = true;
self.faceDirection(dir);
};
self.stopMoving = function () {
self.isMoving = false;
};
// Update method - called every frame
self.update = function () {
// Store last position for collision detection
var lastY = self.y;
var lastX = self.x;
// Handle movement
if (self.isMoving) {
self.x += self.speed * self.direction;
// Update animation
self.frameTime += 1 / 60;
if (self.frameTime >= 1 / self.frameRate) {
self.frameTime = 0;
// We would change animation frame here if we had sprite frames
}
}
// Keep character in bounds
if (self.x < 50) self.x = 50;
if (self.x > 2000) self.x = 2000;
// --- Begin Physics for Character ---
if (typeof self.velocityY === "undefined") self.velocityY = 0;
if (typeof self.lastOnGround === "undefined") self.lastOnGround = false;
// Gravity
var gravityForce = 1.2;
self.velocityY += gravityForce;
// Limit max fall speed
if (self.velocityY > 32) self.velocityY = 32;
// Move vertically
self.y += self.velocityY;
// Check for ground collision
var gridX = Math.floor(self.x / blockSize);
var gridY = Math.floor((self.y + 10) / blockSize);
var onGround = false;
for (var checkX = gridX - 1; checkX <= gridX + 1; checkX++) {
if (checkX >= 0 && gridY >= 0 && gridY < worldData.length && checkX < (worldData[gridY] ? worldData[gridY].length : 0) && worldData[gridY] && worldData[gridY][checkX] && worldData[gridY][checkX] !== 'water') {
var distX = Math.abs(self.x - (checkX * blockSize + blockSize / 2));
if (distX < blockSize * 0.8) {
// Snap to top of block
self.y = gridY * blockSize - 10;
self.velocityY = 0;
onGround = true;
break;
}
}
}
// Check if we just landed on a platform
if (!self.lastOnGround && onGround) {
self.velocityY = 0;
self.y = Math.floor(self.y / blockSize) * blockSize - 10;
}
self.lastOnGround = onGround;
// --- End Physics for Character ---
// Check for horizontal collisions
if (lastX !== self.x) {
var checkGridY = Math.floor((self.y - 50) / blockSize); // Check at character's mid height
var newGridX = Math.floor(self.x / blockSize);
// Check if there's a block at character's new position
if (checkGridY >= 0 && checkGridY < worldData.length && newGridX >= 0 && newGridX < worldData[checkGridY].length && worldData[checkGridY][newGridX]) {
// Collision detected, revert to previous position
self.x = lastX;
self.isMoving = false;
}
}
};
// Interactive events
self.down = function (x, y, obj) {
// Handle touch down on character
self.startDrag();
// Convert to world container's coordinate system for proper positioning
var worldX = obj.parent.toGlobal(obj.position).x;
var worldY = obj.parent.toGlobal(obj.position).y;
// Determine initial direction based on touch position
if (x > self.width / 2) {
self.faceDirection(1); // Face right
} else {
self.faceDirection(-1); // Face left
}
};
// Add touch controls for character
self.startDrag = function () {
self.isDragging = true;
};
self.stopDrag = function () {
self.isDragging = false;
self.isMoving = false;
};
// Add jump functionality
self.jump = function () {
// Find where the player is standing
var gridX = Math.floor(self.x / blockSize);
var gridY = Math.floor((self.y + 10) / blockSize);
// Check if character is on ground
var onGround = false;
for (var checkX = gridX - 1; checkX <= gridX + 1; checkX++) {
if (checkX >= 0 && gridY >= 0 && gridY < worldData.length && checkX < (worldData[gridY] ? worldData[gridY].length : 0) && worldData[gridY] && worldData[gridY][checkX] && worldData[gridY][checkX] !== 'water') {
var distX = Math.abs(self.x - (checkX * blockSize + blockSize / 2));
if (distX < blockSize * 0.8) {
onGround = true;
break;
}
}
}
if (onGround) {
// Apply upward force when jumping
self.velocityY = -22;
}
};
self.drag = function (x, y) {
if (self.isDragging) {
// Convert global coordinates to character's local frame
var localX = x - game.toLocal(self.parent.toGlobal(self.position)).x + self.x;
// Calculate difference for movement threshold
var diffX = localX - self.x;
// Determine direction based on current position and touch position
if (diffX > 10) {
self.faceDirection(1);
self.isMoving = true;
} else if (diffX < -10) {
self.faceDirection(-1);
self.isMoving = true;
} else {
self.isMoving = false;
}
}
};
return self;
});
var ControlButton = Container.expand(function (text, callback, width, height) {
var self = Container.call(this);
width = width || 150;
height = height || 150;
// Create button background
var background = self.attachAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5,
width: width,
height: height
});
// Create button text
self.buttonText = new Text2(text, {
size: 48,
fill: 0xFFFFFF
});
self.buttonText.anchor.set(0.5, 0.5);
self.addChild(self.buttonText);
// Store callback function
self.callback = callback;
// Add control type to identify button function
self.controlType = '';
if (text === '←') self.controlType = 'left';else if (text === '→') self.controlType = 'right';else if (text === '↑') self.controlType = 'jump';else if (text === '■') self.controlType = 'stop';
// Button interaction
self.down = function (x, y, obj) {
if (self.callback) {
background.alpha = 0.7;
self.callback();
// Set control state for continuous button press
if (self.controlType && controlState) {
if (self.controlType === 'left') {
controlState.left = true;
controlState.right = false;
} else if (self.controlType === 'right') {
controlState.right = true;
controlState.left = false;
} else if (self.controlType === 'jump') {
controlState.jump = true;
} else if (self.controlType === 'stop') {
controlState.left = false;
controlState.right = false;
}
}
}
};
self.up = function (x, y, obj) {
background.alpha = 1.0;
// Clear control state when button is released
if (self.controlType && controlState) {
if (self.controlType === 'left') {
controlState.left = false;
} else if (self.controlType === 'right') {
controlState.right = false;
} else if (self.controlType === 'jump') {
controlState.jump = false;
}
}
};
return self;
});
var InventorySlot = Container.expand(function (index, type) {
var self = Container.call(this);
self.index = index;
self.type = type;
var background = self.attachAsset('inventorySlot', {
anchorX: 0.5,
anchorY: 0.5
});
if (type) {
var blockIcon = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5,
width: 60,
height: 60
});
}
self.countText = new Text2("0", {
size: 24,
fill: 0xFFFFFF
});
self.countText.anchor.set(1, 1);
self.countText.x = 30;
self.countText.y = 30;
self.addChild(self.countText);
self.updateCount = function (count) {
self.countText.setText(count.toString());
};
self.down = function (x, y, obj) {
selectInventorySlot(self.index);
};
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
// Create a semi-transparent background overlay
var overlay = LK.getAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 0.7
});
overlay.tint = 0x000000;
self.addChild(overlay);
// Game title
self.title = new Text2("Pixel Realms", {
size: 120,
fill: 0xFFFFFF
});
self.title.anchor.set(0.5, 0.5);
self.title.x = 2048 / 2;
self.title.y = 800;
self.addChild(self.title);
// Start game button
self.startButton = new Button("Start Game", function () {
self.hide();
worldEnterMenu.show();
});
self.startButton.x = 2048 / 2;
self.startButton.y = 1200;
self.addChild(self.startButton);
// Add animated elements
self.show = function () {
self.visible = true;
// Reset positions for animation
self.title.y = 600;
self.title.alpha = 0;
self.startButton.y = 1300;
self.startButton.alpha = 0;
// Animate title
tween(self.title, {
y: 800,
alpha: 1
}, {
duration: 800,
easing: tween.easeOutBack
});
// Animate button with slight delay
tween(self.startButton, {
y: 1200,
alpha: 1
}, {
duration: 800,
easing: tween.easeOutBack
});
};
self.hide = function () {
// Animate out
tween(self.title, {
y: 600,
alpha: 0
}, {
duration: 500,
easing: tween.easeInBack
});
tween(self.startButton, {
y: 1300,
alpha: 0
}, {
duration: 500,
easing: tween.easeInBack,
onFinish: function onFinish() {
self.visible = false;
}
});
};
return self;
});
var Platform = Container.expand(function (width, height) {
var self = Container.call(this);
self.width = width || 5;
self.height = height || 1;
// Create platform blocks
for (var x = 0; x < self.width; x++) {
for (var y = 0; y < self.height; y++) {
var block = new Block('stone', blockSize);
block.x = x * blockSize + blockSize / 2;
block.y = y * blockSize + blockSize / 2;
self.addChild(block);
}
}
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1,
width: 60,
height: 120
});
// Movement properties
self.speed = 5;
self.velocity = {
x: 0,
y: 0
};
self.gravity = 0.5;
self.jumping = false;
self.grounded = false;
self.move = function (direction) {
if (direction === 'left') {
self.velocity.x = -self.speed;
} else if (direction === 'right') {
self.velocity.x = self.speed;
}
};
self.stopMove = function () {
self.velocity.x = 0;
};
self.jump = function () {
if (self.grounded) {
self.velocity.y = -22;
self.grounded = false;
self.jumping = true;
}
};
self.update = function () {
// --- Begin Physics for Player ---
if (typeof self.velocity === "undefined") self.velocity = {
x: 0,
y: 0
};
if (typeof self.gravity === "undefined") self.gravity = 1.2;
if (typeof self.grounded === "undefined") self.grounded = false;
if (!self.grounded) {
self.velocity.y += self.gravity;
if (self.velocity.y > 32) self.velocity.y = 32;
}
self.x += self.velocity.x;
self.y += self.velocity.y;
// --- End Physics for Player ---
// Check for ground collision
var gridX = Math.floor(self.x / blockSize);
var gridY = Math.floor((self.y + 10) / blockSize);
// Simple collision check with the block below
if (gridY >= 0 && gridY < worldData.length && gridX >= 0 && worldData[gridY] && gridX < worldData[gridY].length && worldData[gridY][gridX] && worldData[gridY][gridX] !== 'water') {
if (self.velocity.y > 0) {
self.y = gridY * blockSize - 10;
self.velocity.y = 0;
self.grounded = true;
self.jumping = false;
}
} else {
self.grounded = false;
}
// Update camera to follow player
updateCamera();
// Save player position periodically
if (LK.ticks % 60 === 0) {
storage.playerPosition = {
x: self.x,
y: self.y
};
}
};
return self;
});
var WorldEnterMenu = Container.expand(function () {
var self = Container.call(this);
// Create a semi-transparent background
var overlay = LK.getAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5,
width: 2048,
height: 2732,
alpha: 0.8
});
overlay.tint = 0x000022;
self.addChild(overlay);
// World title
self.title = new Text2("Enter World", {
size: 100,
fill: 0xFFFFFF
});
self.title.anchor.set(0.5, 0.5);
self.title.x = 2048 / 2;
self.title.y = 600;
self.addChild(self.title);
// World description
self.description = new Text2("Select your world to start building", {
size: 48,
fill: 0xCCCCCC
});
self.description.anchor.set(0.5, 0.5);
self.description.x = 2048 / 2;
self.description.y = 720;
self.addChild(self.description);
// World selection buttons
self.createWorldButton = new Button("Create New World", function () {
// Prompt for world name (simple prompt, can be improved)
var worldName = "world" + Math.floor(Math.random() * 10000);
// Generate new world and save with name
var newWorldData = generateWorld();
pixelWorlds.saveWorld(worldName, newWorldData);
worldData = newWorldData;
pixelWorlds.currentWorld = worldName;
// Reset player position
player.x = 1024;
player.y = 1600;
storage.playerPosition = {
x: player.x,
y: player.y
};
// Move character to main door entrance (bottom center) on new world creation
if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") {
setCharacterToMainDoor();
}
// Reset inventory
inventory = {
"grass": 10,
"stone": 10,
"wood": 10,
"water": 5
};
storage.inventory = inventory;
// Start game
self.hide();
gameStarted = true;
initializeWorld();
setupUI();
});
self.createWorldButton.x = 2048 / 2;
self.createWorldButton.y = 1000;
self.addChild(self.createWorldButton);
// Add a world selection menu for pixel worlds
self.loadWorldButton = new Button("Select World", function () {
// Show a simple world selection overlay
var overlay = new Container();
var bg = LK.getAsset('buttonBg', {
anchorX: 0.5,
anchorY: 0.5,
width: 1200,
height: 1000,
alpha: 0.95
});
bg.tint = 0x222244;
overlay.addChild(bg);
overlay.x = 2048 / 2;
overlay.y = 1200;
// List all worlds
var worlds = pixelWorlds.listWorlds();
if (worlds.length === 0) {
var noWorlds = new Text2("No worlds found", {
size: 60,
fill: 0xffffff
});
noWorlds.anchor.set(0.5, 0.5);
noWorlds.y = 0;
overlay.addChild(noWorlds);
} else {
for (var i = 0; i < worlds.length; i++) {
(function (worldName, idx) {
var btn = new Button(worldName, function () {
// Switch to selected world
pixelWorlds.switchWorld(worldName);
// Move character to main door entrance (bottom center) on world select
if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") {
setCharacterToMainDoor();
}
overlay.visible = false;
self.hide();
gameStarted = true;
});
btn.x = 0;
btn.y = -400 + idx * 120;
overlay.addChild(btn);
})(worlds[i], i);
}
}
// Add close button
var closeBtn = new Button("Close", function () {
overlay.visible = false;
});
closeBtn.x = 0;
closeBtn.y = 500;
overlay.addChild(closeBtn);
LK.gui.center.addChild(overlay);
});
self.loadWorldButton.x = 2048 / 2;
self.loadWorldButton.y = 1150;
self.addChild(self.loadWorldButton);
self.backButton = new Button("Back to Menu", function () {
self.hide();
mainMenu.show();
});
self.backButton.x = 2048 / 2;
self.backButton.y = 1400;
self.addChild(self.backButton);
// Show animation
self.show = function () {
self.visible = true;
// Reset positions for animation
self.title.y = 400;
self.title.alpha = 0;
self.description.y = 620;
self.description.alpha = 0;
self.createWorldButton.y = 1100;
self.createWorldButton.alpha = 0;
self.loadWorldButton.y = 1250;
self.loadWorldButton.alpha = 0;
self.backButton.y = 1500;
self.backButton.alpha = 0;
// Animate title
tween(self.title, {
y: 600,
alpha: 1
}, {
duration: 600,
easing: tween.easeOutBack
});
// Animate description
tween(self.description, {
y: 720,
alpha: 1
}, {
duration: 600,
delay: 100,
easing: tween.easeOutBack
});
// Animate buttons
tween(self.createWorldButton, {
y: 1000,
alpha: 1
}, {
duration: 600,
delay: 200,
easing: tween.easeOutBack
});
tween(self.loadWorldButton, {
y: 1150,
alpha: 1
}, {
duration: 600,
delay: 300,
easing: tween.easeOutBack
});
tween(self.backButton, {
y: 1400,
alpha: 1
}, {
duration: 600,
delay: 400,
easing: tween.easeOutBack
});
};
// Hide animation
self.hide = function () {
// Animate out
tween(self.title, {
y: 400,
alpha: 0
}, {
duration: 400,
easing: tween.easeInBack
});
tween(self.description, {
y: 620,
alpha: 0
}, {
duration: 400,
easing: tween.easeInBack
});
tween(self.createWorldButton, {
y: 1100,
alpha: 0
}, {
duration: 400,
easing: tween.easeInBack
});
tween(self.loadWorldButton, {
y: 1250,
alpha: 0
}, {
duration: 400,
easing: tween.easeInBack
});
tween(self.backButton, {
y: 1500,
alpha: 0
}, {
duration: 400,
easing: tween.easeInBack,
onFinish: function onFinish() {
self.visible = false;
}
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB // Sky blue background
});
/****
* Game Code
****/
//{bedrock_skin}
// Make sure JSON is defined for storage operations
// Game constants
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
var JSON = {
parse: function parse(text) {
return LK.parseJSON(text);
},
stringify: function stringify(obj) {
// Convert JavaScript object to a JSON string
var str = '';
if (obj === null) return 'null';
if (typeof obj === 'undefined') return undefined;
if (typeof obj === 'string') return '"' + obj.replace(/"/g, '\\"') + '"';
if (typeof obj === 'number' || typeof obj === 'boolean') return obj.toString();
if (Array.isArray(obj)) {
str = '[';
for (var i = 0; i < obj.length; i++) {
str += (i > 0 ? ',' : '') + JSON.stringify(obj[i]);
}
return str + ']';
}
if (_typeof(obj) === 'object') {
str = '{';
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
str += (i > 0 ? ',' : '') + '"' + key + '":' + JSON.stringify(obj[key]);
}
return str + '}';
}
return '';
}
};
var WorldGenerator = function WorldGenerator() {
// Generate a new world with more advanced terrain features
this.generate = function (width, height, blockSize) {
var data = [];
// Initialize with empty arrays
for (var y = 0; y < height; y++) {
data[y] = [];
for (var x = 0; x < width; x++) {
data[y][x] = null;
}
}
// Add bedrock border (unbreakable) around the world
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
if (y === 0 || y === height - 1 || x === 0 || x === width - 1) {
data[y][x] = 'bedrock';
}
}
}
// Generate terrain using simple noise
var terrain = this.generateTerrain(width, height);
// Apply terrain to world data
for (var x = 0; x < width; x++) {
var groundHeight = Math.floor(terrain[x] * height * 0.4) + Math.floor(height * 0.5);
// Fill all blocks below the surface with 'ground' (dirt)
for (var y = groundHeight; y < height; y++) {
if (y === groundHeight) {
// Don't overwrite bedrock border
if (data[y][x] !== 'bedrock') data[y][x] = 'grass';
} else {
if (data[y][x] !== 'bedrock') data[y][x] = 'ground';
}
}
// Generate caves
this.generateCaves(data, x, groundHeight, height);
}
// Add trees
this.addTrees(data, width, height);
// Add water bodies
this.addWater(data, width, height);
return data;
};
// Generate basic terrain height map using simple noise
this.generateTerrain = function (width, height) {
var terrain = [];
var smoothness = 8; // Higher = smoother terrain
// Start with random height
terrain[0] = Math.random();
// Generate rest using midpoint displacement-like approach
for (var x = 1; x < width; x++) {
// Get previous height with some randomness
var prevHeight = terrain[x - 1];
var randomFactor = (Math.random() - 0.5) * 2 / smoothness;
// New height with constraints
terrain[x] = Math.max(0.1, Math.min(0.9, prevHeight + randomFactor));
// Add some hills/mountains occasionally
if (Math.random() < 0.05) {
var hillHeight = 0.1 + Math.random() * 0.2;
var hillWidth = 3 + Math.floor(Math.random() * 5);
// Create a hill centered at x
for (var h = 0; h < hillWidth && x + h < width; h++) {
var offset = hillHeight * Math.sin(h / hillWidth * Math.PI);
if (x + h < width) {
terrain[x + h] = Math.max(0.1, Math.min(0.9, terrain[x + h] - offset));
}
}
// Skip ahead
x += hillWidth;
}
}
return terrain;
};
// Add random caves under the terrain
this.generateCaves = function (data, x, groundHeight, height) {
// Random caves deeper underground
if (groundHeight + 5 < height) {
for (var c = 0; c < 2; c++) {
if (Math.random() < 0.05) {
var caveY = groundHeight + 5 + Math.floor(Math.random() * (height - groundHeight - 10));
var caveSize = 1 + Math.floor(Math.random() * 3);
for (var cy = caveY; cy < caveY + caveSize && cy < height; cy++) {
if (data[cy] && data[cy][x]) {
data[cy][x] = null;
}
}
}
}
}
};
// Add trees on the surface
this.addTrees = function (data, width, height) {
for (var x = 0; x < width; x++) {
// Find the ground level
var groundY = 0;
for (var y = 0; y < height; y++) {
if (data[y] && data[y][x] === 'grass') {
groundY = y;
break;
}
}
// Add random trees (if we found ground and not at the edge)
if (groundY > 0 && x > 2 && x < width - 2 && Math.random() < 0.1) {
var treeHeight = 3 + Math.floor(Math.random() * 3);
// Remove grass block below the tree (set to null)
if (groundY + 1 < height && data[groundY + 1][x] === 'grass') {
data[groundY + 1][x] = null;
}
// Tree trunk
for (var ty = 1; ty <= treeHeight; ty++) {
if (groundY - ty >= 0) {
data[groundY - ty][x] = 'wood';
}
}
// Tree top (add leaves here)
var treeTop = groundY - treeHeight - 1;
if (treeTop >= 0) {
// Add leaves in a 3x3 area centered on the trunk top
for (var ly = -1; ly <= 1; ly++) {
for (var lx = -1; lx <= 1; lx++) {
var leafX = x + lx;
var leafY = treeTop + ly;
if (leafX >= 0 && leafX < width && leafY >= 0 && leafY < height && (ly !== 0 || lx !== 0) // Don't overwrite trunk top
) {
data[leafY][leafX] = 'Leaf'; // Use 'Leaf' as leaf block
}
}
}
// Place trunk top (wood) in the center
data[treeTop][x] = 'wood';
// Optionally, add a single leaf block above the trunk top
if (treeTop - 1 >= 0) {
data[treeTop - 1][x] = 'Leaf';
}
}
}
}
};
// Add water bodies (lakes, rivers)
this.addWater = function (data, width, height) {
// Add some water pools/lakes
var lakeAttempts = Math.floor(width / 20);
for (var l = 0; l < lakeAttempts; l++) {
var lakeX = 5 + Math.floor(Math.random() * (width - 10));
var lakeWidth = 3 + Math.floor(Math.random() * 5);
// Find ground level at lakeX
var lakeY = 0;
for (var y = 0; y < height; y++) {
if (data[y] && data[y][lakeX] === 'grass') {
lakeY = y;
break;
}
}
// Create lake
if (lakeY > 0) {
for (var wx = 0; wx < lakeWidth && lakeX + wx < width; wx++) {
if (data[lakeY] && data[lakeY][lakeX + wx]) {
data[lakeY][lakeX + wx] = 'water';
// Sometimes make deeper water
if (Math.random() < 0.5 && lakeY + 1 < height) {
data[lakeY + 1][lakeX + wx] = 'water';
}
}
}
}
}
};
return this;
};
var blockSize = 64;
var worldWidth = 100; // 100 blocks horizontal
var worldHeight = 54; // 54 blocks vertical
var gravity = 0;
// Game state
var gameStarted = false;
// Parse worldData from storage if it exists, checking for undefined/null values
// Pixel World System: Support for multiple worlds and world switching
var pixelWorlds = {
currentWorld: "default",
worlds: {},
// Load world data from storage or generate new
loadWorld: function loadWorld(worldName) {
var key = "pixelWorld_" + worldName;
var data;
try {
data = storage[key] && storage[key] !== "undefined" ? JSON.parse(storage[key]) : null;
} catch (e) {
data = null;
}
if (!data) {
data = generateWorld();
storage[key] = JSON.stringify(data);
}
this.worlds[worldName] = data;
this.currentWorld = worldName;
return data;
},
// Save current world data to storage
saveWorld: function saveWorld(worldName, data) {
var key = "pixelWorld_" + worldName;
storage[key] = JSON.stringify(data);
this.worlds[worldName] = data;
},
// Switch to a different world
switchWorld: function switchWorld(worldName) {
worldData = this.loadWorld(worldName);
this.currentWorld = worldName;
initializeWorld();
// Move character to main door entrance (bottom center) on world switch
if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") {
setCharacterToMainDoor();
}
setupUI();
},
// List all saved worlds (by checking storage keys)
listWorlds: function listWorlds() {
var result = [];
for (var k in storage) {
if (k.indexOf("pixelWorld_") === 0) {
result.push(k.replace("pixelWorld_", ""));
}
}
return result;
}
};
// Use pixelWorlds to load the default world at start
var worldData = pixelWorlds.loadWorld("default");
var inventory = storage.inventory || {
"grass": 0,
"stone": 0,
"wood": 0,
"water": 0
};
var currentTool = 'place'; // 'place' or 'break'
var selectedBlockType = 'grass';
var selectedInventorySlot = 0;
// Game containers
var worldContainer = new Container();
var uiContainer = new Container();
var inventoryContainer = new Container();
var toolbarContainer = new Container();
game.addChild(worldContainer);
game.addChild(uiContainer);
// Create player
var player = new Player();
player.x = storage.playerPosition ? storage.playerPosition.x : 1024;
player.y = storage.playerPosition ? storage.playerPosition.y : 1600;
worldContainer.addChild(player);
// Create character at the main door entrance (bottom center)
var character = new Character();
// Find the main door entrance (bottom center)
function setCharacterToMainDoor() {
var doorGridX = Math.floor(worldWidth / 2);
var doorGridY = worldHeight - 2;
character.x = doorGridX * blockSize + blockSize / 2;
character.y = doorGridY * blockSize + blockSize / 2;
}
setCharacterToMainDoor();
worldContainer.addChild(character);
// Initialize world blocks
function initializeWorld() {
// Clear any existing blocks
while (worldContainer.children.length > 1) {
// Keep player
worldContainer.removeChildAt(1);
}
// Place blocks based on worldData
for (var y = 0; y < worldData.length; y++) {
for (var x = 0; x < worldData[y].length; x++) {
if (worldData[y][x]) {
var blockType = worldData[y][x];
// If this is a main door location, use 'main_door' type
if (blockType === 'main_door') {
var block = new Block('main_door', blockSize);
} else {
var block = new Block(blockType, blockSize);
}
block.x = x * blockSize + blockSize / 2;
block.y = y * blockSize + blockSize / 2;
worldContainer.addChild(block);
}
}
}
// Place a main door at all world enter locations if not present
// For this game, we define the main doors as blocks at the bottom center, top center, left center, and right center of the world
var entrances = [{
x: Math.floor(worldWidth / 2),
y: worldHeight - 2
},
// bottom center
{
x: Math.floor(worldWidth / 2),
y: 1
},
// top center
{
x: 1,
y: Math.floor(worldHeight / 2)
},
// left center
{
x: worldWidth - 2,
y: Math.floor(worldHeight / 2)
} // right center
];
for (var i = 0; i < entrances.length; i++) {
var ex = entrances[i].x;
var ey = entrances[i].y;
if (!worldData[ey]) worldData[ey] = [];
if (worldData[ey][ex] !== 'main_door') {
worldData[ey][ex] = 'main_door';
var mainDoorBlock = new Block('main_door', blockSize);
mainDoorBlock.x = ex * blockSize + blockSize / 2;
mainDoorBlock.y = ey * blockSize + blockSize / 2;
worldContainer.addChild(mainDoorBlock);
}
}
// Create platforms if this is a new world
if (!storage.platformsCreated) {
createPlatforms();
storage.platformsCreated = true;
}
}
// Generate a new world
function generateWorld() {
var worldGen = new WorldGenerator();
var data = worldGen.generate(worldWidth, worldHeight, blockSize);
// Place a main door at the bottom center of the world
var doorGridX = Math.floor(worldWidth / 2);
var doorGridY = worldHeight - 2;
if (!data[doorGridY]) data[doorGridY] = [];
data[doorGridY][doorGridX] = 'main_door';
// Place main doors at all four world entrances (bottom center, top center, left center, right center)
var entrances = [{
x: Math.floor(worldWidth / 2),
y: worldHeight - 2
},
// bottom center
{
x: Math.floor(worldWidth / 2),
y: 1
},
// top center
{
x: 1,
y: Math.floor(worldHeight / 2)
},
// left center
{
x: worldWidth - 2,
y: Math.floor(worldHeight / 2)
} // right center
];
for (var i = 0; i < entrances.length; i++) {
var ex = entrances[i].x;
var ey = entrances[i].y;
if (!data[ey]) data[ey] = [];
data[ey][ex] = 'main_door';
}
// Save the generated world
pixelWorlds.saveWorld(pixelWorlds.currentWorld, data);
// Give player some starter blocks
inventory = {
"grass": 10,
"stone": 10,
"wood": 10,
"water": 5
};
storage.inventory = inventory;
return data;
}
// Setup UI
function setupUI() {
// Create inventory bar
setupInventory();
// Create tool selection buttons
setupToolbar();
// Create control buttons (left, right, jump)
setupControls();
// Create main menu button
setupMainMenuButton();
}
// Add main menu button to return to menu
function setupMainMenuButton() {
var menuButton = new Button("Menu", function () {
// Hide game elements
gameStarted = false;
// Show main menu
mainMenu.show();
});
menuButton.x = 120;
menuButton.y = 100;
LK.gui.topRight.addChild(menuButton);
// Add a Change World button for switching between 'old world' and 'new world'
var changeWorldButton = new Button("Change World", function () {
// If current world is 'old world', switch to 'new world', else switch to 'old world'
var nextWorld = pixelWorlds.currentWorld === "old world" ? "new world" : "old world";
// If the world does not exist, generate it
if (!pixelWorlds.worlds[nextWorld]) {
var newWorldData = generateWorld();
pixelWorlds.saveWorld(nextWorld, newWorldData);
}
pixelWorlds.switchWorld(nextWorld);
// Optionally, reset player position for new world
player.x = 1024;
player.y = 1600;
storage.playerPosition = {
x: player.x,
y: player.y
};
// Move character to main door entrance (bottom center) on Change World
if (typeof character !== "undefined" && typeof setCharacterToMainDoor === "function") {
setCharacterToMainDoor();
}
});
// Move the button to the top left, but not in the top 100x100 area
changeWorldButton.x = 120;
changeWorldButton.y = 200;
LK.gui.topLeft.addChild(changeWorldButton);
// Add a character control button
var characterButton = new Button("Character", function () {
// Show character info or focus on character
var targetX = -character.x + 2048 / 2;
var targetY = -character.y + 2732 / 2;
// Animate the camera movement to the character
tween(worldContainer, {
x: targetX,
y: targetY
}, {
duration: 500,
easing: tween.easeOutQuad
});
});
characterButton.x = 120;
characterButton.y = 200;
LK.gui.topRight.addChild(characterButton);
}
function setupInventory() {
inventoryContainer = new Container();
var blockTypes = ['grass', 'stone', 'wood', 'water'];
var slotSpacing = 100;
// Create the background for selected slot
var selectedSlotBg = LK.getAsset('selectedSlot', {
anchorX: 0.5,
anchorY: 0.5
});
inventoryContainer.addChild(selectedSlotBg);
// Create inventory slots
for (var i = 0; i < blockTypes.length; i++) {
var slot = new InventorySlot(i, blockTypes[i]);
slot.x = i * slotSpacing;
slot.countText.setText((inventory[blockTypes[i]] || 0).toString());
inventoryContainer.addChild(slot);
}
// Position the inventory at the top center
inventoryContainer.x = 2048 / 2 - (blockTypes.length - 1) * slotSpacing / 2;
inventoryContainer.y = 100;
// Create inventory title
var inventoryTitle = new Text2("Inventory", {
size: 40,
fill: 0xFFFFFF
});
inventoryTitle.anchor.set(0.5, 1);
inventoryTitle.x = (blockTypes.length - 1) * slotSpacing / 2;
inventoryTitle.y = -20;
inventoryContainer.addChild(inventoryTitle);
// Update selected slot visual
updateSelectedSlot();
LK.gui.top.addChild(inventoryContainer);
}
function setupToolbar() {
toolbarContainer = new Container();
// Place tool
var placeToolBtn = new Button("Place", function () {
currentTool = 'place';
updateToolbarSelection();
});
placeToolBtn.x = 0;
toolbarContainer.addChild(placeToolBtn);
// Break tool
var breakToolBtn = new Button("Break", function () {
currentTool = 'break';
updateToolbarSelection();
});
breakToolBtn.x = 250;
toolbarContainer.addChild(breakToolBtn);
// Position toolbar at bottom right
toolbarContainer.x = 2048 - 400;
toolbarContainer.y = 2732 - 100;
LK.gui.bottomRight.addChild(toolbarContainer);
// Update the initial tool selection
updateToolbarSelection();
}
function setupControls() {
// Container for player movement controls (bottom left)
var moveControls = new Container();
// Player Left
var leftBtn = new ControlButton("←", function () {
player.move('left');
});
leftBtn.x = 0;
leftBtn.y = 0;
moveControls.addChild(leftBtn);
// Player Stop
var stopBtn = new ControlButton("■", function () {
player.stopMove();
});
stopBtn.x = 100;
stopBtn.y = 0;
moveControls.addChild(stopBtn);
// Player Right
var rightBtn = new ControlButton("→", function () {
player.move('right');
});
rightBtn.x = 200;
rightBtn.y = 0;
moveControls.addChild(rightBtn);
// Position at bottom left
moveControls.x = 150;
moveControls.y = 2732 - 100;
LK.gui.bottomLeft.addChild(moveControls);
// Container for character controls (bottom left, above player controls)
var characterControls = new Container();
// Character Left
var charLeftBtn = new ControlButton("←", function () {
controlState.left = true;
controlState.right = false;
}, 150, 150);
charLeftBtn.x = 0;
charLeftBtn.y = 0;
characterControls.addChild(charLeftBtn);
// Character Stop
var charStopBtn = new ControlButton("■", function () {
controlState.left = false;
controlState.right = false;
}, 150, 150);
charStopBtn.x = 100;
charStopBtn.y = 0;
characterControls.addChild(charStopBtn);
// Character Right
var charRightBtn = new ControlButton("→", function () {
controlState.right = true;
controlState.left = false;
}, 150, 150);
charRightBtn.x = 200;
charRightBtn.y = 0;
characterControls.addChild(charRightBtn);
// Character Jump
var charJumpBtn = new ControlButton("↑", function () {
controlState.jump = true;
}, 150, 150);
charJumpBtn.x = 300;
charJumpBtn.y = 0;
characterControls.addChild(charJumpBtn);
// Position above player controls
characterControls.x = 150;
characterControls.y = 2732 - 250;
LK.gui.bottomLeft.addChild(characterControls);
// Container for action controls (bottom right)
var actionControls = new Container();
// Player Jump
var jumpBtn = new ControlButton("↑", function () {
player.jump();
});
jumpBtn.x = 0;
jumpBtn.y = 0;
actionControls.addChild(jumpBtn);
// Character Jump (alternative)
var characterJumpBtn = new ControlButton("C↑", function () {
character.jump();
controlState.jump = true;
});
characterJumpBtn.x = -200;
characterJumpBtn.y = 0;
actionControls.addChild(characterJumpBtn);
// Position at bottom right
actionControls.x = 2048 - 150;
actionControls.y = 2732 - 100;
LK.gui.bottomRight.addChild(actionControls);
}
function updateSelectedSlot() {
var selectedSlotBg = inventoryContainer.getChildAt(0);
var slot = inventoryContainer.getChildAt(selectedInventorySlot + 1);
if (slot) {
selectedSlotBg.x = slot.x;
selectedSlotBg.y = slot.y;
selectedBlockType = slot.type;
}
}
function updateToolbarSelection() {
var placeToolBtn = toolbarContainer.getChildAt(0);
var breakToolBtn = toolbarContainer.getChildAt(1);
if (currentTool === 'place') {
if (placeToolBtn && placeToolBtn.buttonText) {
placeToolBtn.buttonText.style = {
fill: 0xFFFF00
};
}
if (breakToolBtn && breakToolBtn.buttonText) {
breakToolBtn.buttonText.style = {
fill: 0xFFFFFF
};
}
} else {
if (placeToolBtn && placeToolBtn.buttonText) {
placeToolBtn.buttonText.style = {
fill: 0xFFFFFF
};
}
if (breakToolBtn && breakToolBtn.buttonText) {
breakToolBtn.buttonText.style = {
fill: 0xFFFF00
};
}
}
}
function selectInventorySlot(index) {
selectedInventorySlot = index;
updateSelectedSlot();
// Play select sound
LK.getSound('select').play();
}
function updateInventoryDisplay() {
for (var i = 1; i < inventoryContainer.children.length; i++) {
var slot = inventoryContainer.getChildAt(i);
if (slot && typeof slot.updateCount === 'function') {
slot.updateCount(inventory[slot.type] || 0);
} else if (slot && slot.countText) {
slot.countText.setText((inventory[slot.type] || 0).toString());
}
}
}
function updateCamera() {
// Calculate how much to offset the world to center the player
var targetX = -player.x + 2048 / 2;
var targetY = -player.y + 2732 / 2;
// Add bounds to prevent seeing outside the world
targetX = Math.min(0, Math.max(targetX, -(worldWidth * blockSize - 2048)));
targetY = Math.min(0, Math.max(targetY, -(worldHeight * blockSize - 2732)));
// Smooth camera movement
worldContainer.x = targetX;
worldContainer.y = targetY;
}
function placeBlock(x, y) {
// Convert screen position to world position
var worldX = x - worldContainer.x;
var worldY = y - worldContainer.y;
// Convert world position to grid position
var gridX = Math.floor(worldX / blockSize);
var gridY = Math.floor(worldY / blockSize);
// Check if we have this block type in inventory
if (inventory[selectedBlockType] <= 0) {
return;
}
// Check if position is valid
if (gridX < 0 || gridX >= worldWidth || gridY < 0 || gridY >= worldHeight) {
return;
}
// Check if space is empty
if (!worldData[gridY] || gridX >= worldData[gridY].length || gridX < 0 || gridY < 0 || worldData[gridY][gridX] !== null) {
return;
}
// Don't allow placing blocks where the player is standing
var playerGridX = Math.floor(player.x / blockSize);
var playerGridY = Math.floor(player.y / blockSize);
var playerGridYBottom = Math.floor((player.y - 60) / blockSize); // Check player's head position too
if (gridX === playerGridX && (gridY === playerGridY || gridY === playerGridYBottom)) {
return; // Can't place block where player is standing
}
// Place the block
worldData[gridY][gridX] = selectedBlockType;
// Remove from inventory
inventory[selectedBlockType]--;
updateInventoryDisplay();
// Create the block visually
var block = new Block(selectedBlockType, blockSize);
block.x = gridX * blockSize + blockSize / 2;
block.y = gridY * blockSize + blockSize / 2;
worldContainer.addChild(block);
// Play place sound
LK.getSound('place').play();
// Save world data
// Save the data directly to storage
pixelWorlds.saveWorld(pixelWorlds.currentWorld, worldData);
storage.inventory = inventory;
}
// Game event handlers
game.down = function (x, y, obj) {
if (!gameStarted) return; // Don't handle interactions if game hasn't started
if (currentTool === 'place') {
placeBlock(x, y);
}
// Check if we clicked on the character
if (obj && (obj === character || obj.parent === character)) {
character.startDrag();
dragTarget = character;
// Prevent placing blocks when clicking character
return;
}
};
// Add move handler for dragging character
game.move = function (x, y, obj) {
if (dragTarget === character) {
// Convert global coordinates to character's local space
var localX = x - worldContainer.x;
var localY = y - worldContainer.y;
// Determine movement direction based on touch position relative to character
if (localX > character.x + 10) {
character.startMoving(1); // Move right
} else if (localX < character.x - 10) {
character.startMoving(-1); // Move left
} else {
character.stopMoving(); // Stop if touch is directly on character
}
}
};
// Add up handler to stop dragging
game.up = function (x, y, obj) {
if (dragTarget === character) {
character.stopDrag();
character.stopMoving(); // Make sure character stops moving when touch is released
dragTarget = null;
}
};
// Initialize drag target variable
var dragTarget = null;
// Track control state for continuous button presses
var controlState = {
left: false,
right: false,
jump: false
};
// Create platforms in the world
function createPlatforms() {
// Create several platforms at different positions
var platforms = [{
x: 10,
y: 20,
width: 8,
height: 1
}, {
x: 25,
y: 18,
width: 6,
height: 1
}, {
x: 5,
y: 15,
width: 4,
height: 1
}, {
x: 15,
y: 12,
width: 5,
height: 1
}, {
x: 30,
y: 10,
width: 7,
height: 1
}];
for (var i = 0; i < platforms.length; i++) {
var p = platforms[i];
var platform = new Platform(p.width, p.height);
platform.x = p.x * blockSize;
platform.y = p.y * blockSize;
worldContainer.addChild(platform);
// Add platform blocks to worldData
for (var x = 0; x < p.width; x++) {
for (var y = 0; y < p.height; y++) {
var gridX = p.x + x;
var gridY = p.y + y;
if (gridY < worldHeight && gridX < worldWidth) {
if (!worldData[gridY]) worldData[gridY] = [];
worldData[gridY][gridX] = 'stone';
}
}
}
}
// Save world data after creating platforms
pixelWorlds.saveWorld(pixelWorlds.currentWorld, worldData);
}
// Main game loop
game.update = function () {
// Only update game elements if the game has started
if (gameStarted) {
// --- Main Door Logic Start ---
// Find all main door blocks in the world and check if player is at any of them
if (typeof player.lastWasAtDoor === "undefined") player.lastWasAtDoor = false;
var atDoor = false;
for (var y = 0; y < worldData.length; y++) {
for (var x = 0; x < worldData[y].length; x++) {
if (worldData[y][x] === 'main_door') {
var doorX = x * blockSize + blockSize / 2;
var doorY = y * blockSize + blockSize / 2;
var dx = Math.abs(player.x - doorX);
var dy = Math.abs(player.y - doorY);
if (dx < blockSize * 0.7 && dy < blockSize * 0.7) {
atDoor = true;
}
}
}
}
// Trigger world enter menu on entering any main door
if (!player.lastWasAtDoor && atDoor) {
worldEnterMenu.show();
gameStarted = false;
}
player.lastWasAtDoor = atDoor;
// --- Main Door Logic End ---
// Update player
player.update();
// Update character
// Handle character movement based on controlState
if (controlState) {
if (controlState.left) {
character.startMoving(-1);
} else if (controlState.right) {
character.startMoving(1);
} else {
character.stopMoving();
}
if (controlState.jump) {
character.jump();
controlState.jump = false; // Only jump once per press
}
}
character.update();
// Simple AI: Make character move back and forth
if (LK.ticks % 120 === 0 && !dragTarget) {
// Change direction every 2 seconds (only if not being controlled by player)
character.startMoving(character.direction * -1);
}
// Save game data periodically
if (LK.ticks % 300 === 0) {
// Convert worldData to string before storing
pixelWorlds.saveWorld(pixelWorlds.currentWorld, worldData);
storage.inventory = inventory;
}
}
};
// Create main menu
var mainMenu = new MainMenu();
mainMenu.x = 0;
mainMenu.y = 0;
game.addChild(mainMenu);
// Create world enter menu
var worldEnterMenu = new WorldEnterMenu();
worldEnterMenu.x = 0;
worldEnterMenu.y = 0;
worldEnterMenu.visible = false;
game.addChild(worldEnterMenu);
// Show main menu to start
mainMenu.show();
// Remove auto-show of worldEnterMenu. Instead, show it when player enters the main door.
// Start background music
LK.playMusic('bgmusic');
;
the character has a red hair, green t shirt and blue pant. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
wooden. In-Game asset. 2d. High contrast. No shadows
rock. In-Game asset. 2d. High contrast. No shadows
grasses. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
dirt. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
make the down side is square
bedrock. In-Game asset. 2d. High contrast. No shadows
left button. In-Game asset. 2d. High contrast. No shadows
right button. In-Game asset. 2d. High contrast. No shadows
up button. In-Game asset. 2d. High contrast. No shadows
sun. In-Game asset. 2d. High contrast. No shadows
moon. In-Game asset. 2d. High contrast. No shadows
cloud. In-Game asset. 2d. High contrast. No shadows
make a butterfly (horizontal). In-Game asset. 2d. High contrast. No shadows