/** \param fDeltaTime: time since last Update */ void Player::Update(shoot::f32 fDeltaTime) { super::Update(fDeltaTime); bool bRightPressed = shoot::InputManager::Instance()->IsKeyPressed(shoot::InputManager::KT_Right); bool bLeftPressed = shoot::InputManager::Instance()->IsKeyPressed(shoot::InputManager::KT_Left); if(bRightPressed) { m_vVelocity = m_vSlidingDirection*m_fAcceleration; } else if(bLeftPressed) { m_vVelocity = m_vSlidingDirection*-m_fAcceleration; } bool bWasInTheAir = IsInTheAir(); if(bWasInTheAir) { m_vVelocity.Y += m_fGravity; } if(IsInTheAir() || (bRightPressed || bLeftPressed)) { CheckCollision(m_vPosition, m_vVelocity, m_vPosition, m_vVelocity); if(bWasInTheAir && !IsInTheAir()) { shoot::Print("*** bWasInTheAir && !IsInTheAir()\n"); } m_vPosition += m_vVelocity; } }
void Player::Move(Instruction _inst) { switch (_inst) { case GO_LEFT: m_facing = DLEFT; m_state = m_isRunning ? RUN : WALK; break; case GO_RIGHT: m_facing = DRIGHT; m_state = m_isRunning ? RUN : WALK; break; case STOP_LEFT: if (m_facing == DLEFT) // In case the user presses LEFT then presses RIGHT then releases LEFT { m_state = STATIC; if (IsInTheAir()) m_previousState = STATIC; } break; case STOP_RIGHT: if (m_facing == DRIGHT) { m_state = STATIC; if (IsInTheAir()) m_previousState = STATIC; } break; } }
void Player::AddOwnAcceleration() { // Player keeps acceleration when jumping if (m_state == WALK || (IsInTheAir() && m_previousState == WALK)) m_acceleration.x = PhysicsConstants::PlayerAcc_Walk * (m_facing == DLEFT ? -1 : 1); if (m_state == RUN || (IsInTheAir() && m_previousState == RUN)) m_acceleration.x = PhysicsConstants::PlayerAcc_Run * (m_facing == DLEFT ? -1 : 1); // Takes off if enough speed on the Y axis if (m_jumpState == JUMPING) { if (abs(m_velocity.y) < PhysicsConstants::MinSpeed) // Little push at the beginning of the jump m_velocity.y -= PhysicsConstants::InitialYVelForJump; if (abs(m_velocity.y) < PhysicsConstants::MaxYVelForJump) m_acceleration.y += PhysicsConstants::PlayerJumpAcc; else m_jumpState = REACHINGAPEX; } }
//! checks if there is collision void Player::CheckCollision(const shoot::Vector3D& vPosition, const shoot::Vector3D& vVelocity, shoot::Vector3D& vNewPosition, shoot::Vector3D& vNewVelocity) { shoot::Vertex3D* pVertices = m_pEnvironment->GetMesh()->GetVertexBuffer()->GetVertices(); shoot::u16* pIndices = m_pEnvironment->GetMesh()->GetIndexBuffer(0)->Indices; shoot::s32 numIndices = m_pEnvironment->GetMesh()->GetIndexBuffer(0)->NumIndices; bool bFound = false; for(shoot::s32 i=0; i<numIndices; i += 3) { shoot::s32 newTriangleIndex = i/3; if(newTriangleIndex != m_iCurrentCollidingTriangle) // don't re-process the current colliding triangle { shoot::Vertex3D v1 = pVertices[pIndices[i + 0]]; shoot::Vertex3D v2 = pVertices[pIndices[i + 1]]; shoot::Vertex3D v3 = pVertices[pIndices[i + 2]]; shoot::Plane plane(v1.Pos, v2.Pos, v3.Pos); // only process front facing planes shoot::Plane::E_Classification eObjectClass = plane.ClassifyPoint(vPosition); if(eObjectClass == shoot::Plane::C_Front) { bool bInTheAir = IsInTheAir(); bool bWall = IsWall(plane); shoot::Vector3D vTestVelocity; shoot::Vector3D vPointToCheck; if(bInTheAir || bWall) { vTestVelocity = vVelocity; vPointToCheck = vPosition - (plane.Normal*m_fRadius); } else { vTestVelocity = shoot::Vector3D(0.0f, -1.0f, 0.0f); vPointToCheck = vPosition + shoot::Vector3D(0.0f, -m_fRadius, 0.0f); } shoot::Vector3D normalizedVelocity = vTestVelocity; normalizedVelocity.Normalize(); shoot::f32 cosAngle = (normalizedVelocity).DotProduct(plane.Normal); if(cosAngle < 0.0f) { shoot::Vector3D vDestPoint = vPointToCheck + vTestVelocity; shoot::Vector3D vIntersection; shoot::Plane::E_Classification eClass; bool bIntersection = plane.IntersectWithRay(vPointToCheck, vTestVelocity, &vIntersection, &eClass); shoot::Triangle triangle(v1.Pos, v2.Pos, v3.Pos); bool bPointInside = bIntersection ? triangle.IsPointInside(vIntersection) : false; if(bIntersection && !bPointInside) { // check if point is on the triangle edges //bPointInside = shoot::Math::IsPointOnLineSegment(vIntersection, triangle.A, triangle.B) // || shoot::Math::IsPointOnLineSegment(vIntersection, triangle.B, triangle.C) // || shoot::Math::IsPointOnLineSegment(vIntersection, triangle.C, triangle.A); } if(bIntersection && bPointInside) { // determine class of dest point shoot::Plane::E_Classification eDestClass = plane.ClassifyPoint(vDestPoint); // if dest point is not front-facing the plane, we have a collision if(eDestClass != shoot::Plane::C_Front) { m_pIntersection1->SetPosition(vIntersection); m_pIntersection1->GetMesh()->GetMaterial(0).SetColor(shoot::Color::Green); shoot::Print("Colliding with triangle '%d' - Normal (%.2f, %.2f, %.2f)\n", i/3, plane.Normal.X, plane.Normal.Y, plane.Normal.Z); if(bWall) { vNewPosition = vIntersection + plane.Normal*m_fRadius; vNewVelocity = shoot::Vector3D(0.0f, 0.0f, 0.0f); } else { vNewPosition = GetNewPosition(vPosition, vIntersection, plane); if(bInTheAir) { vNewVelocity = shoot::Vector3D(0.0f, 0.0f, 0.0f); } m_vSlidingDirection = GetSlidingDirection(plane); m_iCurrentCollidingTriangle = newTriangleIndex; } shoot::Print("bWall = '%d', vNewVelocity(%.2f, %.2f, %.2f)\n", bWall, vNewVelocity.X, vNewVelocity.Y, vNewVelocity.Z); bFound = true; break; } } } } } } if(!bFound) { // quickly check if still in contact with current triangle, if not then we are in the air! if(m_iCurrentCollidingTriangle >= 0) { } } }