std::string Morton3D::toString() const { std::stringstream stream; stream << "(" << std::to_string(m_key) << " / " << std::bitset<32>(m_key).to_string() << " / " << toVec() << ")"; return stream.str(); }
void DynamicGoo::moveToTarget() { //Stop to follow if the goo is dragged for the use if (isDragging()) { stopFollow(); return; } if (onGround && groundPoint!=getPPosition()) { onGround=false; } if (isFalling()) return; if (hasJoint()) { return; } if (!hasJoint() && !isDragging() && isOnGround() && target==NULL ) { emit this->nextTargetPlease(NULL); } if (following && !falling) { if (prevTarget) { if (!target->isLinked(prevTarget)) { drop(); return; } QPoint meTarget=target->getPPosition()-getPPosition(); if (toVec(meTarget).Length()>15+radius/10) { stopFollow(); fallDown(); return; } //Compute mx and my for the position float mx,my; mx=(target->getVPosition().x-prevTarget->getVPosition().x); my=(target->getVPosition().y-prevTarget->getVPosition().y); float d=qSqrt(mx*mx+my*my); float md=qSqrt(qPow((target->getVPosition().x-getVPosition().x),2)+qPow((target->getVPosition().y-getVPosition().y),2)); mx/=d; my/=d; float tx,ty; //Compute tehorical x and y tx=(getVPosition().x-prevTarget->getVPosition().x)/mx; ty=(getVPosition().y-prevTarget->getVPosition().y)/my; float yt=my*tx+prevTarget->getVPosition().y; float xt=mx*ty+prevTarget->getVPosition().x; //if my y position is different at least of 12 falldown and return if ((qAbs(getVPosition().y-yt)>getRadius() && qAbs(getVPosition().x-xt)>getRadius()) || (md>d+radius)) { stopFollow(); fallDown(); return; } } //this is a work around for the very ugly bug of the "FLYING GOOS" //description of the bug if no prevTarget is setted but target is and the goo tower start to fall down the goo start to fly //for reach his target! //check if prevtarget is not setted and target is if (!prevTarget && target && !target->isOnGround()) { //compute distance between target and me float d=(target->getVPosition()-getVPosition()).Length(); //if that distance is more than 25 falldown and return //PS: remember that 30 is a single point contact between two goos if (d>=radius*0.2) { stopFollow(); fallDown(); return; } else if (d<radius*0.2) { emit this->nextTargetPlease(target); body->SetLinearVelocity(b2Vec2(0,0)); return; } } b2Vec2 dP; if (target!=NULL /*&& target->getBody()!=NULL*/) dP=target->getVPosition()-this->getVPosition(); else { stopFollow(); fallDown(); return; } if (dP.Length()<=(radius-radius/4.0)/10.0) { emit this->nextTargetPlease(target); body->SetLinearVelocity(b2Vec2(0,0)); return; } if (!prevTarget) { b2Vec2 dvec=(target->getVPosition()-getVPosition()); float d=qSqrt(dvec.x*dvec.x+dvec.y*dvec.y); if (onGround && target->isOnGround() && d<distanceToJoint) { double omega =(dP.x>0 ? speed*body->GetMass() : -speed*body->GetMass()); body->SetAngularVelocity(omega); body->ApplyForceToCenter(body->GetMass()*body->GetWorld()->GetGravity()); } else if (!onGround && d<radius*2) { emit this->nextTargetPlease(target); body->SetLinearVelocity(b2Vec2(0,0)); return; dP.x=(dP.x>0 ? speed*2 : -speed*2); dP.y=body->GetMass()*body->GetWorld()->GetGravity().y; body->ApplyForceToCenter(dP); } else { body->SetGravityScale(1); stopFollow(); } } else { dP.x=dP.x*speed/dP.Length(); dP.y=dP.y*speed/dP.Length() ; body->SetLinearVelocity(dP); } } }