Move to Mouse Click

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
  4Right-click to cause the tank to move to that point.
  5
  6If Python and Arcade are installed, this example can be run from the command line with:
  7python -m arcade.examples.turn_and_move
  8"""
  9import math
 10import arcade
 11
 12WINDOW_WIDTH = 1280
 13WINDOW_HEIGHT = 720
 14WINDOW_TITLE = "Turn and Move Example"
 15
 16# Image might not be lined up right, set this to offset
 17IMAGE_ROTATION = -90
 18
 19
 20class Player(arcade.Sprite):
 21    """
 22    Sprite that turns and moves
 23    """
 24    def __init__(self):
 25        super().__init__(":resources:images/topdown_tanks/tank_green.png")
 26
 27        # Destination point is where we are going
 28        self._destination_point = None
 29
 30        # Max speed px / s
 31        self.speed = 300
 32
 33        # what percent of the angle do we move by each frame
 34        self.rot_speed = 0.1
 35
 36    @property
 37    def destination_point(self):
 38        return self._destination_point
 39
 40    @destination_point.setter
 41    def destination_point(self, destination_point):
 42        self._destination_point = destination_point
 43        self.change_x = 0.0
 44        self.change_y = 0.0
 45
 46    def update(self, delta_time: float = 1 / 60):
 47        """ Update the player """
 48
 49        # If we have no destination, don't go anywhere.
 50        if not self._destination_point:
 51            self.change_x = 0
 52            self.change_y = 0
 53            return
 54
 55        # Position the start at our current location
 56        start_x = self.center_x
 57        start_y = self.center_y
 58
 59        # Get the destination location
 60        dest_x = self._destination_point[0]
 61        dest_y = self._destination_point[1]
 62
 63        # Do math to calculate how to get the sprite to the destination.
 64        # Calculation the angle in radians between the start points
 65        # and end points. This is the angle the player will travel.
 66        target_angle = arcade.math.get_angle_degrees(start_x, start_y, dest_x, dest_y)
 67        current_angle = self.angle - IMAGE_ROTATION
 68
 69        new_angle = arcade.math.lerp_angle(current_angle, target_angle, self.rot_speed)
 70
 71        self.angle = new_angle + IMAGE_ROTATION
 72        angle_diff = abs(target_angle - new_angle)
 73        if  angle_diff < 0.1 or 359.9 < angle_diff:
 74            self.angle = target_angle + IMAGE_ROTATION
 75            target_radians = math.radians(target_angle)
 76            self.change_x = math.cos(-target_radians) * self.speed
 77            self.change_y = math.sin(-target_radians) * self.speed
 78
 79        # Fine-tune our change_x/change_y if we are really close to destination
 80        # point and just need to set to that location.
 81        traveling = False
 82        if abs(self.center_x - dest_x) < abs(self.change_x * delta_time):
 83            self.center_x = dest_x
 84        else:
 85            self.center_x += self.change_x * delta_time
 86            traveling = True
 87
 88        if abs(self.center_y - dest_y) < abs(self.change_y * delta_time):
 89            self.center_y = dest_y
 90        else:
 91            self.center_y += self.change_y * delta_time
 92            traveling = True
 93
 94        # If we have arrived, then cancel our destination point
 95        if not traveling:
 96            self._destination_point = None
 97
 98
 99class GameView(arcade.View):
100    """
101    Main application class.
102    """
103
104    def __init__(self):
105        super().__init__()
106
107        self.background_color = arcade.color.SAND
108
109        self.player_sprite = None
110
111        # Sprite Lists
112        self.player_list = None
113
114    def setup(self):
115        """ Set up the game variables. Call to re-start the game. """
116
117        # Sprite Lists
118        self.player_list = arcade.SpriteList()
119        self.player_sprite = Player()
120        self.player_sprite.center_x = 300
121        self.player_sprite.center_y = 300
122        self.player_list.append(self.player_sprite)
123
124    def on_draw(self):
125        """
126        Render the screen.
127        """
128
129        # This command should happen before we start drawing. It will clear
130        # the screen to the background color, and erase what we drew last frame.
131        self.clear()
132
133        # Call draw() on all your sprite lists below
134        self.player_list.draw()
135
136    def on_update(self, delta_time):
137        """
138        All the logic to move, and the game logic goes here.
139        """
140        self.player_list.update(delta_time)
141
142    def on_mouse_press(self, x, y, button, key_modifiers):
143        """
144        Called when the user presses a mouse button.
145        """
146        if button == arcade.MOUSE_BUTTON_RIGHT:
147            self.player_sprite.destination_point = x, y
148
149
150def main():
151    """ Main function """
152    # Create a window class. This is what actually shows up on screen
153    window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
154
155    # Create and setup the GameView
156    game = GameView()
157    game.setup()
158
159    # Show GameView on screen
160    window.show_view(game)
161
162    # Start the arcade game loop
163    arcade.run()
164
165if __name__ == "__main__":
166    main()