/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { worldData: undefined, inventory: { dirt: 0, stone: 0, wood: 0, special: 0 } }); /**** * Classes ****/ var Block = Container.expand(function (type, solid) { var self = Container.call(this); self.type = type || 'dirt'; self.solid = solid !== undefined ? solid : true; var colors = { 'dirt': 0x8B4513, 'stone': 0x777777, 'wood': 0x8B5A2B, 'special': 0x00BFFF }; // Create block graphic var blockGraphic = self.attachAsset(self.type + 'Block', { anchorX: 0.5, anchorY: 0.5 }); // Make block interactive for mining self.interactive = true; self.down = function (x, y, obj) { if (self.solid && currentTool === 'mine') { // Mine the block LK.getSound('mine').play(); // Add to inventory storage.inventory[self.type]++; updateInventoryDisplay(); // Remove block from world var gridPos = worldToGrid(self.x, self.y); worldGrid[gridPos.y][gridPos.x] = null; self.destroy(); // Check surrounding blocks for physics updates checkPhysics(gridPos.x, gridPos.y - 1); } }; return self; }); var InventorySlot = Container.expand(function (index, type) { var self = Container.call(this); self.index = index; self.type = type; // Create background slot var slotGraphic = self.attachAsset('inventorySlot', { anchorX: 0.5, anchorY: 0.5 }); // Create block preview if this slot has a block type if (type) { var blockPreview = self.attachAsset(type + 'Block', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.8, scaleY: 0.8 }); } // Create count text self.countText = new Text2('0', { size: 30, fill: 0xFFFFFF }); self.countText.anchor.set(1, 1); self.countText.x = 40; self.countText.y = 40; self.addChild(self.countText); self.updateCount = function (count) { self.countText.setText(count.toString()); }; self.setSelected = function (selected) { if (selected) { slotGraphic.tint = 0xFFFFFF; tween(slotGraphic, { scaleX: 1.1, scaleY: 1.1 }, { duration: 200 }); } else { slotGraphic.tint = 0xAAAAAA; tween(slotGraphic, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }; // Make slot interactive self.interactive = true; self.down = function (x, y, obj) { selectInventorySlot(self.index); }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphic = self.attachAsset('playerShape', { anchorX: 0.5, anchorY: 0.5 }); self.velocity = { x: 0, y: 0 }; self.grounded = false; self.speed = 8; self.gravity = 0.5; self.jumpStrength = 12; self.update = function () { // Apply gravity if (!self.grounded) { self.velocity.y += self.gravity; } else { self.velocity.y = 0; } // Apply movement self.x += self.velocity.x; self.y += self.velocity.y; // Check for collisions checkPlayerCollisions(); // Keep player in bounds if (self.x < 50) { self.x = 50; } if (self.x > worldWidth * blockSize - 50) { self.x = worldWidth * blockSize - 50; } if (self.y < 50) { self.y = 50; } if (self.y > worldHeight * blockSize - 50) { self.y = worldHeight * blockSize - 50; } // Update camera to follow player updateCamera(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ // Constants var blockSize = 100; var worldWidth = 50; var worldHeight = 30; var gravity = 0.5; var jumpStrength = 12; // Game state var worldGrid = []; var player = null; var camera = { x: 0, y: 0 }; var currentTool = 'mine'; // 'mine' or 'place' var selectedBlockType = null; var selectedInventorySlot = 0; var inventorySlots = []; var worldContainer = null; var uiContainer = null; var currentlyDragging = false; var dragStartX = 0; var dragStartY = 0; // Initialize world function initWorld() { // If we have saved world data, use it if (storage.worldData) { worldGrid = storage.worldData; } else { // Generate new world generateWorld(); } // Create a container for all world elements worldContainer = new Container(); game.addChild(worldContainer); // Create blocks based on world grid for (var y = 0; y < worldHeight; y++) { for (var x = 0; x < worldWidth; x++) { if (worldGrid[y][x]) { var block = new Block(worldGrid[y][x], true); block.x = x * blockSize + blockSize / 2; block.y = y * blockSize + blockSize / 2; worldContainer.addChild(block); } } } // Create player player = new Player(); player.x = worldWidth * blockSize / 2; player.y = 500; worldContainer.addChild(player); // Initialize UI initUI(); // Apply initial camera position updateCamera(); // Start music LK.playMusic('gameMusic'); } function generateWorld() { // Initialize empty grid for (var y = 0; y < worldHeight; y++) { worldGrid[y] = []; for (var x = 0; x < worldWidth; x++) { worldGrid[y][x] = null; } } // Generate ground var groundHeight = Math.floor(worldHeight * 0.7); for (var x = 0; x < worldWidth; x++) { // Surface layer worldGrid[groundHeight][x] = 'dirt'; // Dirt layer (3 blocks) for (var d = 1; d < 4; d++) { if (groundHeight + d < worldHeight) { worldGrid[groundHeight + d][x] = 'dirt'; } } // Stone layer (below dirt) for (var s = 4; s < worldHeight - groundHeight; s++) { if (groundHeight + s < worldHeight) { worldGrid[groundHeight + s][x] = 'stone'; } } } // Generate some trees generateTrees(groundHeight); // Generate some special blocks generateSpecialBlocks(groundHeight); } function generateTrees(groundHeight) { var treePositions = []; var treeCount = Math.floor(worldWidth / 10); // Generate random tree positions for (var i = 0; i < treeCount; i++) { var treeX = Math.floor(Math.random() * (worldWidth - 4)) + 2; treePositions.push(treeX); } // Create trees for (var t = 0; t < treePositions.length; t++) { var x = treePositions[t]; var treeHeight = Math.floor(Math.random() * 3) + 3; // Tree trunk for (var h = 1; h <= treeHeight; h++) { worldGrid[groundHeight - h][x] = 'wood'; } // Tree leaves worldGrid[groundHeight - treeHeight - 1][x] = 'wood'; if (x > 0) { worldGrid[groundHeight - treeHeight][x - 1] = 'wood'; } if (x < worldWidth - 1) { worldGrid[groundHeight - treeHeight][x + 1] = 'wood'; } } } function generateSpecialBlocks(groundHeight) { var specialCount = Math.floor(worldWidth / 15); for (var i = 0; i < specialCount; i++) { var x = Math.floor(Math.random() * worldWidth); var y = Math.floor(Math.random() * (worldHeight - groundHeight - 5)) + groundHeight + 3; worldGrid[y][x] = 'special'; } } function initUI() { // Create UI container uiContainer = new Container(); game.addChild(uiContainer); // Create inventory bar var inventoryBar = LK.getAsset('inventoryBar', { anchorX: 0.5, anchorY: 0.5 }); inventoryBar.x = 2048 / 2; inventoryBar.y = 2732 - 70; uiContainer.addChild(inventoryBar); // Create inventory slots var slotTypes = ['dirt', 'stone', 'wood', 'special']; for (var i = 0; i < 4; i++) { var slot = new InventorySlot(i, slotTypes[i]); slot.x = 2048 / 2 - 300 + i * 200; slot.y = 2732 - 70; inventorySlots.push(slot); uiContainer.addChild(slot); } // Create tool toggle button var toolButton = new Text2("MINE", { size: 50, fill: 0xFFFFFF }); toolButton.anchor.set(0.5, 0.5); toolButton.x = 2048 - 150; toolButton.y = 2732 - 70; toolButton.interactive = true; toolButton.down = function (x, y, obj) { if (currentTool === 'mine') { currentTool = 'place'; toolButton.setText("PLACE"); } else { currentTool = 'mine'; toolButton.setText("MINE"); } }; uiContainer.addChild(toolButton); // Select the first inventory slot by default selectInventorySlot(0); // Update inventory display updateInventoryDisplay(); } function updateInventoryDisplay() { var slotTypes = ['dirt', 'stone', 'wood', 'special']; for (var i = 0; i < inventorySlots.length; i++) { inventorySlots[i].updateCount(storage.inventory[slotTypes[i]]); } } function selectInventorySlot(index) { // Deselect previous slot if (selectedInventorySlot !== null) { inventorySlots[selectedInventorySlot].setSelected(false); } // Select new slot selectedInventorySlot = index; inventorySlots[selectedInventorySlot].setSelected(true); // Set selected block type var slotTypes = ['dirt', 'stone', 'wood', 'special']; selectedBlockType = slotTypes[selectedInventorySlot]; } function worldToGrid(worldX, worldY) { return { x: Math.floor(worldX / blockSize), y: Math.floor(worldY / blockSize) }; } function gridToWorld(gridX, gridY) { return { x: gridX * blockSize + blockSize / 2, y: gridY * blockSize + blockSize / 2 }; } function checkPlayerCollisions() { // Get player bounds var playerWidth = 80; var playerHeight = 180; var playerLeft = player.x - playerWidth / 2; var playerRight = player.x + playerWidth / 2; var playerTop = player.y - playerHeight / 2; var playerBottom = player.y + playerHeight / 2; // Get surrounding grid cells var gridX = Math.floor(player.x / blockSize); var gridY = Math.floor(player.y / blockSize); // Check each surrounding cell player.grounded = false; for (var y = Math.max(0, gridY - 2); y <= Math.min(worldHeight - 1, gridY + 2); y++) { for (var x = Math.max(0, gridX - 2); x <= Math.min(worldWidth - 1, gridX + 2); x++) { // Skip empty cells if (!worldGrid[y][x]) { continue; } // Calculate block bounds var blockLeft = x * blockSize; var blockRight = blockLeft + blockSize; var blockTop = y * blockSize; var blockBottom = blockTop + blockSize; // Check for collision if (playerRight > blockLeft && playerLeft < blockRight && playerBottom > blockTop && playerTop < blockBottom) { // Calculate overlap var overlapLeft = playerRight - blockLeft; var overlapRight = blockRight - playerLeft; var overlapTop = playerBottom - blockTop; var overlapBottom = blockBottom - playerTop; // Find smallest overlap var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom); // Resolve collision if (minOverlap === overlapTop) { player.y -= overlapTop; player.velocity.y = 0; player.grounded = true; } else if (minOverlap === overlapBottom) { player.y += overlapBottom; player.velocity.y = 0; } else if (minOverlap === overlapLeft) { player.x -= overlapLeft; player.velocity.x = 0; } else if (minOverlap === overlapRight) { player.x += overlapRight; player.velocity.x = 0; } } } } } function updateCamera() { // Calculate target camera position (centered on player) var targetX = player.x - 2048 / 2; var targetY = player.y - 2732 / 2; // Apply camera constraints targetX = Math.max(0, Math.min(targetX, worldWidth * blockSize - 2048)); targetY = Math.max(0, Math.min(targetY, worldHeight * blockSize - 2732)); // Smooth camera movement camera.x = targetX; camera.y = targetY; // Apply camera position to world container worldContainer.x = -camera.x; worldContainer.y = -camera.y; } function checkPhysics(x, y) { // Skip if out of bounds if (x < 0 || x >= worldWidth || y < 0 || y >= worldHeight) { return; } // Skip if empty if (!worldGrid[y][x]) { return; } // Skip if supported if (y + 1 < worldHeight && worldGrid[y + 1][x]) { return; } // Block is unsupported, apply gravity applyGravityToBlock(x, y); } function applyGravityToBlock(x, y) { // Skip special blocks (they don't fall) if (worldGrid[y][x] === 'special') { return; } // Find all world objects at this position var blockToMove = null; for (var i = 0; i < worldContainer.children.length; i++) { var child = worldContainer.children[i]; if (child instanceof Block) { var gridPos = worldToGrid(child.x, child.y); if (gridPos.x === x && gridPos.y === y) { blockToMove = child; break; } } } if (!blockToMove) { return; } // Remove from current position worldGrid[y][x] = null; // Find landing position var newY = y; while (newY + 1 < worldHeight && !worldGrid[newY + 1][x]) { newY++; } // Update grid worldGrid[newY][x] = blockToMove.type; // Animate block falling tween(blockToMove, { y: newY * blockSize + blockSize / 2 }, { duration: (newY - y) * 100, easing: tween.easeIn, onFinish: function onFinish() { // Check surrounding blocks for more physics updates checkPhysics(x, newY - 1); checkPhysics(x - 1, newY); checkPhysics(x + 1, newY); } }); } // Handle player movement and game interaction var leftPressed = false; var rightPressed = false; var moveTimer = null; function handleGameClick(x, y, obj) { // Convert screen position to world position var worldX = x + camera.x; var worldY = y + camera.y; // Convert to grid position var gridPos = worldToGrid(worldX, worldY); // Check if position is within grid bounds if (gridPos.x < 0 || gridPos.x >= worldWidth || gridPos.y < 0 || gridPos.y >= worldHeight) { return; } if (currentTool === 'place' && selectedBlockType) { // Check if we have blocks of this type in inventory if (storage.inventory[selectedBlockType] > 0) { // Check if position is empty if (!worldGrid[gridPos.y][gridPos.x]) { // Check if position is within reach of player var playerGridPos = worldToGrid(player.x, player.y); var distance = Math.sqrt(Math.pow(playerGridPos.x - gridPos.x, 2) + Math.pow(playerGridPos.y - gridPos.y, 2)); if (distance <= 5) { // Place block worldGrid[gridPos.y][gridPos.x] = selectedBlockType; // Create block var block = new Block(selectedBlockType, true); block.x = gridPos.x * blockSize + blockSize / 2; block.y = gridPos.y * blockSize + blockSize / 2; worldContainer.addChild(block); // Remove from inventory storage.inventory[selectedBlockType]--; updateInventoryDisplay(); // Play sound LK.getSound('place').play(); // Save world storage.worldData = worldGrid; // Check physics checkPhysics(gridPos.x, gridPos.y - 1); } } } } } function startMovingLeft() { leftPressed = true; if (!moveTimer) { moveTimer = LK.setInterval(movePlayer, 16); } } function startMovingRight() { rightPressed = true; if (!moveTimer) { moveTimer = LK.setInterval(movePlayer, 16); } } function stopMovingLeft() { leftPressed = false; if (!leftPressed && !rightPressed && moveTimer) { LK.clearInterval(moveTimer); moveTimer = null; player.velocity.x = 0; } } function stopMovingRight() { rightPressed = false; if (!leftPressed && !rightPressed && moveTimer) { LK.clearInterval(moveTimer); moveTimer = null; player.velocity.x = 0; } } function movePlayer() { if (leftPressed) { player.velocity.x = -player.speed; } else if (rightPressed) { player.velocity.x = player.speed; } else { player.velocity.x = 0; } } function jump() { if (player.grounded) { player.velocity.y = -player.jumpStrength; player.grounded = false; } } // Game event handlers game.down = function (x, y, obj) { // Check if click is on UI var isUIClick = false; for (var i = 0; i < uiContainer.children.length; i++) { if (uiContainer.children[i].intersects({ x: x, y: y })) { isUIClick = true; break; } } if (!isUIClick) { // Handle game world interaction handleGameClick(x, y, obj); // Start drag for player movement currentlyDragging = true; dragStartX = x; dragStartY = y; } }; game.up = function (x, y, obj) { if (currentlyDragging) { currentlyDragging = false; stopMovingLeft(); stopMovingRight(); // Check if this was a tap (not a drag) var dx = Math.abs(x - dragStartX); var dy = Math.abs(y - dragStartY); if (dx < 20 && dy < 20) { // This was a tap, check if we should jump if (y < 2732 / 2) { jump(); } } } }; game.move = function (x, y, obj) { if (currentlyDragging) { var dx = x - dragStartX; if (dx < -30) { startMovingLeft(); } else if (dx > 30) { startMovingRight(); } else { stopMovingLeft(); stopMovingRight(); } } }; // Game update function game.update = function () { // Skip if player not initialized yet if (!player) { return; } // Player and physics updates happen automatically through the Player class }; // Initialize game initWorld();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,632 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ worldData: undefined,
+ inventory: {
+ dirt: 0,
+ stone: 0,
+ wood: 0,
+ special: 0
+ }
+});
+
+/****
+* Classes
+****/
+var Block = Container.expand(function (type, solid) {
+ var self = Container.call(this);
+ self.type = type || 'dirt';
+ self.solid = solid !== undefined ? solid : true;
+ var colors = {
+ 'dirt': 0x8B4513,
+ 'stone': 0x777777,
+ 'wood': 0x8B5A2B,
+ 'special': 0x00BFFF
+ };
+ // Create block graphic
+ var blockGraphic = self.attachAsset(self.type + 'Block', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Make block interactive for mining
+ self.interactive = true;
+ self.down = function (x, y, obj) {
+ if (self.solid && currentTool === 'mine') {
+ // Mine the block
+ LK.getSound('mine').play();
+ // Add to inventory
+ storage.inventory[self.type]++;
+ updateInventoryDisplay();
+ // Remove block from world
+ var gridPos = worldToGrid(self.x, self.y);
+ worldGrid[gridPos.y][gridPos.x] = null;
+ self.destroy();
+ // Check surrounding blocks for physics updates
+ checkPhysics(gridPos.x, gridPos.y - 1);
+ }
+ };
+ return self;
+});
+var InventorySlot = Container.expand(function (index, type) {
+ var self = Container.call(this);
+ self.index = index;
+ self.type = type;
+ // Create background slot
+ var slotGraphic = self.attachAsset('inventorySlot', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Create block preview if this slot has a block type
+ if (type) {
+ var blockPreview = self.attachAsset(type + 'Block', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.8,
+ scaleY: 0.8
+ });
+ }
+ // Create count text
+ self.countText = new Text2('0', {
+ size: 30,
+ fill: 0xFFFFFF
+ });
+ self.countText.anchor.set(1, 1);
+ self.countText.x = 40;
+ self.countText.y = 40;
+ self.addChild(self.countText);
+ self.updateCount = function (count) {
+ self.countText.setText(count.toString());
+ };
+ self.setSelected = function (selected) {
+ if (selected) {
+ slotGraphic.tint = 0xFFFFFF;
+ tween(slotGraphic, {
+ scaleX: 1.1,
+ scaleY: 1.1
+ }, {
+ duration: 200
+ });
+ } else {
+ slotGraphic.tint = 0xAAAAAA;
+ tween(slotGraphic, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200
+ });
+ }
+ };
+ // Make slot interactive
+ self.interactive = true;
+ self.down = function (x, y, obj) {
+ selectInventorySlot(self.index);
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var playerGraphic = self.attachAsset('playerShape', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.velocity = {
+ x: 0,
+ y: 0
+ };
+ self.grounded = false;
+ self.speed = 8;
+ self.gravity = 0.5;
+ self.jumpStrength = 12;
+ self.update = function () {
+ // Apply gravity
+ if (!self.grounded) {
+ self.velocity.y += self.gravity;
+ } else {
+ self.velocity.y = 0;
+ }
+ // Apply movement
+ self.x += self.velocity.x;
+ self.y += self.velocity.y;
+ // Check for collisions
+ checkPlayerCollisions();
+ // Keep player in bounds
+ if (self.x < 50) {
+ self.x = 50;
+ }
+ if (self.x > worldWidth * blockSize - 50) {
+ self.x = worldWidth * blockSize - 50;
+ }
+ if (self.y < 50) {
+ self.y = 50;
+ }
+ if (self.y > worldHeight * blockSize - 50) {
+ self.y = worldHeight * blockSize - 50;
+ }
+ // Update camera to follow player
+ updateCamera();
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x87CEEB
+});
+
+/****
+* Game Code
+****/
+// Constants
+var blockSize = 100;
+var worldWidth = 50;
+var worldHeight = 30;
+var gravity = 0.5;
+var jumpStrength = 12;
+// Game state
+var worldGrid = [];
+var player = null;
+var camera = {
+ x: 0,
+ y: 0
+};
+var currentTool = 'mine'; // 'mine' or 'place'
+var selectedBlockType = null;
+var selectedInventorySlot = 0;
+var inventorySlots = [];
+var worldContainer = null;
+var uiContainer = null;
+var currentlyDragging = false;
+var dragStartX = 0;
+var dragStartY = 0;
+// Initialize world
+function initWorld() {
+ // If we have saved world data, use it
+ if (storage.worldData) {
+ worldGrid = storage.worldData;
+ } else {
+ // Generate new world
+ generateWorld();
+ }
+ // Create a container for all world elements
+ worldContainer = new Container();
+ game.addChild(worldContainer);
+ // Create blocks based on world grid
+ for (var y = 0; y < worldHeight; y++) {
+ for (var x = 0; x < worldWidth; x++) {
+ if (worldGrid[y][x]) {
+ var block = new Block(worldGrid[y][x], true);
+ block.x = x * blockSize + blockSize / 2;
+ block.y = y * blockSize + blockSize / 2;
+ worldContainer.addChild(block);
+ }
+ }
+ }
+ // Create player
+ player = new Player();
+ player.x = worldWidth * blockSize / 2;
+ player.y = 500;
+ worldContainer.addChild(player);
+ // Initialize UI
+ initUI();
+ // Apply initial camera position
+ updateCamera();
+ // Start music
+ LK.playMusic('gameMusic');
+}
+function generateWorld() {
+ // Initialize empty grid
+ for (var y = 0; y < worldHeight; y++) {
+ worldGrid[y] = [];
+ for (var x = 0; x < worldWidth; x++) {
+ worldGrid[y][x] = null;
+ }
+ }
+ // Generate ground
+ var groundHeight = Math.floor(worldHeight * 0.7);
+ for (var x = 0; x < worldWidth; x++) {
+ // Surface layer
+ worldGrid[groundHeight][x] = 'dirt';
+ // Dirt layer (3 blocks)
+ for (var d = 1; d < 4; d++) {
+ if (groundHeight + d < worldHeight) {
+ worldGrid[groundHeight + d][x] = 'dirt';
+ }
+ }
+ // Stone layer (below dirt)
+ for (var s = 4; s < worldHeight - groundHeight; s++) {
+ if (groundHeight + s < worldHeight) {
+ worldGrid[groundHeight + s][x] = 'stone';
+ }
+ }
+ }
+ // Generate some trees
+ generateTrees(groundHeight);
+ // Generate some special blocks
+ generateSpecialBlocks(groundHeight);
+}
+function generateTrees(groundHeight) {
+ var treePositions = [];
+ var treeCount = Math.floor(worldWidth / 10);
+ // Generate random tree positions
+ for (var i = 0; i < treeCount; i++) {
+ var treeX = Math.floor(Math.random() * (worldWidth - 4)) + 2;
+ treePositions.push(treeX);
+ }
+ // Create trees
+ for (var t = 0; t < treePositions.length; t++) {
+ var x = treePositions[t];
+ var treeHeight = Math.floor(Math.random() * 3) + 3;
+ // Tree trunk
+ for (var h = 1; h <= treeHeight; h++) {
+ worldGrid[groundHeight - h][x] = 'wood';
+ }
+ // Tree leaves
+ worldGrid[groundHeight - treeHeight - 1][x] = 'wood';
+ if (x > 0) {
+ worldGrid[groundHeight - treeHeight][x - 1] = 'wood';
+ }
+ if (x < worldWidth - 1) {
+ worldGrid[groundHeight - treeHeight][x + 1] = 'wood';
+ }
+ }
+}
+function generateSpecialBlocks(groundHeight) {
+ var specialCount = Math.floor(worldWidth / 15);
+ for (var i = 0; i < specialCount; i++) {
+ var x = Math.floor(Math.random() * worldWidth);
+ var y = Math.floor(Math.random() * (worldHeight - groundHeight - 5)) + groundHeight + 3;
+ worldGrid[y][x] = 'special';
+ }
+}
+function initUI() {
+ // Create UI container
+ uiContainer = new Container();
+ game.addChild(uiContainer);
+ // Create inventory bar
+ var inventoryBar = LK.getAsset('inventoryBar', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ inventoryBar.x = 2048 / 2;
+ inventoryBar.y = 2732 - 70;
+ uiContainer.addChild(inventoryBar);
+ // Create inventory slots
+ var slotTypes = ['dirt', 'stone', 'wood', 'special'];
+ for (var i = 0; i < 4; i++) {
+ var slot = new InventorySlot(i, slotTypes[i]);
+ slot.x = 2048 / 2 - 300 + i * 200;
+ slot.y = 2732 - 70;
+ inventorySlots.push(slot);
+ uiContainer.addChild(slot);
+ }
+ // Create tool toggle button
+ var toolButton = new Text2("MINE", {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ toolButton.anchor.set(0.5, 0.5);
+ toolButton.x = 2048 - 150;
+ toolButton.y = 2732 - 70;
+ toolButton.interactive = true;
+ toolButton.down = function (x, y, obj) {
+ if (currentTool === 'mine') {
+ currentTool = 'place';
+ toolButton.setText("PLACE");
+ } else {
+ currentTool = 'mine';
+ toolButton.setText("MINE");
+ }
+ };
+ uiContainer.addChild(toolButton);
+ // Select the first inventory slot by default
+ selectInventorySlot(0);
+ // Update inventory display
+ updateInventoryDisplay();
+}
+function updateInventoryDisplay() {
+ var slotTypes = ['dirt', 'stone', 'wood', 'special'];
+ for (var i = 0; i < inventorySlots.length; i++) {
+ inventorySlots[i].updateCount(storage.inventory[slotTypes[i]]);
+ }
+}
+function selectInventorySlot(index) {
+ // Deselect previous slot
+ if (selectedInventorySlot !== null) {
+ inventorySlots[selectedInventorySlot].setSelected(false);
+ }
+ // Select new slot
+ selectedInventorySlot = index;
+ inventorySlots[selectedInventorySlot].setSelected(true);
+ // Set selected block type
+ var slotTypes = ['dirt', 'stone', 'wood', 'special'];
+ selectedBlockType = slotTypes[selectedInventorySlot];
+}
+function worldToGrid(worldX, worldY) {
+ return {
+ x: Math.floor(worldX / blockSize),
+ y: Math.floor(worldY / blockSize)
+ };
+}
+function gridToWorld(gridX, gridY) {
+ return {
+ x: gridX * blockSize + blockSize / 2,
+ y: gridY * blockSize + blockSize / 2
+ };
+}
+function checkPlayerCollisions() {
+ // Get player bounds
+ var playerWidth = 80;
+ var playerHeight = 180;
+ var playerLeft = player.x - playerWidth / 2;
+ var playerRight = player.x + playerWidth / 2;
+ var playerTop = player.y - playerHeight / 2;
+ var playerBottom = player.y + playerHeight / 2;
+ // Get surrounding grid cells
+ var gridX = Math.floor(player.x / blockSize);
+ var gridY = Math.floor(player.y / blockSize);
+ // Check each surrounding cell
+ player.grounded = false;
+ for (var y = Math.max(0, gridY - 2); y <= Math.min(worldHeight - 1, gridY + 2); y++) {
+ for (var x = Math.max(0, gridX - 2); x <= Math.min(worldWidth - 1, gridX + 2); x++) {
+ // Skip empty cells
+ if (!worldGrid[y][x]) {
+ continue;
+ }
+ // Calculate block bounds
+ var blockLeft = x * blockSize;
+ var blockRight = blockLeft + blockSize;
+ var blockTop = y * blockSize;
+ var blockBottom = blockTop + blockSize;
+ // Check for collision
+ if (playerRight > blockLeft && playerLeft < blockRight && playerBottom > blockTop && playerTop < blockBottom) {
+ // Calculate overlap
+ var overlapLeft = playerRight - blockLeft;
+ var overlapRight = blockRight - playerLeft;
+ var overlapTop = playerBottom - blockTop;
+ var overlapBottom = blockBottom - playerTop;
+ // Find smallest overlap
+ var minOverlap = Math.min(overlapLeft, overlapRight, overlapTop, overlapBottom);
+ // Resolve collision
+ if (minOverlap === overlapTop) {
+ player.y -= overlapTop;
+ player.velocity.y = 0;
+ player.grounded = true;
+ } else if (minOverlap === overlapBottom) {
+ player.y += overlapBottom;
+ player.velocity.y = 0;
+ } else if (minOverlap === overlapLeft) {
+ player.x -= overlapLeft;
+ player.velocity.x = 0;
+ } else if (minOverlap === overlapRight) {
+ player.x += overlapRight;
+ player.velocity.x = 0;
+ }
+ }
+ }
+ }
+}
+function updateCamera() {
+ // Calculate target camera position (centered on player)
+ var targetX = player.x - 2048 / 2;
+ var targetY = player.y - 2732 / 2;
+ // Apply camera constraints
+ targetX = Math.max(0, Math.min(targetX, worldWidth * blockSize - 2048));
+ targetY = Math.max(0, Math.min(targetY, worldHeight * blockSize - 2732));
+ // Smooth camera movement
+ camera.x = targetX;
+ camera.y = targetY;
+ // Apply camera position to world container
+ worldContainer.x = -camera.x;
+ worldContainer.y = -camera.y;
+}
+function checkPhysics(x, y) {
+ // Skip if out of bounds
+ if (x < 0 || x >= worldWidth || y < 0 || y >= worldHeight) {
+ return;
+ }
+ // Skip if empty
+ if (!worldGrid[y][x]) {
+ return;
+ }
+ // Skip if supported
+ if (y + 1 < worldHeight && worldGrid[y + 1][x]) {
+ return;
+ }
+ // Block is unsupported, apply gravity
+ applyGravityToBlock(x, y);
+}
+function applyGravityToBlock(x, y) {
+ // Skip special blocks (they don't fall)
+ if (worldGrid[y][x] === 'special') {
+ return;
+ }
+ // Find all world objects at this position
+ var blockToMove = null;
+ for (var i = 0; i < worldContainer.children.length; i++) {
+ var child = worldContainer.children[i];
+ if (child instanceof Block) {
+ var gridPos = worldToGrid(child.x, child.y);
+ if (gridPos.x === x && gridPos.y === y) {
+ blockToMove = child;
+ break;
+ }
+ }
+ }
+ if (!blockToMove) {
+ return;
+ }
+ // Remove from current position
+ worldGrid[y][x] = null;
+ // Find landing position
+ var newY = y;
+ while (newY + 1 < worldHeight && !worldGrid[newY + 1][x]) {
+ newY++;
+ }
+ // Update grid
+ worldGrid[newY][x] = blockToMove.type;
+ // Animate block falling
+ tween(blockToMove, {
+ y: newY * blockSize + blockSize / 2
+ }, {
+ duration: (newY - y) * 100,
+ easing: tween.easeIn,
+ onFinish: function onFinish() {
+ // Check surrounding blocks for more physics updates
+ checkPhysics(x, newY - 1);
+ checkPhysics(x - 1, newY);
+ checkPhysics(x + 1, newY);
+ }
+ });
+}
+// Handle player movement and game interaction
+var leftPressed = false;
+var rightPressed = false;
+var moveTimer = null;
+function handleGameClick(x, y, obj) {
+ // Convert screen position to world position
+ var worldX = x + camera.x;
+ var worldY = y + camera.y;
+ // Convert to grid position
+ var gridPos = worldToGrid(worldX, worldY);
+ // Check if position is within grid bounds
+ if (gridPos.x < 0 || gridPos.x >= worldWidth || gridPos.y < 0 || gridPos.y >= worldHeight) {
+ return;
+ }
+ if (currentTool === 'place' && selectedBlockType) {
+ // Check if we have blocks of this type in inventory
+ if (storage.inventory[selectedBlockType] > 0) {
+ // Check if position is empty
+ if (!worldGrid[gridPos.y][gridPos.x]) {
+ // Check if position is within reach of player
+ var playerGridPos = worldToGrid(player.x, player.y);
+ var distance = Math.sqrt(Math.pow(playerGridPos.x - gridPos.x, 2) + Math.pow(playerGridPos.y - gridPos.y, 2));
+ if (distance <= 5) {
+ // Place block
+ worldGrid[gridPos.y][gridPos.x] = selectedBlockType;
+ // Create block
+ var block = new Block(selectedBlockType, true);
+ block.x = gridPos.x * blockSize + blockSize / 2;
+ block.y = gridPos.y * blockSize + blockSize / 2;
+ worldContainer.addChild(block);
+ // Remove from inventory
+ storage.inventory[selectedBlockType]--;
+ updateInventoryDisplay();
+ // Play sound
+ LK.getSound('place').play();
+ // Save world
+ storage.worldData = worldGrid;
+ // Check physics
+ checkPhysics(gridPos.x, gridPos.y - 1);
+ }
+ }
+ }
+ }
+}
+function startMovingLeft() {
+ leftPressed = true;
+ if (!moveTimer) {
+ moveTimer = LK.setInterval(movePlayer, 16);
+ }
+}
+function startMovingRight() {
+ rightPressed = true;
+ if (!moveTimer) {
+ moveTimer = LK.setInterval(movePlayer, 16);
+ }
+}
+function stopMovingLeft() {
+ leftPressed = false;
+ if (!leftPressed && !rightPressed && moveTimer) {
+ LK.clearInterval(moveTimer);
+ moveTimer = null;
+ player.velocity.x = 0;
+ }
+}
+function stopMovingRight() {
+ rightPressed = false;
+ if (!leftPressed && !rightPressed && moveTimer) {
+ LK.clearInterval(moveTimer);
+ moveTimer = null;
+ player.velocity.x = 0;
+ }
+}
+function movePlayer() {
+ if (leftPressed) {
+ player.velocity.x = -player.speed;
+ } else if (rightPressed) {
+ player.velocity.x = player.speed;
+ } else {
+ player.velocity.x = 0;
+ }
+}
+function jump() {
+ if (player.grounded) {
+ player.velocity.y = -player.jumpStrength;
+ player.grounded = false;
+ }
+}
+// Game event handlers
+game.down = function (x, y, obj) {
+ // Check if click is on UI
+ var isUIClick = false;
+ for (var i = 0; i < uiContainer.children.length; i++) {
+ if (uiContainer.children[i].intersects({
+ x: x,
+ y: y
+ })) {
+ isUIClick = true;
+ break;
+ }
+ }
+ if (!isUIClick) {
+ // Handle game world interaction
+ handleGameClick(x, y, obj);
+ // Start drag for player movement
+ currentlyDragging = true;
+ dragStartX = x;
+ dragStartY = y;
+ }
+};
+game.up = function (x, y, obj) {
+ if (currentlyDragging) {
+ currentlyDragging = false;
+ stopMovingLeft();
+ stopMovingRight();
+ // Check if this was a tap (not a drag)
+ var dx = Math.abs(x - dragStartX);
+ var dy = Math.abs(y - dragStartY);
+ if (dx < 20 && dy < 20) {
+ // This was a tap, check if we should jump
+ if (y < 2732 / 2) {
+ jump();
+ }
+ }
+ }
+};
+game.move = function (x, y, obj) {
+ if (currentlyDragging) {
+ var dx = x - dragStartX;
+ if (dx < -30) {
+ startMovingLeft();
+ } else if (dx > 30) {
+ startMovingRight();
+ } else {
+ stopMovingLeft();
+ stopMovingRight();
+ }
+ }
+};
+// Game update function
+game.update = function () {
+ // Skip if player not initialized yet
+ if (!player) {
+ return;
+ }
+ // Player and physics updates happen automatically through the Player class
+};
+// Initialize game
+initWorld();
\ No newline at end of file