User prompt
make a world enter menu
User prompt
make a world for the character
User prompt
make a character
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'placeToolBtn.buttonText.style.fill = "#FFFF00";' Line Number: 468
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot read properties of undefined (reading '14')' in or related to this line: 'if (worldData[gridY][gridX] !== null) {' Line Number: 514
User prompt
add a main menu ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Pixel Realms
Initial prompt
make a game like pixel worlds
/**** * 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; var graphics = self.attachAsset(type, { 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 () { // 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 storage.worldData = 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 () { // 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; }; // Interactive events self.down = function (x, y, obj) { console.log("Character clicked!"); }; 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(); gameStarted = true; initializeWorld(); setupUI(); }); 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 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 = -12; self.grounded = false; self.jumping = true; } }; self.update = function () { // Apply gravity if (!self.grounded) { self.velocity.y += self.gravity; } // Update position self.x += self.velocity.x; self.y += self.velocity.y; // 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 && 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; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB // Sky blue background }); /**** * Game Code ****/ // Game constants 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; } } // 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); // Generate ground layers for (var y = groundHeight; y < height; y++) { if (y === groundHeight) { data[y][x] = 'grass'; } else if (y < groundHeight + 3) { data[y][x] = 'ground'; } else { // More stones deeper underground var stoneChance = Math.min(0.8, 0.2 + (y - groundHeight) * 0.05); data[y][x] = Math.random() < stoneChance ? 'stone' : '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); // Tree trunk for (var ty = 1; ty <= treeHeight; ty++) { if (groundY - ty >= 0) { data[groundY - ty][x] = 'wood'; } } // Tree top (leaves would be added here if we had them) var treeTop = groundY - treeHeight - 1; if (treeTop >= 0) { for (var tx = -1; tx <= 1; tx++) { if (x + tx >= 0 && x + tx < width) { data[treeTop][x + tx] = 'wood'; if (treeTop - 1 >= 0 && tx === 0) { data[treeTop - 1][x] = 'wood'; } } } } } } }; // 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 = 64; var worldHeight = 32; var gravity = 0.5; // Game state var gameStarted = false; var worldData = storage.worldData || generateWorld(); 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 var character = new Character(); character.x = 500; character.y = 1500; 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 block = new Block(worldData[y][x], blockSize); block.x = x * blockSize + blockSize / 2; block.y = y * blockSize + blockSize / 2; worldContainer.addChild(block); } } } } // Generate a new world function generateWorld() { var worldGen = new WorldGenerator(); var data = worldGen.generate(worldWidth, worldHeight, blockSize); // Save the generated world storage.worldData = data; return data; } // Setup UI function setupUI() { // Create inventory bar setupInventory(); // Create tool selection buttons setupToolbar(); // Create control buttons (left, right, jump) setupControls(); } 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.updateCount(inventory[blockTypes[i]] || 0); inventoryContainer.addChild(slot); } // Position the inventory at the top center inventoryContainer.x = 2048 / 2 - (blockTypes.length - 1) * slotSpacing / 2; inventoryContainer.y = 100; // 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() { var controlsContainer = new Container(); // Left button var leftBtn = new Button("←", function () { player.move('left'); }); leftBtn.x = 0; controlsContainer.addChild(leftBtn); // Right button var rightBtn = new Button("→", function () { player.move('right'); }); rightBtn.x = 250; controlsContainer.addChild(rightBtn); // Jump button var jumpBtn = new Button("Jump", function () { player.jump(); }); jumpBtn.x = 500; controlsContainer.addChild(jumpBtn); // Position controls at bottom left controlsContainer.x = 200; controlsContainer.y = 2732 - 100; LK.gui.bottomLeft.addChild(controlsContainer); } 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') { placeToolBtn.buttonText.style = { fill: 0xFFFF00 }; breakToolBtn.buttonText.style = { fill: 0xFFFFFF }; } else { placeToolBtn.buttonText.style = { fill: 0xFFFFFF }; 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); slot.updateCount(inventory[slot.type] || 0); } } 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] || 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 storage.worldData = worldData; storage.inventory = inventory; } // Game event handlers game.down = function (x, y, obj) { if (currentTool === 'place') { placeBlock(x, y); } // If we click on character, make it change direction if (obj && obj.parent === character) { character.faceDirection(character.direction * -1); character.startMoving(character.direction); } }; // Main game loop game.update = function () { // Only update game elements if the game has started if (gameStarted) { // Update player player.update(); // Update character character.update(); // Simple AI: Make character move back and forth if (LK.ticks % 120 === 0) { // Change direction every 2 seconds character.startMoving(character.direction * -1); } // Save game data periodically if (LK.ticks % 300 === 0) { storage.worldData = worldData; storage.inventory = inventory; } } }; // Create and show main menu var mainMenu = new MainMenu(); mainMenu.x = 0; mainMenu.y = 0; game.addChild(mainMenu); mainMenu.show(); // Start background music LK.playMusic('bgmusic');
===================================================================
--- original.js
+++ change.js
@@ -37,9 +37,9 @@
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]) {
+ if (worldData[gridY] && worldData[gridY][gridX] !== undefined && worldData[gridY][gridX] !== null) {
worldData[gridY][gridX] = null;
self.destroy();
}
// Save world data
@@ -275,9 +275,9 @@
// 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 (worldData[gridY] && worldData[gridY][gridX] && worldData[gridY][gridX] !== 'water') {
+ if (gridY >= 0 && gridY < worldData.length && gridX >= 0 && 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;
@@ -309,8 +309,158 @@
/****
* Game Code
****/
// Game constants
+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;
+ }
+ }
+ // 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);
+ // Generate ground layers
+ for (var y = groundHeight; y < height; y++) {
+ if (y === groundHeight) {
+ data[y][x] = 'grass';
+ } else if (y < groundHeight + 3) {
+ data[y][x] = 'ground';
+ } else {
+ // More stones deeper underground
+ var stoneChance = Math.min(0.8, 0.2 + (y - groundHeight) * 0.05);
+ data[y][x] = Math.random() < stoneChance ? 'stone' : '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);
+ // Tree trunk
+ for (var ty = 1; ty <= treeHeight; ty++) {
+ if (groundY - ty >= 0) {
+ data[groundY - ty][x] = 'wood';
+ }
+ }
+ // Tree top (leaves would be added here if we had them)
+ var treeTop = groundY - treeHeight - 1;
+ if (treeTop >= 0) {
+ for (var tx = -1; tx <= 1; tx++) {
+ if (x + tx >= 0 && x + tx < width) {
+ data[treeTop][x + tx] = 'wood';
+ if (treeTop - 1 >= 0 && tx === 0) {
+ data[treeTop - 1][x] = 'wood';
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+ // 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 = 64;
var worldHeight = 32;
var gravity = 0.5;
@@ -363,49 +513,10 @@
}
}
// Generate a new world
function generateWorld() {
- var data = [];
- // Initialize with empty arrays
- for (var y = 0; y < worldHeight; y++) {
- data[y] = [];
- for (var x = 0; x < worldWidth; x++) {
- data[y][x] = null;
- }
- }
- // Generate terrain
- for (var x = 0; x < worldWidth; x++) {
- // Base ground height (with some randomness)
- var groundHeight = Math.floor(worldHeight * 0.7) + Math.floor(Math.random() * 4) - 2;
- // Generate ground layers
- for (var y = groundHeight; y < worldHeight; y++) {
- if (y === groundHeight) {
- data[y][x] = 'grass';
- } else if (y < groundHeight + 3) {
- data[y][x] = 'ground';
- } else {
- data[y][x] = Math.random() < 0.3 ? 'stone' : 'ground';
- }
- }
- // Add some trees
- if (Math.random() < 0.1) {
- var treeHeight = 3 + Math.floor(Math.random() * 2);
- for (var ty = 1; ty <= treeHeight; ty++) {
- if (groundHeight - ty >= 0) {
- data[groundHeight - ty][x] = 'wood';
- }
- }
- }
- // Add some water pools
- if (Math.random() < 0.05 && x > 0 && x < worldWidth - 2) {
- var poolWidth = 2 + Math.floor(Math.random() * 3);
- for (var wx = 0; wx < poolWidth && x + wx < worldWidth; wx++) {
- data[groundHeight][x + wx] = 'water';
- // Ensure the next iterations skip this area
- if (wx > 0) x++;
- }
- }
- }
+ var worldGen = new WorldGenerator();
+ var data = worldGen.generate(worldWidth, worldHeight, blockSize);
// Save the generated world
storage.worldData = data;
return data;
}
@@ -502,21 +613,21 @@
function updateToolbarSelection() {
var placeToolBtn = toolbarContainer.getChildAt(0);
var breakToolBtn = toolbarContainer.getChildAt(1);
if (currentTool === 'place') {
- placeToolBtn.buttonText.setText(placeToolBtn.buttonText.text, {
+ placeToolBtn.buttonText.style = {
fill: 0xFFFF00
- });
- breakToolBtn.buttonText.setText(breakToolBtn.buttonText.text, {
+ };
+ breakToolBtn.buttonText.style = {
fill: 0xFFFFFF
- });
+ };
} else {
- placeToolBtn.buttonText.setText(placeToolBtn.buttonText.text, {
+ placeToolBtn.buttonText.style = {
fill: 0xFFFFFF
- });
- breakToolBtn.buttonText.setText(breakToolBtn.buttonText.text, {
+ };
+ breakToolBtn.buttonText.style = {
fill: 0xFFFF00
- });
+ };
}
}
function selectInventorySlot(index) {
selectedInventorySlot = index;
@@ -559,8 +670,15 @@
// Check if space is empty
if (!worldData[gridY] || 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]--;
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