1

我在 KineticJS 中做了一个简单的应用程序。在我的应用程序中,我需要创建一些可以拖放的圆圈,并且我需要检测它们之间的碰撞。现在我有 6 个气泡(圆圈),我可以移动它们并使用“dragmove”事件检测碰撞。这是有效的,气泡从我拖动的气泡中跑掉。但我也需要检测其他气泡之间的碰撞。我怎么能这样做?我没有看到“移动”事件只有“鼠标移动”。有什么想法可以让我自己举办活动或其他解决方案吗?

这是我的代码:

<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.6.0.min.js"></script>
    <script type="text/javascript" src="js/greensock/plugins/CSSPlugin.min.js"></script>
    <script type="text/javascript" src="js/greensock/TweenLite.min.js"></script>

    <script defer="defer">
      function collide(id, x, y, radius)<!-- moja własne metoda kolizji -->
      {
        for(var i = 0; i < 6; i++)
        {

            if(bubbleTab[i].getId() != id)
            {
                if(Math.sqrt(((bubbleTab[i].getX()-x)*(bubbleTab[i].getX()-x))+((bubbleTab[i].getY()-y)*(bubbleTab[i].getY()-y))) < (radius+bubbleTab[i].getRadius()))
                    {
                        if(Math.abs(x-bubbleTab[i].getX()) <= radius/2)
                        {
                            <!-- Kierunek góra dół -->
                            if(y>bubbleTab[i].getY())
                            {
                                bubbleTab[i].setY(y-radius-bubbleTab[i].getRadius()-1);
                            }
                            else
                            {
                                bubbleTab[i].setY(y+radius+bubbleTab[i].getRadius()+1);
                            }
                        }
                        else if(Math.abs(y-bubbleTab[i].getY()) <= radius/2)
                        {
                            <!-- Kierunek lewo prawo -->
                            if(x>bubbleTab[i].getX())
                            {
                                bubbleTab[i].setX(x-radius-bubbleTab[i].getRadius()-1);
                            }
                            else
                            {
                                bubbleTab[i].setX(x+radius+bubbleTab[i].getRadius()+1);
                            }
                        }
                        else if(x > bubbleTab[i].getX())
                        {
                            <!-- gora lewo dol lewo -->
                            if(y>bubbleTab[i].getY())
                            {
                                bubbleTab[i].setX(bubbleTab[i].getX()-4);
                                bubbleTab[i].setY(bubbleTab[i].getY()-4);
                            }
                            else
                            {
                                bubbleTab[i].setX(bubbleTab[i].getX()-4);
                                bubbleTab[i].setY(bubbleTab[i].getY()+4);
                            }                           
                        }
                        else
                        {
                            <!-- gora prawo dol prawo -->
                            if(y>bubbleTab[i].getY())
                            {
                                bubbleTab[i].setX(bubbleTab[i].getX()+4);
                                bubbleTab[i].setY(bubbleTab[i].getY()-4);
                            }
                            else
                            {
                                bubbleTab[i].setX(bubbleTab[i].getX()+4);
                                bubbleTab[i].setY(bubbleTab[i].getY()+4);
                            }
                        }

                    }
            }
        }
      }

      var stage = new Kinetic.Stage({
        container: 'container',
        width: 1300,
        height: 500
      });

      var layer = new Kinetic.Layer();

      var bubbleTab = new Array(6);
      for(var i = 0; i < 6; i++)
      {
        var bubble = new Kinetic.Circle({
          x: (stage.getWidth() / 2)-80+(i%3)*80,
          y: (stage.getHeight() / 2)-40+(i%2)*80,
          radius: 40,
          fillRadialGradientStartPoint: 0,
          fillRadialGradientStartRadius: 0,
          fillRadialGradientEndPoint: 0,
          fillRadialGradientEndRadius: 70,
          fillRadialGradientColorStops: [0, "rgb(225,17,17)", 1, "rgb(113,0,0)"],
          shadowColor: 'black',
          shadowBlur: 10,
          shadowOffset: 10,
          shadowOpacity: 0.5,
          opacity: 0.9,
          draggable: true,
          id: 'bubble'+i
        });

        bubble.on('mouseover touchstart', function() {
          this.setScale(1.2);
          document.body.style.cursor = 'pointer'; <!-- zmiana kursora na lapke -->
          layer.draw();
        });
        bubble.on('dragmove', function() {
          <!-- miejsce na metode kolizji -->

          collide(this.getId(), this.getX(), this.getY(), this.getRadius()*1.2);

        });     
        bubble.on('mouseout touchend', function() {
          this.setScale(1);
          document.body.style.cursor = 'default'; <!-- zmiana kursora na domyslny -->
          layer.draw();
        });

        bubbleTab[i] = bubble;
        layer.add(bubble);
      }

      stage.add(layer);

      var transparentBtn =  document.getElementById("transparentBtn"),
          tween = TweenLite.to(group, 1, {setX:500, setY:0, onUpdate:layer.draw, onUpdateScope:layer, paused:true});

          transparentBtn.onclick = function() {
          tween.restart();
        }
    </script>

编辑:

好的,我考虑了一下,我知道如何在没有新事件的情况下做到这一点。当任何气泡与我移动的气泡发生碰撞时,我总是调用碰撞函数。它正在工作,但我担心性能。如果您有任何想法;)请告诉我。

下面是我添加到 in 的每个调用方法中的代码setX()setY()function collide()

collide(bubbleTab[i].getId(), bubbleTab[i].getX(), bubbleTab[i].getY(), bubbleTab[i].getRadius());
4

1 回答 1

0

好的,这是一个您可以尝试实现的可能算法!将您的舞台 ( Kinetic.Layer) 划分为多个重叠的Kinetic.Groups(矩形/正方形区域)。重叠应略大于最大值。气泡的可能半径,即r' > 1.2*radius.

现在,对于每个以 x,y 为中心的圆,将其添加到覆盖该区域 x,y 的组中。现在,在您的碰撞检测期间,您只需检查该组内的圆圈,并且可以使用.getChildren()方法检索它们。这对于包含大量圆圈的更大模拟空间非常有帮助。

并且可以将相同的逻辑应用于与您正在移动的圆圈发生碰撞的所有圆圈,以找出进一步的碰撞。请注意,当他们跨越边界时,您必须从组中添加/删除圈子。

这当然假设您的气泡分布良好,否则,您最坏的情况将与您当前的实现相同。

于 2013-09-12T15:01:45.247 回答