float GetAngle( Vector3 &a, Vector3 &b ) { float lengthA = a.GetLength(); float lengthB = b.GetLength(); float dot = DotProduct( a, b ); return acos( dot / (lengthA * lengthB) ); }
void Corpse::Spring(NodeType n1, NodeType n2, float distance, float dt){ SPADES_MARK_FUNCTION_DEBUG(); SPAssert(n1 >= 0); SPAssert(n1 < NodeCount); SPAssert(n2 >= 0); SPAssert(n2 < NodeCount); Node& a = nodes[n1]; Node& b = nodes[n2]; Vector3 diff = b.pos - a.pos; float dist = diff.GetLength(); Vector3 force = diff.Normalize() * (distance - dist); force *= dt * 50.f; b.vel += force; a.vel -= force; b.pos += force / (dt * 50.f) * 0.5f; a.pos -= force / (dt * 50.f) * 0.5f; Vector3 velMid = (a.vel + b.vel) * .5f; float dump = 1.f - powf(.1f, dt); a.vel += (velMid - a.vel) * dump; b.vel += (velMid - b.vel) * dump; }
void Corpse::Spring(NodeType n1a, NodeType n1b, NodeType n2, float distance, float dt){ SPADES_MARK_FUNCTION_DEBUG(); SPAssert(n1a >= 0); SPAssert(n1a < NodeCount); SPAssert(n1b >= 0); SPAssert(n1b < NodeCount); SPAssert(n2 >= 0); SPAssert(n2 < NodeCount); Node& x = nodes[n1a]; Node& y = nodes[n1b]; Node& b = nodes[n2]; Vector3 diff = b.pos - (x.pos + y.pos) * .5f; float dist = diff.GetLength(); Vector3 force = diff.Normalize() * (distance - dist); force *= dt * 50.f; b.vel += force; force *= .5f; x.vel -= force; y.vel -= force; Vector3 velMid = (x.vel + y.vel) * .25f + b.vel * .5f; float dump = 1.f - powf(.05f, dt); x.vel += (velMid - x.vel) * dump; y.vel += (velMid - y.vel) * dump; b.vel += (velMid - b.vel) * dump; }
void Corpse::AngleSpring(NodeType n1id, NodeType n2id, Vector3 dir, float minDot, float maxDot, float dt){ Node& n1 = nodes[n1id]; Node& n2 = nodes[n2id]; Vector3 diff = n2.pos - n1.pos; float ln1 = diff.GetLength(); float dot = Vector3::Dot(diff, dir) / (ln1 + 0.000000001f); if(dot >= minDot && dot <= maxDot) return; float strength = 0.f; Vector3 a1 = Vector3::Cross(dir, diff); a1 = Vector3::Cross(diff, a1).Normalize(); Vector3 a2 = -a1; //a1=-a1; a2=-a2; //a1 = -a1; if(dot > maxDot){ strength = MyACos(dot) - MyACos(maxDot); }else if(dot < minDot){ strength = MyACos(dot) - MyACos(minDot); } SPAssert(!isnan(strength)); strength *= 100.f; strength *= dt; a1 *= strength; a2 *= strength; n2.vel += a1; n1.vel += a2; //nBase.vel -= a1 + a2; /* d1 += a1 * 0.01; d2 += a2 * 0.01; float nd = Vector3::Dot(d1, d2) / (d1.GetLength() * d2.GetLength()); if(dot > maxDot){ if(nd < dot) printf("GOOD %f -> %f\n", dot, nd); else printf("BAD %f -> %f\n", dot, nd); }else{ if(nd > dot) printf("GOOD %f -> %f\n", dot, nd); else printf("BAD %f -> %f\n", dot, nd); }*/ }
/** * @brief * Called when the scene node needs to be updated */ void PGSparkles::OnUpdate() { // If this scene node wasn't drawn at the last frame, we can skip some update stuff if ((GetFlags() & ForceUpdate) || m_bUpdate) { m_bUpdate = true; // If there are free particles, create new particles if (!(System::GetInstance()->GetMicroseconds() % BuildPerSec)) { while (Math::GetRand() % 5) { Particle *pParticle = AddParticle(); if (pParticle) InitParticle(*pParticle); else break; } } { // Update particles float fTimeDiff = Timing::GetInstance()->GetTimeDifference(); Iterator<Particle> cIterator = GetParticleIterator(); while (cIterator.HasNext()) { Particle &cParticle = cIterator.Next(); // Update velocity cParticle.vVelocity += GetGravity()*fTimeDiff*(200-cParticle.fEnergy)/10; cParticle.vVelocity -= cParticle.vVelocity*fTimeDiff; // Self induction to make the sparkles a bit more interesting ;-) if (!(System::GetInstance()->GetMicroseconds() % 500) && !(Math::GetRand() % 5)) { cParticle.fEnergy += 100; cParticle.fSize += 0.2f; } // Update position Vector3 vMove = cParticle.vVelocity*fTimeDiff*cParticle.fEnergy/100; cParticle.vPos += vMove/10; // Update distortion cParticle.fCustom1 += fTimeDiff; float dLength = cParticle.fCustom1/vMove.GetLength()*5; cParticle.vDistortion = vMove*dLength; // Update energy, size and lifetime cParticle.fEnergy -= fTimeDiff*EnergyPerSec; cParticle.fSize -= fTimeDiff; if (cParticle.fEnergy <= 0 || cParticle.fSize <= 0) InitParticle(cParticle); else cParticle.vColor[3] = cParticle.fEnergy/255; } } // We have to recalculate the current axis align bounding box in 'scene node space' DirtyAABoundingBox(); } }
//! returns the closest point on a line segment [A B] Vector3 Math::GetClosestPointOnLine(const Vector3& vPoint, const Vector3& vA, const Vector3& vB) { Vector3 vC = vPoint-vA; Vector3 vD = vB-vA; float fLength = vD.GetLength(); vD = vD / fLength; float t = vD.DotProduct(vC); if(t < 0.0f) { return vA; } else if(t > fLength) { return vB; } return vA + vD*t; }
const F32 FreetypeFont::Measure(const std::string & text, const Vector3<F32> & forward) { F32 length = 0.0f; for(auto it = text.begin(); it != text.end(); ++it) { char c = *it; if(FT_Load_Char(m_FontFace, c, FT_LOAD_RENDER)) { LOG("could not load character, " << c); } FT_GlyphSlot g = m_FontFace->glyph; length += static_cast<F32>(g->advance.x >> 6) * m_ResolutionScale.x(); } return length * forward.GetLength(); }
//! 3D sphere vs ray intersection check bool CollisionUtils::SphereIntersectsWithRay(const Vector3& vCenter, f32 fRadius, const Vector3& vRayStart, const Vector3& vRayDir, f32* fRayLength /*= 0*/, f32* fDistToIntersection /*= 0*/) { Vector3 vToSphere = vCenter-vRayStart; f32 fDist = vToSphere.GetLength(); f32 fV = vToSphere.DotProduct(vRayDir); f32 fD = fRadius*fRadius - (fDist*fDist - fV*fV); f32 _fDistToIntersection = fV - Math::SquareRoot(fD); if(fD < 0.0f || _fDistToIntersection < 0.0f) { return false; } if(fRayLength && (*fRayLength < _fDistToIntersection)) { return false; } if(fDistToIntersection) { *fDistToIntersection = _fDistToIntersection; } return true; }
void PhysicsEngine::CollisionSphereResponse(PowerBall* b, PowerBall* b1) { // normal of the "collision plane" //Vector3 nColl = this->GetPositionVector3() - b1->GetPositionVector3(); Vector3 nColl = b->GetTempPosition() - b1->GetTempPosition(); // for easy projecting of vector, no div by |n|^2 in proj formula Vector3 tempa = nColl; nColl.normalize(); // savning the important stuff for easy acc float m1 = b->GetMass(); float m2 = b1->GetMass(); float mSum = m1+m2; Vector3 v1 = b->GetVelocity(); Vector3 v2 = b1->GetVelocity(); // projecting the vector v1 on nColl float x1 = nColl.GetDotProduct(v1); // factor in nColl dir Vector3 v1x = nColl*x1; // projetion done Vector3 v1y = v1 - v1x; // perpendicular vector // projecting the vector v2 on nColl nColl = nColl*(-1); // switching direction of "plane normal" float x2 = nColl.GetDotProduct(v2); // factor in nColl dir Vector3 v2x = nColl*x2; // projetion done Vector3 v2y = v2 - v2x; // perpendicular vector float e1 = b->GetRestitution(); float e2 = b1->GetRestitution(); float e = (e1 + e2)/2.0f; if(((v1x-v2x).GetLength() > 0.6f) && b->SoundEnabled()) this->mCollisionWithBall->Play(); /* this->mVelocity = Vector3( v1x*(m1-m2)/(mSum) + v2x*(2*m2)/(mSum) + v1y ); b1->mVelocity = Vector3( v1x*(2*m1)/(mSum) + v2x*(m2-m1)/(mSum) + v2y ); */ b->SetVelocity(Vector3( v1x*(m1-m2*e)/(mSum) + v2x*((1+e)*m2)/(mSum) + v1y )); b1->SetVelocity(Vector3( v1x*((1+e)*m1)/(mSum) + v2x*(m2-m1*e)/(mSum) + v2y )); /* calculating damage. */ if(b->WarlockMode()) { Vector3 ve1 = b->GetVelocity(); Vector3 ve2 = b1->GetVelocity(); Vector3 relativeV = ve1 - ve2; if( relativeV.GetLength() > 0.6f) { float v1 = ve1.GetLength(); float v2 = ve2.GetLength(); float mass1 = b->GetMass(); float mass2 = b1->GetMass(); float momentum1 = v1 * mass1; float momentum2 = v2 * mass2; float sumMomentum = momentum1 + momentum2; /* to make it clear. if ball 1 has the speed of 10 m/s and ball 2 has ** the speed 0 m/s, ball 1 will not get any damage but ball 2 gets ** his health minus 10* (10 / 10) = 10 so ball 2 has lost 10 in hp. ** this works good because we using momentum as a weighted value. */ float damage1 = 10.0f* (momentum2 / sumMomentum); float damage2 = 10.0f* (momentum1 / sumMomentum); float health1 = b->GetHealth(); health1 -= damage1; b->SetHealth(health1); float health2 = b1->GetHealth(); health2 -= damage2; b1->SetHealth(health2); } } /* informing the spells to the balls that it has been a collision */ Spell** spells = b->GetSpells(); for(int i = 0;i<b->GetNrOfSpells();i++) spells[i]->InformCollision(); spells = b1->GetSpells(); for(int i = 0;i<b1->GetNrOfSpells();i++) spells[i]->InformCollision(); }
bool PhysicsEngine::CollisionWithSphereSimple(PowerBall* b, PowerBall* b1) { Vector3 r = b->GetPositionVector3() - b1->GetPositionVector3(); r = b->GetTempPosition() - b1->GetTempPosition(); float distanceBalls = r.GetLength(); float sumRadius = b->GetRadius() + b1->GetRadius(); if(distanceBalls > sumRadius) return false; /* we have collision but we need to move the balls so they are not inside each other * solve this equation: ((pos1 - t*vel1) - (pos2 - t*vel2)).length = radie1 + radie2 * * this gives ut the following: * d = distance = p1-p2 * rV = relative velocity = v2-v1 * sumR = sumRadius = r1 + r2 * * t = - rV.dot(d)/|rV|^2 +- sqrt( rV.dot(d)^2/|rV|^4 - (sumR^2 - |d|^2) / |rV|^2 * */ Vector3 d = b->GetPositionVector3() - b1->GetPositionVector3(); d = b->GetTempPosition() - b1->GetTempPosition(); Vector3 rV = b1->GetVelocity() - b->GetVelocity(); float sumR = b->GetRadius() + b1->GetRadius(); float tempA = rV.GetDotProduct(d) / rV.GetLengthSquared(); float tempB = tempA*tempA; float tempC = (d.GetLengthSquared() - sumR*sumR) / rV.GetLengthSquared(); float tempSq = tempB - tempC; if( tempSq < 0) // no real solutions return false; else { float t1 = - tempA - sqrt(tempSq); float t2 = - tempA + sqrt(tempSq); Vector3 newPos1, newPos2; if(t1 >= 0) { /* newPos1 = this->GetPositionVector3() - this->mVelocity*t1; newPos2 = b1->GetPositionVector3() - b1->mVelocity*t1; this->SetPosition(newPos1); b1->SetPosition(newPos2); */ newPos1 = b->GetTempPosition() - b->GetVelocity()*t1; newPos2 = b1->GetTempPosition() - b1->GetVelocity()*t1; b->SetTempPosition(newPos1); b1->SetTempPosition(newPos2); } else if(t2 >= 0) { /* newPos1 = this->GetPositionVector3() - this->mVelocity*t2; newPos2 = b1->GetPositionVector3() - b1->mVelocity*t2; this->SetPosition(newPos1); b1->SetPosition(newPos2); */ newPos1 = b->GetTempPosition() - b->GetVelocity()*t2; newPos2 = b1->GetTempPosition() - b1->GetVelocity()*t2; b->SetTempPosition(newPos1); b1->SetTempPosition(newPos2); } else return false; } return true; }
float Vector3::AngleWith(const Vector3 &vec) const { return (float)acos( DotProduct(vec))/(GetLength() * vec.GetLength()); }
void Game::PlayGameMode2() { GraphicsEngine* mGe = GetGraphics(); GetGraphics()->ShowLoadingScreen("Media/LoadingScreen/LoadingScreenBG2.png", "Media/LoadingScreen/LoadingScreenPB.png", 1.0f, 1.0f); GetGraphics()->ChangeSkyBox("Media/StarMap.dds"); GetGraphics()->GetCamera()->SetUpVector(Vector3(0, 1, 0)); GetGraphics()->GetCamera()->SetForward(Vector3(1, 0, 0)); GetGraphics()->GetCamera()->SetPosition(Vector3(-17.0f, 56.0f, 0)); GetGraphics()->GetCamera()->LookAt(GetGraphics()->GetCamera()->GetPosition() - Vector3(1, 0.3f, 0)); iLight* mLights[5]; mLights[0] = mGe->CreateLight(Vector3(0, 50, 0)); mLights[1] = mGe->CreateLight(Vector3(0, 50, -20)); mLights[2] = mGe->CreateLight(Vector3(0, 50, 20)); mLights[3] = mGe->CreateLight(Vector3(10, 50, 0)); mLights[4] = mGe->CreateLight(Vector3(-10, 50, 0)); for(int i = 0; i < 5; i++) mLights[i]->SetIntensity(30.0f); GetGraphics()->SetSunLightDisabled(); GetGraphics()->SetSceneAmbientLight(Vector3(0.4f, 0.4f, 0.4f)); Vector3 centerPlatform = Vector3(0,20,0); Map* mPlatform = new Map("Media/MazeMapFixed.obj", centerPlatform); Map* mBox = new Map("Media/MazeMapFrame.obj", centerPlatform + Vector3(0,1,0) ); mPlatform->SetShrinkValue(0.0f); /* set so we cant tilt it more than these angles. */ mPlatform->SetMaxAngleX(10.0f*(PI/180.0f)); mPlatform->SetMaxAngleZ(10.0f*(PI/180.0f)); mPlatform->SetRotate(false); mPlatform->SetTargetAngleX(0.5f); mPlatform->SetTargetAngleZ(-0.5f); PowerBall* mBalls = new PowerBall("Media/Ball.obj", START_POS); mBalls->SetForwardVector(Vector3(0,0,1)); mBalls->SetKnockoutMode(); mBalls->SetAcceleration(mBalls->GetAcceleration()*30.0f); iText* timeTxt = GetGraphics()->CreateText("", Vector2(50, 60), 1.0f, "Media/fonts/new"); iText* scoreTxt = GetGraphics()->CreateText("", Vector2(50, 95), 1.0f, "Media/fonts/new"); iImage* guiStar = GetGraphics()->CreateImage(Vector2(200, 90), Vector2(75, 75), "Media/star.png"); guiStar->SetOpacity(0.0f); float starTimer = 0.0f; GetGraphics()->LoadingScreen("Media/LoadingScreen/LoadingScreenBG2.png", "Media/LoadingScreen/LoadingScreenPB.png", 1.0f, 1.0f, 1.0f, 1.0f); this->FlushQueue(); mGe->GetCamera()->SetPosition(centerPlatform + Vector3(0.0f, 30.0f, 20.0f)); mGe->GetCamera()->LookAt(centerPlatform); // Score / results: float time = 0.0f; bool started = false; int score = 0; float delayTimer = 1000.0f; GetGraphics()->GetKeyListener()->SetCursorVisibility(false); go = true; const Vector3 DefaultDir = Vector3(0.0f, 1.0f, 0.0f); int currentPrev = 0; Vector3 prevVectors[NROFPREV]; for(int i = 0; i < NROFPREV; i++) { prevVectors[i] = DefaultDir; } while(delayTimer > 0) { float diff = GetGraphics()->Update(); delayTimer -= diff; } while(GetGraphics()->IsRunning() && go) { if(mGe->GetKeyListener()->IsPressed('1')) { mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(20.0f, 30.0f, 20.0f)); mGe->GetCamera()->LookAt(centerPlatform ); } if(mGe->GetKeyListener()->IsPressed('2')) { mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(20.0f, 30.0f, -20.0f)); mGe->GetCamera()->LookAt(centerPlatform ); } if(mGe->GetKeyListener()->IsPressed('3')) { mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(-20.0f, 30.0f, 20.0f)); mGe->GetCamera()->LookAt(centerPlatform ); } if(mGe->GetKeyListener()->IsPressed('4')) { mGe->GetCamera()->SetPosition(centerPlatform+ Vector3(-20.0f, 30.0f, -20.0f)); mGe->GetCamera()->LookAt(centerPlatform ); } // Updates GFX float diff = GetGraphics()->Update(); // Handle events such as network packets and client connections this->HandleEvent(diff); if(GetGraphics()->GetKeyListener()->IsPressed(VK_ESCAPE)) go = false; if(GetGraphics()->GetKeyListener()->IsPressed('R') || (this->networkController != NULL && this->networkController->needRestart == true)) { if(this->networkController != NULL) { this->networkController->needRestart = false; } delete mBalls; // Spawn at last score - 1; if(score == 0) mBalls = new PowerBall("Media/Ball.obj", scorePos[0]); else mBalls = new PowerBall("Media/Ball.obj", scorePos[score - 1]); mBalls->SetForwardVector(Vector3(0,0,1)); mBalls->SetKnockoutMode(); mBalls->SetAcceleration(mBalls->GetAcceleration()*15.0f); mPlatform->ResetXZAngles(); mPlatform->RotateX(0); } iPhysicsEngine* pe = GetGraphics()->GetPhysicsEngine(); mBalls->UpdateBallParentMode(mPlatform); mBalls->Update(diff); Vector3 normalPlane; if(pe->DoSpecialPhoneCollisionGame(mBalls, mPlatform, normalPlane, diff)) mBalls->collisionPlatformResponse(mPlatform, normalPlane, diff); mBalls->UpdatePost(); mPlatform->Update(diff); if(this->networkController) { mPlatform->SetRotate(true); Vector3 phoneDirr = Vector3(this->networkController->direction.y, this->networkController->direction.z, -this->networkController->direction.x); //Vector3 phoneDirr = this->networkController->direction; phoneDirr.Normalize(); prevVectors[currentPrev] = phoneDirr; float angle = CalcAngle(phoneDirr, DefaultDir, prevVectors, currentPrev); float angleX = acos(DefaultDir.GetDotProduct(Vector3(0, phoneDirr.y , phoneDirr.z).Normalize())); float angleZ = acos(DefaultDir.GetDotProduct(Vector3(phoneDirr.x, phoneDirr.y, 0).Normalize())); if(phoneDirr.z > 0) { angleX *= -1; } if(phoneDirr.x < 0) { angleZ *= -1; } mPlatform->SetTargetAngleX(angleX/4); mPlatform->SetTargetAngleZ(angleZ/4); angle /= 4; currentPrev++; if(currentPrev >= NROFPREV) currentPrev = 0; } if(mGe->GetKeyListener()->IsPressed('W')) { mPlatform->RotateX(-diff); Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition(); tempPos.RotateAroundAxis(Vector3(1,0,0), (PI/8.0f)*-diff*0.001f); mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos); } if(mGe->GetKeyListener()->IsPressed('S')) { mPlatform->RotateX(diff); Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition(); tempPos.RotateAroundAxis(Vector3(1,0,0), (PI/8.0f)*diff*0.001f); mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos); } if(mGe->GetKeyListener()->IsPressed('A')) { mPlatform->RotateZ(-diff); Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition(); tempPos.RotateAroundAxis(Vector3(0,0,1), (PI/8.0f)*-diff*0.001f); mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos); } if(mGe->GetKeyListener()->IsPressed('D')) { mPlatform->RotateZ(diff); Vector3 tempPos = mBalls->GetPosition() - mPlatform->GetMesh()->GetPosition(); tempPos.RotateAroundAxis(Vector3(0,0,1), (PI/8.0f)*diff*0.001f); mBalls->SetPosition(mPlatform->GetMesh()->GetPosition() + tempPos); } ////////////////////////////////////////////////////////////////////////// static bool posb = true; if(GetGraphics()->GetKeyListener()->IsPressed('Q')) { if(posb) { MaloW::Debug(mBalls->GetPosition()); posb = false; } } else posb = true; ////////////////////////////////////////////////////////////////////////// if(started) { for(int i = score + 1; i < 15; i++) { Vector3 toScore = scorePos[i] - mBalls->GetPosition(); toScore.y = 0.0f; float distanceToScore = toScore.GetLength(); if(distanceToScore < 2.0f) { score = i; starTimer = 2.0f; // Do Vibration if(this->networkController) { this->networkController->cc->sendData("VIB: 100"); } } } time += diff * 0.001f; } else { if((mBalls->GetPosition() - Vector3(-13.0f,25,-13)).GetLength() > 3) { started = true; } } starTimer -= diff * 0.001f; if(starTimer < 0.0f) starTimer = 0.0f; guiStar->SetOpacity(starTimer); // print score and time text scoreTxt->SetText(string("SCORE: " + MaloW::convertNrToString(score)).c_str()); timeTxt->SetText(string("TIME: " + MaloW::convertNrToString(time)).c_str()); // End game after 2 mins if(time > 120.0f || score > 13) { this->FinishScreen(score, "2, Labyrinth", time); go = false; } } if(this->networkController) { this->networkController->cc->sendData("QUITTING"); } for(int i = 0; i < 5; i++) mGe->DeleteLight(mLights[i]); delete mPlatform; delete mBalls; delete mBox; mGe->DeleteText(timeTxt); mGe->DeleteText(scoreTxt); GetGraphics()->DeleteImage(guiStar); }
bool Warlock::checkWinConditions(float dt) { float newdt = dt/1000.0f; this->mTimeElapsed += newdt; Vector3 pos; Vector3 posLav; float distance = -1; int numberBallsAlive = 0; for(int i = 0; i<this->mNumberOfPlayers; i++) { pos = this->mBalls[i]->GetPositionVector3(); posLav = Vector3(pos.x,this->mGe->GetLavaHeightAt(pos.x, pos.z), pos.z); Vector3 distanceVector = (pos - posLav); distance = distanceVector.GetLength(); if(distance < this->mBalls[i]->GetRadius() || distanceVector.y < 0.0f ) { /* here the ball take damage. */ float radiusMapInside = 55.0f; float moreDamageDistance = pos.GetLength() - radiusMapInside; moreDamageDistance *= 0.5f; /* minus 4 hp per sec and minus distance in lava per sec */ this->mBalls[i]->SetHealth(this->mBalls[i]->GetHealth() - 4.0f*newdt - moreDamageDistance*newdt); } } /* if(this->mTimeElapsed > 600.0f) return true; return false;*/ int ballIndex = 0; int* arrayIndexs = new int[this->mNumberOfPlayers]; bool returnValue = false; /* checking which balls that are alive. */ for(int i = 0; i<this->mNumberOfPlayers; i++) { if(this->mBalls[i]->GetHealth() > 0) { /* saving the index of the balls that are alive and how many they are. */ arrayIndexs[numberBallsAlive] = i; numberBallsAlive++; } } /* checking so they belong to the same team. */ int numberRed = 0; int numberBlue = 0; int numberNone = 0; for(int i = 0; i<numberBallsAlive; i++) { ballIndex = arrayIndexs[i]; if(this->mBalls[ballIndex]->GetTeam() == TEAM::BLUETEAM) numberBlue++; if(this->mBalls[ballIndex]->GetTeam() == TEAM::REDTEAM) numberRed++; if(this->mBalls[ballIndex]->GetTeam() == TEAM::NOTEAM) // this is for free 4 all numberNone++; } /* if all balls belong to the same team and they are more that zero alive on the map or one alive in free 4 all. */ if((numberBallsAlive >0) && (numberBallsAlive == numberBlue || numberBallsAlive == numberRed || numberNone == 1 )) { /* here the round is over. */ /* to do. add winning information to teams or to player in free 4 all. */ returnValue = true; } else { returnValue = false; } delete arrayIndexs; /* when someone starts a game there will only be one alive on the map and he will be the winner by algoritm ** but for free 4 all it has to be at least 2 players for the win condition to be able to be true. ** and at least one player for each team in team mode of warlock for the win condition to be able to be true. ** */ /* checking which ball belong to which team and how many they are and how many that are no team aka free 4 all. */ numberRed = 0; numberBlue = 0; numberNone = 0; for(int i = 0; i<this->mNumberOfPlayers; i++) { if(this->mBalls[i]->GetTeam() == TEAM::BLUETEAM) numberBlue++; if(this->mBalls[i]->GetTeam() == TEAM::REDTEAM) numberRed++; if(this->mBalls[i]->GetTeam() == TEAM::NOTEAM) // this is for free 4 all numberNone++; } if(returnValue && ( (numberRed > 0 && numberBlue > 0) || numberNone > 1)) { for(int i = 0; i<this->mNumberOfPlayers; i++) { this->mBalls[i]->ResetTime(); this->mBalls[i]->SetToStartPosition(); this->mBalls[i]->SetForwardVector(this->mNet->GetBall(i)->GetStartForwardVector()); this->mNet->GetBall(i)->SetPos(this->mBalls[i]->GetPosition()); Vector3 vel = Vector3(0,0,0); this->mNet->GetBall(i)->SetVel(::D3DXVECTOR3(vel.x, vel.y, vel.z)); this->mNet->GetBall(i)->SetForwardVector(this->mNet->GetBall(i)->GetStartForwardVector()); } returnValue = true; } else returnValue = false; return returnValue; }
const float Vector3::GetDistance(const Vector3& v) const { const Vector3 d(v.x - x, v.y - y, v.z - z); return d.GetLength(); }
bool PhysicsEngine::CollisionWithMapSimple(PowerBall* b, Map* map, Vector3 &normalPlane) { MaloW::Array<MeshStrip*>* temp = map->GetMesh()->GetStrips(); //int sizeMstrip = temp->size(); int sizeVertexS0 = temp->get(0)->getNrOfVerts(); Vertex* verts; //Vector3 origin = this->GetPositionVector3(); Vector3 origin = b->GetTempPosition(); Vector3 dir = b->GetVelocity(); Vector3 dirN = dir/dir.GetLength(); verts = temp->get(0)->getVerts(); /* for(int i = 0;i<sizeMstrip;i++) { } */ Vector3 p0,p1,p2, normal, v1,v2; float smalestTime = -1; bool firstHit = false; float u, v,t; float lengthProjN = 0; Vector3 p0Store, p1Store,p2Store, normalStore; Vector3 pos = Vector3(map->GetMesh()->GetPosition()); Vector3 posS = b->GetTempPosition();//this->GetPositionVector3(); Vector3 rayDirection; Vector3 scalingMesh = map->GetMesh()->GetScaling(); D3DXMATRIX quat; D3DXMatrixRotationQuaternion(&quat, &map->GetMesh()->GetRotation()); Matrix4 rotate(quat); rotate.TransposeThis(); Matrix4 scaling; scaling.SetScale(scalingMesh); Matrix4 translate; translate.SetTranslate(pos); Matrix4 world = translate*rotate*scaling; for(int i =0; i< sizeVertexS0; i+=3) { /* p0 = Vector3(verts[i].pos).GetComponentMultiplication(scalingMesh) + pos; p1 = Vector3(verts[i+1].pos).GetComponentMultiplication(scalingMesh) +pos; p2 = Vector3(verts[i+2].pos).GetComponentMultiplication(scalingMesh) + pos; */ p0 = world*Vector3(verts[i].pos); p1 = world*Vector3(verts[i+1].pos); p2 = world*Vector3(verts[i+2].pos); v1 = p1-p0; v2 = p2-p0; rayDirection = v1.GetCrossProduct(v2); rayDirection.normalize(); float tempLength; Vector3 ny; Vector3 projN; if(RayTriIntersect(origin , rayDirection, p0, p1, p2, u, v, t) ) { normal = rayDirection; ny = origin - p0; projN = normal*ny.GetDotProduct(normal); tempLength = projN.GetLength(); if(!firstHit) { firstHit = true; smalestTime = t; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normal; } else { if( tempLength < lengthProjN ) { smalestTime = t; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normal; } } } // check agains all edges Vector3 lineDirection; float scalarProj; Vector3 projOnLine; Vector3 normalToLine; // edge 1: ny = origin - p0; lineDirection = p1 - p0; scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared()); projOnLine = lineDirection * scalarProj; if( (scalarProj >= 0.0f) && (scalarProj <= 1) ) { normalToLine = ny - projOnLine; tempLength = normalToLine.GetLength(); if(!firstHit) { firstHit = true; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } else { if( tempLength < lengthProjN ) { lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } } } // edge 2: ny = origin - p1; lineDirection = p2 - p1; scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared()); projOnLine = lineDirection * scalarProj; if( (scalarProj >= 0.0f) && (scalarProj <= 1) ) { normalToLine = ny - projOnLine; tempLength = normalToLine.GetLength(); if(!firstHit) { firstHit = true; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } else { if( tempLength < lengthProjN ) { lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } } } // edge 3: ny = origin - p2; lineDirection = p0 - p2; scalarProj = (ny.GetDotProduct(lineDirection)/lineDirection.GetLengthSquared()); projOnLine = lineDirection * scalarProj; if( (scalarProj >= 0.0f) && (scalarProj <= 1) ) { normalToLine = ny - projOnLine; tempLength = normalToLine.GetLength(); if(!firstHit) { firstHit = true; lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normalToLine; normalStore.normalize(); } else { if( tempLength < lengthProjN ) { lengthProjN = tempLength; p0Store = p0; p1Store = p1; p2Store = p2; normalStore = normal; } } } } if(firstHit) { // for checking if the ball are in the air not turned on at the moment, float eps = 0.5f; //0.001 if( (lengthProjN < (b->GetRadius() + eps)) && (lengthProjN > (b->GetRadius() - eps)) ) { b->SetNormalContact(normalStore); b->SetHasContact(true); } else { b->SetNormalContact(normalStore); b->SetHasContact(false); } if( lengthProjN <= b->GetRadius()) { Vector3 velNorm = b->GetVelocity(); velNorm.normalize(); if(normalStore.GetDotProduct(velNorm) >=0) return false; float diff = abs(lengthProjN- b->GetRadius()); //Vector3 newPo = origin -dirN*diff; //Vector3 projVel = normalStore * this->mVelocity.GetDotProduct(normalStore); Vector3 newPo = origin + normalStore*diff; /* if( projVel.GetDotProduct(normalStore) < 0.0f) { newPo = origin - normalStore*diff; return false; } else newPo = origin + normalStore*diff; */ //this->SetPosition(newPo); b->SetTempPosition(newPo); normalPlane = normalStore; //this->mNormalContact = normalPlane; //this->mHasContact = true; return true; } else { normalPlane = Vector3(0,0,0); //this->mNormalContact = normalPlane; //this->mHasContact = false; return false; } } normalPlane = Vector3(0,0,0); b->SetNormalContact(normalPlane); //this->mHasContact = false; return false; }
void Helicopter::Update(float dt) { // Gravity this->direction.y -= GRAVITY * dt; // Air friction float velocity = this->GetVelocity(); float newVelocity = velocity - ((AIR_FRICTION_CONSTANT * (velocity * velocity)) / this->mass) * dt; float dv = newVelocity / velocity; this->direction *= dv; // Collision against terrain float terrY = this->terrain->GetYPositionAt(this->pos.x, this->pos.z); if(this->pos.y + this->direction.y * dt <= terrY) { // Bounce this->direction.y = 0 - this->direction.y * this->elacticity; // Take damage float damage = (abs(this->direction.y * 5) + abs(this->direction.x) + abs(this->direction.z)); if(damage > 5.0f) this->health -= damage; } // Regen health: this->health += dt; if(this->health > 100.0f) this->health = 100.0f; // Friction against terrain here if close to it, simplified calculating only in the XZ plane and not angled terrain. if(this->pos.y - 0.5f < terrY) { float frictionForce = GROUND_FRICTION_CONSTANT * this->mass * GRAVITY; float frictionAcc = (frictionForce / this->mass) * dt; if(frictionAcc > this->GetXZVelocity()) { this->direction.x = 0; this->direction.z = 0; } else { velocity = this->GetVelocity(); newVelocity = velocity - frictionAcc; dv = newVelocity / velocity; this->direction *= dv; } // Reset rolling when touching ground. Vector3 defup = Vector3(0, 1, 0); defup.Normalize(); Vector3 cross = this->up.GetCrossProduct(this->forward); cross.Normalize(); float dotCrossDefup = cross.GetDotProduct(defup); // Roll left if(dotCrossDefup < 0.0f) { this->RollLeft(true); this->RollRight(false); } // Roll right else if(dotCrossDefup > 0.0f) { this->RollLeft(false); this->RollRight(true); } float dotForUp = this->forward.GetDotProduct(defup); // Roll forward if(dotForUp > 0.0f) { this->RollForward(true); this->RollBackward(false); } // Roll backward else if(dotForUp < 0.0f) { this->RollForward(false); this->RollBackward(true); } } if(this->health > 95.0f) this->UpdateChopperSpec(dt); // For funness we need to reset the direction.y a little, it's too hard to handle up&downs otherwise //direction.y *= 1.0f - dt; // AutoHoverEffect this->AutoHover(dt); if(this->health > 95.0f) { this->pos += this->direction * dt; this->chopper->SetPosition(this->pos); this->rotor->SetPosition(this->pos); this->secrotor->SetPosition(this->pos - this->forward * 28 + this->up * 11); // Adding offset for the second rotor. Vector3 lookAt = this->forward; lookAt.y = 0.0f; GetGraphics()->GetCamera()->SetPosition(this->pos + Vector3(0, this->camOffsetHeight, 0) - lookAt * this->camOffsetDistance); GetGraphics()->GetCamera()->LookAt(this->pos + lookAt * 30 + Vector3(0, 10, 0)); // Attune forward to direction. Vector3 xzdir = this->direction; xzdir.y = 0.0f; float xzlen = xzdir.GetLength(); xzdir.Normalize(); Vector3 xzfor = this->forward; xzfor.y = 0.0f; xzfor.Normalize(); float dotDirFor = xzdir.GetDotProduct(xzfor); Vector3 vecRight = xzfor.GetCrossProduct(Vector3(0, 1, 0)); vecRight.y = 0.0f; vecRight.Normalize(); float dotDirRight = xzdir.GetDotProduct(vecRight); // When flying backwards remove the "BAM SNAP" effect when dot product gets 0.0f at the sides. if(dotDirFor < 0.0f) dotDirFor = 0.0f; float angle = dt * xzlen * xzlen * xzlen * xzlen * (1 - abs(dotDirFor)) * 0.000001f; if(dotDirRight < 0.0f) angle *= -1.0f; this->forward.RotateAroundAxis(this->up, -angle); this->chopper->RotateAxis(this->up, -angle); this->rotor->RotateAxis(this->up, angle); } }
bool Plane<T>::IntersectsWithPlane( const Plane<T> &other ) const { Vector3<T> cross = other.normal.CrossProduct(normal); return cross.GetLength() > ROUNDING_ERROR_FLT; }