import { Robot } from "./robot.js"; import { GameWorld } from "./gameworld.js"; const consoleElement = document.getElementById("console"); const gameCanvas = document.getElementById("gameCanvas"); const ctx = gameCanvas.getContext("2d"); const gameWorld = new GameWorld(); let pyodideWorker = startPyodideWorker(); let robots = createInitialRobots(); let paused = false; let scale = 1; // Zoom level let offsetX = 0; // Pan X let offsetY = 0; // Pan Y let isPanning = false; let startX, startY; // Mouse start positions // ✅ Function to create the Pyodide Worker function startPyodideWorker() { const worker = new Worker("pyodide-worker.js"); // ✅ Reattach the event listener when a new worker is created worker.onmessage = (event) => { if (paused) return; switch (event.data.type) { case "console": logToConsole(event.data.data); break; case "error": logToConsole(`${event.data.message}`); break; case "fire": fire(); break; case "turn": turn(event.data.data); break; case "move": move(event.data.data); break; } }; return worker; } // ✅ Function to create initial robots function createInitialRobots() { return { "player": new Robot("player", 50, 50, "blue") //"enemy1": new Robot("enemy1", 200, 150, "red"), //"enemy2": new Robot("enemy2", 400, 250, "red") }; } // ✅ Function to log messages to console function logToConsole(text) { console.log(text.replace("", "").replace("", "")); consoleElement.innerHTML += text.replace(/\n/g, "
") + "
"; consoleElement.scrollTop = consoleElement.scrollHeight; } // ✅ Game Control Functions function fire() { logToConsole("🔥 Gun Fired! 🔥"); } function turn(deg) { robots["player"].turn(deg); } function move(distance) { robots["player"].move(distance); } // ✅ Pause/Resume Function function togglePause() { paused = !paused; document.getElementById("pause-button").innerText = paused ? "Resume" : "Pause"; } // ✅ Reset Function (Fixed) function resetGame() { // Terminate the worker pyodideWorker.terminate(); // Restart the worker and rebind event listener pyodideWorker = startPyodideWorker(); // Reset the robots to their initial state robots = createInitialRobots(); // Clear the console consoleElement.innerHTML = ""; // Unpause the game if it was paused paused = false; document.getElementById("pause-button").innerText = "Pause"; } // ✅ Game Loop function gameLoop() { if (!paused) { ctx.resetTransform(); // Fill the entire visible canvas to remove artifacts ctx.fillStyle = "#DDD"; ctx.fillRect(0, 0, gameCanvas.width, gameCanvas.height); ctx.translate(offsetX, offsetY); // Apply panning ctx.scale(scale, scale); // Apply zooming gameWorld.draw(ctx); for (let id in robots) { robots[id].update(ctx, gameWorld); } } requestAnimationFrame(gameLoop); } // Start game loop gameLoop(); // ✅ Button Event Listeners document.getElementById("compile-button").addEventListener("click", () => { if (paused) return; const code = document.getElementById("python-code").value; consoleElement.innerHTML = ""; pyodideWorker.postMessage({ type: "execute", code: code }); }); document.getElementById("pause-button").addEventListener("click", togglePause); document.getElementById("reset-button").addEventListener("click", resetGame); gameCanvas.addEventListener("wheel", (event) => { event.preventDefault(); const scaleFactor = 1.1; const mouseX = event.offsetX; const mouseY = event.offsetY; // Convert mouse coordinates to world coordinates (before zoom) const worldX = (mouseX - offsetX) / scale; const worldY = (mouseY - offsetY) / scale; // Apply zoom if (event.deltaY < 0) { scale *= scaleFactor; // Zoom in } else { scale /= scaleFactor; // Zoom out } // Keep zoom within limits scale = Math.max(0.5, Math.min(3, scale)); // Adjust offset so zooming is centered at mouse position offsetX = mouseX - worldX * scale; offsetY = mouseY - worldY * scale; }); gameCanvas.addEventListener("mousedown", (event) => { isPanning = true; startX = event.clientX - offsetX; startY = event.clientY - offsetY; }); gameCanvas.addEventListener("mousemove", (event) => { if (!isPanning) return; offsetX = event.clientX - startX; offsetY = event.clientY - startY; }); gameCanvas.addEventListener("mouseup", () => { isPanning = false; });