int Check(Point &p1,Point &p2) { int i; if (fabs(p1.x-p2.x)<eps && fabs(p1.y-p2.y)<eps) return 0; for (i=0;i<n;i++) if (!IsIntersected(p1,p2,s[i],e[i])) return 0; return 1; }
void GamePlaying::onTouchEnded(Touch* t,Event* ev){ if(_slushLimit==0){ return; } auto stigma = getChildByName("stigma"); stigma->setName(""); stigma->runAction(Sequence::createWithTwoActions(FadeOut::create(0.5f),RemoveSelf::create())); //CreateSlushParticle(_touchedPos,t->getLocation()); bool flg=false; ///カットチェック for(MyPolygon& p : _polygons){ auto nnode = getChildByTag(p.tag); if(nnode==nullptr){ continue; } auto psp=(MyPhysicsShape*)(nnode->getPhysicsBody()->getFirstShape()); auto cps=(cpPolyShape*)(psp->getPolyShape()); auto& polyPos = getChildByTag(p.tag)->getPosition(); for(int j=0;j<cps->numVerts;++j){ if(j==cps->numVerts-1){ flg=IsIntersected(_touchedPos, t->getLocation(), Vec2(cps->tVerts[j].x,cps->tVerts[j].y), Vec2(cps->tVerts[0].x,cps->tVerts[0].y)); if(flg){ PosUv posuv; posuv.pos = IntersectedPoint(_touchedPos, t->getLocation(), Vec2(cps->tVerts[j].x,cps->tVerts[j].y), Vec2(cps->tVerts[0].x,cps->tVerts[0].y)); //とりあえずvertsのインデックスとp.vertices,p.uvsのインデクスが同一であると仮定する。 posuv.uv = GetMidUV(Vec2(cps->verts[j].x,cps->verts[j].y)+polyPos, p.uvs[j], Vec2(cps->tVerts[0].x,cps->tVerts[0].y), p.uvs[0], posuv.pos); p.cutEdges.push_back(std::make_pair(j,posuv));//インデックスとuv&posのペア p.wasCut=true; } }else{ flg=IsIntersected(_touchedPos, t->getLocation(), Vec2(cps->tVerts[j].x,cps->tVerts[j].y), Vec2(cps->tVerts[j+1].x,cps->tVerts[j+1].y)); if(flg){ PosUv posuv; posuv.pos =IntersectedPoint(_touchedPos, t->getLocation(), Vec2(cps->tVerts[j].x,cps->tVerts[j].y), Vec2(cps->tVerts[j+1].x,cps->tVerts[j+1].y)); //とりあえずvertsのインデックスとp.vertices,p.uvsのインデクスが同一であると仮定する。 posuv.uv = GetMidUV(Vec2(cps->tVerts[j].x,cps->tVerts[j].y), p.uvs[j], Vec2(cps->tVerts[j+1].x,cps->tVerts[j+1].y), p.uvs[j+1], posuv.pos); p.cutEdges.push_back(std::make_pair(j,posuv)); p.wasCut=true; } } } } std::vector<Vec2> cuttingEdges; ///一時的…追加用ベクタ作成 std::vector<MyPolygon> addedpolygons(0); int cutcount=0; ///分離処理(頂点の生成) for(MyPolygon& p : _polygons){ if(p.cutEdges.empty() || p.cutEdges.size()==1){//カットできてない場合は次へ p.wasCut=false; p.cutEdges.clear(); continue; } ++cutcount; //n番目がカットされている場合、nとn+1の間をカットしている //カットされている場合は2つのカットポイントが存在する Vec2& fpos=p.cutEdges[0].second.pos; Vec2& spos=p.cutEdges[1].second.pos; if((_touchedPos-fpos).length()>(_touchedPos-spos).length()){ //切るエフェクトの発生 CreateSlushParticle(spos,fpos); }else{ //切るエフェクトの発生 CreateSlushParticle(fpos,spos); } //とりあえず複製を一つ用意する //頂点数も変わる。エッジ番号の差が1なら残りの頂点数は1つまり差=残り頂点数となる //↑2つが新たな頂点となる(ソートが必要) if(p.cutEdges[0].first > p.cutEdges[1].first){ std::swap(p.cutEdges[0],p.cutEdges[1]); } auto nnode = getChildByTag(p.tag); auto& polyPos = nnode->getPosition(); auto psp=(MyPhysicsShape*)(nnode->getPhysicsBody()->getFirstShape()); auto cps=(cpPolyShape*)(psp->getPolyShape()); //sort完了 //差を算出 int diff = p.cutEdges[1].first-p.cutEdges[0].first; Vec2 pos=p.position; MyPolygon poly; std::vector<Vec2>& tmpUvs=p.uvs; poly.vertices.clear(); poly.uvs.clear(); poly.tag = p.tag; poly.texId = p.texId; poly.wasCut=p.wasCut; Vec2 newpos = p.cutEdges[0].second.pos-polyPos; poly.vertices.push_back(newpos); poly.uvs.push_back(p.cutEdges[0].second.uv);//切断端点 for(int i=1;i<=diff;++i){ int idx=p.cutEdges[0].first+i; cpVect& ve=cps->tVerts[idx];//元の座標を利用 newpos = Vec2(ve.x,ve.y)-polyPos; poly.vertices.push_back(newpos); poly.uvs.push_back(tmpUvs[idx]); } newpos = p.cutEdges[1].second.pos-polyPos; poly.vertices.push_back(newpos); poly.uvs.push_back(p.cutEdges[1].second.uv);//切断端点 poly.position = polyPos; addedpolygons.push_back(poly); poly.vertices.clear(); poly.uvs.clear(); //もうひとつのポリゴン diff=p.vertices.size()-diff; poly.texId = p.texId; poly.wasCut=p.wasCut; newpos = p.cutEdges[1].second.pos-polyPos; poly.vertices.push_back(newpos); poly.uvs.push_back(p.cutEdges[1].second.uv);//切断端点 for(int i=1;i<=diff;++i){ int idx = (p.cutEdges[1].first+i)%p.vertices.size(); cpVect& ve=cps->tVerts[idx];//元の座標を利用 newpos = Vec2(ve.x,ve.y)-polyPos; poly.vertices.push_back(newpos); poly.uvs.push_back(tmpUvs[idx]); } newpos = p.cutEdges[0].second.pos-polyPos; poly.vertices.push_back(newpos); poly.uvs.push_back(p.cutEdges[0].second.uv);//切断端点 poly.position = polyPos; addedpolygons.push_back(poly); } //切れてなければリターンする if(cutcount==0){ removeChild(stigma); return; } for(auto& p : _polygons){ auto node = getChildByTag(p.tag); if(node==nullptr){ continue; } auto& polyPos = node->getPosition(); if(!p.wasCut){ p.position=polyPos; } } //切れてしまっている奴は、別の2つに生まれ変わっているので、元のは消す。 for(auto& p : _polygons){ if(p.wasCut){ removeChild(getChildByTag(p.tag)); } } class IFunction{ public: bool operator()(MyPolygon& a){ return a.wasCut; } }; _polygons.erase(std::remove_if(_polygons.begin(),_polygons.end(),IFunction()),_polygons.end()); std::copy(addedpolygons.begin(),addedpolygons.end(),std::back_inserter(_polygons)); ///実際のポリゴン生成 for(auto& pl : _polygons){ if(!pl.wasCut){ continue; } auto& v=pl.vertices; auto& uvs=pl.uvs; auto node = DrawNodeWithTex::create(); node->SetTexture(pl.texId); //重心の計算(疑似) Vec2 center=Vec2(0,0); for(auto& vert : v){ center+=vert; } center = center/v.size(); for(auto& vert : v){ vert-=center; } auto grave=PhysicsBody::createPolygon(&v[0],v.size(),_pm); node->drawPolygonT(&v[0],&uvs[0],v.size(),cocos2d::Color4F::YELLOW,0,Color4F::WHITE); for(Vec2& uv : uvs){ log("u=%f,v=%f",uv.x,uv.y); } pl.position+=center; node->setPosition(pl.position); node->setPhysicsBody(grave); node->setTag(_tag++); pl.tag=node->getTag(); pl.wasCut=false; addChild(node); DrawNode* border=DrawNode::create(); border->drawPolygon(&v[0],v.size(),Color4F(0,0,0,0.0),BORDER_WIDTH,Color4F::WHITE); node->addChild(border); } --_slushLimit; }