移动到鼠标单击#
在此示例中,坦克转向用户单击鼠标的任何位置。
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
12SCREEN_WIDTH = 800
13SCREEN_HEIGHT = 600
14SCREEN_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
31 self.speed = 5
32
33 # Max speed we can rotate
34 self.rot_speed = 5
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
44 def on_update(self, delta_time: float = 1 / 60):
45 """ Update the player """
46
47 # If we have no destination, don't go anywhere.
48 if not self._destination_point:
49 self.change_x = 0
50 self.change_y = 0
51 return
52
53 # Position the start at our current location
54 start_x = self.center_x
55 start_y = self.center_y
56
57 # Get the destination location
58 dest_x = self._destination_point[0]
59 dest_y = self._destination_point[1]
60
61 # Do math to calculate how to get the sprite to the destination.
62 # Calculation the angle in radians between the start points
63 # and end points. This is the angle the player will travel.
64 x_diff = dest_x - start_x
65 y_diff = dest_y - start_y
66 target_angle_radians = math.atan2(y_diff, x_diff)
67 if target_angle_radians < 0:
68 target_angle_radians += 2 * math.pi
69
70 # What angle are we at now in radians?
71 actual_angle_radians = math.radians(self.angle - IMAGE_ROTATION)
72
73 # How fast can we rotate?
74 rot_speed_radians = math.radians(self.rot_speed)
75
76 # What is the difference between what we want, and where we are?
77 angle_diff_radians = target_angle_radians - actual_angle_radians
78
79 # Figure out if we rotate clockwise or counter-clockwise
80 if abs(angle_diff_radians) <= rot_speed_radians:
81 # Close enough, let's set our angle to the target
82 actual_angle_radians = target_angle_radians
83 clockwise = None
84 elif angle_diff_radians > 0 and abs(angle_diff_radians) < math.pi:
85 clockwise = False
86 elif angle_diff_radians > 0 and abs(angle_diff_radians) >= math.pi:
87 clockwise = True
88 elif angle_diff_radians < 0 and abs(angle_diff_radians) < math.pi:
89 clockwise = True
90 else:
91 clockwise = False
92
93 # Rotate the proper direction if needed
94 if actual_angle_radians != target_angle_radians and clockwise:
95 actual_angle_radians -= rot_speed_radians
96 elif actual_angle_radians != target_angle_radians:
97 actual_angle_radians += rot_speed_radians
98
99 # Keep in a range of 0 to 2pi
100 if actual_angle_radians > 2 * math.pi:
101 actual_angle_radians -= 2 * math.pi
102 elif actual_angle_radians < 0:
103 actual_angle_radians += 2 * math.pi
104
105 # Convert back to degrees
106 self.angle = math.degrees(actual_angle_radians) + IMAGE_ROTATION
107
108 # Are we close to the correct angle? If so, move forward.
109 if abs(angle_diff_radians) < math.pi / 4:
110 self.change_x = math.cos(actual_angle_radians) * self.speed
111 self.change_y = math.sin(actual_angle_radians) * self.speed
112
113 # Fine-tune our change_x/change_y if we are really close to destination
114 # point and just need to set to that location.
115 traveling = False
116 if abs(self.center_x - dest_x) < abs(self.change_x):
117 self.center_x = dest_x
118 else:
119 self.center_x += self.change_x
120 traveling = True
121
122 if abs(self.center_y - dest_y) < abs(self.change_y):
123 self.center_y = dest_y
124 else:
125 self.center_y += self.change_y
126 traveling = True
127
128 # If we have arrived, then cancel our destination point
129 if not traveling:
130 self._destination_point = None
131
132
133class MyGame(arcade.Window):
134 """
135 Main application class.
136 """
137
138 def __init__(self):
139 super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)
140
141 self.background_color = arcade.color.SAND
142
143 self.player_sprite = None
144
145 # Sprite Lists
146 self.player_list = None
147
148 def setup(self):
149 """ Set up the game variables. Call to re-start the game. """
150
151 # Sprite Lists
152 self.player_list = arcade.SpriteList()
153 self.player_sprite = Player()
154 self.player_sprite.center_x = 300
155 self.player_sprite.center_y = 300
156 self.player_list.append(self.player_sprite)
157
158 def on_draw(self):
159 """
160 Render the screen.
161 """
162
163 # This command should happen before we start drawing. It will clear
164 # the screen to the background color, and erase what we drew last frame.
165 self.clear()
166
167 # Call draw() on all your sprite lists below
168 self.player_list.draw()
169
170 def on_update(self, delta_time):
171 """
172 All the logic to move, and the game logic goes here.
173 """
174 self.player_list.on_update(delta_time)
175
176 def on_mouse_press(self, x, y, button, key_modifiers):
177 """
178 Called when the user presses a mouse button.
179 """
180 if button == arcade.MOUSE_BUTTON_RIGHT:
181 self.player_sprite.destination_point = x, y
182
183
184def main():
185 """ Main function """
186 game = MyGame()
187 game.center_window()
188 game.setup()
189 arcade.run()
190
191
192if __name__ == "__main__":
193 main()