Hi, I'm ThadeusB.

I code stuff. I raise bees. I game.

Rotate Sprite Towards Point

Smoothly turn a sprite towards a desired located based on a turning speed. Implemented in python for use with pygame, however the concepts can easily be taken to any other programming language.

class a_sprite():
    TURN_SPEED = 5.25 # radians degree's

    def change_direction(self, desired_pos):
        """
         Turns the sprite in the direction given
         desired_pos - desired coordinates for the sprite to look at.
               ex: (x, y) - (128, 256)
        """

        #Create a vector of the desired position
        destination = Vector2(desired_pos)
        #Get the normalized vector between sprites current position and
        # the destination vector. This is the heading to destination.
        new_heading = Vector2.from_vectors(self.position,destination).normalized()

        #Calculate the angle between current heading (normalized vector) and
        # the new heading.
        angle = self.heading.get_angle_between(new_heading)

        #Clamp it to turn speed
        angle = self.clamp(angle, -TURN_SPEED, TURN_SPEED)

        #Rotate our heading vector accordingly
        self.heading.rotate(angle)

        #Now calculate displacement and movement as normal with the newheading.

    def clamp(self, val, lower, higher):
        """ Clamps a value between low and high """
        if val > higher:
            val = higher
        if val < lower:
            val = lower
        return val

#Example needed methods from the vector2 class
class Vector2():
    @classmethod
    def from_vectors(cls, v1, v2):
        """Creates a Vector2 object between two Vector2
        v1 -- First Vector2
        v2 -- Second Vector2
        """
        return Vector2((v2.x - v1.x), (v2.y - v1.y))

    def normalize(self):
        self.isnormalized = True

        length = self.length
        if length != 0:
            self.x /= length
            self.y /= length

    def get_angle_between(self, other):
        cross = self.x*other[1] - self.y*other[0]
        dot = self.x*other[0] + self.y*other[1]
        return math.degrees(math.atan2(cross, dot))

    def dot(self, other):
        return float(self.x*other[0] + self.y*other[1])

    def cross(self, other):
        return self.x*other[1] - self.y*other[0]

    def rotate(self, angle_degrees):
        radians = math.radians(angle_degrees)
        cos = math.cos(radians)
        sin = math.sin(radians)
        x = self.x*cos - self.y*sin
        y = self.x*sin + self.y*cos
        self.x = x
        self.y = y

Any questions feel free to ask.

Vector2 Class: Download (altered from pygame wiki vec2d class)