|
| 1 | +<!DOCTYPE html> |
| 2 | +<html> |
| 3 | +<head> |
| 4 | + <title>Gödel's Gauntlet</title> |
| 5 | + <style> |
| 6 | + body { margin: 0; overflow: hidden; } |
| 7 | + canvas { position: absolute; top: 0; left: 0; } |
| 8 | + </style> |
| 9 | +</head> |
| 10 | +<body> |
| 11 | + <canvas id="gameCanvas"></canvas> |
| 12 | + <script> |
| 13 | + var canvas = document.getElementById('gameCanvas'); |
| 14 | + var ctx = canvas.getContext('2d'); |
| 15 | + |
| 16 | + // Set canvas size to fill the window |
| 17 | + canvas.width = window.innerWidth; |
| 18 | + canvas.height = window.innerHeight; |
| 19 | + |
| 20 | + // Player and goal objects |
| 21 | + var player = { |
| 22 | + x: canvas.width / 2, |
| 23 | + y: 50, |
| 24 | + radius: 20, |
| 25 | + vx: 0, |
| 26 | + vy: 0, |
| 27 | + speed: 0.1, |
| 28 | + maxSpeed: 3 |
| 29 | + }; |
| 30 | + var goal = { |
| 31 | + x: canvas.width / 2, |
| 32 | + y: canvas.height / 2, |
| 33 | + radius: 30, |
| 34 | + angle1: 0, |
| 35 | + angle2: 0, |
| 36 | + angle3: 0 |
| 37 | + }; |
| 38 | + |
| 39 | + // Listen for keydown events |
| 40 | + window.addEventListener('keydown', function(e) { |
| 41 | + var acceleration = player.speed; |
| 42 | + if(e.key === 'ArrowUp' || e.key === 'w') player.vy -= acceleration; |
| 43 | + if(e.key === 'ArrowDown' || e.key === 's') player.vy += acceleration; |
| 44 | + if(e.key === 'ArrowLeft' || e.key === 'a') player.vx -= acceleration; |
| 45 | + if(e.key === 'ArrowRight' || e.key === 'd') player.vx += acceleration; |
| 46 | + }); |
| 47 | + |
| 48 | + // Listen for deviceorientation events |
| 49 | + window.addEventListener('deviceorientation', function(e) { |
| 50 | + var acceleration = player.speed; |
| 51 | + player.vx += Math.sin(e.alpha * Math.PI / 180) * acceleration; |
| 52 | + player.vy += Math.sin((e.beta - 90) * Math.PI / 180) * acceleration; |
| 53 | + }); |
| 54 | + |
| 55 | + // Main game loop |
| 56 | + function gameLoop() { |
| 57 | + // Apply velocity to player position |
| 58 | + if (!player.reset) { |
| 59 | + player.x += player.vx; |
| 60 | + player.y += player.vy; |
| 61 | + } |
| 62 | + |
| 63 | + // Limit speed |
| 64 | + var speed = Math.sqrt(player.vx * player.vx + player.vy * player.vy); |
| 65 | + if(speed > player.maxSpeed) { |
| 66 | + player.vx *= player.maxSpeed / speed; |
| 67 | + player.vy *= player.maxSpeed / speed; |
| 68 | + } |
| 69 | + |
| 70 | + // Clear the canvas |
| 71 | + ctx.clearRect(0, 0, canvas.width, canvas.height); |
| 72 | + |
| 73 | + // Create and store the path for the first rotating circle |
| 74 | + var circlePath1 = new Path2D(); |
| 75 | + goal.angle1 += 0.01; |
| 76 | + var startAngle = goal.angle1; |
| 77 | + var endAngle = startAngle + Math.PI * 2 - player.radius * 3 / goal.radius; |
| 78 | + circlePath1.arc(goal.x, goal.y, goal.radius * 3, startAngle, endAngle); |
| 79 | + ctx.strokeStyle = 'red'; |
| 80 | + ctx.lineWidth = 5; |
| 81 | + ctx.stroke(circlePath1); |
| 82 | + |
| 83 | + // Create and store the path for the second rotating circle |
| 84 | + var circlePath2 = new Path2D(); |
| 85 | + goal.angle2 -= 0.01; |
| 86 | + startAngle = goal.angle2; |
| 87 | + endAngle = startAngle + Math.PI * 2 - player.radius * 3 / goal.radius; |
| 88 | + circlePath2.arc(goal.x, goal.y, goal.radius * 2.5, startAngle, endAngle); |
| 89 | + ctx.strokeStyle = 'blue'; |
| 90 | + ctx.lineWidth = 5; |
| 91 | + ctx.stroke(circlePath2); |
| 92 | + |
| 93 | + // Create and store the path for the third rotating circle |
| 94 | + var circlePath3 = new Path2D(); |
| 95 | + goal.angle3 = Math.atan2(player.y - goal.y, player.x - goal.x) + Math.PI; |
| 96 | + startAngle = goal.angle3; |
| 97 | + endAngle = startAngle + Math.PI * 2 - player.radius * 3 / goal.radius; |
| 98 | + circlePath3.arc(goal.x, goal.y, goal.radius * 2, startAngle, endAngle); |
| 99 | + ctx.strokeStyle = 'purple'; |
| 100 | + ctx.lineWidth = 5; |
| 101 | + ctx.stroke(circlePath3); |
| 102 | + |
| 103 | + // Check for collision with the rotating circles |
| 104 | + if(!player.reset && |
| 105 | + (ctx.isPointInStroke(circlePath1, player.x, player.y) || |
| 106 | + ctx.isPointInStroke(circlePath2, player.x, player.y) || |
| 107 | + ctx.isPointInStroke(circlePath3, player.x, player.y))) { |
| 108 | + player.reset = true; |
| 109 | + player.flash = 3; |
| 110 | + setTimeout(() => {player.reset = false}, 3000); // Wait for 3 seconds before resetting |
| 111 | + } |
| 112 | + |
| 113 | + // Reset and flash the player |
| 114 | + if(player.reset) { |
| 115 | + player.x = canvas.width / 2; |
| 116 | + player.y = 50; |
| 117 | + player.vx = 0; |
| 118 | + player.vy = 0; |
| 119 | + |
| 120 | + if(player.flash > 0) { |
| 121 | + ctx.globalAlpha = 0.5; |
| 122 | + player.flash--; |
| 123 | + } else { |
| 124 | + player.reset = false; |
| 125 | + } |
| 126 | + } else { |
| 127 | + ctx.globalAlpha = 1; |
| 128 | + } |
| 129 | + |
| 130 | + // Draw the player |
| 131 | + ctx.beginPath(); |
| 132 | + ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2); |
| 133 | + ctx.fillStyle = 'blue'; |
| 134 | + ctx.fill(); |
| 135 | + |
| 136 | + // Draw the goal |
| 137 | + ctx.beginPath(); |
| 138 | + ctx.arc(goal.x, goal.y, goal.radius, 0, Math.PI * 2); |
| 139 | + ctx.fillStyle = 'green'; |
| 140 | + ctx.fill(); |
| 141 | + |
| 142 | + // Check for collision with the goal |
| 143 | + var dx = player.x - goal.x; |
| 144 | + var dy = player.y - goal.y; |
| 145 | + var distance = Math.sqrt(dx * dx + dy * dy); |
| 146 | + if(distance < player.radius + goal.radius) { |
| 147 | + alert('You reached the goal!'); |
| 148 | + player.x = canvas.width / 2; |
| 149 | + player.y = 50; |
| 150 | + player.vx = 0; |
| 151 | + player.vy = 0; |
| 152 | + } |
| 153 | + |
| 154 | + // Wrap player circle if out of screen bounds |
| 155 | + if (player.x < -player.radius) player.x = canvas.width + player.radius; |
| 156 | + if (player.x > canvas.width + player.radius) player.x = -player.radius; |
| 157 | + if (player.y < -player.radius) player.y = canvas.height + player.radius; |
| 158 | + if (player.y > canvas.height + player.radius) player.y = -player.radius; |
| 159 | + |
| 160 | + // Request next animation frame |
| 161 | + requestAnimationFrame(gameLoop); |
| 162 | + } |
| 163 | + |
| 164 | + gameLoop(); |
| 165 | + </script> |
| 166 | +</body> |
| 167 | +</html> |
0 commit comments