User prompt
Oyuna mobil tuşlar ekle
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'storage.world = world;' Line Number: 283
User prompt
Please fix the bug: 'Uncaught TypeError: storage.setItem is not a function' in or related to this line: 'storage.setItem('world', world);' Line Number: 283
User prompt
Blokların doğma noktası ortada olsun
User prompt
Please fix the bug: 'Uncaught TypeError: storage.save is not a function' in or related to this line: 'storage.save('world', world);' Line Number: 280
User prompt
Please fix the bug: 'Uncaught TypeError: storage.set is not a function' in or related to this line: 'storage.set('world', world);' Line Number: 280
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'storage.world = world;' Line Number: 280
Code edit (1 edits merged)
Please save this source code
User prompt
MiniCraft: Block Builder
Initial prompt
Minecraft
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Block class: represents a single block in the world grid var Block = Container.expand(function () { var self = Container.call(this); self.blockType = 'grass'; // default, will be set on init self.gridX = 0; self.gridY = 0; // The block asset self.blockAsset = null; self.setType = function (type) { self.blockType = type; if (self.blockAsset) { self.removeChild(self.blockAsset); } self.blockAsset = self.attachAsset('block_' + type, { anchorX: 0.5, anchorY: 0.5 }); }; self.setGrid = function (x, y) { self.gridX = x; self.gridY = y; }; return self; }); // InventorySlot class: represents a selectable block type in the inventory var InventorySlot = Container.expand(function () { var self = Container.call(this); self.blockType = 'grass'; self.selected = false; // Slot background self.bg = self.attachAsset('inv_slot', { anchorX: 0.5, anchorY: 0.5 }); // Block icon self.icon = self.attachAsset('block_grass', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); // Selection highlight self.selectHighlight = self.attachAsset('block_select', { anchorX: 0.5, anchorY: 0.5 }); self.selectHighlight.alpha = 0; self.setType = function (type) { self.blockType = type; self.removeChild(self.icon); self.icon = self.attachAsset('block_' + type, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); self.addChild(self.icon); }; self.setSelected = function (sel) { self.selected = sel; self.selectHighlight.alpha = sel ? 0.7 : 0; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87ceeb // light blue sky }); /**** * Game Code ****/ // --- World/grid setup --- // Block types: grass, dirt, stone, water, wood, sand // Each block is a colored box shape, 120x120px // Selection highlight // Inventory slot background var BLOCK_SIZE = 120; var GRID_COLS = 16; // 16x16 visible grid (1920x1920), fits on iPad Pro with some margin var GRID_ROWS = 16; var WORLD_COLS = 32; // world is 32x32 blocks var WORLD_ROWS = 32; // The world data: 2D array of block types var world = []; // Try to load from storage, else generate new if (storage.world && storage.world.length === WORLD_ROWS) { for (var y = 0; y < WORLD_ROWS; y++) { world[y] = []; for (var x = 0; x < WORLD_COLS; x++) { world[y][x] = storage.world[y][x]; } } } else { // Generate a simple world: grass on top, dirt below, stone at bottom, some water and sand for (var y = 0; y < WORLD_ROWS; y++) { world[y] = []; for (var x = 0; x < WORLD_COLS; x++) { if (y === WORLD_ROWS - 1) { world[y][x] = 'stone'; } else if (y > WORLD_ROWS - 4) { world[y][x] = 'dirt'; } else if (y === WORLD_ROWS - 4) { world[y][x] = 'grass'; } else if (y > WORLD_ROWS - 8 && x > 5 && x < 10) { world[y][x] = 'water'; } else if (y > WORLD_ROWS - 8 && x > 20 && x < 25) { world[y][x] = 'sand'; } else { world[y][x] = 'air'; } } } } // The block types available to the player var blockTypes = ['grass', 'dirt', 'stone', 'water', 'wood', 'sand']; var blockTypeNames = { grass: 'Grass', dirt: 'Dirt', stone: 'Stone', water: 'Water', wood: 'Wood', sand: 'Sand' }; // The currently selected block type for placement var selectedBlockType = storage.selectedBlockType || 'grass'; // Camera offset (in grid units) // Center the camera on the world spawn (center of the world) var defaultCameraX = Math.floor((WORLD_COLS - GRID_COLS) / 2); var defaultCameraY = Math.floor((WORLD_ROWS - GRID_ROWS) / 2); var cameraX = typeof storage.cameraX === "number" ? storage.cameraX : defaultCameraX; var cameraY = typeof storage.cameraY === "number" ? storage.cameraY : defaultCameraY; // Clamp camera to world bounds function clampCamera() { if (cameraX < 0) cameraX = 0; if (cameraY < 0) cameraY = 0; if (cameraX > WORLD_COLS - GRID_COLS) cameraX = WORLD_COLS - GRID_COLS; if (cameraY > WORLD_ROWS - GRID_ROWS) cameraY = WORLD_ROWS - GRID_ROWS; } // --- Block rendering --- var blockLayer = new Container(); game.addChild(blockLayer); // 2D array of Block objects for visible grid var blockObjs = []; for (var y = 0; y < GRID_ROWS; y++) { blockObjs[y] = []; for (var x = 0; x < GRID_COLS; x++) { var block = new Block(); block.x = x * BLOCK_SIZE + BLOCK_SIZE / 2; block.y = y * BLOCK_SIZE + BLOCK_SIZE / 2 + 100; // leave space for inventory block.setGrid(x, y); blockLayer.addChild(block); blockObjs[y][x] = block; } } // Center the grid horizontally blockLayer.x = (2048 - GRID_COLS * BLOCK_SIZE) / 2; blockLayer.y = 0; // --- Inventory UI --- var inventoryBar = new Container(); LK.gui.bottom.addChild(inventoryBar); var invSlots = []; var invSlotMargin = 20; var invBarWidth = blockTypes.length * (130 + invSlotMargin) - invSlotMargin; for (var i = 0; i < blockTypes.length; i++) { var slot = new InventorySlot(); slot.setType(blockTypes[i]); slot.x = i * (130 + invSlotMargin) - invBarWidth / 2 + 2048 / 2; slot.y = -80; // above bottom edge inventoryBar.addChild(slot); invSlots.push(slot); // Touch/click to select block type (function (slot, i) { slot.down = function (x, y, obj) { selectedBlockType = slot.blockType; for (var j = 0; j < invSlots.length; j++) { invSlots[j].setSelected(j === i); } storage.selectedBlockType = selectedBlockType; }; })(slot, i); // Set initial selection if (blockTypes[i] === selectedBlockType) { slot.setSelected(true); } } // --- Instructions UI --- var instructions = new Text2("Tap/drag to place blocks\nDouble tap to remove\nUse arrows to scroll", { size: 60, fill: 0xFFFFFF }); instructions.anchor.set(0.5, 0); LK.gui.top.addChild(instructions); instructions.x = 2048 / 2; instructions.y = 120; // --- Mobile Control Buttons --- var controlsContainer = new Container(); LK.gui.bottomLeft.addChild(controlsContainer); // Create arrow buttons for camera movement var arrowButtons = []; var buttonSize = 120; var buttonMargin = 20; // Up arrow var upButton = LK.getAsset('inv_slot', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); upButton.x = buttonSize + buttonMargin; upButton.y = -buttonSize * 3 - buttonMargin * 2; controlsContainer.addChild(upButton); // Down arrow var downButton = LK.getAsset('inv_slot', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); downButton.x = buttonSize + buttonMargin; downButton.y = -buttonSize - buttonMargin; controlsContainer.addChild(downButton); // Left arrow var leftButton = LK.getAsset('inv_slot', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); leftButton.x = buttonMargin; leftButton.y = -buttonSize * 2 - buttonMargin; controlsContainer.addChild(leftButton); // Right arrow var rightButton = LK.getAsset('inv_slot', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); rightButton.x = buttonSize * 2 + buttonMargin * 2; rightButton.y = -buttonSize * 2 - buttonMargin; controlsContainer.addChild(rightButton); // Add text labels for arrows var upText = new Text2("↑", { size: 80, fill: 0xFFFFFF }); upText.anchor.set(0.5, 0.5); upText.x = upButton.x; upText.y = upButton.y; controlsContainer.addChild(upText); var downText = new Text2("↓", { size: 80, fill: 0xFFFFFF }); downText.anchor.set(0.5, 0.5); downText.x = downButton.x; downText.y = downButton.y; controlsContainer.addChild(downText); var leftText = new Text2("←", { size: 80, fill: 0xFFFFFF }); leftText.anchor.set(0.5, 0.5); leftText.x = leftButton.x; leftText.y = leftButton.y; controlsContainer.addChild(leftText); var rightText = new Text2("→", { size: 80, fill: 0xFFFFFF }); rightText.anchor.set(0.5, 0.5); rightText.x = rightButton.x; rightText.y = rightButton.y; controlsContainer.addChild(rightText); // Add touch handlers for camera movement upButton.down = function (x, y, obj) { cameraY -= 1; clampCamera(); updateBlockObjs(); storage.cameraY = cameraY; }; downButton.down = function (x, y, obj) { cameraY += 1; clampCamera(); updateBlockObjs(); storage.cameraY = cameraY; }; leftButton.down = function (x, y, obj) { cameraX -= 1; clampCamera(); updateBlockObjs(); storage.cameraX = cameraX; }; rightButton.down = function (x, y, obj) { cameraX += 1; clampCamera(); updateBlockObjs(); storage.cameraX = cameraX; }; arrowButtons.push(upButton, downButton, leftButton, rightButton); // --- World update/render --- function updateBlockObjs() { for (var y = 0; y < GRID_ROWS; y++) { for (var x = 0; x < GRID_COLS; x++) { var wx = x + cameraX; var wy = y + cameraY; var blockType = world[wy] && world[wy][wx] ? world[wy][wx] : 'air'; var block = blockObjs[y][x]; block.setGrid(wx, wy); block.visible = blockType !== 'air'; if (block.visible) { block.setType(blockType); } } } } updateBlockObjs(); // --- Touch/drag controls --- var dragMode = null; // 'place', 'remove', 'scroll' var lastTouchGrid = { x: -1, y: -1 }; var lastTouchTime = 0; var lastTouchPos = { x: 0, y: 0 }; var scrollStart = { x: 0, y: 0 }; var cameraStart = { x: 0, y: 0 }; // Convert game coordinates to grid coordinates function gameToGrid(x, y) { var gx = Math.floor((x - blockLayer.x) / BLOCK_SIZE); var gy = Math.floor((y - blockLayer.y - 100) / BLOCK_SIZE); return { x: gx, y: gy }; } // Place a block at grid (gx, gy) function placeBlock(gx, gy) { var wx = gx + cameraX; var wy = gy + cameraY; if (wx < 0 || wx >= WORLD_COLS || wy < 0 || wy >= WORLD_ROWS) return; if (world[wy][wx] === selectedBlockType) return; world[wy][wx] = selectedBlockType; updateBlockObjs(); } // Remove a block at grid (gx, gy) function removeBlock(gx, gy) { var wx = gx + cameraX; var wy = gy + cameraY; if (wx < 0 || wx >= WORLD_COLS || wy < 0 || wy >= WORLD_ROWS) return; if (world[wy][wx] === 'air') return; world[wy][wx] = 'air'; updateBlockObjs(); } // --- Main touch handlers --- game.down = function (x, y, obj) { // Check if touch is on inventory bar var guiY = y / 2732 * LK.gui.height; if (guiY > LK.gui.height - 200) { // Let inventory slots handle their own down return; } var grid = gameToGrid(x, y); lastTouchGrid.x = grid.x; lastTouchGrid.y = grid.y; lastTouchPos.x = x; lastTouchPos.y = y; scrollStart.x = x; scrollStart.y = y; cameraStart.x = cameraX; cameraStart.y = cameraY; // Double tap to remove var now = Date.now(); if (now - lastTouchTime < 350) { removeBlock(grid.x, grid.y); dragMode = 'remove'; } else { placeBlock(grid.x, grid.y); dragMode = 'place'; } lastTouchTime = now; }; game.move = function (x, y, obj) { if (dragMode === 'scroll') { // Drag to scroll var dx = x - scrollStart.x; var dy = y - scrollStart.y; cameraX = cameraStart.x - Math.round(dx / BLOCK_SIZE); cameraY = cameraStart.y - Math.round(dy / BLOCK_SIZE); clampCamera(); updateBlockObjs(); return; } var grid = gameToGrid(x, y); if (grid.x === lastTouchGrid.x && grid.y === lastTouchGrid.y) return; lastTouchGrid.x = grid.x; lastTouchGrid.y = grid.y; if (dragMode === 'place') { placeBlock(grid.x, grid.y); } else if (dragMode === 'remove') { removeBlock(grid.x, grid.y); } else { // If moved far, start scrolling var dist = Math.abs(x - scrollStart.x) + Math.abs(y - scrollStart.y); if (dist > 40) { dragMode = 'scroll'; } } }; game.up = function (x, y, obj) { dragMode = null; storage.cameraX = cameraX; storage.cameraY = cameraY; }; // --- Save selected block type and camera on exit --- LK.on('destroy', function () { storage.selectedBlockType = selectedBlockType; storage.cameraX = cameraX; storage.cameraY = cameraY; }); // --- Game update loop (not much needed) --- game.update = function () { // No per-frame logic needed for MVP };
===================================================================
--- original.js
+++ change.js
@@ -81,13 +81,13 @@
/****
* Game Code
****/
-// Inventory slot background
-// Selection highlight
-// Each block is a colored box shape, 120x120px
-// Block types: grass, dirt, stone, water, wood, sand
// --- World/grid setup ---
+// Block types: grass, dirt, stone, water, wood, sand
+// Each block is a colored box shape, 120x120px
+// Selection highlight
+// Inventory slot background
var BLOCK_SIZE = 120;
var GRID_COLS = 16; // 16x16 visible grid (1920x1920), fits on iPad Pro with some margin
var GRID_ROWS = 16;
var WORLD_COLS = 32; // world is 32x32 blocks
@@ -195,16 +195,122 @@
slot.setSelected(true);
}
}
// --- Instructions UI ---
-var instructions = new Text2("Tap/drag to place blocks\nDouble tap to remove\nDrag background to scroll", {
+var instructions = new Text2("Tap/drag to place blocks\nDouble tap to remove\nUse arrows to scroll", {
size: 60,
fill: 0xFFFFFF
});
instructions.anchor.set(0.5, 0);
LK.gui.top.addChild(instructions);
instructions.x = 2048 / 2;
instructions.y = 120;
+// --- Mobile Control Buttons ---
+var controlsContainer = new Container();
+LK.gui.bottomLeft.addChild(controlsContainer);
+// Create arrow buttons for camera movement
+var arrowButtons = [];
+var buttonSize = 120;
+var buttonMargin = 20;
+// Up arrow
+var upButton = LK.getAsset('inv_slot', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+});
+upButton.x = buttonSize + buttonMargin;
+upButton.y = -buttonSize * 3 - buttonMargin * 2;
+controlsContainer.addChild(upButton);
+// Down arrow
+var downButton = LK.getAsset('inv_slot', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+});
+downButton.x = buttonSize + buttonMargin;
+downButton.y = -buttonSize - buttonMargin;
+controlsContainer.addChild(downButton);
+// Left arrow
+var leftButton = LK.getAsset('inv_slot', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+});
+leftButton.x = buttonMargin;
+leftButton.y = -buttonSize * 2 - buttonMargin;
+controlsContainer.addChild(leftButton);
+// Right arrow
+var rightButton = LK.getAsset('inv_slot', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+});
+rightButton.x = buttonSize * 2 + buttonMargin * 2;
+rightButton.y = -buttonSize * 2 - buttonMargin;
+controlsContainer.addChild(rightButton);
+// Add text labels for arrows
+var upText = new Text2("↑", {
+ size: 80,
+ fill: 0xFFFFFF
+});
+upText.anchor.set(0.5, 0.5);
+upText.x = upButton.x;
+upText.y = upButton.y;
+controlsContainer.addChild(upText);
+var downText = new Text2("↓", {
+ size: 80,
+ fill: 0xFFFFFF
+});
+downText.anchor.set(0.5, 0.5);
+downText.x = downButton.x;
+downText.y = downButton.y;
+controlsContainer.addChild(downText);
+var leftText = new Text2("←", {
+ size: 80,
+ fill: 0xFFFFFF
+});
+leftText.anchor.set(0.5, 0.5);
+leftText.x = leftButton.x;
+leftText.y = leftButton.y;
+controlsContainer.addChild(leftText);
+var rightText = new Text2("→", {
+ size: 80,
+ fill: 0xFFFFFF
+});
+rightText.anchor.set(0.5, 0.5);
+rightText.x = rightButton.x;
+rightText.y = rightButton.y;
+controlsContainer.addChild(rightText);
+// Add touch handlers for camera movement
+upButton.down = function (x, y, obj) {
+ cameraY -= 1;
+ clampCamera();
+ updateBlockObjs();
+ storage.cameraY = cameraY;
+};
+downButton.down = function (x, y, obj) {
+ cameraY += 1;
+ clampCamera();
+ updateBlockObjs();
+ storage.cameraY = cameraY;
+};
+leftButton.down = function (x, y, obj) {
+ cameraX -= 1;
+ clampCamera();
+ updateBlockObjs();
+ storage.cameraX = cameraX;
+};
+rightButton.down = function (x, y, obj) {
+ cameraX += 1;
+ clampCamera();
+ updateBlockObjs();
+ storage.cameraX = cameraX;
+};
+arrowButtons.push(upButton, downButton, leftButton, rightButton);
// --- World update/render ---
function updateBlockObjs() {
for (var y = 0; y < GRID_ROWS; y++) {
for (var x = 0; x < GRID_COLS; x++) {