/** * Auto-generated Worker file for PhysicsWorkerSystem * 自动生成的 Worker 文件 * * Source: F:/ecs-framework/examples/core-demos/src/demos/WorkerSystemDemo.ts * Generated by @esengine/worker-generator * * 使用方式 | Usage: * 1. 将此文件放入 workers/ 目录 * 2. 在 game.json 中配置 "workers": "workers" * 3. 在 System 中配置 workerScriptPath: 'workers/physics-worker-system-worker.js' */ // 微信小游戏 Worker 环境 // WeChat Mini Game Worker environment let sharedFloatArray = null; const ENTITY_DATA_SIZE = 9; worker.onMessage(function(res) { // 微信小游戏 Worker 消息直接传递数据,不需要 .data // WeChat Mini Game Worker passes data directly, no .data wrapper var type = res.type; var id = res.id; var entities = res.entities; var deltaTime = res.deltaTime; var systemConfig = res.systemConfig; var startIndex = res.startIndex; var endIndex = res.endIndex; var sharedBuffer = res.sharedBuffer; try { // 处理 SharedArrayBuffer 初始化 // Handle SharedArrayBuffer initialization if (type === 'init' && sharedBuffer) { sharedFloatArray = new Float32Array(sharedBuffer); worker.postMessage({ type: 'init', success: true }); return; } // 处理 SharedArrayBuffer 数据 // Handle SharedArrayBuffer data if (type === 'shared' && sharedFloatArray) { processSharedArrayBuffer(startIndex, endIndex, deltaTime, systemConfig); worker.postMessage({ id: id, result: null }); return; } // 传统处理方式 // Traditional processing if (entities) { var result = workerProcess(entities, deltaTime, systemConfig); // 处理 Promise 返回值 // Handle Promise return value if (result && typeof result.then === 'function') { result.then(function(finalResult) { worker.postMessage({ id: id, result: finalResult }); }).catch(function(error) { worker.postMessage({ id: id, error: error.message }); }); } else { worker.postMessage({ id: id, result: result }); } } } catch (error) { worker.postMessage({ id: id, error: error.message }); } }); /** * 实体处理函数 - 从 PhysicsWorkerSystem.workerProcess 提取 * Entity processing function - extracted from PhysicsWorkerSystem.workerProcess */ function workerProcess(entities, deltaTime, systemConfig) { var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var config = systemConfig || this.physicsConfig; var result = entities.map(function (e) { return (__assign({}, e)); }); for (var i = 0; i < result.length; i++) { var entity = result[i]; entity.dy += config.gravity * deltaTime; entity.x += entity.dx * deltaTime; entity.y += entity.dy * deltaTime; if (entity.x <= entity.radius) { entity.x = entity.radius; entity.dx = -entity.dx * entity.bounce; } else if (entity.x >= config.canvasWidth - entity.radius) { entity.x = config.canvasWidth - entity.radius; entity.dx = -entity.dx * entity.bounce; } if (entity.y <= entity.radius) { entity.y = entity.radius; entity.dy = -entity.dy * entity.bounce; } else if (entity.y >= config.canvasHeight - entity.radius) { entity.y = config.canvasHeight - entity.radius; entity.dy = -entity.dy * entity.bounce; entity.dx *= config.groundFriction; } entity.dx *= entity.friction; entity.dy *= entity.friction; } for (var i = 0; i < result.length; i++) { for (var j = i + 1; j < result.length; j++) { var ball1 = result[i]; var ball2 = result[j]; var dx = ball2.x - ball1.x; var dy = ball2.y - ball1.y; var distance = Math.sqrt(dx * dx + dy * dy); var minDistance = ball1.radius + ball2.radius; if (distance < minDistance && distance > 0) { var nx = dx / distance; var ny = dy / distance; var overlap = minDistance - distance; var separationX = nx * overlap * 0.5; var separationY = ny * overlap * 0.5; ball1.x -= separationX; ball1.y -= separationY; ball2.x += separationX; ball2.y += separationY; var relativeVelocityX = ball2.dx - ball1.dx; var relativeVelocityY = ball2.dy - ball1.dy; var velocityAlongNormal = relativeVelocityX * nx + relativeVelocityY * ny; if (velocityAlongNormal > 0) continue; var restitution = (ball1.bounce + ball2.bounce) * 0.5; var impulseScalar = -(1 + restitution) * velocityAlongNormal / (1 / ball1.mass + 1 / ball2.mass); var impulseX = impulseScalar * nx; var impulseY = impulseScalar * ny; ball1.dx -= impulseX / ball1.mass; ball1.dy -= impulseY / ball1.mass; ball2.dx += impulseX / ball2.mass; ball2.dy += impulseY / ball2.mass; var energyLoss = 0.98; ball1.dx *= energyLoss; ball1.dy *= energyLoss; ball2.dx *= energyLoss; ball2.dy *= energyLoss; } } } return result; } /** * SharedArrayBuffer 处理函数 * SharedArrayBuffer processing function */ function processSharedArrayBuffer(startIndex, endIndex, deltaTime, systemConfig) { if (!sharedFloatArray) return; var config = systemConfig || { gravity: 100, canvasWidth: 800, canvasHeight: 600, groundFriction: 0.98 }; var actualEntityCount = sharedFloatArray[0]; // 基础物理更新 for (var i = startIndex; i < endIndex && i < actualEntityCount; i++) { var offset = i * 9 + 9; var id = sharedFloatArray[offset + 0]; if (id === 0) continue; var x = sharedFloatArray[offset + 1]; var y = sharedFloatArray[offset + 2]; var dx = sharedFloatArray[offset + 3]; var dy = sharedFloatArray[offset + 4]; var bounce = sharedFloatArray[offset + 6]; var friction = sharedFloatArray[offset + 7]; var radius = sharedFloatArray[offset + 8]; // 应用重力 dy += config.gravity * deltaTime; // 更新位置 x += dx * deltaTime; y += dy * deltaTime; // 边界碰撞 if (x <= radius) { x = radius; dx = -dx * bounce; } else if (x >= config.canvasWidth - radius) { x = config.canvasWidth - radius; dx = -dx * bounce; } if (y <= radius) { y = radius; dy = -dy * bounce; } else if (y >= config.canvasHeight - radius) { y = config.canvasHeight - radius; dy = -dy * bounce; dx *= config.groundFriction; } // 空气阻力 dx *= friction; dy *= friction; // 写回数据 sharedFloatArray[offset + 1] = x; sharedFloatArray[offset + 2] = y; sharedFloatArray[offset + 3] = dx; sharedFloatArray[offset + 4] = dy; } // 碰撞检测 for (var i = startIndex; i < endIndex && i < actualEntityCount; i++) { var offset1 = i * 9 + 9; var id1 = sharedFloatArray[offset1 + 0]; if (id1 === 0) continue; var x1 = sharedFloatArray[offset1 + 1]; var y1 = sharedFloatArray[offset1 + 2]; var dx1 = sharedFloatArray[offset1 + 3]; var dy1 = sharedFloatArray[offset1 + 4]; var mass1 = sharedFloatArray[offset1 + 5]; var bounce1 = sharedFloatArray[offset1 + 6]; var radius1 = sharedFloatArray[offset1 + 8]; for (var j = 0; j < actualEntityCount; j++) { if (i === j) continue; var offset2 = j * 9 + 9; var id2 = sharedFloatArray[offset2 + 0]; if (id2 === 0) continue; var x2 = sharedFloatArray[offset2 + 1]; var y2 = sharedFloatArray[offset2 + 2]; var dx2 = sharedFloatArray[offset2 + 3]; var dy2 = sharedFloatArray[offset2 + 4]; var mass2 = sharedFloatArray[offset2 + 5]; var bounce2 = sharedFloatArray[offset2 + 6]; var radius2 = sharedFloatArray[offset2 + 8]; if (isNaN(x2) || isNaN(y2) || isNaN(radius2) || radius2 <= 0) continue; var deltaX = x2 - x1; var deltaY = y2 - y1; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); var minDistance = radius1 + radius2; if (distance < minDistance && distance > 0) { var nx = deltaX / distance; var ny = deltaY / distance; var overlap = minDistance - distance; var separationX = nx * overlap * 0.5; var separationY = ny * overlap * 0.5; x1 -= separationX; y1 -= separationY; var relativeVelocityX = dx2 - dx1; var relativeVelocityY = dy2 - dy1; var velocityAlongNormal = relativeVelocityX * nx + relativeVelocityY * ny; if (velocityAlongNormal > 0) continue; var restitution = (bounce1 + bounce2) * 0.5; var impulseScalar = -(1 + restitution) * velocityAlongNormal / (1 / mass1 + 1 / mass2); var impulseX = impulseScalar * nx; var impulseY = impulseScalar * ny; dx1 -= impulseX / mass1; dy1 -= impulseY / mass1; var energyLoss = 0.98; dx1 *= energyLoss; dy1 *= energyLoss; } } sharedFloatArray[offset1 + 1] = x1; sharedFloatArray[offset1 + 2] = y1; sharedFloatArray[offset1 + 3] = dx1; sharedFloatArray[offset1 + 4] = dy1; } }