occluder.js 1.76 KB
// occluder.js — 遮挡片:背景像素按多边形裁出 + zIndex=baseY(移植自 pixi-stage.js addOccluder)。
//
// 不需额外素材,复用背景像素:把背景图按多边形裁出一块,放进人物 Y 排序层。
//   人物脚下 worldY < baseY(在它后面/更远)→ 被遮挡;> baseY(更近)→ 盖住它。

import { depthZIndex } from './geom.js'

/**
 * 遮挡判定(纯函数,测试用):人物脚下 worldY 是否被 baseY 的遮挡片遮住。
 * @param {number} actorWorldY
 * @param {number} occluderBaseY
 * @returns {boolean} true=被遮(actor 在遮挡片后面)
 */
export function isOccluded(actorWorldY, occluderBaseY) {
  return depthZIndex(actorWorldY) < depthZIndex(occluderBaseY)
}

/**
 * 用背景纹理按多边形裁出一块遮挡片,挂到 actorsLayer,zIndex=baseY。
 * @param {Object} deps
 * @param {*} deps.PIXI
 * @param {*} deps.bgTexture          背景纹理(已就绪)
 * @param {*} deps.actorsLayer        Y 排序层容器
 * @param {number} deps.worldW
 * @param {number} deps.worldH
 * @param {{polygon:number[][], baseY:number}} def  polygon=[[x,y],...](世界坐标)
 * @returns {*|null} 遮挡片容器;条件不满足返回 null
 */
export function createOccluder({ PIXI, bgTexture, actorsLayer, worldW, worldH }, def) {
  const { polygon, baseY } = def || {}
  if (!bgTexture || !polygon || polygon.length < 3) return null
  const sprite = new PIXI.Sprite(bgTexture)
  sprite.width = worldW
  sprite.height = worldH
  const mask = new PIXI.Graphics()
  mask.poly(polygon.flat()).fill(0xffffff)
  const cont = new PIXI.Container()
  cont.addChild(sprite, mask)
  sprite.mask = mask
  cont.zIndex = depthZIndex(baseY) // 与人物 worldY 同一排序尺度
  actorsLayer.addChild(cont)
  return cont
}