(
p: Particle,
worldX: number,
worldY: number,
worldRotation: number = 0,
worldScaleX: number = 1,
worldScaleY: number = 1
)
| 245 | } |
| 246 | |
| 247 | private _initParticle( |
| 248 | p: Particle, |
| 249 | worldX: number, |
| 250 | worldY: number, |
| 251 | worldRotation: number = 0, |
| 252 | worldScaleX: number = 1, |
| 253 | worldScaleY: number = 1 |
| 254 | ): void { |
| 255 | const config = this.config; |
| 256 | |
| 257 | // 获取形状偏移 | Get shape offset |
| 258 | const [ox, oy] = this._getShapeOffset(); |
| 259 | |
| 260 | // 应用旋转和缩放到发射偏移 | Apply rotation and scale to emission offset |
| 261 | // 先缩放,再旋转 | Scale first, then rotate |
| 262 | const scaledOx = ox * worldScaleX; |
| 263 | const scaledOy = oy * worldScaleY; |
| 264 | const cos = Math.cos(worldRotation); |
| 265 | const sin = Math.sin(worldRotation); |
| 266 | const rotatedOx = scaledOx * cos - scaledOy * sin; |
| 267 | const rotatedOy = scaledOx * sin + scaledOy * cos; |
| 268 | |
| 269 | // 位置 | Position |
| 270 | p.x = worldX + rotatedOx; |
| 271 | p.y = worldY + rotatedOy; |
| 272 | |
| 273 | // 生命时间 | Lifetime |
| 274 | p.lifetime = randomRange(config.lifetime.min, config.lifetime.max); |
| 275 | p.age = 0; |
| 276 | |
| 277 | // 速度方向(应用世界旋转)| Velocity direction (apply world rotation) |
| 278 | const baseDir = config.direction + randomRange(-config.directionSpread / 2, config.directionSpread / 2); |
| 279 | const dir = baseDir + worldRotation; |
| 280 | const speed = randomRange(config.speed.min, config.speed.max); |
| 281 | |
| 282 | // 速度也应用缩放(使用平均缩放)| Speed also applies scale (use average scale) |
| 283 | const avgScale = (worldScaleX + worldScaleY) / 2; |
| 284 | p.vx = Math.cos(dir) * speed * avgScale; |
| 285 | p.vy = Math.sin(dir) * speed * avgScale; |
| 286 | |
| 287 | // 加速度(重力)| Acceleration (gravity) |
| 288 | p.ax = config.gravityX; |
| 289 | p.ay = config.gravityY; |
| 290 | |
| 291 | // 旋转 | Rotation |
| 292 | p.rotation = randomRange(config.startRotation.min, config.startRotation.max); |
| 293 | p.angularVelocity = randomRange(config.angularVelocity.min, config.angularVelocity.max); |
| 294 | |
| 295 | // 缩放(应用世界缩放)| Scale (apply world scale) |
| 296 | const baseScale = randomRange(config.startScale.min, config.startScale.max); |
| 297 | p.scaleX = baseScale * worldScaleX; |
| 298 | p.scaleY = baseScale * worldScaleY; |
| 299 | p.startScaleX = p.scaleX; |
| 300 | p.startScaleY = p.scaleY; |
| 301 | |
| 302 | // 颜色 | Color |
| 303 | p.r = clamp(config.startColor.r + randomRange(-config.startColorVariance.r, config.startColorVariance.r), 0, 1); |
| 304 | p.g = clamp(config.startColor.g + randomRange(-config.startColorVariance.g, config.startColorVariance.g), 0, 1); |
no test coverage detected