# Turn and Move¶

In this example, the tank turns and moves towards where ever the user clicks the mouse.

turn_and_move.py
```  1"""
2Turn and Move Example
3"""
4
5
6import math
8
9SCREEN_WIDTH = 800
10SCREEN_HEIGHT = 600
11SCREEN_TITLE = "Turn and Move Example"
12
13# Image might not be lined up right, set this to offset
14IMAGE_ROTATION = 90
15
16
18    """
19    Sprite that turns and moves
20    """
21    def __init__(self):
22        super().__init__(":resources:images/topdown_tanks/tank_green.png")
23
24        # Destination point is where we are going
25        self._destination_point = None
26
27        # Max speed
28        self.speed = 5
29
30        # Max speed we can rotate
31        self.rot_speed = 5
32
33    @property
34    def destination_point(self):
35        return self._destination_point
36
37    @destination_point.setter
38    def destination_point(self, destination_point):
39        self._destination_point = destination_point
40
41    def on_update(self, delta_time: float = 1/60):
42        """ Update the player """
43
44        # If we have no destination, don't go anywhere.
45        if not self._destination_point:
46            self.change_x = 0
47            self.change_y = 0
48            return
49
50        # Position the start at our current location
51        start_x = self.center_x
52        start_y = self.center_y
53
54        # Get the destination location
55        dest_x = self._destination_point[0]
56        dest_y = self._destination_point[1]
57
58        # Do math to calculate how to get the sprite to the destination.
59        # Calculation the angle in radians between the start points
60        # and end points. This is the angle the player will travel.
61        x_diff = dest_x - start_x
62        y_diff = dest_y - start_y
65            target_angle_radians += 2 * math.pi
66
67        # What angle are we at now in radians?
69
70        # How fast can we rotate?
72
73        # What is the difference between what we want, and where we are?
75
76        # Figure out if we rotate clockwise or counter-clockwise
78            # Close enough, let's set our angle to the target
80            clockwise = None
82            clockwise = False
84            clockwise = True
86            clockwise = True
87        else:
88            clockwise = False
89
90        # Rotate the proper direction if needed
95
96        # Keep in a range of 0 to 2pi
97        if actual_angle_radians > 2 * math.pi:
98            actual_angle_radians -= 2 * math.pi
100            actual_angle_radians += 2 * math.pi
101
102        # Convert back to degrees
103        self.angle = math.degrees(actual_angle_radians) + IMAGE_ROTATION
104
105        # Are we close to the correct angle? If so, move forward.
106        if abs(angle_diff_radians) < math.pi / 4:
107            self.change_x = math.cos(actual_angle_radians) * self.speed
108            self.change_y = math.sin(actual_angle_radians) * self.speed
109
110        # Fine-tune our change_x/change_y if we are really close to destination
111        # point and just need to set to that location.
112        traveling = False
113        if abs(self.center_x - dest_x) < abs(self.change_x):
114            self.center_x = dest_x
115        else:
116            self.center_x += self.change_x
117            traveling = True
118
119        if abs(self.center_y - dest_y) < abs(self.change_y):
120            self.center_y = dest_y
121        else:
122            self.center_y += self.change_y
123            traveling = True
124
125        # If we have arrived, then cancel our destination point
126        if not traveling:
127            self._destination_point = None
128
129
131    """
132    Main application class.
133    """
134
135    def __init__(self):
136        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)
137
139
140        self.player_sprite = None
141
142        # Sprite Lists
143        self.player_list = None
144
145    def setup(self):
146        """ Set up the game variables. Call to re-start the game. """
147
148        # Sprite Lists
150        self.player_sprite = Player()
151        self.player_sprite.center_x = 300
152        self.player_sprite.center_y = 300
153        self.player_list.append(self.player_sprite)
154
155    def on_draw(self):
156        """
157        Render the screen.
158        """
159
160        # This command should happen before we start drawing. It will clear
161        # the screen to the background color, and erase what we drew last frame.
163
164        # Call draw() on all your sprite lists below
165        self.player_list.draw()
166
167    def on_update(self, delta_time):
168        """
169        All the logic to move, and the game logic goes here.
170        """
171        self.player_list.on_update(delta_time)
172
173    def on_mouse_press(self, x, y, button, key_modifiers):
174        """
175        Called when the user presses a mouse button.
176        """
178            self.player_sprite.destination_point = x, y
179
180
181def main():
182    """ Main method """
183    game = MyGame()
184    game.center_window()
185    game.setup()