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 = 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        # 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=0.5)
 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        # Scroll left
154        left_boundary = self.cam.left + VIEWPORT_MARGIN
155        if self.player.left < left_boundary:
156            self.cam.left -= left_boundary - self.player.left
157            changed = True
158
159        # Scroll right
160        right_boundary = self.cam.right - VIEWPORT_MARGIN
161        if self.player.right > right_boundary:
162            self.cam.right += self.player.right - right_boundary
163            changed = True
164
165        # Scroll up
166        top_boundary = self.cam.top - VIEWPORT_MARGIN
167        if self.player.top > top_boundary:
168            self.cam.top += self.player.top - top_boundary
169            changed = True
170
171        # Scroll down
172        bottom_boundary = self.cam.bottom + VIEWPORT_MARGIN
173        if self.player.bottom < bottom_boundary:
174            self.cam.bottom -= bottom_boundary - self.player.bottom
175            changed = True
176
177        # If we changed the boundary values, update the view port to match
178        if changed:
179            # Make sure our boundaries are integer values. While the view port does
180            # support floating point numbers, for this application we want every pixel
181            # in the view port to map directly onto a pixel on the screen. We don't want
182            # any rounding errors.
183            self.cam.left = int(self.cam.left)
184            self.cam.bottom = int(self.cam.bottom)
185
186            self.cam.use()
187
188    def on_key_press(self, key, modifiers):
189        """Called whenever a key is pressed. """
190
191        if key == arcade.key.UP:
192            self.up_pressed = True
193        elif key == arcade.key.DOWN:
194            self.down_pressed = True
195        elif key == arcade.key.LEFT:
196            self.left_pressed = True
197        elif key == arcade.key.RIGHT:
198            self.right_pressed = True
199
200    def on_key_release(self, key, modifiers):
201        """Called when the user releases a key. """
202
203        if key == arcade.key.UP:
204            self.up_pressed = False
205        elif key == arcade.key.DOWN:
206            self.down_pressed = False
207        elif key == arcade.key.LEFT:
208            self.left_pressed = False
209        elif key == arcade.key.RIGHT:
210            self.right_pressed = False
211
212
213def main():
214    """ Main function """
215    window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
216    window.setup()
217    arcade.run()
218
219
220if __name__ == "__main__":
221    main()