Canvas Pixi.js sprites“;摇动;当其他精灵旋转时

Canvas Pixi.js sprites“;摇动;当其他精灵旋转时,canvas,coffeescript,rotation,pixi.js,Canvas,Coffeescript,Rotation,Pixi.js,我正在用Coffeescript开发一个Pixi.js游戏,主要关注旋转六角体。关于旋转的一切都在正确地工作,包括设置旋转动画和识别旋转的基础电路板状态。但是,对于棋盘上的某些六角(不是全部),旋转它们会导致舞台上的其他(不是全部)精灵“抖动”。它们暂时移向一侧,然后在旋转结束后再次移回。我试着到处寻找这个问题;我发现的一个结果是,有人在另一个网站上有类似的问题,但没有答案: 我自己也不知道从哪里开始诊断这个bug。如果这是画布的问题,我可以看看那里,但也可能是Pixi的问题。这是这个问题的gi

我正在用Coffeescript开发一个Pixi.js游戏,主要关注旋转六角体。关于旋转的一切都在正确地工作,包括设置旋转动画和识别旋转的基础电路板状态。但是,对于棋盘上的某些六角(不是全部),旋转它们会导致舞台上的其他(不是全部)精灵“抖动”。它们暂时移向一侧,然后在旋转结束后再次移回。我试着到处寻找这个问题;我发现的一个结果是,有人在另一个网站上有类似的问题,但没有答案:

我自己也不知道从哪里开始诊断这个bug。如果这是画布的问题,我可以看看那里,但也可能是Pixi的问题。这是这个问题的gif图。当我点击第一个十六进制(在右边)时,许多行都会抖动。当我点击第二个十六进制(左),他们没有

就代码而言,该项目在这一点上相当大。以下是动画函数和辅助对象方法:

## The frame count the window is on ##
@count = 0

### Moves the connector to the correct lit layer ###
@toLit = (connector) ->
  try
    @colorContainers[connector.color].unlit.removeChild(connector.panel)
  catch
  if @typeIsArray connector.color
    if connector.color.length > 0
      c = connector.color[0].toUpperCase()
    else
      c = Color.asString(Color.NONE).toUpperCase()
  else
    c = connector.color.toUpperCase()
  if c is Color.asString(Color.NONE).toUpperCase()
    @toUnlit(connector) ## Prevent lighting of color.NONE
  else
    @colorContainers[c.toUpperCase()].lit.addChild(connector.panel)
    connector.linked = true
  return

### Moves the connector to the correct unlit layer ###
@toUnlit = (connector) ->
  try
    @colorContainers[connector.color].lit.removeChild(connector.panel)
  catch
  if @typeIsArray connector.color
    if connector.color.length > 0
      c = connector.color[0]
    else
      c = Color.asString(Color.NONE)
  else
    c = connector.color
  if connector.hex? and connector.hex instanceof Crystal  
    @colorContainers[Color.asString(Color.NONE).toUpperCase()].unlit.addChild(connector.panel)
  else
    @colorContainers[c.toUpperCase()].unlit.addChild(connector.panel)
  connector.linked = false
  return

### Creates a frame offset for the each color ###
@colorOffset = {}
for c in Color.values()
  if not isNaN(c)
    c = Color.fromString(c).toUpperCase()
  else
    c = c.toUpperCase()
  @colorOffset[c] = Math.random() + 0.5

### Updates the pulse filter that controls lighting effects ###
@calcPulseFilter = (count) ->
  for col, val of @colorContainers
    pulse = val.lit.filters[0]
    cont = (count + val.lit.pulseOffset)/val.lit.pulseLength
    m = pulse.matrix
    m[0] = Math.abs(Math.sin(cont * 2 * Math.PI)) * 0.5 + 0.5
    m[5] = Math.abs(Math.sin(cont * 2 * Math.PI)) * 0.5 + 0.5
    m[10] = Math.abs(Math.sin(cont * 2 * Math.PI)) * 0.5 + 0.5
    m[15] = Math.abs(Math.sin(cont * 2 * Math.PI)) * 0.25 + 0.75
    pulse.matrix = m
  for cont in @goalContainer.children
    if cont.children.length >= 2 and cont.filters.length >= 2
      pulse = cont.filters[1]
      correspondCont = @colorContainers[cont.children[0].color.toUpperCase()].lit
      c = (count + correspondCont.pulseOffset)/correspondCont.pulseLength
      m = pulse.matrix
      if parseInt(cont.children[1].text.substring(0, 1)) >= parseInt(cont.children[1].text.substring(2))
        m[0] = Math.abs(Math.sin(c * 2 * Math.PI)) * 0.5 + 0.5
        m[5] = Math.abs(Math.sin(c * 2 * Math.PI)) * 0.5 + 0.5
        m[10] = Math.abs(Math.sin(c * 2 * Math.PI)) * 0.5 + 0.5
        m[15] = Math.abs(Math.sin(c * 2 * Math.PI)) * 0.25 + 0.75
      else
        m[0] = 1
        m[5] = 1
        m[10] = 1
        m[15] = 1
      pulse.matrix = m
  return

### The animation function. Called by pixi and requests to be recalled ###
@animate = () ->
    ## Color animation
    window.count += 1;  ## Frame count
    @calcPulseFilter(window.count)
    rotSpeed = 1/5
    tolerance = 0.000001 ## For floating point errors - difference below this is considered 'equal'
    radTo60Degree = 1.04719755 ## 1 radian * this coefficient = 60 degrees
    if (@BOARD?)
      ## Update text on goal
      curLit = @BOARD.crystalLitCount()
      goalContainer = @menu.children[@goalContainerIndex]
      isWin = true ## True if this user has won - every goal set.
      for pan in goalContainer.children
        for spr in pan.children
          if spr instanceof PIXI.Text and spr.color.toUpperCase() of curLit
            spr.setText(curLit[spr.color.toUpperCase()] + spr.text.substring(1))
            if curLit[spr.color.toUpperCase()] < parseInt(spr.text.substring(2))
              isWin = false

      if isWin and (not @winContainer?) and @showWinContainer
        @gameOn = false
        @makeWinGameContainer()

      for h in @BOARD.allHexes()
        ##Update lighting of all hexes
        if h.isLit().length > 0 and not h.backPanel.children[0].lit
          h.backPanel.children[0].lit = true
          if not (h instanceof Prism)
            @toLit(h.backPanel.spr)
        if h.isLit().length is 0 and h.backPanel.children[0].lit
          h.backPanel.children[0].lit = false
          if not (h instanceof Prism)
            @toUnlit(h.backPanel.spr)

        hLit = h.isLit()
        if h instanceof Prism
          ## Adjust opacity of cores
          for col, core of h.cores
            if col.toLowerCase() not in hLit and core.alpha > 0
              core.alpha = 0
            else if col.toLowerCase() in hLit and core.alpha is 0
              core.alpha = 0.75

        nS = h.getNeighborsWithBlanks()
        ## Fixing lighting of connectors 
        for panel in h.colorPanels
          col = panel.color.toLowerCase()
          for connector in panel.children
            for side in connector.sides
              n = nS[side]

              if n? and col in hLit and n.colorOfSide(n.indexLinked(h)) is col and not connector.linked
                @toLit(connector)
                for nPanel in n.colorPanels
                  for nConnector in nPanel.children
                    for nSide in nConnector.sides
                      if nSide is n.indexLinked(h) and not nConnector.linked
                        @toLit(nConnector)
              else if connector.linked and col not in hLit
                @toUnlit(connector)
                if n?
                  for nPanel in n.colorPanels
                    for nConnector in nPanel.children
                      for nSide in nConnector.sides
                        if nSide is n.indexLinked(h) and not nConnector.linked
                          @toUnlit(nConnector)

        ### Rotation of a prism - finds a prism that wants to rotate and rotates it a bit. ###
        ### If this is the first notification that this prism wants to rotate, stops providing light. ###
        ### If the prism is now done rotating, starts providing light again ###
        if h instanceof Prism and h.currentRotation isnt h.targetRotation
          if h.canLight
            h.canLight = false
            h.light()
          inc = 
            if (h.targetRotation - h.prevRotation) >= 0 
              rotSpeed
            else
              -rotSpeed
          h.backPanel.rotation += inc * radTo60Degree
          h.currentRotation += inc 
          for value in h.colorPanels
            value.rotation += inc * radTo60Degree
          if Math.abs(h.targetRotation - h.currentRotation) < tolerance
            inc = (h.targetRotation - h.currentRotation)
            h.backPanel.rotation += inc * radTo60Degree
            h.currentRotation += inc
            for value in h.colorPanels
              value.rotation += inc * radTo60Degree
              ## Update side index of each sprite
              for spr in value.children
                newSides = []
                for side in spr.sides
                  newSides.push((side + (h.currentRotation - h.prevRotation)) %% Hex.SIDES)
                spr.sides = newSides
            h.prevRotation = h.currentRotation
            h.canLight = true
            h.light()

        ### Spark and crystal color changing ###
        if (h instanceof Spark or h instanceof Crystal) and h.toColor isnt ""
          col = if (not isNaN(h.toColor)) 
                  Color.asString(h.toColor).toUpperCase() 
                else 
                  h.toColor.toUpperCase()
          h.backPanel.spr.color = col
          @toLit(h.backPanel.spr)
          h.toColor = ""
    requestAnimFrame(animate )
    @renderer.render(@stage)
    return
##窗口所在的帧数##
@计数=0
###将连接器移动到正确的照明层###
@toLit=(连接器)->
尝试
@colorContainers[connector.color].unlight.removeChild(connector.panel)
抓住
如果@typeIsArray connector.color
如果connector.color.length>0
c=连接器。颜色[0]。toUpperCase()
其他的
c=Color.asString(Color.NONE.toUpperCase())
其他的
c=connector.color.toUpperCase()的
如果c是Color.asString(Color.NONE).toUpperCase()
@toUnlit(连接器)##防止彩色照明。无
其他的
@colorContainers[c.toUpperCase()].lit.addChild(connector.panel)
connector.linked=true
返回
###将连接器移动到正确的未照明图层###
@toUnlit=(连接器)->
尝试
@colorContainers[connector.color].lit.removeChild(connector.panel)
抓住
如果@typeIsArray connector.color
如果connector.color.length>0
c=连接器。颜色[0]
其他的
c=Color.asString(Color.NONE)
其他的
c=连接器颜色
如果连接器是十六进制的?和连接器.hex晶体实例
@colorContainers[Color.asString(Color.NONE.toUpperCase()].unlight.addChild(connector.panel)
其他的
@colorContainers[c.toUpperCase()].unlight.addChild(connector.panel)
connector.linked=false
返回
###为每种颜色创建帧偏移###
@colorOffset={}
对于c,在Color.values()中
如果不是,isNaN(c)
c=Color.fromString(c).toUpperCase()
其他的
c=c.toUpperCase()
@colorOffset[c]=数学随机数()+0.5
###更新控制照明效果的脉冲过滤器###
@calcPulseFilter=(计数)->
对于col,@colorContainers的val
脉冲=val.lit.filters[0]
cont=(计数+val.lit.PULSESOFFSET)/val.lit.pulseLength
m=脉冲矩阵
m[0]=Math.abs(Math.sin(cont*2*Math.PI))*0.5+0.5
m[5]=Math.abs(Math.sin(cont*2*Math.PI))*0.5+0.5
m[10]=Math.abs(Math.sin(cont*2*Math.PI))*0.5+0.5
m[15]=Math.abs(Math.sin(cont*2*Math.PI))*0.25+0.75
脉冲矩阵=m
对于cont in@goalContainer.children
如果cont.childrence.length>=2和cont.filters.length>=2
脉冲=连续滤波器[1]
correspondCont=@colorContainers[cont.children[0].color.toUpperCase()].lit
c=(计数+对应的控制脉冲偏移量)/对应的控制脉冲长度
m=脉冲矩阵
如果parseInt(cont.children[1].text.substring(0,1))>=parseInt(cont.children[1].text.substring(2))
m[0]=Math.abs(Math.sin(c*2*Math.PI))*0.5+0.5
m[5]=Math.abs(Math.sin(c*2*Math.PI))*0.5+0.5
m[10]=Math.abs(Math.sin(c*2*Math.PI))*0.5+0.5
m[15]=Math.abs(Math.sin(c*2*Math.PI))*0.25+0.75
其他的
m[0]=1
m[5]=1
m[10]=1
m[15]=1
脉冲矩阵=m
返回
###动画功能。pixi打电话要求召回###
@动画=()->
##彩色动画
window.count+=1;##帧数
@calcPulseFilter(窗口计数)
旋转速度=1/5
浮点错误的公差=0.000001###-低于此值的差值被视为“相等”
Radto60度=1.04719755##1弧度*此系数=60度
如果(@BOARD?)
##更新目标文本
curLit=@BOARD.CrystalitCount()
goalContainer=@menu.children[@goalContainerIndex]
isWin=true##如果此用户已赢得-每个目标集,则为true。
用于目标容器中的pan。儿童
对于泛太平洋地区的spr儿童
如果PIXI.Text的spr instanceof和curLit的spr.color.toUpperCase()
spr.setText(curLit[spr.color.toUpperCase()]+spr.text.substring(1))
如果curLit[spr.color.toUpperCase()]0而不是h.backPanel.children[0].lit
h、 backPanel.children[0]。lit=true
如果不是(棱镜的h实例)
@托利特(h.背板.spr)
如果h.isLit().length为0且h.backPanel.children[0]为亮起
h、 backPanel.children[0]。lit=false
如果不是(棱镜的h实例)
@toUnlit(h.背板.spr)
hLit=h.isLit()
棱镜的若h实例
##调整核心的不透明度
对于col,为h型芯的芯
如果col.toLowerCase()不在hLit中且core.alpha>0
core.alpha=0
否则,如果hLit和core.alpha中的col.toLowerCase()为0
core.alpha=0.75
nS=h.getneightswithblanks()
##连接器的固定照明
用于h.colorPanels中的面板
col=panel.color.toLowerCase()
用于panel.children中的连接器
用于连接器中的侧面。侧面
n=nS[侧面]
如果n?以及hLit和n.co的col