164 lines
4.5 KiB
JavaScript
164 lines
4.5 KiB
JavaScript
importScripts("https://cdn.jsdelivr.net/pyodide/v0.23.4/full/pyodide.js");
|
|
|
|
let sensorData = {}; // ✅ Store sensor values
|
|
let gameWorld = null;
|
|
|
|
async function initializePyodide() {
|
|
self.pyodide = await loadPyodide({
|
|
indexURL: "https://cdn.jsdelivr.net/pyodide/v0.23.4/full/"
|
|
});
|
|
|
|
self.pyodide.globals.set("send_to_main", (event, data) => {
|
|
self.postMessage({ type: event, data: data });
|
|
});
|
|
|
|
|
|
|
|
// ✅ Expose sensor data to Python
|
|
self.pyodide.globals.set("get_sensor_data", (name) => {
|
|
if (gameWorld == null) {
|
|
return null;
|
|
}
|
|
|
|
|
|
//console.log(gameWorld.robots);
|
|
let robot = gameWorld.robots[0];
|
|
//console.log(robot);
|
|
let sensorArray = robot.sensors || []; // Assuming `sensors` is an array inside the robot object
|
|
sensorData = sensorArray.map(sensor => ({
|
|
"type": sensor.type, // Individual sensor's type
|
|
"angle": sensor.angle, // Individual sensor's angle
|
|
"distance": sensor.distance, // Individual sensor's distance
|
|
"hitpoint": sensor.hitpoint // Whatever other attributes you need
|
|
}));
|
|
//console.log(sensorData["x"]);
|
|
sensorData = JSON.stringify(sensorData);
|
|
return sensorData;
|
|
});
|
|
|
|
|
|
self.pyodide.globals.set("get_robot_data", () => {
|
|
if (gameWorld == null) {
|
|
return null;
|
|
}
|
|
let robot = gameWorld.robots[0];
|
|
|
|
let robotData = {
|
|
"position": robot.body.position,
|
|
"angle": robot.body.angle,
|
|
"velocity": robot.body.velocity
|
|
};
|
|
robotData = JSON.stringify(robotData);
|
|
return robotData;
|
|
});
|
|
|
|
// ✅ Run Python initialization
|
|
await self.pyodide.runPythonAsync(`
|
|
import sys
|
|
import pyodide
|
|
import asyncio
|
|
import time
|
|
import json
|
|
import math
|
|
|
|
class RobotModule:
|
|
def get_sensor(self, name):
|
|
sensor_data = json.loads(get_sensor_data(name))
|
|
return sensor_data
|
|
|
|
def get_sensors(self):
|
|
return json.loads(get_sensor_data("sensors")) # Returns list of sensor dicts
|
|
|
|
def get_pos(self):
|
|
robot_data = json.loads(get_robot_data())
|
|
position = robot_data["position"]
|
|
return position
|
|
|
|
def get_x(self):
|
|
robot_data = json.loads(get_robot_data())
|
|
position = robot_data["position"]["x"]
|
|
return position
|
|
|
|
def get_y(self):
|
|
robot_data = json.loads(get_robot_data())
|
|
position = robot_data["position"]["y"]
|
|
return position
|
|
|
|
def get_velocity(self):
|
|
robot_data = json.loads(get_robot_data())
|
|
velocity = robot_data["velocity"]
|
|
return velocity
|
|
|
|
def get_velocity_magnitude(self):
|
|
velXY = self.get_velocity()
|
|
velX = velXY["x"]
|
|
velY = velXY["y"]
|
|
magnitude = math.sqrt(velX**2 + velY**2)
|
|
|
|
return magnitude
|
|
|
|
def move(self, speed):
|
|
send_to_main("move", speed)
|
|
|
|
def fire(self):
|
|
send_to_main("fire", None)
|
|
|
|
def turn(self, deg):
|
|
send_to_main("turn", deg)
|
|
|
|
robot = RobotModule()
|
|
|
|
|
|
class ConsoleOutput:
|
|
def write(self, text):
|
|
if text.strip():
|
|
send_to_main("console", text)
|
|
|
|
def flush(self):
|
|
pass
|
|
|
|
sys.stdout = ConsoleOutput()
|
|
sys.stderr = ConsoleOutput()
|
|
sys.modules["robot"] = robot
|
|
|
|
# ✅ Override time.sleep() with an async version
|
|
_original_sleep = time.sleep # Backup original sleep
|
|
|
|
async def async_sleep(seconds):
|
|
await asyncio.sleep(seconds) # ✅ Allows JavaScript to process events while sleeping
|
|
|
|
|
|
time.sleep = async_sleep # ✅ Monkey-patch time.sleep()
|
|
`);
|
|
|
|
self.postMessage({ type: "ready" }); // ✅ Notify main thread that Pyodide is ready
|
|
}
|
|
|
|
initializePyodide();
|
|
|
|
self.onmessage = async (event) => {
|
|
if (!self.pyodide) {
|
|
self.postMessage({ type: "error", message: "Pyodide not initialized yet." });
|
|
return;
|
|
}
|
|
|
|
if (event.data.type === "sensor_update") {
|
|
// ✅ Update sensor data
|
|
Object.assign(sensorData, event.data.data);
|
|
} else if (event.data.type === "game_state") {
|
|
gameWorld = event.data.state;
|
|
//console.log(event.data);
|
|
|
|
} else if (event.data.type === "execute") {
|
|
try {
|
|
let result = await self.pyodide.runPythonAsync(event.data.code);
|
|
if (result !== undefined && result !== null && result !== "") {
|
|
self.postMessage({ type: "console", data: result });
|
|
}
|
|
} catch (error) {
|
|
self.postMessage({ type: "error", message: error.toString() });
|
|
}
|
|
self.postMessage({ type: "execution_done" });
|
|
}
|
|
};
|