278 lines
9.8 KiB
JavaScript
278 lines
9.8 KiB
JavaScript
|
|
/**
|
||
|
|
* 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;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|