Line of Sight

Line of Sight
line_of_sight.py
  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 = 250
 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        # Camera for scrolling
 54        self.cam = None
 55
 56        # Set the background color
 57        self.background_color = arcade.color.AMAZON
 58
 59    def setup(self):
 60        """ Set up the game and initialize the variables. """
 61
 62        # Camera
 63        self.cam = arcade.camera.Camera2D()
 64
 65        # Sprite lists
 66        self.player_list = arcade.SpriteList()
 67        self.wall_list = arcade.SpriteList(use_spatial_hash=True)
 68        self.enemy_list = arcade.SpriteList()
 69
 70        # Set up the player
 71        self.player = arcade.Sprite(":resources:images/animated_characters/female_person/femalePerson_idle.png",
 72                                    scale=SPRITE_SCALING)
 73        self.player.center_x = 50
 74        self.player.center_y = 350
 75        self.player_list.append(self.player)
 76
 77        # Set enemies
 78        enemy = arcade.Sprite(":resources:images/animated_characters/zombie/zombie_idle.png", scale=SPRITE_SCALING)
 79        enemy.center_x = 350
 80        enemy.center_y = 350
 81        self.enemy_list.append(enemy)
 82
 83        spacing = 200
 84        for column in range(10):
 85            for row in range(10):
 86                sprite = arcade.Sprite(":resources:images/tiles/grassCenter.png", scale=SPRITE_SCALING)
 87
 88                x = (column + 1) * spacing
 89                y = (row + 1) * sprite.height
 90
 91                sprite.center_x = x
 92                sprite.center_y = y
 93                if random.randrange(100) > 20:
 94                    self.wall_list.append(sprite)
 95
 96        self.physics_engine = arcade.PhysicsEngineSimple(self.player,
 97                                                         self.wall_list)
 98
 99    def on_draw(self):
100        """
101        Render the screen.
102        """
103        try:
104            # This command has to happen before we start drawing
105            self.clear()
106
107            # Draw all the sprites.
108            self.player_list.draw()
109            self.wall_list.draw()
110            self.enemy_list.draw()
111
112            for enemy in self.enemy_list:
113                if arcade.has_line_of_sight(self.player.position,
114                                            enemy.position,
115                                            self.wall_list):
116                    color = arcade.color.RED
117                else:
118                    color = arcade.color.WHITE
119                arcade.draw_line(self.player.center_x,
120                                 self.player.center_y,
121                                 enemy.center_x,
122                                 enemy.center_y,
123                                 color,
124                                 2)
125
126        except Exception as e:
127            print(e)
128
129    def on_update(self, delta_time):
130        """ Movement and game logic """
131
132        # Calculate speed based on the keys pressed
133        self.player.change_x = 0
134        self.player.change_y = 0
135
136        if self.up_pressed and not self.down_pressed:
137            self.player.change_y = MOVEMENT_SPEED
138        elif self.down_pressed and not self.up_pressed:
139            self.player.change_y = -MOVEMENT_SPEED
140        if self.left_pressed and not self.right_pressed:
141            self.player.change_x = -MOVEMENT_SPEED
142        elif self.right_pressed and not self.left_pressed:
143            self.player.change_x = MOVEMENT_SPEED
144
145        self.physics_engine.update()
146
147        # --- Manage Scrolling ---
148
149        # Keep track of if we changed the boundary. We don't want to
150        # update the camera if we don't need to.
151        changed = False
152
153        pos = self.cam.position
154
155        top_left = self.cam.top_left
156        bottom_right = self.cam.bottom_right
157
158        # Scroll left
159        left_boundary = top_left[0] + VIEWPORT_MARGIN
160        if self.player.left < left_boundary:
161            changed = True
162            pos = pos[0] + (self.player.left - left_boundary), pos[1]
163
164        # Scroll up
165        top_boundary = top_left[1] - VIEWPORT_MARGIN
166        if self.player.top > top_boundary:
167            changed = True
168            pos = pos[0], pos[1] + (self.player.top - top_boundary)
169
170        # Scroll right
171        right_boundary = bottom_right[0] - VIEWPORT_MARGIN
172        if self.player.right > right_boundary:
173            changed = True
174            pos = pos[0] + (self.player.right - right_boundary), pos[1]
175
176        # Scroll down
177        bottom_boundary = bottom_right[1] + VIEWPORT_MARGIN
178        if self.player.bottom < bottom_boundary:
179            changed = True
180            pos = pos[0], pos[1] + (self.player.bottom - bottom_boundary)
181
182        # If we changed the boundary values, update the view port to match
183        if changed:
184            self.cam.position = pos
185            self.cam.use()
186
187    def on_key_press(self, key, modifiers):
188        """Called whenever a key is pressed. """
189
190        if key == arcade.key.UP:
191            self.up_pressed = True
192        elif key == arcade.key.DOWN:
193            self.down_pressed = True
194        elif key == arcade.key.LEFT:
195            self.left_pressed = True
196        elif key == arcade.key.RIGHT:
197            self.right_pressed = True
198
199    def on_key_release(self, key, modifiers):
200        """Called when the user releases a key. """
201
202        if key == arcade.key.UP:
203            self.up_pressed = False
204        elif key == arcade.key.DOWN:
205            self.down_pressed = False
206        elif key == arcade.key.LEFT:
207            self.left_pressed = False
208        elif key == arcade.key.RIGHT:
209            self.right_pressed = False
210
211
212def main():
213    """ Main function """
214    window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
215    window.setup()
216    arcade.run()
217
218
219if __name__ == "__main__":
220    main()