Pixi.js : обработка столкновений
Вот и вылез огромный минус работы с этим 2D движком: в «базе» нет функционала по определению столкновений двух объектов. Можно конечно самому дописать этот функционал если нужно..НО..вот моя реализация распознавания столкновения двух кружков получилась совсем не оптимальной по быстродействию.
Первым делом напишем алгоритм столкновения двух окружностей. А именно вспомним школу: Две окружности пересекаются,если расстояние между центрами меньше либо равно сумме радиусов
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function CircleHit(c0,c1){ res=false; r0=c0.getBounds().height/2; r1=c1.getBounds().height/2; x0=c0.getBounds().x+r0; x1=c1.getBounds().x+r1; y0=c0.getBounds().y+r0; y1=c1.getBounds().y+r1; len= Math.sqrt( Math.pow(x0-x1,2) + Math.pow(y0-y1,2) ); //расстояние между центрами sum=Math.abs(r0+r1); //сумма радиусов if (len<=sum) return true; return res; } |
Далее нарисуем на холсте случайным образом кружочки. Проследим, чтоб во время разрисовки они не накладывались и не пересекались:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
for (let i = 0; i < count_grand_mamas; i++) { graphics = new PIXI.Graphics(); graphics.beginFill(0xDE3249); graphics.lineStyle(2, 0xFEEB77, 1); graphics.beginFill(0x650A5A, 1); radius=randomIntFromInterval(5,30); graphics.drawCircle(0,0, radius); need_random=true; while (need_random==true){ x=randomIntFromInterval(1,width-2*radius); y=randomIntFromInterval(1,height-2*2*radius); if (i>0){ need_random=false; for (let it = 0; it < i-1; it++) { if (FutureCircleHit(grand_mamas[it],x,y,radius)==true) { need_random=true; }; } } else { need_random=false; } }; graphics.position.set(x, y); graphics.stepx=GetRandomStep(); // определяем направление движения по оси х graphics.stepy=GetRandomStep(); // определяем направление движения по оси y graphics.endFill(); grand_mamas.push(graphics); app.stage.addChild(grand_mamas[i]); } |
И теперь каждый «тик» двигаем кружок, проверяя не сталкиваются ли кружки. Если сталкиваются — то меняем направление движения обоих:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
ticker.add(function (time) { FPSText.text='FPS:'+ticker.FPS; // выводим FPS for (let i = 0; i < grand_mamas.length; i++) { grand_mamas[i].position.x=grand_mamas[i].position.x+grand_mamas[i].stepx; grand_mamas[i].position.y=grand_mamas[i].position.y+grand_mamas[i].stepy; if (((grand_mamas[i].getBounds().x+grand_mamas[i].getBounds().height)>width)||(grand_mamas[i].getBounds().x<0)){ grand_mamas[i].stepx=-grand_mamas[i].stepx; }; if (((grand_mamas[i].getBounds().y+grand_mamas[i].getBounds().height)>height)||(grand_mamas[i].getBounds().y<0)){ grand_mamas[i].stepy=-grand_mamas[i].stepy; }; grand_mamas[i].hit=false; }; // обрабатываем столкновения for (let i1 = 0; i1 < grand_mamas.length; i1++) { for (let i2 = 0; i2 < grand_mamas.length; i2++) { if (i1!=i2){ if (CircleHit(grand_mamas[i1],grand_mamas[i2])==true){ if (grand_mamas[i1].hit==false) { grand_mamas[i1].stepx=-1*grand_mamas[i1].stepx; grand_mamas[i2].stepx=-1*grand_mamas[i2].stepx; grand_mamas[i1].stepy=-1*grand_mamas[i1].stepy; grand_mamas[i2].stepy=-1*grand_mamas[i2].stepy; grand_mamas[i1].hit=true; grand_mamas[i2].hit=true; }; }; }; } } }); |