feat: Add mouse-based world navigation with drag and touch support
This commit is contained in:
parent
dbcf3a0e61
commit
eb9900478d
@ -6,7 +6,7 @@
|
|||||||
<title>Pixel Sand Simulation</title>
|
<title>Pixel Sand Simulation</title>
|
||||||
<link rel="stylesheet" href="styles.css">
|
<link rel="stylesheet" href="styles.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body oncontextmenu="return false;">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<div class="tools">
|
<div class="tools">
|
||||||
@ -23,6 +23,7 @@
|
|||||||
<div class="info">
|
<div class="info">
|
||||||
<span id="coords">Chunk: 0,0</span>
|
<span id="coords">Chunk: 0,0</span>
|
||||||
<span id="fps">FPS: 0</span>
|
<span id="fps">FPS: 0</span>
|
||||||
|
<span class="help-text">Hold Shift/Ctrl or right-click to drag the world</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<canvas id="simulation-canvas"></canvas>
|
<canvas id="simulation-canvas"></canvas>
|
||||||
|
108
script.js
108
script.js
@ -17,6 +17,8 @@ const WALL = 3;
|
|||||||
let canvas, ctx;
|
let canvas, ctx;
|
||||||
let currentTool = SAND;
|
let currentTool = SAND;
|
||||||
let isDrawing = false;
|
let isDrawing = false;
|
||||||
|
let isDragging = false;
|
||||||
|
let lastMouseX, lastMouseY;
|
||||||
let lastFrameTime = 0;
|
let lastFrameTime = 0;
|
||||||
let fps = 0;
|
let fps = 0;
|
||||||
let worldOffsetX = 0;
|
let worldOffsetX = 0;
|
||||||
@ -44,15 +46,15 @@ window.onload = function() {
|
|||||||
document.getElementById('move-down').addEventListener('click', () => moveWorld(0, CHUNK_SIZE/2));
|
document.getElementById('move-down').addEventListener('click', () => moveWorld(0, CHUNK_SIZE/2));
|
||||||
|
|
||||||
// Drawing events
|
// Drawing events
|
||||||
canvas.addEventListener('mousedown', startDrawing);
|
canvas.addEventListener('mousedown', handleMouseDown);
|
||||||
canvas.addEventListener('mousemove', draw);
|
canvas.addEventListener('mousemove', handleMouseMove);
|
||||||
canvas.addEventListener('mouseup', stopDrawing);
|
canvas.addEventListener('mouseup', handleMouseUp);
|
||||||
canvas.addEventListener('mouseleave', stopDrawing);
|
canvas.addEventListener('mouseleave', handleMouseUp);
|
||||||
|
|
||||||
// Touch events for mobile
|
// Touch events for mobile
|
||||||
canvas.addEventListener('touchstart', handleTouchStart);
|
canvas.addEventListener('touchstart', handleTouchStart);
|
||||||
canvas.addEventListener('touchmove', handleTouchMove);
|
canvas.addEventListener('touchmove', handleTouchMove);
|
||||||
canvas.addEventListener('touchend', stopDrawing);
|
canvas.addEventListener('touchend', handleMouseUp);
|
||||||
|
|
||||||
// Initialize the first chunk
|
// Initialize the first chunk
|
||||||
getOrCreateChunk(0, 0);
|
getOrCreateChunk(0, 0);
|
||||||
@ -79,28 +81,51 @@ function setTool(tool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function startDrawing(e) {
|
function handleMouseDown(e) {
|
||||||
isDrawing = true;
|
|
||||||
draw(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
function stopDrawing() {
|
|
||||||
isDrawing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function draw(e) {
|
|
||||||
if (!isDrawing) return;
|
|
||||||
|
|
||||||
const rect = canvas.getBoundingClientRect();
|
const rect = canvas.getBoundingClientRect();
|
||||||
let x, y;
|
const x = e.clientX - rect.left;
|
||||||
|
const y = e.clientY - rect.top;
|
||||||
|
|
||||||
if (e.type.startsWith('touch')) {
|
// Right mouse button for dragging the world
|
||||||
x = e.touches[0].clientX - rect.left;
|
if (e.button === 2 || e.ctrlKey || e.shiftKey) {
|
||||||
y = e.touches[0].clientY - rect.top;
|
isDragging = true;
|
||||||
|
lastMouseX = x;
|
||||||
|
lastMouseY = y;
|
||||||
} else {
|
} else {
|
||||||
x = e.clientX - rect.left;
|
// Left mouse button for drawing
|
||||||
y = e.clientY - rect.top;
|
isDrawing = true;
|
||||||
|
draw(x, y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseMove(e) {
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
const x = e.clientX - rect.left;
|
||||||
|
const y = e.clientY - rect.top;
|
||||||
|
|
||||||
|
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;
|
||||||
|
isDragging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw(x, y) {
|
||||||
|
if (!isDrawing) return;
|
||||||
|
|
||||||
// Convert to world coordinates
|
// Convert to world coordinates
|
||||||
const worldX = Math.floor(x / PIXEL_SIZE) + worldOffsetX;
|
const worldX = Math.floor(x / PIXEL_SIZE) + worldOffsetX;
|
||||||
@ -116,12 +141,45 @@ function draw(e) {
|
|||||||
|
|
||||||
function handleTouchStart(e) {
|
function handleTouchStart(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
startDrawing(e);
|
|
||||||
|
// 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;
|
||||||
|
} 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;
|
||||||
|
draw(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTouchMove(e) {
|
function handleTouchMove(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
draw(e);
|
|
||||||
|
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;
|
||||||
|
draw(x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveWorld(dx, dy) {
|
function moveWorld(dx, dy) {
|
||||||
|
@ -54,6 +54,10 @@ body {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.help-text {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
#simulation-canvas {
|
#simulation-canvas {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user