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
 15WINDOW_WIDTH = 1280
 16WINDOW_HEIGHT = 720
 17WINDOW_TITLE = "Line of Sight"
 18
 19MOVEMENT_SPEED = 5
 20
 21VIEWPORT_MARGIN = 250
 22HORIZONTAL_BOUNDARY = WINDOW_WIDTH / 2.0 - VIEWPORT_MARGIN
 23VERTICAL_BOUNDARY = WINDOW_HEIGHT / 2.0 - VIEWPORT_MARGIN
 24# If the player moves further than this boundary away from
 25# the camera we use a constraint to move the camera
 26CAMERA_BOUNDARY = arcade.LRBT(
 27    -HORIZONTAL_BOUNDARY,
 28    HORIZONTAL_BOUNDARY,
 29    -VERTICAL_BOUNDARY,
 30    VERTICAL_BOUNDARY,
 31)
 32
 33
 34class GameView(arcade.View):
 35    """
 36    Main application class.
 37    """
 38
 39    def __init__(self):
 40        """
 41        Initializer
 42        """
 43
 44        # Call the parent class initializer
 45        super().__init__()
 46
 47        # Variables that will hold sprite lists
 48        self.player_list = None
 49        self.wall_list = None
 50        self.enemy_list = None
 51
 52        # Set up the player info
 53        self.player = None
 54
 55        # Track the current state of what key is pressed
 56        self.left_pressed = False
 57        self.right_pressed = False
 58        self.up_pressed = False
 59        self.down_pressed = False
 60
 61        self.physics_engine = None
 62
 63        # Camera for scrolling
 64        self.camera = None
 65
 66        # Set the background color
 67        self.background_color = arcade.color.AMAZON
 68
 69    def setup(self):
 70        """ Set up the game and initialize the variables. """
 71
 72        # Camera
 73        self.camera = arcade.Camera2D()
 74
 75        # Sprite lists
 76        self.player_list = arcade.SpriteList()
 77        self.wall_list = arcade.SpriteList(use_spatial_hash=True)
 78        self.enemy_list = arcade.SpriteList()
 79
 80        # Set up the player
 81        self.player = arcade.Sprite(
 82            ":resources:images/animated_characters/female_person/femalePerson_idle.png",
 83            scale=SPRITE_SCALING,
 84        )
 85        self.player.center_x = 50
 86        self.player.center_y = 350
 87        self.player_list.append(self.player)
 88
 89        # Set enemies
 90        enemy = arcade.Sprite(
 91            ":resources:images/animated_characters/zombie/zombie_idle.png",
 92            scale=SPRITE_SCALING,
 93        )
 94        enemy.center_x = 350
 95        enemy.center_y = 350
 96        self.enemy_list.append(enemy)
 97
 98        spacing = 200
 99        for column in range(10):
100            for row in range(10):
101                sprite = arcade.Sprite(
102                    ":resources:images/tiles/grassCenter.png",
103                    scale=SPRITE_SCALING,
104                )
105
106                x = (column + 1) * spacing
107                y = (row + 1) * sprite.height
108
109                sprite.center_x = x
110                sprite.center_y = y
111                if random.randrange(100) > 20:
112                    self.wall_list.append(sprite)
113
114        self.physics_engine = arcade.PhysicsEngineSimple(
115            self.player,
116            self.wall_list,
117        )
118
119    def on_draw(self):
120        """
121        Render the screen.
122        """
123        # This command has to happen before we start drawing
124        self.clear()
125
126        # Draw all the sprites.
127        self.player_list.draw()
128        self.wall_list.draw()
129        self.enemy_list.draw()
130
131        for enemy in self.enemy_list:
132            if arcade.has_line_of_sight(
133                self.player.position, enemy.position, self.wall_list
134            ):
135                color = arcade.color.RED
136            else:
137                color = arcade.color.WHITE
138            arcade.draw_line(self.player.center_x,
139                             self.player.center_y,
140                             enemy.center_x,
141                             enemy.center_y,
142                             color,
143                             2)
144
145    def on_update(self, delta_time):
146        """ Movement and game logic """
147
148        # Calculate speed based on the keys pressed
149        self.player.change_x = 0
150        self.player.change_y = 0
151
152        if self.up_pressed and not self.down_pressed:
153            self.player.change_y = MOVEMENT_SPEED
154        elif self.down_pressed and not self.up_pressed:
155            self.player.change_y = -MOVEMENT_SPEED
156        if self.left_pressed and not self.right_pressed:
157            self.player.change_x = -MOVEMENT_SPEED
158        elif self.right_pressed and not self.left_pressed:
159            self.player.change_x = MOVEMENT_SPEED
160
161        self.physics_engine.update()
162
163        # --- Manage Scrolling ---
164        self.camera.position = arcade.camera.grips.constrain_boundary_xy(
165            self.camera.view_data, CAMERA_BOUNDARY, self.player.position
166        )
167        self.camera.use()
168
169    def on_key_press(self, key, modifiers):
170        """Called whenever a key is pressed. """
171
172        if key == arcade.key.UP:
173            self.up_pressed = True
174        elif key == arcade.key.DOWN:
175            self.down_pressed = True
176        elif key == arcade.key.LEFT:
177            self.left_pressed = True
178        elif key == arcade.key.RIGHT:
179            self.right_pressed = True
180
181    def on_key_release(self, key, modifiers):
182        """Called when the user releases a key. """
183
184        if key == arcade.key.UP:
185            self.up_pressed = False
186        elif key == arcade.key.DOWN:
187            self.down_pressed = False
188        elif key == arcade.key.LEFT:
189            self.left_pressed = False
190        elif key == arcade.key.RIGHT:
191            self.right_pressed = False
192
193
194def main():
195    """ Main function """
196    # Create a window class. This is what actually shows up on screen
197    window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
198
199    # Create and setup the GameView
200    game = GameView()
201    game.setup()
202
203    # Show GameView on screen
204    window.show_view(game)
205
206    # Start the arcade game loop
207    arcade.run()
208
209
210if __name__ == "__main__":
211    main()