about summary refs log tree commit diff stats
path: root/js
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-01-05 20:59:39 -0500
committerelioat <elioat@tilde.institute>2024-01-05 20:59:39 -0500
commit166a055a3df448839cc5564e20fc7e37205d875e (patch)
tree87e3f73809afe48557f3342547e6bbcb11993080 /js
parent92b42b5a86fcacdb479e54e99fe045d72f337ff9 (diff)
downloadtour-166a055a3df448839cc5564e20fc7e37205d875e.tar.gz
8
Diffstat (limited to 'js')
-rw-r--r--js/ship-game/game.js340
-rw-r--r--js/ship-game/index.html1
2 files changed, 223 insertions, 118 deletions
diff --git a/js/ship-game/game.js b/js/ship-game/game.js
index e50814c..072561f 100644
--- a/js/ship-game/game.js
+++ b/js/ship-game/game.js
@@ -1,147 +1,251 @@
-const canvas = document.getElementById('gameCanvas');
-const ctx = canvas.getContext('2d');
-canvas.style.display = "block";
-canvas.width = window.innerWidth - 100;
-canvas.height = window.innerHeight - 200;
+// this code is terrible. it currently doesn't run at a smooth rate, the rate at which it runs seems to be linked to the mouse moving around
+(() => {
+    const canvas = document.getElementById('gameCanvas');
+    const ctx = canvas.getContext('2d');
 
-let audio = new Audio('./zap.wav');
-audio.preload = 'auto';
+    canvas.style.display = "block";
+    canvas.width = window.innerWidth - 100;
+    canvas.height = window.innerHeight - 200;
 
-let audioLoaded = false;
+    const audio = new Audio('./zap.wav');
+    audio.preload = 'auto';
 
-audio.addEventListener('canplaythrough', function() {
-    audioLoaded = true;
-});
+    let audioLoaded = false;
 
-audio.addEventListener('error', function() {
-    console.error('Error loading audio file');
-});
+    const getRandomColor = () => {
+        const letters = '0123456789ABCDEF';
+        return Array.from({ length: 6 }, () => letters[Math.floor(Math.random() * 16)]).join('');
+    };
+
+    const createTargets = () => {
+        const numTargets = 5;
+        const minDistance = 100;
+
+        const targets = Array.from({ length: numTargets }).reduce((acc) => {
+            let isRound = Math.random() < 0.5;
+            let sides = isRound ? 0 : Math.floor(Math.random() * 5) + 3;
+            let radius = Math.random() * 50 + 20;
+            let x, y, validPosition;
 
-const createTargets = () => {
-    let targets = [];
+            do {
+                validPosition = true;
+                x = Math.random() * (canvas.width - 2 * radius - 120) + radius + 60;
+                y = Math.random() * (canvas.height - 2 * radius - 120) + radius + 60;
 
-    for(let i = 0; i < 10; i++) {
-        let radius = Math.random() * 50 + 20;
-        let x = Math.random() * (canvas.width - 2 * radius - 120) + radius + 60;
-        let y = Math.random() * (canvas.height - 2 * radius - 120) + radius + 60;
-        let vx = (Math.random() - 0.5) * 10;
-        let vy = (Math.random() - 0.5) * 10;
+                validPosition = !acc.some((otherTarget) => {
+                    const dx = otherTarget.x - x;
+                    const dy = otherTarget.y - y;
+                    const distance = Math.sqrt(dx * dx + dy * dy);
 
-        targets.push({x, y, vx, vy, radius});
-    }
+                    return distance < minDistance;
+                });
+            } while (!validPosition);
 
-    return targets;
-}
+            let vx = (Math.random() - 0.5) * 5;
+            let vy = (Math.random() - 0.5) * 5;
+            let color = getRandomColor();
 
-let score = 0;
-const drawScore = () => {
-    ctx.font = '20px Arial';
-    ctx.fillStyle = 'white';
-    ctx.fillText('Score: ' + score, 10, 30);
-};
+            while (color === canvas.style.backgroundColor) {
+                color = getRandomColor();
+            }
 
+            acc.push({ x, y, vx, vy, radius, sides, color });
+            return acc;
+        }, []);
+
+        return targets;
+    };
 
-let showHelp = true;
-const drawHelp = () => {
-    if(showHelp) {
+    const drawScore = () => {
         ctx.font = '20px Arial';
         ctx.fillStyle = 'white';
-        ctx.fillText('Click to shoot. Press R to respawn targets. Press H to toggle help text.', 10, 50);
-    }
-}
+        ctx.fillText('Score: ' + score, 10, 30);
+    };
 
-const drawLine = (line) => {
-    if (line && Date.now() - line.time < 500) {
-        ctx.beginPath();
-        ctx.moveTo(line.startX, line.startY);
-        ctx.lineTo(line.endX, line.endY);
-        ctx.strokeStyle = 'red';
-        ctx.lineWidth = 4;
-        ctx.stroke();
-    }
-};
-
-const drawTargets = (targets) => {
-    for (let target of targets) {
-        target.x += target.vx;
-        target.y += target.vy;
-
-        if (target.x - target.radius < 0 || target.x + target.radius > canvas.width) {
-            target.vx = -target.vx;
+    const drawHelp = () => {
+        if (showHelp) {
+            ctx.font = '20px Arial';
+            ctx.fillStyle = 'white';
+            ctx.fillText('Click to shoot. Press R to respawn targets. Press H to toggle help text.', 10, 50);
+        }
+    };
+
+    const drawLine = (line) => {
+        if (line && Date.now() - line.time < 500) {
+            ctx.beginPath();
+            ctx.moveTo(canvas.width, canvas.height);
+            ctx.lineTo(line.endX, line.endY);
+            ctx.strokeStyle = 'red';
+            ctx.lineWidth = 4;
+            ctx.stroke();
         }
-        if (target.y - target.radius < 0 || target.y + target.radius > canvas.height) {
-            target.vy = -target.vy;
+    };
+
+    const detectCollision = (target, otherTarget) => {
+        const dx = otherTarget.x - target.x;
+        const dy = otherTarget.y - target.y;
+        const distance = Math.sqrt(dx * dx + dy * dy);
+
+        if (distance < target.radius + otherTarget.radius) {
+            const normalX = dx / distance;
+            const normalY = dy / distance;
+            const tangentX = -normalY;
+            const tangentY = normalX;
+
+            const dotProductTarget = target.vx * normalX + target.vy * normalY;
+            const dotProductOtherTarget = otherTarget.vx * normalX + otherTarget.vy * normalY;
+
+            const targetVxAfterCollision = dotProductOtherTarget * normalX + dotProductTarget * tangentX;
+            const targetVyAfterCollision = dotProductOtherTarget * normalY + dotProductTarget * tangentY;
+            const otherTargetVxAfterCollision = dotProductTarget * normalX + dotProductOtherTarget * tangentX;
+            const otherTargetVyAfterCollision = dotProductTarget * normalY + dotProductOtherTarget * tangentY;
+
+            target.vx = targetVxAfterCollision;
+            target.vy = targetVyAfterCollision;
+            otherTarget.vx = otherTargetVxAfterCollision;
+            otherTarget.vy = otherTargetVyAfterCollision;
         }
+    };
+
+    const drawTargets = (targets) => {
+        targets.forEach((target, index) => {
+            target.x += target.vx;
+            target.y += target.vy;
+
+            if (target.x - target.radius < 0 || target.x + target.radius > canvas.width) {
+                target.vx = -target.vx;
+            }
+            if (target.y - target.radius < 0 || target.y + target.radius > canvas.height) {
+                target.vy = -target.vy;
+            }
+
+            targets.forEach((target, index) => {
+                const otherTargets = targets.slice(index + 1);
+                otherTargets.forEach((otherTarget) => {
+                    detectCollision(target, otherTarget);
+                });
+            });
+
+            ctx.beginPath();
+            if (target.sides === 0) {
+                ctx.arc(target.x, target.y, target.radius, 0, 2 * Math.PI);
+            } else if (target.sides === 3) {
+                ctx.moveTo(target.x + target.radius * Math.cos(0), target.y + target.radius * Math.sin(0));
+                for (let i = 1; i <= target.sides; i++) {
+                    ctx.lineTo(target.x + target.radius * Math.cos(i * 2 * Math.PI / target.sides), target.y + target.radius * Math.sin(i * 2 * Math.PI / target.sides));
+                }
+            } else if (target.sides === 4) {
+                ctx.rect(target.x - target.radius, target.y - target.radius, target.radius * 2, target.radius * 2);
+            } else {
+                ctx.moveTo(target.x + target.radius, target.y);
+                for (let i = 1; i <= target.sides; i++) {
+                    ctx.lineTo(target.x + target.radius * Math.cos(i * 2 * Math.PI / target.sides), target.y + target.radius * Math.sin(i * 2 * Math.PI / target.sides));
+                }
+            }
+            ctx.fillStyle = target.color;
+            ctx.fill();
+        });
+    };
+
+    let score = 0;
+    let showHelp = true;
+    let line = null;
+    let targets = createTargets();
+
+    let mousePos = { x: 0, y: 0 };
+    let prevMousePos = { x: 0, y: 0 };
+
+    canvas.addEventListener('mousemove', (e) => {
+        const rect = canvas.getBoundingClientRect();
+        prevMousePos.x = mousePos.x;
+        prevMousePos.y = mousePos.y;
+        mousePos.x = e.clientX - rect.left;
+        mousePos.y = e.clientY - rect.top;
+    });
+
+    const drawMouseCircle = () => {
+        if (mousePos.x !== prevMousePos.x || mousePos.y !== prevMousePos.y) {
+            ctx.clearRect(0, 0, canvas.width, canvas.height);
+            drawScore();
+            drawHelp();
+            drawLine(line);
+            drawTargets(targets);
+        }
+
+        ctx.beginPath();
+        ctx.arc(mousePos.x, mousePos.y, 10, 0, Math.PI * 2);
+        ctx.fillStyle = 'white';
+        ctx.fill();
 
         ctx.beginPath();
-        ctx.arc(target.x, target.y, target.radius, 0, Math.PI * 2);
-        ctx.fillStyle = '#aaa';
+        ctx.arc(mousePos.x, mousePos.y, 5, 0, Math.PI * 2);
+        ctx.fillStyle = 'black';
         ctx.fill();
-    }
-};
+    };
 
-const gameLoop = () => {
-    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    const gameLoop = () => {
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
 
-    drawScore();
-    drawHelp();
-    drawLine(line);
-    drawTargets(targets);
+        drawScore();
+        drawHelp();
+        drawLine(line);
+        drawTargets(targets);
+        drawMouseCircle();
 
-    requestAnimationFrame(gameLoop);
-};
+        requestAnimationFrame(gameLoop);
+    };
 
-let line = null;
+    audio.addEventListener('canplaythrough', function () {
+        audioLoaded = true;
+    });
 
-canvas.addEventListener('click', (e) => {
-    const rect = canvas.getBoundingClientRect();
-    const x = e.clientX - rect.left;
-    const y = e.clientY - rect.top;
+    audio.addEventListener('error', function () {
+        console.error('Error loading audio file');
+    });
 
-    if (audioLoaded) {
-        audio.play().catch((error) => {
-            console.error('Error playing audio:', error);
+    canvas.addEventListener('click', (e) => {
+        const rect = canvas.getBoundingClientRect();
+        const x = e.clientX - rect.left;
+        const y = e.clientY - rect.top;
+
+        if (audioLoaded) {
+            audio.play().catch((error) => {
+                console.error('Error playing audio:', error);
+            });
+        }
+
+        line = {
+            startX: 0,
+            startY: canvas.height,
+            endX: x,
+            endY: y,
+            time: Date.now()
+        };
+
+        targets = targets.filter((target) => {
+            const dx = target.x - x;
+            const dy = target.y - y;
+            if (dx * dx + dy * dy <= target.radius * target.radius) {
+                score++;
+                return false;
+            }
+            return true;
         });
-    }
-
-    line = {
-        startX: 0,
-        startY: canvas.height,
-        endX: x,
-        endY: y,
-        time: Date.now()
-    };
+    });
 
-    targets = targets.filter((target) => {
-        const dx = target.x - x;
-        const dy = target.y - y;
-        if (dx * dx + dy * dy <= target.radius * target.radius) {
-            score++;
-            return false;
+    window.addEventListener('resize', () => {
+        canvas.width = window.innerWidth;
+        canvas.height = window.innerHeight;
+    });
+
+    window.addEventListener('keydown', (e) => {
+        if (e.key === 'r' || e.key === 'R') {
+            targets = createTargets();
+        }
+        if (e.key === 'h' || e.key === 'H') {
+            showHelp = !showHelp;
         }
-        return true;
     });
-});
-
-window.addEventListener('resize', () => {
-    canvas.width = window.innerWidth;
-    canvas.height = window.innerHeight;
-});
-
-window.addEventListener('keydown', (e) => {
-    if (e.key === 'r' || e.key === 'R') {
-        targets = createTargets();
-    }
-});
-
-window.addEventListener('keydown', (e) => {
-    if (e.key === 'h' || e.key === 'H') {
-        showHelp = !showHelp;
-    } else if (e.key === 'r' || e.key === 'R') {
-        targets = createTargets();
-    }
-});
-
-let targets = createTargets();
-
-gameLoop();
\ No newline at end of file
+
+    gameLoop();
+})();
diff --git a/js/ship-game/index.html b/js/ship-game/index.html
index 8c46ae7..4b8ada6 100644
--- a/js/ship-game/index.html
+++ b/js/ship-game/index.html
@@ -10,6 +10,7 @@
         canvas {
             background-color: rgb(5, 10, 94);
             border: 1px solid black;
+            cursor: none;
         }
         body, canvas {
             padding: 1em;