1

KineticJS で簡単なアプリケーションを作成しました。私のアプリでは、ドラッグ アンド ドロップできるいくつかの円を作成する必要があり、それらの間の衝突を検出する必要があります。これで 6 つのバブル (円) ができました。それらを移動し、「dragmove」イベントを使用して衝突を検出することもできます。うまくいきました、ドラッグしている泡から泡が逃げます。しかし、他のバブルとの衝突も検出する必要があります。どうすればこれを行うことができますか? 「move」イベントが表示されないのは「mousemove」だけです。独自のイベントやその他のソリューションを作成する方法はありますか?

これが私のコードです:

<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>

編集:

わかりましたそれについて考えてみると、新しいイベントなしでこれを行う方法がわかりました。バブルが私が動かしたバブルと衝突するときは、常に衝突関数を呼び出すだけです。動作していますが、パフォーマンスが心配です。何かアイデアがあれば ;) 教えてください。

以下は、のすべての呼び出しメソッド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 に答える