//-------------------------------------------------------------------------------------- // Updates the position and velocity of the entity associated to this movement manager // using the accumulated sum of all forces impacting the entity. // Param1: The time in seconds passed since the last frame. // Param2: The maximal speed of the entity. // Param3: The maximal size of the accumulated forces. // Param4: The handicap to use if the entity is currently being handicapped. //-------------------------------------------------------------------------------------- void EntityMovementManager::UpdatePosition(float deltaTime, float maxSpeed, float maxForce, float handicap) { // Truncate steering force to not be greater than the maximal allowed force float magnitude = 0.0f; XMStoreFloat(&magnitude, XMVector2Length(XMLoadFloat2(&m_steeringForce))); if(magnitude > maxForce) { // Truncate the vector to be of the magnitude corresponding to the maximal allowed force XMStoreFloat2(&m_steeringForce, XMVector2Normalize(XMLoadFloat2(&m_steeringForce)) * maxForce); } // Calculate the new velocity for the entity XMFLOAT2 newVelocity; XMStoreFloat2(&newVelocity, XMLoadFloat2(&m_velocity) + XMLoadFloat2(&m_steeringForce)); // Truncate the velocity if it is greater than the maximally allowed velocity for the entity XMStoreFloat(&magnitude, XMVector2Length(XMLoadFloat2(&newVelocity))); if(magnitude > maxSpeed) { // Truncate the vector to be of the magnitude corresponding to the maximal allowed velocity XMStoreFloat2(&newVelocity, XMVector2Normalize(XMLoadFloat2(&newVelocity)) * maxSpeed); } // Set the new velocity and position on the entity m_velocity = newVelocity; XMFLOAT2 newPosition; if(m_pEntity->IsHandicapped()) { XMStoreFloat2(&newPosition, XMLoadFloat2(&m_pEntity->GetPosition()) + XMLoadFloat2(&newVelocity) * deltaTime * handicap); }else { XMStoreFloat2(&newPosition, XMLoadFloat2(&m_pEntity->GetPosition()) + XMLoadFloat2(&newVelocity) * deltaTime); } m_pEntity->SetPosition(newPosition); m_pEntity->UpdateColliderPosition(newPosition); // Update the rotation to make the entity face the direction, in which it is moving if(!(newVelocity.x == 0.0f && newVelocity.y == 0.0f)) { XMFLOAT2 lookAtPoint(0.0f, 0.0f); XMStoreFloat2(&lookAtPoint, XMLoadFloat2(&m_pEntity->GetPosition()) + XMLoadFloat2(&newVelocity)); LookAt(lookAtPoint); } // Reset the steering force for the next frame m_steeringForce.x = 0.0f; m_steeringForce.y = 0.0f; }
//-------------------------------------------------------------------------------------- // Tells whether a soldier is at a certain target or not. Accounts for the target reached // radius used by the soldier. // Param1: The target position, for which to check if the soldier has reached it. // Returns true if the soldier has reached the target, false otherwise. //-------------------------------------------------------------------------------------- bool Soldier::IsAtTarget(const XMFLOAT2& target) { float distance(0.0f); XMStoreFloat(&distance, XMVector2Length(XMLoadFloat2(&target) - XMLoadFloat2(&GetPosition()))); return (distance <= m_soldierProperties.m_targetReachedRadius); }
//-------------------------------------------------------------------------------------- // Move the entity to a specified target position. // Param1: The target position of the entity. // Param2: The radius around the target position from which the target counts as reached. // Param3: The speed, at which the entity should seek the target. // Returns true if the target was reached, false if there is still way to go. //-------------------------------------------------------------------------------------- bool EntityMovementManager::Seek(const XMFLOAT2& targetPosition, float targetReachedRadius, float speed) { XMFLOAT2 desiredVelocity; XMStoreFloat2(&desiredVelocity, XMLoadFloat2(&targetPosition) - XMLoadFloat2(&m_pEntity->GetPosition())); // Get the distance from the current position of the entity to the target float distance; XMStoreFloat(&distance, XMVector2Length(XMLoadFloat2(&desiredVelocity))); // Normalise the desired velocity XMStoreFloat2(&desiredVelocity, XMVector2Normalize(XMLoadFloat2(&desiredVelocity))); XMStoreFloat2(&desiredVelocity, XMLoadFloat2(&desiredVelocity) * speed); bool targetReached = false; // Target reached if(distance <= targetReachedRadius) { desiredVelocity = XMFLOAT2(0.0f, 0.0f); targetReached = true; } XMFLOAT2 force; XMStoreFloat2(&force, XMLoadFloat2(&desiredVelocity) - XMLoadFloat2(&m_velocity)); // Add the seek force to the accumulated steering force XMStoreFloat2(&m_steeringForce, XMLoadFloat2(&m_steeringForce) + XMLoadFloat2(&force)); return targetReached; }
void Small::BigDetect() { if (TeamID != RED) { for (int i = 0; i < RedList->size(); i++) { XMVECTOR tempvector = {XMVectorGetX(RedList->at(i)->Location), XMVectorGetY(RedList->at(i)->Location), 0, 0}; XMVECTOR tempdifference = Location - tempvector; if (XMVectorGetX(XMVector2Length(tempdifference)) < 40) { SetChaseTarget(RedList->at(i)); TeamID = Target->TeamID; Chasing = true; Flocking = true; } } } if (TeamID != BLUE) { for (int i = 0; i < BlueList->size(); i++) { XMVECTOR tempvector = {XMVectorGetX(BlueList->at(i)->Location), XMVectorGetY(BlueList->at(i)->Location), 0, 0}; XMVECTOR tempdifference = Location - tempvector; if (XMVectorGetX(XMVector2Length(tempdifference)) < 40) { SetChaseTarget(BlueList->at(i)); TeamID = Target->TeamID; Chasing = true; Flocking = true; } } } }
//-------------------------------------------------------------------------------------- // Calculate the path following force and add it to the total force. // Param1: A pointer to the path to follow. // Param2: When the entity has approached the target by this distance, it counts as reached. // Param3: The speed, at which the entity should follow the path. // Returns true if the end of the current path was reached, false if there is still way to go. //-------------------------------------------------------------------------------------- bool EntityMovementManager::FollowPath(std::vector<XMFLOAT2>* pPath, float nodeReachedRadius, float speed) { if(!pPath) { return false; } if(!pPath->empty()) { // There is an active path XMFLOAT2 target = (*pPath)[m_currentNode]; // Calculate the distance between the current position of the entity and the target float distance = 0.0f; XMStoreFloat(&distance, XMVector2Length(XMLoadFloat2(&target) - XMLoadFloat2(&m_pEntity->GetPosition()))); if(distance <= nodeReachedRadius) { // The entity has reached the node ++m_currentNode; if(m_currentNode >= pPath->size()) { // Final destination reached, clear the path pPath->clear(); m_velocity = XMFLOAT2(0.0f, 0.0f); return true; }else { Seek((*pPath)[m_currentNode], nodeReachedRadius, speed); return false; } }else { Seek((*pPath)[m_currentNode], nodeReachedRadius, speed); return false; } } return true; }
std::vector<std::pair<float, XMFLOAT4*>> Terrain::getBlendmapDataWithinRadius(const XMFLOAT3 position, const UINT radius) { const int col = (int)floorf( position.x + 0.5f * m_width); const int row = (int)floorf(-position.z + 0.5f * m_depth); const UINT width = m_width; const UINT depth = m_depth; const float halfWidth = 0.5f * (float)width; const float halfDepth = 0.5f * (float)depth; const float dx = (float)width / ((float)width - 1); const float dz = (float)depth / ((float)depth - 1); XMVECTOR p = XMVectorSet(position.x, position.z, 0.f, 0.f); std::vector<std::pair<float, XMFLOAT4*>> blendmapData; for (int i = row - (int)radius; i < row + (int)radius + 1; i++) { if (i >= 0 && i < (int)depth) { for (int j = col - (int)radius; j < col + (int)radius + 1; j++) { if (j >= 0 && j < (int)width) { XMVECTOR v = XMVectorSet(-halfWidth + j * dx, halfDepth - i * dz, 0.f, 0.f); const float length = XMVectorGetX(XMVector2Length(v - p)) / radius; if (length <= 1.f) blendmapData.push_back( std::pair<float, XMFLOAT4*>(length, &m_blendmap.texels[i * width + j])); } } } } return blendmapData; }
//-------------------------------------------------------------------------------------- // Checks for collision of a line with this collider. // Param1: The start point of the line. // Param2: The end point of the line. // Returns true if the line intersects with the collider, that includes touching it and // being fully encompassed by it, false otherwise. //-------------------------------------------------------------------------------------- bool CircleCollider::CheckLineCollision(const XMFLOAT2& lineStart, const XMFLOAT2& lineEnd) const { if(lineStart.x == lineEnd.x && lineStart.y == lineEnd.y) { // If the points are identical, check whether that shared point lies within the collider. return CheckPointCollision(lineStart); } XMVECTOR lineSegment = XMLoadFloat2(&lineEnd) - XMLoadFloat2(&lineStart); XMVECTOR startToCollider = XMLoadFloat2(&GetCentre()) - XMLoadFloat2(&lineStart); float segmentLength = 0.0f; XMStoreFloat(&segmentLength, XMVector2Length(lineSegment)); XMVECTOR normLineSegment = lineSegment / segmentLength; float projection = 0.0f; XMStoreFloat(&projection, XMVector2Dot(startToCollider, normLineSegment)); if((projection < 0.0f) || (projection > segmentLength)) { // Projection is beyond the start or end point of the segment return false; } // Get the projected point XMVECTOR projectedPoint = XMLoadFloat2(&lineStart) + normLineSegment * projection; // Check if the projected point lies within the radius of the collider float squareRadius = GetRadius() * GetRadius(); float squareDistance = 0.0f; XMStoreFloat(&squareDistance, XMVector2Dot(XMLoadFloat2(&GetCentre()) - projectedPoint, XMLoadFloat2(&GetCentre()) - projectedPoint)); return squareRadius >= squareDistance; }
void Small::Separation(float weight) { XMMATRIX rotationmatrix; XMVECTOR closestflockmatedifference = {-1000.0f, -1000.0f, 0, 0}; bool isalone = true; for (int i = 0; i < SmallVector->size(); i++) { if (SmallVector->at(i)->ID != this->ID) { if (SmallVector->at(i)->Chasing) { if (Target->ID == SmallVector->at(i)->Target->ID) { XMVECTOR tempvector = {XMVectorGetX(SmallVector->at(i)->Location), XMVectorGetY(SmallVector->at(i)->Location), 0, 0}; XMVECTOR tempdifference = Location - tempvector; if (XMVectorGetX(XMVector2Length(tempdifference)) < XMVectorGetX(XMVector2Length(closestflockmatedifference))) { closestflockmatedifference = tempdifference; isalone = false; } } } } } if (!isalone) { XMVECTOR leftvector = {0, 0, 0, 0}; XMVECTOR rightvector = {0, 0, 0, 0}; XMMATRIX rotationmatrixleft = XMMatrixRotationZ(float(M_PI)/2.0f); XMMATRIX rotationmatrixright = XMMatrixRotationZ(float(M_PI)/-2.0f); leftvector = XMVector3Transform(Direction, rotationmatrixleft); rightvector = XMVector3Transform(Direction, rotationmatrixright); Direction = XMVector2Normalize(Direction); XMVECTOR differencevector = closestflockmatedifference; differencevector = XMVector2Normalize(differencevector); float radiandifference = XMVectorGetX(XMVector2AngleBetweenNormals(leftvector, differencevector)); float epsilon = XMVectorGetX(XMVector2AngleBetweenNormals(Direction, differencevector)); if (radiandifference <= float(M_PI/2.0f)) { rotationmatrix = XMMatrixRotationZ(weight); if (epsilon <= (1.25f * weight)) { Direction = differencevector; Direction = XMVector2Normalize(Direction); } else { Direction = XMVector3Transform(Direction, rotationmatrix); Direction = XMVector2Normalize(Direction); } } else if (radiandifference > float(M_PI/2.0f)) { rotationmatrix = XMMatrixRotationZ(-weight); if (epsilon <= (1.25f * weight)) { Direction = differencevector; Direction = XMVector2Normalize(Direction); } else { Direction = XMVector3Transform(Direction, rotationmatrix); Direction = XMVector2Normalize(Direction); } } } }
float VectorMath::Magnitude(const Vec2* vec) { XMVECTOR xmVec = XMLoadFloat2((_XMFLOAT2*) vec); return XMVector2Length(xmVec).m128_f32[0]; }