about summary refs log tree commit diff stats
path: root/js/ship-game
diff options
context:
space:
mode:
authorelioat <hi@eli.li>2024-01-14 19:22:18 -0500
committerelioat <hi@eli.li>2024-01-14 19:22:18 -0500
commitfe57eefd7c58d6bd95f059c0e5681d140aa8237e (patch)
tree5bd9624cd5928848de361969a0fee7e906c7f289 /js/ship-game
parent2a6a42a136b3e7b9db37fe150a94ab3b8bff5807 (diff)
downloadtour-fe57eefd7c58d6bd95f059c0e5681d140aa8237e.tar.gz
*
Diffstat (limited to 'js/ship-game')
-rw-r--r--js/ship-game/background.jpegbin0 -> 174565 bytes
-rw-r--r--js/ship-game/game.js411
-rw-r--r--js/ship-game/index.html20
3 files changed, 187 insertions, 244 deletions
diff --git a/js/ship-game/background.jpeg b/js/ship-game/background.jpeg
new file mode 100644
index 0000000..f171285
--- /dev/null
+++ b/js/ship-game/background.jpeg
Binary files differdiff --git a/js/ship-game/game.js b/js/ship-game/game.js
index 412288c..44a5df0 100644
--- a/js/ship-game/game.js
+++ b/js/ship-game/game.js
@@ -1,256 +1,197 @@
-(() => {
-    const canvas = document.getElementById('gameCanvas');
-    const ctx = canvas.getContext('2d');
-
-    canvas.style.display = "block";
-    canvas.width = window.innerWidth - 100;
-    canvas.height = window.innerHeight - 200;
-
-    const audio = new Audio('./zap.wav');
-    audio.preload = 'auto';
-
-    let audioLoaded = false;
-
-    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;
-
-            do {
-                validPosition = true;
-                x = Math.random() * (canvas.width - 2 * radius - 120) + radius + 60;
-                y = Math.random() * (canvas.height - 2 * radius - 120) + radius + 60;
-
-                validPosition = !acc.some((otherTarget) => {
-                    const dx = otherTarget.x - x;
-                    const dy = otherTarget.y - y;
-                    const distance = Math.sqrt(dx * dx + dy * dy);
-
-                    return distance < minDistance;
-                });
-            } while (!validPosition);
-
-            let vx = (Math.random() - 0.5) * 5;
-            let vy = (Math.random() - 0.5) * 5;
-            let color = getRandomColor();
-
-            while (color === canvas.style.backgroundColor) {
-                color = getRandomColor();
-            }
-
-            acc.push({ x, y, vx, vy, radius, sides, color });
-            return acc;
-        }, []);
-
-        return targets;
-    };
-
-    const drawScore = () => {
+const canvas = document.getElementById('gameCanvas');
+const ctx = canvas.getContext('2d');
+canvas.style.display = "block";
+canvas.width = window.innerWidth;
+canvas.height = window.innerHeight;
+
+let audio = new Audio('./zap.wav');
+audio.preload = 'auto';
+
+let audioLoaded = false;
+
+audio.addEventListener('canplaythrough', function() {
+    audioLoaded = true;
+});
+
+audio.addEventListener('error', function() {
+    console.error('Error loading audio file');
+});
+
+const createTargets = () => {
+    let targets = [];
+
+    for(let i = 0; i < 10; i++) {
+        let shape = getRandomShape();
+        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;
+
+        targets.push({x, y, vx, vy, radius, shape});
+    }
+
+    return targets;
+}
+
+const getRandomShape = () => {
+    const shapes = ['circle', 'pentagon', 'triangle', 'square'];
+    const randomIndex = Math.floor(Math.random() * shapes.length);
+    return shapes[randomIndex];
+}
+
+let score = 0;
+const drawScore = () => {
+    ctx.font = '20px Arial';
+    ctx.fillStyle = 'white';
+    ctx.fillText('Score: ' + score, 10, 30);
+};
+
+let level = 1;
+const drawLevel = () => {
+    ctx.font = '20px Arial';
+    ctx.fillStyle = 'white';
+    ctx.fillText('Level: ' + level, 10, 60);
+}
+
+
+let showHelp = false;
+const drawHelp = () => {
+    if(showHelp) {
         ctx.font = '20px Arial';
         ctx.fillStyle = 'white';
-        ctx.fillText('Score: ' + score, 10, 30);
-    };
-
-    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);
-        }
-    };
+        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 = 5;            
-            ctx.shadowColor = 'rgba(255, 255, 0, 0.75)';
-            ctx.shadowBlur = 50;
-            ctx.shadowOffsetX = 0;
-            ctx.shadowOffsetY = 0;
-            ctx.stroke();
-            ctx.shadowColor = 'transparent';
-            ctx.shadowBlur = 0;
+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 colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF'];
+
+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 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;
+        if (target.y - target.radius < 0 || target.y + target.radius > canvas.height) {
+            target.vy = -target.vy;
         }
-    };
 
-    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;
+        ctx.beginPath();
+        if (target.shape === 'circle') {
+            ctx.arc(target.x, target.y, target.radius, 0, Math.PI * 2);
+        } else if (target.shape === 'pentagon') {
+            ctx.moveTo(target.x + target.radius * Math.cos(0), target.y + target.radius * Math.sin(0));
+            for (let i = 1; i <= 5; i++) {
+                ctx.lineTo(target.x + target.radius * Math.cos(i * (Math.PI * 2) / 5), target.y + target.radius * Math.sin(i * (Math.PI * 2) / 5));
             }
-            if (target.y - target.radius < 0 || target.y + target.radius > canvas.height) {
-                target.vy = -target.vy;
+        } else if (target.shape === 'triangle') {
+            ctx.moveTo(target.x + target.radius * Math.cos(0), target.y + target.radius * Math.sin(0));
+            for (let i = 1; i <= 3; i++) {
+                ctx.lineTo(target.x + target.radius * Math.cos(i * (Math.PI * 2) / 3), target.y + target.radius * Math.sin(i * (Math.PI * 2) / 3));
             }
-
-            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);
+        } else if (target.shape === 'square') {
+            ctx.rect(target.x - target.radius, target.y - target.radius, target.radius * 2, target.radius * 2);
         }
-
-        ctx.beginPath();
-        ctx.arc(mousePos.x, mousePos.y, 10, 0, Math.PI * 2);
-        ctx.fillStyle = 'white';
+        
+        const randomColor = colors[Math.floor(Math.random() * colors.length)];
+        ctx.fillStyle = randomColor;
         ctx.fill();
+    }
+};
 
-        ctx.beginPath();
-        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();
+    drawLevel();
+    drawHelp();
+    drawLine(line);
+    drawTargets(targets);
 
-        drawScore();
-        drawHelp();
-        drawLine(line);
-        drawTargets(targets);
-        drawMouseCircle();
+    requestAnimationFrame(gameLoop);
 
-        requestAnimationFrame(gameLoop);
-    };
-
-    audio.addEventListener('canplaythrough', function () {
-        audioLoaded = true;
-    });
+    if (targets.length === 0) {
+        level++;
+        targets = createTargets();
+    }
+};
 
-    audio.addEventListener('error', function () {
-        console.error('Error loading audio file');
-    });
+let line = null;
 
-    canvas.addEventListener('click', (e) => {
-        const rect = canvas.getBoundingClientRect();
-        const x = e.clientX - rect.left;
-        const y = e.clientY - rect.top;
+const handleInteraction = (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;
+    if (audioLoaded) {
+        audio.play().catch((error) => {
+            console.error('Error playing audio:', error);
         });
-    });
-
-    window.addEventListener('resize', () => {
-        canvas.width = window.innerWidth;
-        canvas.height = window.innerHeight;
-    });
+    }
+
+    line = {
+        startX: 0,
+        startY: canvas.height,
+        endX: x,
+        endY: y,
+        time: Date.now()
+    };
 
-    window.addEventListener('keydown', (e) => {
-        if (e.key === 'r' || e.key === 'R') {
-            targets = createTargets();
-        }
-        if (e.key === 'h' || e.key === 'H') {
-            showHelp = !showHelp;
+    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;
     });
-
-    gameLoop();
-})();
+};
+
+canvas.addEventListener('click', handleInteraction);
+canvas.addEventListener('touchstart', function(e) {
+    // Prevent the window from scrolling
+    e.preventDefault();
+
+    // A touch event can have multiple touches so we just get the first one
+    e.clientX = e.touches[0].clientX;
+    e.clientY = e.touches[0].clientY;
+
+    handleInteraction(e);
+}, { passive: 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();
+    }
+});
+
+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
diff --git a/js/ship-game/index.html b/js/ship-game/index.html
index 4b8ada6..1ff3485 100644
--- a/js/ship-game/index.html
+++ b/js/ship-game/index.html
@@ -5,17 +5,19 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <style>
         body {
-            background-color: beige;
+            background-color: rgb(15, 16, 28);
+            background-image: url("./background.jpeg");
+            background-position: center;
+            background-repeat: no-repeat;
+            background-size: cover;
+            padding: 0;
+            margin: 0;
+            border: 0;
         }
         canvas {
-            background-color: rgb(5, 10, 94);
-            border: 1px solid black;
-            cursor: none;
-        }
-        body, canvas {
-            padding: 1em;
-            margin: 1em;
-            border: 1em;
+            cursor: crosshair;
+            margin: 0;
+            display: block;
         }
     </style>
 </head>