sandsim/js/input.js
2025-04-05 17:24:10 +02:00

210 lines
7.3 KiB
JavaScript

// Input handling functions
let isDrawing = false;
let isDragging = false;
let lastMouseX, lastMouseY;
let currentMouseX, currentMouseY;
function setTool(tool) {
currentTool = tool;
document.querySelectorAll('.tools button').forEach(btn => btn.classList.remove('active'));
if (tool === SAND) {
document.getElementById('sand-btn').classList.add('active');
} else if (tool === WATER) {
document.getElementById('water-btn').classList.add('active');
} else if (tool === DIRT) {
document.getElementById('dirt-btn').classList.add('active');
} else if (tool === STONE) {
document.getElementById('stone-btn').classList.add('active');
} else if (tool === GRASS) {
document.getElementById('grass-btn').classList.add('active');
} else if (tool === WOOD) {
document.getElementById('wood-btn').classList.add('active');
} else if (tool === SEED) {
document.getElementById('seed-btn').classList.add('active');
} else if (tool === TREE_SEED) {
document.getElementById('tree-seed-btn').classList.add('active');
} else if (tool === FIRE) {
document.getElementById('fire-btn').classList.add('active');
} else if (tool === LAVA) {
document.getElementById('lava-btn').classList.add('active');
} else if (tool === RABBIT) {
document.getElementById('rabbit-btn').classList.add('active');
} else if (tool === SQUARE) {
document.getElementById('square-btn').classList.add('active');
} else if (tool === CIRCLE) {
document.getElementById('circle-btn').classList.add('active');
} else if (tool === TRIANGLE) {
document.getElementById('triangle-btn').classList.add('active');
} else if (tool === EMPTY) {
document.getElementById('eraser-btn').classList.add('active');
}
}
function handleMouseDown(e) {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// Right mouse button for dragging the world
if (e.button === 2 || e.ctrlKey || e.shiftKey) {
isDragging = true;
lastMouseX = x;
lastMouseY = y;
worldOffsetXBeforeDrag = worldOffsetX;
worldOffsetYBeforeDrag = worldOffsetY;
} else {
// Left mouse button for drawing
isDrawing = true;
draw(x, y);
}
}
function handleMouseMove(e) {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// Always update current mouse position
currentMouseX = x;
currentMouseY = y;
if (isDragging) {
// Calculate how much the mouse has moved
const dx = x - lastMouseX;
const dy = y - lastMouseY;
// Move the world in the opposite direction (divide by pixel size to convert to world coordinates)
moveWorld(-dx / PIXEL_SIZE, -dy / PIXEL_SIZE);
// Update the last mouse position
lastMouseX = x;
lastMouseY = y;
} else if (isDrawing) {
draw(x, y);
}
}
function handleMouseUp(e) {
isDrawing = false;
if (isDragging) {
// Calculate the total movement during this drag
const totalDragX = worldOffsetX - worldOffsetXBeforeDrag;
const totalDragY = worldOffsetY - worldOffsetYBeforeDrag;
if (debugMode) {
console.log(`Drag completed: ${totalDragX}, ${totalDragY}`);
}
}
isDragging = false;
}
function draw(x, y) {
if (!isDrawing) return;
// Convert screen coordinates to world coordinates
const worldX = Math.floor(x / PIXEL_SIZE) + worldOffsetX;
const worldY = Math.floor(y / PIXEL_SIZE) + worldOffsetY;
// Special handling for physics objects
if (currentTool === SQUARE || currentTool === CIRCLE || currentTool === TRIANGLE) {
// Create a physics object at the cursor position
const size = 10; // Default size
createPhysicsObject(currentTool, worldX, worldY, size);
return;
}
// Draw a small brush (3x3)
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
const pixelX = worldX + dx;
const pixelY = worldY + dy;
// Special handling for fire - only set fire to flammable materials
if (currentTool === FIRE) {
const currentPixel = getPixel(pixelX, pixelY);
if (FLAMMABLE_MATERIALS.includes(currentPixel)) {
setPixel(pixelX, pixelY, FIRE);
setMetadata(pixelX, pixelY, {
lifetime: 100 + Math.floor(Math.random() * 100),
colorIndex: Math.floor(Math.random() * FIRE_COLORS.length)
});
}
}
// Special handling for rabbits - create rabbit entity
else if (currentTool === RABBIT) {
createEntity(ENTITY_TYPES.RABBIT, pixelX, pixelY);
return; // Only create one rabbit per click
} else {
setPixel(pixelX, pixelY, currentTool);
// Add metadata for special types
if (currentTool === SEED) {
setMetadata(pixelX, pixelY, { type: 'regular' });
} else if (currentTool === FLOWER) {
setMetadata(pixelX, pixelY, {
type: 'flower',
color: FLOWER_COLORS[Math.floor(Math.random() * FLOWER_COLORS.length)],
age: 0,
height: 1
});
}
}
}
}
}
function handleTouchStart(e) {
e.preventDefault();
// Check if we have multiple touch points (for dragging)
if (e.touches.length > 1) {
isDragging = true;
lastMouseX = e.touches[0].clientX;
lastMouseY = e.touches[0].clientY;
worldOffsetXBeforeDrag = worldOffsetX;
worldOffsetYBeforeDrag = worldOffsetY;
} else {
// Single touch for drawing
isDrawing = true;
const rect = canvas.getBoundingClientRect();
const x = e.touches[0].clientX - rect.left;
const y = e.touches[0].clientY - rect.top;
currentMouseX = x;
currentMouseY = y;
draw(x, y);
}
}
function handleTouchMove(e) {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
if (isDragging && e.touches.length > 1) {
// Calculate how much the touch has moved
const x = e.touches[0].clientX;
const y = e.touches[0].clientY;
const dx = x - lastMouseX;
const dy = y - lastMouseY;
// Move the world in the opposite direction
moveWorld(-dx / PIXEL_SIZE, -dy / PIXEL_SIZE);
// Update the last touch position
lastMouseX = x;
lastMouseY = y;
} else if (isDrawing) {
const x = e.touches[0].clientX - rect.left;
const y = e.touches[0].clientY - rect.top;
currentMouseX = x;
currentMouseY = y;
draw(x, y);
}
}
function toggleDebug() {
debugMode = !debugMode;
document.getElementById('debug-btn').classList.toggle('active');
}