1"""
2Line of Sight
3
4Artwork from https://kenney.nl
5
6If Python and Arcade are installed, this example can be run from the command line with:
7python -m arcade.examples.line_of_sight
8"""
9
10import arcade
11import random
12
13SPRITE_SCALING = 0.5
14
15SCREEN_WIDTH = 800
16SCREEN_HEIGHT = 600
17SCREEN_TITLE = "Line of Sight"
18
19MOVEMENT_SPEED = 5
20
21VIEWPORT_MARGIN = 300
22
23
24class MyGame(arcade.Window):
25 """
26 Main application class.
27 """
28
29 def __init__(self, width, height, title):
30 """
31 Initializer
32 """
33
34 # Call the parent class initializer
35 super().__init__(width, height, title)
36
37 # Variables that will hold sprite lists
38 self.player_list = None
39 self.wall_list = None
40 self.enemy_list = None
41
42 # Set up the player info
43 self.player = None
44
45 # Track the current state of what key is pressed
46 self.left_pressed = False
47 self.right_pressed = False
48 self.up_pressed = False
49 self.down_pressed = False
50
51 self.physics_engine = None
52
53 # Used in scrolling
54 self.view_bottom = 0
55 self.view_left = 0
56
57 # Set the background color
58 self.background_color = arcade.color.AMAZON
59
60 def setup(self):
61 """ Set up the game and initialize the variables. """
62
63 # Sprite lists
64 self.player_list = arcade.SpriteList()
65 self.wall_list = arcade.SpriteList(use_spatial_hash=True)
66 self.enemy_list = arcade.SpriteList()
67
68 # Set up the player
69 self.player = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png",
70 scale=SPRITE_SCALING)
71 self.player.center_x = 50
72 self.player.center_y = 350
73 self.player_list.append(self.player)
74
75 # Set enemies
76 enemy = arcade.Sprite(":resources:images/animated_characters/zombie/zombie_idle.png", scale=SPRITE_SCALING)
77 enemy.center_x = 350
78 enemy.center_y = 350
79 self.enemy_list.append(enemy)
80
81 spacing = 200
82 for column in range(10):
83 for row in range(10):
84 sprite = arcade.Sprite(":resources:images/tiles/grassCenter.png", scale=0.5)
85
86 x = (column + 1) * spacing
87 y = (row + 1) * sprite.height
88
89 sprite.center_x = x
90 sprite.center_y = y
91 if random.randrange(100) > 20:
92 self.wall_list.append(sprite)
93
94 self.physics_engine = arcade.PhysicsEngineSimple(self.player,
95 self.wall_list)
96
97 def on_draw(self):
98 """
99 Render the screen.
100 """
101 try:
102 # This command has to happen before we start drawing
103 self.clear()
104
105 # Draw all the sprites.
106 self.player_list.draw()
107 self.wall_list.draw()
108 self.enemy_list.draw()
109
110 for enemy in self.enemy_list:
111 if arcade.has_line_of_sight(self.player.position,
112 enemy.position,
113 self.wall_list):
114 color = arcade.color.RED
115 else:
116 color = arcade.color.WHITE
117 arcade.draw_line(self.player.center_x,
118 self.player.center_y,
119 enemy.center_x,
120 enemy.center_y,
121 color,
122 2)
123
124 except Exception as e:
125 print(e)
126
127 def on_update(self, delta_time):
128 """ Movement and game logic """
129
130 # Calculate speed based on the keys pressed
131 self.player.change_x = 0
132 self.player.change_y = 0
133
134 if self.up_pressed and not self.down_pressed:
135 self.player.change_y = MOVEMENT_SPEED
136 elif self.down_pressed and not self.up_pressed:
137 self.player.change_y = -MOVEMENT_SPEED
138 if self.left_pressed and not self.right_pressed:
139 self.player.change_x = -MOVEMENT_SPEED
140 elif self.right_pressed and not self.left_pressed:
141 self.player.change_x = MOVEMENT_SPEED
142
143 self.physics_engine.update()
144
145 # --- Manage Scrolling ---
146
147 # Keep track of if we changed the boundary. We don't want to call the
148 # set_viewport command if we didn't change the view port.
149 changed = False
150
151 # Scroll left
152 left_boundary = self.view_left + VIEWPORT_MARGIN
153 if self.player.left < left_boundary:
154 self.view_left -= left_boundary - self.player.left
155 changed = True
156
157 # Scroll right
158 right_boundary = self.view_left + SCREEN_WIDTH - VIEWPORT_MARGIN
159 if self.player.right > right_boundary:
160 self.view_left += self.player.right - right_boundary
161 changed = True
162
163 # Scroll up
164 top_boundary = self.view_bottom + SCREEN_HEIGHT - VIEWPORT_MARGIN
165 if self.player.top > top_boundary:
166 self.view_bottom += self.player.top - top_boundary
167 changed = True
168
169 # Scroll down
170 bottom_boundary = self.view_bottom + VIEWPORT_MARGIN
171 if self.player.bottom < bottom_boundary:
172 self.view_bottom -= bottom_boundary - self.player.bottom
173 changed = True
174
175 # Make sure our boundaries are integer values. While the view port does
176 # support floating point numbers, for this application we want every pixel
177 # in the view port to map directly onto a pixel on the screen. We don't want
178 # any rounding errors.
179 self.view_left = int(self.view_left)
180 self.view_bottom = int(self.view_bottom)
181
182 # If we changed the boundary values, update the view port to match
183 if changed:
184 arcade.set_viewport(self.view_left,
185 SCREEN_WIDTH + self.view_left,
186 self.view_bottom,
187 SCREEN_HEIGHT + self.view_bottom)
188
189 def on_key_press(self, key, modifiers):
190 """Called whenever a key is pressed. """
191
192 if key == arcade.key.UP:
193 self.up_pressed = True
194 elif key == arcade.key.DOWN:
195 self.down_pressed = True
196 elif key == arcade.key.LEFT:
197 self.left_pressed = True
198 elif key == arcade.key.RIGHT:
199 self.right_pressed = True
200
201 def on_key_release(self, key, modifiers):
202 """Called when the user releases a key. """
203
204 if key == arcade.key.UP:
205 self.up_pressed = False
206 elif key == arcade.key.DOWN:
207 self.down_pressed = False
208 elif key == arcade.key.LEFT:
209 self.left_pressed = False
210 elif key == arcade.key.RIGHT:
211 self.right_pressed = False
212
213
214def main():
215 """ Main function """
216 window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
217 window.setup()
218 arcade.run()
219
220
221if __name__ == "__main__":
222 main()