about summary refs log tree commit diff stats
path: root/js
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-01-10 21:30:43 -0500
committerelioat <elioat@tilde.institute>2024-01-10 21:30:43 -0500
commitcabd602f4006e3781d04bc314f66058d4ea157be (patch)
treebf034344b03a0b2efdecafabcf1dccd4732760cd /js
parent4c732e8889e895ce1a22ee4df88c42e0afd8bc63 (diff)
downloadtour-cabd602f4006e3781d04bc314f66058d4ea157be.tar.gz
*
Diffstat (limited to 'js')
-rw-r--r--js/toadmode/APL386.ttfbin0 -> 203668 bytes
-rw-r--r--js/toadmode/index.html6
-rw-r--r--js/toadmode/toad.js145
3 files changed, 111 insertions, 40 deletions
diff --git a/js/toadmode/APL386.ttf b/js/toadmode/APL386.ttf
new file mode 100644
index 0000000..5e3a338
--- /dev/null
+++ b/js/toadmode/APL386.ttf
Binary files differdiff --git a/js/toadmode/index.html b/js/toadmode/index.html
index 7d1fb17..6a0696e 100644
--- a/js/toadmode/index.html
+++ b/js/toadmode/index.html
@@ -5,10 +5,16 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>toad mode</title>
     <style>
+        /* https://github.com/abrudz/APL386 */
+        @font-face {font-family: 'APL386';src: url('APL386.ttf');}
+        /* https://shantellsans.com/process */
+        @import url('https://fonts.googleapis.com/css2?family=Shantell+Sans&display=swap');
         body {
             margin: 0;
             padding: 0;
             background-color: #000;
+            font-family: 'APL386', monospace;
+            /* font-family: 'Shantell Sans', sans-serif; */
         }
         canvas {
             display: block;
diff --git a/js/toadmode/toad.js b/js/toadmode/toad.js
index 73d4cbf..3b7ba84 100644
--- a/js/toadmode/toad.js
+++ b/js/toadmode/toad.js
@@ -7,11 +7,8 @@ canvas.height = viewportHeight;
 
 const context = canvas.getContext('2d');
 
-context.fillStyle = '#f0f0f0';
-context.fillRect(0, 0, canvas.width, canvas.height);
-
 const gridSize = 50;
-context.strokeStyle = 'white';
+let shapes = [];
 
 const drawLine = (x1, y1, x2, y2) => {
     context.moveTo(x1, y1);
@@ -19,45 +16,61 @@ const drawLine = (x1, y1, x2, y2) => {
     context.stroke();
 };
 
-for (let x = 0; x <= viewportWidth; x += gridSize) {
-    drawLine(x, 0, x, viewportHeight);
-}
-
-for (let y = 0; y <= viewportHeight; y += gridSize) {
-    drawLine(0, y, viewportWidth, y);
-}
-
-const contextMenu = document.createElement('ul');
-contextMenu.id = 'context-menu';
-contextMenu.style.display = 'none';
-contextMenu.style.position = 'fixed';
-contextMenu.style.listStyle = 'none';
-contextMenu.style.padding = '10px';
-contextMenu.style.backgroundColor = 'white';
-contextMenu.style.border = '1px solid black';
-
 const drawShape = (shape, x, y) => {
     context.beginPath();
     context.strokeStyle = '#2d2d2d';
     context.fillStyle = '#2d2d2d';
+    const size = gridSize * 0.8;
+    const offset = (gridSize - size) / 2;
     if (shape === 'square') {
-        context.rect(x, y, gridSize, gridSize);
-        context.fill();
+        context.rect(x + offset, y + offset, size, size);
     } else if (shape === 'triangle') {
-        context.moveTo(x, y);
-        context.lineTo(x + gridSize, y);
-        context.lineTo(x + gridSize / 2, y + gridSize);
+        context.moveTo(x + gridSize / 2, y + offset);
+        context.lineTo(x + offset, y + size + offset);
+        context.lineTo(x + size + offset, y + size + offset);
         context.closePath();
-        context.fill();
     } else if (shape === 'circle') {
-        context.arc(x + gridSize / 2, y + gridSize / 2, gridSize / 2, 0, 2 * Math.PI);
-        context.fill();
+        const radius = gridSize * 0.4;
+        const centerX = x + gridSize / 2;
+        const centerY = y + gridSize / 2;
+        context.arc(centerX, centerY, radius, 0, 2 * Math.PI);
+    } else if (shape === 'octagon') {
+        const cellCenterX = x + gridSize / 2;
+        const cellCenterY = y + gridSize / 2;
+        const sideLength = gridSize / (2 + Math.sqrt(2));
+        const angle = (2 * Math.PI) / 8;
+        context.moveTo(cellCenterX + sideLength * Math.cos(0), cellCenterY + sideLength * Math.sin(0));
+        [...Array(8).keys()].slice(1).forEach(i => {
+            const newX = cellCenterX + sideLength * Math.cos(i * angle);
+            const newY = cellCenterY + sideLength * Math.sin(i * angle);
+            context.lineTo(newX, newY);
+        });
+        context.closePath();
+    } else if (shape === 'pentagon') {
+        const cellCenterX = x + gridSize / 2;
+        const cellCenterY = y + gridSize / 2;
+        const sideLength = gridSize / (1 + Math.sqrt(5 / 2));
+        const angle = (2 * Math.PI) / 5;
+        context.moveTo(cellCenterX + sideLength * Math.cos(0), cellCenterY + sideLength * Math.sin(0));
+        [...Array(5).keys()].slice(1).forEach(i => {
+            const newX = cellCenterX + sideLength * Math.cos(i * angle);
+            const newY = cellCenterY + sideLength * Math.sin(i * angle);
+            context.lineTo(newX, newY);
+        });
+        context.closePath();
+    } else if (shape === 'diamond') {
+        context.moveTo(x + gridSize / 2, y + offset);
+        context.lineTo(x + offset, y + gridSize / 2);
+        context.lineTo(x + gridSize / 2, y + size + offset);
+        context.lineTo(x + size + offset, y + gridSize / 2);
+        context.closePath();
     }
+    context.fill();
     context.stroke();
     shapes.push({ type: shape, x, y, color: '#2d2d2d' });
 };
 
-['Square', 'Triangle', 'Circle'].forEach(shape => {
+const createContextMenuOption = (shape) => {
     const option = document.createElement('li');
     option.textContent = shape;
     option.style.cursor = 'pointer';
@@ -67,6 +80,25 @@ const drawShape = (shape, x, y) => {
         const cellY = Math.floor(lastRightClick.y / gridSize) * gridSize;
         drawShape(shape.toLowerCase(), cellX, cellY);
     });
+    if (shape === 'Nope') {
+        option.style.color = 'lightcoral';
+    }
+    return option;
+};
+
+const contextMenu = document.createElement('ul');
+contextMenu.id = 'context-menu';
+contextMenu.style.display = 'none';
+contextMenu.style.position = 'fixed';
+contextMenu.style.listStyle = 'none';
+contextMenu.style.lineHeight = '1.25';
+contextMenu.style.padding = '10px';
+contextMenu.style.fontSize = '18px';
+contextMenu.style.backgroundColor = 'white';
+contextMenu.style.border = '1px solid black';
+
+['Square', 'Triangle', 'Circle', 'Octagon', 'Pentagon', 'Diamond', 'Nope'].forEach(shape => {
+    const option = createContextMenuOption(shape);
     contextMenu.appendChild(option);
 });
 
@@ -74,16 +106,49 @@ document.body.appendChild(contextMenu);
 
 let lastRightClick = { x: 0, y: 0 };
 
-canvas.addEventListener('contextmenu', (event) => {
-    event.preventDefault();
-    lastRightClick = { x: event.clientX, y: event.clientY };
-    contextMenu.style.display = 'block';
-    contextMenu.style.left = `${event.clientX}px`;
-    contextMenu.style.top = `${event.clientY}px`;
+canvas.addEventListener('click', (event) => {
+    const cellX = Math.floor(event.clientX / gridSize) * gridSize;
+    const cellY = Math.floor(event.clientY / gridSize) * gridSize;
+    const clickedShape = shapes.find(shape => shape.x === cellX && shape.y === cellY);
+    if (!clickedShape) {
+        lastRightClick = { x: event.clientX, y: event.clientY };
+        contextMenu.style.display = 'block';
+        contextMenu.style.left = `${event.clientX}px`;
+        contextMenu.style.top = `${event.clientY}px`;
+    }
 });
 
-let shapes = [];
+const removeShape = (x, y) => {
+    shapes = shapes.filter(shape => !(shape.x === x && shape.y === y));
+    redrawGrid();
+    context.fillStyle = '#f0f0f0';
+    context.fillRect(x, y, gridSize, gridSize);
+}
+
+const redrawGrid = () => {
+    context.clearRect(0, 0, canvas.width, canvas.height);
+
+    context.fillStyle = '#f0f0f0';
+    context.fillRect(0, 0, canvas.width, canvas.height);
+
+    context.strokeStyle = 'white';
+    [...Array(Math.ceil(viewportWidth / gridSize)).keys()].forEach(x => {
+        drawLine(x * gridSize, 0, x * gridSize, viewportHeight);
+    });
+
+    [...Array(Math.ceil(viewportHeight / gridSize)).keys()].forEach(y => {
+        drawLine(0, y * gridSize, viewportWidth, y * gridSize);
+    });
+
+    shapes.forEach(shape => {
+        drawShape(shape.type, shape.x, shape.y);
+    });
+}
+
+canvas.addEventListener('dblclick', (event) => {
+    const cellX = Math.floor(event.clientX / gridSize) * gridSize;
+    const cellY = Math.floor(event.clientY / gridSize) * gridSize;
+    removeShape(cellX, cellY);
+});
 
-window.addEventListener('click', () => {
-    contextMenu.style.display = 'none';
-});
\ No newline at end of file
+redrawGrid();