| 72 | } |
| 73 | |
| 74 | void Projectile::update(GameState &state, unsigned int ticks) |
| 75 | { |
| 76 | // Delay the projectile accordingly |
| 77 | if (delay_ticks_remaining > ticks) |
| 78 | { |
| 79 | delay_ticks_remaining -= ticks; |
| 80 | return; |
| 81 | } |
| 82 | else |
| 83 | { |
| 84 | ticks -= delay_ticks_remaining; |
| 85 | delay_ticks_remaining = 0; |
| 86 | if (ticks == 0) |
| 87 | { |
| 88 | return; |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | if (ownerInvulnerableTicks > ticks) |
| 93 | { |
| 94 | ownerInvulnerableTicks -= ticks; |
| 95 | } |
| 96 | else |
| 97 | { |
| 98 | ownerInvulnerableTicks = 0; |
| 99 | } |
| 100 | this->previousPosition = this->position; |
| 101 | |
| 102 | // Tracking |
| 103 | if (turnRate > 0) |
| 104 | { |
| 105 | if (trackedObject) |
| 106 | { |
| 107 | targetPosition = trackedObject->getVoxelCentrePosition(); |
| 108 | } |
| 109 | else |
| 110 | { |
| 111 | // Stop tracking if arrived |
| 112 | if ((Vec3<int>)position == (Vec3<int>)targetPosition) |
| 113 | { |
| 114 | turnRate = 0; |
| 115 | } |
| 116 | } |
| 117 | auto targetVector = targetPosition - position; |
| 118 | auto cross = glm::cross(velocity, targetVector); |
| 119 | // Cross product is 0 if we are moving straight on target |
| 120 | if (cross.x != 0.0f || cross.y != 0.0f || cross.z != 0.0f) |
| 121 | { |
| 122 | float maxAngleToTurn = (float)ticks * turnRate * PROJECTILE_TURN_PER_TICK; |
| 123 | // angle is always > 0, turning direction determined by cross product |
| 124 | float angleToTarget = |
| 125 | clamp(glm::angle(glm::normalize(velocity), glm::normalize(targetVector)), 0.0f, |
| 126 | maxAngleToTurn); |
| 127 | glm::mat4 rotationMat(1); |
| 128 | rotationMat = glm::rotate(rotationMat, angleToTarget, cross); |
| 129 | velocity = glm::vec3(rotationMat * glm::vec4(velocity, 1.0)); |
| 130 | } |
| 131 | } |
nothing calls this directly
no test coverage detected