From 80c243ebf8de213e1c1a8aefae513f3a0d67c45d Mon Sep 17 00:00:00 2001 From: "Kacper Kostka (aider)" Date: Sat, 5 Apr 2025 19:12:11 +0200 Subject: [PATCH] feat: Implement player block breaking with 10-pixel range and inventory collection --- js/entities/player.js | 52 +++++++++++++++++++++++++------------------ js/input.js | 19 ++++++++++++---- js/render.js | 44 ++++++++++++++++++++++++++++-------- 3 files changed, 80 insertions(+), 35 deletions(-) diff --git a/js/entities/player.js b/js/entities/player.js index f9043db..6557750 100644 --- a/js/entities/player.js +++ b/js/entities/player.js @@ -29,7 +29,7 @@ class Player extends Entity { this.maxHealth = 100; this.health = 100; this.breakingPower = 1; - this.breakingRange = 3; + this.breakingRange = 10; // Increased from 3 to 10 pixels this.isBreaking = false; this.breakingCooldown = 0; this.breakingCooldownMax = 10; @@ -252,30 +252,38 @@ class Player extends Entity { } breakBlock() { - // Calculate the position in front of the player - const halfWidth = this.width / 2; - const breakX = Math.floor(this.x + (this.direction * this.breakingRange)); - const breakY = Math.floor(this.y); + // Get mouse position in world coordinates + const worldX = Math.floor(currentMouseX / PIXEL_SIZE) + worldOffsetX; + const worldY = Math.floor(currentMouseY / PIXEL_SIZE) + worldOffsetY; - // Get the block type at that position - const blockType = getPixel(breakX, breakY); + // Calculate distance from player to target block + const distance = Math.sqrt( + Math.pow(worldX - this.x, 2) + + Math.pow(worldY - this.y, 2) + ); - // Only break non-empty blocks that aren't special entities - if (blockType !== EMPTY && - blockType !== WATER && - blockType !== FIRE && - blockType !== SQUARE && - blockType !== CIRCLE && - blockType !== TRIANGLE) { + // Only break blocks within range + if (distance <= this.breakingRange) { + // Get the block type at that position + const blockType = getPixel(worldX, worldY); - // Add to inventory based on block type - this.addToInventory(blockType); - - // Replace with empty space - setPixel(breakX, breakY, EMPTY); - - // Create a breaking effect (particles) - this.createBreakingEffect(breakX, breakY, blockType); + // Only break non-empty blocks that aren't special entities + if (blockType !== EMPTY && + blockType !== WATER && + blockType !== FIRE && + blockType !== SQUARE && + blockType !== CIRCLE && + blockType !== TRIANGLE) { + + // Add to inventory based on block type + this.addToInventory(blockType); + + // Replace with empty space + setPixel(worldX, worldY, EMPTY); + + // Create a breaking effect (particles) + this.createBreakingEffect(worldX, worldY, blockType); + } } } diff --git a/js/input.js b/js/input.js index 6971f35..53a8fa5 100644 --- a/js/input.js +++ b/js/input.js @@ -18,7 +18,7 @@ window.addEventListener('keydown', (e) => { e.preventDefault(); } - // Start breaking blocks with E key + // Start breaking blocks with E key or left mouse button if (e.code === 'KeyE' && player) { player.startBreaking(); } @@ -106,9 +106,15 @@ function handleMouseDown(e) { worldOffsetXBeforeDrag = worldOffsetX; worldOffsetYBeforeDrag = worldOffsetY; } else { - // Left mouse button for drawing - isDrawing = true; - draw(x, y); + // Left mouse button for drawing or breaking blocks + if (player) { + // If player exists, start breaking blocks + player.startBreaking(); + } else { + // Otherwise use normal drawing + isDrawing = true; + draw(x, y); + } } } @@ -149,6 +155,11 @@ function handleMouseUp(e) { } } isDragging = false; + + // Stop breaking blocks if player exists + if (player) { + player.stopBreaking(); + } } function draw(x, y) { diff --git a/js/render.js b/js/render.js index 6caea5e..3587645 100644 --- a/js/render.js +++ b/js/render.js @@ -175,16 +175,42 @@ function displayDebugInfo() { // Render breaking indicator for player function renderBreakingIndicator(ctx, offsetX, offsetY) { - // Calculate position in front of player - const breakX = Math.floor(player.x + (player.direction * player.breakingRange)); - const breakY = Math.floor(player.y); + // Get mouse position in world coordinates + const worldX = Math.floor(currentMouseX / PIXEL_SIZE) + worldOffsetX; + const worldY = Math.floor(currentMouseY / PIXEL_SIZE) + worldOffsetY; + + // Calculate distance from player to target block + const distance = Math.sqrt( + Math.pow(worldX - player.x, 2) + + Math.pow(worldY - player.y, 2) + ); // Convert to screen coordinates - const screenX = (breakX - offsetX) * PIXEL_SIZE; - const screenY = (breakY - offsetY) * PIXEL_SIZE; + const screenX = (worldX - offsetX) * PIXEL_SIZE; + const screenY = (worldY - offsetY) * PIXEL_SIZE; + const playerScreenX = (player.x - offsetX) * PIXEL_SIZE; + const playerScreenY = (player.y - offsetY) * PIXEL_SIZE; + + // Draw breaking range circle + ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)'; + ctx.lineWidth = 2; + ctx.beginPath(); + ctx.arc( + playerScreenX, + playerScreenY, + player.breakingRange * PIXEL_SIZE, + 0, + Math.PI * 2 + ); + ctx.stroke(); + + // Draw target indicator + if (distance <= player.breakingRange) { + ctx.strokeStyle = '#ff0000'; + } else { + ctx.strokeStyle = '#888888'; // Gray when out of range + } - // Draw breaking indicator - ctx.strokeStyle = '#ff0000'; ctx.lineWidth = 2; ctx.strokeRect( screenX - PIXEL_SIZE/2, @@ -193,9 +219,9 @@ function renderBreakingIndicator(ctx, offsetX, offsetY) { PIXEL_SIZE ); - // Draw line from player to breaking point + // Draw line from player to target point ctx.beginPath(); - ctx.moveTo((player.x - offsetX) * PIXEL_SIZE, (player.y - offsetY) * PIXEL_SIZE); + ctx.moveTo(playerScreenX, playerScreenY); ctx.lineTo(screenX, screenY); ctx.stroke(); }