feat: Implement player block breaking with 10-pixel range and inventory collection

This commit is contained in:
Kacper Kostka (aider) 2025-04-05 19:12:11 +02:00
parent d765defa9d
commit 80c243ebf8
3 changed files with 80 additions and 35 deletions

View File

@ -29,7 +29,7 @@ class Player extends Entity {
this.maxHealth = 100; this.maxHealth = 100;
this.health = 100; this.health = 100;
this.breakingPower = 1; this.breakingPower = 1;
this.breakingRange = 3; this.breakingRange = 10; // Increased from 3 to 10 pixels
this.isBreaking = false; this.isBreaking = false;
this.breakingCooldown = 0; this.breakingCooldown = 0;
this.breakingCooldownMax = 10; this.breakingCooldownMax = 10;
@ -252,30 +252,38 @@ class Player extends Entity {
} }
breakBlock() { breakBlock() {
// Calculate the position in front of the player // Get mouse position in world coordinates
const halfWidth = this.width / 2; const worldX = Math.floor(currentMouseX / PIXEL_SIZE) + worldOffsetX;
const breakX = Math.floor(this.x + (this.direction * this.breakingRange)); const worldY = Math.floor(currentMouseY / PIXEL_SIZE) + worldOffsetY;
const breakY = Math.floor(this.y);
// Get the block type at that position // Calculate distance from player to target block
const blockType = getPixel(breakX, breakY); 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 // Only break blocks within range
if (blockType !== EMPTY && if (distance <= this.breakingRange) {
blockType !== WATER && // Get the block type at that position
blockType !== FIRE && const blockType = getPixel(worldX, worldY);
blockType !== SQUARE &&
blockType !== CIRCLE &&
blockType !== TRIANGLE) {
// Add to inventory based on block type // Only break non-empty blocks that aren't special entities
this.addToInventory(blockType); if (blockType !== EMPTY &&
blockType !== WATER &&
blockType !== FIRE &&
blockType !== SQUARE &&
blockType !== CIRCLE &&
blockType !== TRIANGLE) {
// Replace with empty space // Add to inventory based on block type
setPixel(breakX, breakY, EMPTY); this.addToInventory(blockType);
// Create a breaking effect (particles) // Replace with empty space
this.createBreakingEffect(breakX, breakY, blockType); setPixel(worldX, worldY, EMPTY);
// Create a breaking effect (particles)
this.createBreakingEffect(worldX, worldY, blockType);
}
} }
} }

View File

@ -18,7 +18,7 @@ window.addEventListener('keydown', (e) => {
e.preventDefault(); e.preventDefault();
} }
// Start breaking blocks with E key // Start breaking blocks with E key or left mouse button
if (e.code === 'KeyE' && player) { if (e.code === 'KeyE' && player) {
player.startBreaking(); player.startBreaking();
} }
@ -106,9 +106,15 @@ function handleMouseDown(e) {
worldOffsetXBeforeDrag = worldOffsetX; worldOffsetXBeforeDrag = worldOffsetX;
worldOffsetYBeforeDrag = worldOffsetY; worldOffsetYBeforeDrag = worldOffsetY;
} else { } else {
// Left mouse button for drawing // Left mouse button for drawing or breaking blocks
isDrawing = true; if (player) {
draw(x, y); // 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; isDragging = false;
// Stop breaking blocks if player exists
if (player) {
player.stopBreaking();
}
} }
function draw(x, y) { function draw(x, y) {

View File

@ -175,16 +175,42 @@ function displayDebugInfo() {
// Render breaking indicator for player // Render breaking indicator for player
function renderBreakingIndicator(ctx, offsetX, offsetY) { function renderBreakingIndicator(ctx, offsetX, offsetY) {
// Calculate position in front of player // Get mouse position in world coordinates
const breakX = Math.floor(player.x + (player.direction * player.breakingRange)); const worldX = Math.floor(currentMouseX / PIXEL_SIZE) + worldOffsetX;
const breakY = Math.floor(player.y); 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 // Convert to screen coordinates
const screenX = (breakX - offsetX) * PIXEL_SIZE; const screenX = (worldX - offsetX) * PIXEL_SIZE;
const screenY = (breakY - offsetY) * 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.lineWidth = 2;
ctx.strokeRect( ctx.strokeRect(
screenX - PIXEL_SIZE/2, screenX - PIXEL_SIZE/2,
@ -193,9 +219,9 @@ function renderBreakingIndicator(ctx, offsetX, offsetY) {
PIXEL_SIZE PIXEL_SIZE
); );
// Draw line from player to breaking point // Draw line from player to target point
ctx.beginPath(); ctx.beginPath();
ctx.moveTo((player.x - offsetX) * PIXEL_SIZE, (player.y - offsetY) * PIXEL_SIZE); ctx.moveTo(playerScreenX, playerScreenY);
ctx.lineTo(screenX, screenY); ctx.lineTo(screenX, screenY);
ctx.stroke(); ctx.stroke();
} }